Fix race in netlink peer correlator

This commit is contained in:
Jason A. Donenfeld 2018-05-20 03:37:33 +02:00
parent 7c21a3de0a
commit a5b3340e5b

View File

@ -21,6 +21,7 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
"strconv" "strconv"
"sync"
"unsafe" "unsafe"
) )
@ -551,6 +552,7 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
endpoint *Endpoint endpoint *Endpoint
} }
var reqPeer map[uint32]peerEndpointPtr var reqPeer map[uint32]peerEndpointPtr
var reqPeerLock sync.Mutex
defer unix.Close(bind.netlinkSock) defer unix.Close(bind.netlinkSock)
@ -596,10 +598,13 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
} }
if attrhdr.Type == unix.RTA_OIF && attrhdr.Len == unix.SizeofRtAttr+4 { if attrhdr.Type == unix.RTA_OIF && attrhdr.Len == unix.SizeofRtAttr+4 {
ifidx := *(*uint32)(unsafe.Pointer(&attr[unix.SizeofRtAttr])) ifidx := *(*uint32)(unsafe.Pointer(&attr[unix.SizeofRtAttr]))
reqPeerLock.Lock()
if reqPeer == nil { if reqPeer == nil {
reqPeerLock.Unlock()
break break
} }
pePtr, ok := reqPeer[hdr.Seq] pePtr, ok := reqPeer[hdr.Seq]
reqPeerLock.Unlock()
if !ok { if !ok {
break break
} }
@ -620,7 +625,9 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
} }
break break
} }
reqPeerLock.Lock()
reqPeer = make(map[uint32]peerEndpointPtr) reqPeer = make(map[uint32]peerEndpointPtr)
reqPeerLock.Unlock()
go func() { go func() {
device.peers.mutex.RLock() device.peers.mutex.RLock()
i := uint32(1) i := uint32(1)
@ -671,10 +678,12 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
uint32(bind.lastMark), uint32(bind.lastMark),
} }
nlmsg.hdr.Len = uint32(unsafe.Sizeof(nlmsg)) nlmsg.hdr.Len = uint32(unsafe.Sizeof(nlmsg))
reqPeerLock.Lock()
reqPeer[i] = peerEndpointPtr{ reqPeer[i] = peerEndpointPtr{
peer: peer, peer: peer,
endpoint: &peer.endpoint, endpoint: &peer.endpoint,
} }
reqPeerLock.Unlock()
peer.mutex.RUnlock() peer.mutex.RUnlock()
i++ i++
_, err := bind.netlinkCancel.Write((*[unsafe.Sizeof(nlmsg)]byte)(unsafe.Pointer(&nlmsg))[:]) _, err := bind.netlinkCancel.Write((*[unsafe.Sizeof(nlmsg)]byte)(unsafe.Pointer(&nlmsg))[:])