Bug 254212 - can't initialize an if_wg interface with IPv6 disabled
Summary: can't initialize an if_wg interface with IPv6 disabled
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-11 02:45 UTC by Mark Johnston
Modified: 2021-05-01 15:05 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Johnston freebsd_committer 2021-03-11 02:45:08 UTC
if_wg creates IPv4 and IPv6 listening sockets.  sobind() will fail for the IPv6 socket when the vnet has no IPv6 addresses assigned to any interface, see the first check in in6_pcbbind().  So if one creates a fresh vnet and instantiates a wg interface there, the link won't come up.  As a workaround one can do something like "ifconfig lo0 up", since that automatically assigns ::1.  I'm not sure why that check in in6_pcbbind() is needed in the first place.
Comment 1 Kyle Evans freebsd_committer 2021-03-12 20:22:03 UTC
I forwarded this secondary report to melifaro, but your workaround pointed out an rtentry leak somewhere. Try this:

# jail -c path=/ vnet=new command=ifconfig lo0 up
Freed UMA keg (rtentry) was not empty (1 items).  Lost 1 pages of memory.
Comment 2 Kyle Evans freebsd_committer 2021-03-14 22:29:46 UTC
(In reply to Kyle Evans from comment #1)

He pointed out that it was already fixed and our upstream base just a bit too old; rebased forward and my secondary nit is gone.
Comment 3 Jason A. Donenfeld 2021-04-17 23:50:33 UTC
I believe this has now been fixed in the latest wireguard-kmod package, and therefore this bug can be closed?
Comment 4 Mark Johnston freebsd_committer 2021-04-18 19:54:47 UTC
(In reply to Jason A. Donenfeld from comment #3)
I can't quite see how.  The problem is basically that in wg_socket_bind(), the sobind() call for the v6 socket will fail if the VNET does not have a v6 address assigned to some interface.  Looking at the sources from the latest version of the port, this failure will cause the v4 socket to be closed.
Comment 5 Jason A. Donenfeld 2021-04-19 00:34:41 UTC
Woof, I see what you mean now. That problem also applies to v4 sockets too! Basically if there's no interface with an address in the family, then bind fails. We could check for ret==EADDRNOTAVAIL and just let things continue in that case, but the fact that this can happen for both v4 and v6 means the user might find themselves in a very confusing state. Returning a failing rc from the ioctl and maybe even warning in dmesg seems more useful. But I also wish there was a more robust solution for this too. Maybe we should go in the direction of allowing sockets to bind to 0.0.0.0 and ::/0 even in the case in which there's not yet an interface with an address in that addr family? That'd certainly make things easier. Thoughts?
Comment 6 Mark Johnston freebsd_committer 2021-04-19 21:28:10 UTC
(In reply to Jason A. Donenfeld from comment #5)
Indeed, I'm not really sure why we prohibit bind() if no addresses from the corresponding family are assigned.  That behaviour appears to predate FreeBSD even.  It might be just a matter of removing the corresponding checks.  OTOH, it's perfectly valid to disable the use of either v4 or v6 in system (it's even possible to compile corresponding support out of the kernel), and in that case it seems rather odd to require that both sockets bind successfully.  Is it possible to have wg_socket_bind() succeed if it's able to bind at least one of the sockets, assuming that sobind() returns EADDRNOTAVAIL for the other?
Comment 7 Jason A. Donenfeld 2021-04-19 21:55:58 UTC
> Is it possible to have wg_socket_bind() succeed if it's able to bind at least one of the sockets, assuming that sobind() returns EADDRNOTAVAIL for the other?

Nice idea. That seems like a sensible plan and good compromise of conditions. Implemented here: https://git.zx2c4.com/wireguard-freebsd/commit/?id=2b2bd4ef95c2bbbb0da27005278880b4b1c940e0
Comment 8 Mark Johnston freebsd_committer 2021-04-20 13:19:24 UTC
(In reply to Jason A. Donenfeld from comment #7)
Thanks.  I'll test it out and close the bug if all goes well.
Comment 9 Jason A. Donenfeld 2021-04-25 13:49:09 UTC
Should now be released with https://cgit.freebsd.org/ports/commit/?id=4933972df03262847a7609001138597495cd72d5
Comment 10 Jason A. Donenfeld 2021-04-30 15:20:18 UTC
Hey Mark -- wondering if the latest port, v0.0.20210428, solves this for you.
Comment 11 Mark Johnston freebsd_committer 2021-05-01 15:03:46 UTC
(In reply to Jason A. Donenfeld from comment #10)
It does, thanks.  In a vnet jail I have:

# sockstat
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS      
?        ?          ?     ?  udp4   *:1234                *:*
#
Comment 12 Jason A. Donenfeld 2021-05-01 15:05:46 UTC
Terrific!