wgengine/magicsock: fix crash reading DERP packet
Starting at yesterday's (convering some UDPAddrs to
IPPorts), Conn.ReceiveIPv4 could return a nil addr, which would make
its way through wireguard-go and blow up later. The DERP read path
wasn't initializing the addr result parameter any more, and wgRecvAddr
wasn't checking it either.
Fixes
@@ -1221,24 +1221,31 @@ func (c *Conn) awaitUDP4(b []byte) {
}
}
-// wgRecvAddr conditionally alters the returned UDPAddr we tell
-// wireguard-go we received a packet from. For peers with discovery
-// keys, we always use the same one, a unique synthetic value created
-// per peer.
-func wgRecvAddr(e conn.Endpoint, addr *net.UDPAddr) *net.UDPAddr {
+// wgRecvAddr returns the net.UDPAddr we tell wireguard-go the address
+// from which we received a packet for an endpoint.
+//
+// ipp is required. addr can be optionally provided.
+func wgRecvAddr(e conn.Endpoint, ipp netaddr.IPPort, addr *net.UDPAddr) *net.UDPAddr {
+ if ipp == (netaddr.IPPort{}) {
+ panic("zero ipp")
+ }
if de, ok := e.(*discoEndpoint); ok {
return de.fakeWGAddrStd
}
+ if addr != nil {
return addr
}
+ return ipp.UDPAddr()
+}
func (c *Conn) ReceiveIPv4(b []byte) (n int, ep conn.Endpoint, addr *net.UDPAddr, err error) {
Top:
// First, process any buffered packet from earlier.
if from := c.bufferedIPv4From; from != (netaddr.IPPort{}) {
c.bufferedIPv4From = netaddr.IPPort{}
- ep := c.findEndpoint(from, from.UDPAddr())
- return copy(b, c.bufferedIPv4Packet), ep, wgRecvAddr(ep, addr), nil
+ addr = from.UDPAddr()
+ ep := c.findEndpoint(from, addr)
+ return copy(b, c.bufferedIPv4Packet), ep, wgRecvAddr(ep, from, addr), nil
}
go c.awaitUDP4(b)
@@ -1329,7 +1336,7 @@ func (c *Conn) ReceiveIPv4(b []byte) (n int, ep conn.Endpoint, addr *net.UDPAddr
} else {
ep = c.findEndpoint(ipp, addr)
}
- return n, ep, wgRecvAddr(ep, addr), nil
+ return n, ep, wgRecvAddr(ep, ipp, addr), nil
}
func (c *Conn) ReceiveIPv6(b []byte) (int, conn.Endpoint, *net.UDPAddr, error) {
@@ -1355,7 +1362,7 @@ func (c *Conn) ReceiveIPv6(b []byte) (int, conn.Endpoint, *net.UDPAddr, error) {
}
ep := c.findEndpoint(ipp, addr)
- return n, ep, wgRecvAddr(ep, addr), nil
+ return n, ep, wgRecvAddr(ep, ipp, addr), nil
}
}
