device: SendmsgN mutates the input sockaddr
So we take a new granular lock to prevent concurrent writes from
racing.
WARNING: DATA RACE
Write at 0x00c0011f2740 by goroutine 27:
  golang.org/x/sys/unix.(*SockaddrInet4).sockaddr()
      /go/pkg/mod/golang.org/x/sys@v0.0.0-20191105231009-c1f44814a5cd/unix/syscall_linux.go:384
+0x114
  golang.org/x/sys/unix.SendmsgN()
      /go/pkg/mod/golang.org/x/sys@v0.0.0-20191105231009-c1f44814a5cd/unix/syscall_linux.go:1304
+0x288
  golang.zx2c4.com/wireguard/device.send4()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/conn_linux.go:485
+0x11f
  golang.zx2c4.com/wireguard/device.(*nativeBind).Send()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/conn_linux.go:268
+0x1d6
  golang.zx2c4.com/wireguard/device.(*Peer).SendBuffer()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/peer.go:151
+0x285
  golang.zx2c4.com/wireguard/device.(*Peer).SendHandshakeInitiation()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/send.go:163
+0x692
  golang.zx2c4.com/wireguard/device.(*Device).RoutineReadFromTUN()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/send.go:318
+0x4b8
Previous write at 0x00c0011f2740 by goroutine 386:
  golang.org/x/sys/unix.(*SockaddrInet4).sockaddr()
      /go/pkg/mod/golang.org/x/sys@v0.0.0-20191105231009-c1f44814a5cd/unix/syscall_linux.go:384
+0x114
  golang.org/x/sys/unix.SendmsgN()
      /go/pkg/mod/golang.org/x/sys@v0.0.0-20191105231009-c1f44814a5cd/unix/syscall_linux.go:1304
+0x288
  golang.zx2c4.com/wireguard/device.send4()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/conn_linux.go:485
+0x11f
  golang.zx2c4.com/wireguard/device.(*nativeBind).Send()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/conn_linux.go:268
+0x1d6
  golang.zx2c4.com/wireguard/device.(*Peer).SendBuffer()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/peer.go:151
+0x285
  golang.zx2c4.com/wireguard/device.(*Peer).SendHandshakeInitiation()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/send.go:163
+0x692
  golang.zx2c4.com/wireguard/device.expiredRetransmitHandshake()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/timers.go:110
+0x40c
  golang.zx2c4.com/wireguard/device.(*Peer).NewTimer.func1()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/timers.go:42
+0xd8
Goroutine 27 (running) created at:
  golang.zx2c4.com/wireguard/device.NewDevice()
      /go/pkg/mod/golang.zx2c4.com/wireguard@v0.0.20191012/device/device.go:322
+0x5e8
  main.main()
      /go/src/x/main.go:102 +0x58e
Goroutine 386 (finished) created at:
  time.goFunc()
      /usr/local/go/src/time/sleep.go:168 +0x51
Reported-by: Ben Burkert <ben@benburkert.com>
			
			
This commit is contained in:
		
							parent
							
								
									2b242f9393
								
							
						
					
					
						commit
						ddfad453cf
					
				
					 1 changed files with 9 additions and 0 deletions
				
			
		|  | @ -43,6 +43,7 @@ type IPv6Source struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type NativeEndpoint struct { | type NativeEndpoint struct { | ||||||
|  | 	sync.Mutex | ||||||
| 	dst  [unsafe.Sizeof(unix.SockaddrInet6{})]byte | 	dst  [unsafe.Sizeof(unix.SockaddrInet6{})]byte | ||||||
| 	src  [unsafe.Sizeof(IPv6Source{})]byte | 	src  [unsafe.Sizeof(IPv6Source{})]byte | ||||||
| 	isV6 bool | 	isV6 bool | ||||||
|  | @ -482,7 +483,9 @@ func send4(sock int, end *NativeEndpoint, buff []byte) error { | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	end.Lock() | ||||||
| 	_, err := unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst4(), 0) | 	_, err := unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst4(), 0) | ||||||
|  | 	end.Unlock() | ||||||
| 
 | 
 | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -493,7 +496,9 @@ func send4(sock int, end *NativeEndpoint, buff []byte) error { | ||||||
| 	if err == unix.EINVAL { | 	if err == unix.EINVAL { | ||||||
| 		end.ClearSrc() | 		end.ClearSrc() | ||||||
| 		cmsg.pktinfo = unix.Inet4Pktinfo{} | 		cmsg.pktinfo = unix.Inet4Pktinfo{} | ||||||
|  | 		end.Lock() | ||||||
| 		_, err = unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst4(), 0) | 		_, err = unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst4(), 0) | ||||||
|  | 		end.Unlock() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return err | 	return err | ||||||
|  | @ -522,7 +527,9 @@ func send6(sock int, end *NativeEndpoint, buff []byte) error { | ||||||
| 		cmsg.pktinfo.Ifindex = 0 | 		cmsg.pktinfo.Ifindex = 0 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	end.Lock() | ||||||
| 	_, err := unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst6(), 0) | 	_, err := unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst6(), 0) | ||||||
|  | 	end.Unlock() | ||||||
| 
 | 
 | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		return nil | 		return nil | ||||||
|  | @ -533,7 +540,9 @@ func send6(sock int, end *NativeEndpoint, buff []byte) error { | ||||||
| 	if err == unix.EINVAL { | 	if err == unix.EINVAL { | ||||||
| 		end.ClearSrc() | 		end.ClearSrc() | ||||||
| 		cmsg.pktinfo = unix.Inet6Pktinfo{} | 		cmsg.pktinfo = unix.Inet6Pktinfo{} | ||||||
|  | 		end.Lock() | ||||||
| 		_, err = unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst6(), 0) | 		_, err = unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst6(), 0) | ||||||
|  | 		end.Unlock() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return err | 	return err | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue