tun: fix data race on name field
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
abd287159e
commit
85a45a9651
|
@ -31,7 +31,6 @@ const (
|
|||
type NativeTun struct {
|
||||
tunFile *os.File
|
||||
index int32 // if index
|
||||
name string // name of interface
|
||||
errors chan error // async error handling
|
||||
events chan Event // device related events
|
||||
nopi bool // the device was passed IFF_NO_PI
|
||||
|
@ -39,6 +38,10 @@ type NativeTun struct {
|
|||
netlinkCancel *rwcancel.RWCancel
|
||||
hackListenerClosed sync.Mutex
|
||||
statusListenersShutdown chan struct{}
|
||||
|
||||
nameOnce sync.Once // guards calling initNameCache, which sets following fields
|
||||
nameCache string // name of interface
|
||||
nameErr error
|
||||
}
|
||||
|
||||
func (tun *NativeTun) File() *os.File {
|
||||
|
@ -192,6 +195,11 @@ func getIFIndex(name string) (int32, error) {
|
|||
}
|
||||
|
||||
func (tun *NativeTun) setMTU(n int) error {
|
||||
name, err := tun.Name()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// open datagram socket
|
||||
fd, err := unix.Socket(
|
||||
unix.AF_INET,
|
||||
|
@ -206,9 +214,8 @@ func (tun *NativeTun) setMTU(n int) error {
|
|||
defer unix.Close(fd)
|
||||
|
||||
// do ioctl call
|
||||
|
||||
var ifr [ifReqSize]byte
|
||||
copy(ifr[:], tun.name)
|
||||
copy(ifr[:], name)
|
||||
*(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n)
|
||||
_, _, errno := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
|
@ -225,6 +232,11 @@ func (tun *NativeTun) setMTU(n int) error {
|
|||
}
|
||||
|
||||
func (tun *NativeTun) MTU() (int, error) {
|
||||
name, err := tun.Name()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// open datagram socket
|
||||
fd, err := unix.Socket(
|
||||
unix.AF_INET,
|
||||
|
@ -241,7 +253,7 @@ func (tun *NativeTun) MTU() (int, error) {
|
|||
// do ioctl call
|
||||
|
||||
var ifr [ifReqSize]byte
|
||||
copy(ifr[:], tun.name)
|
||||
copy(ifr[:], name)
|
||||
_, _, errno := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(fd),
|
||||
|
@ -256,6 +268,15 @@ func (tun *NativeTun) MTU() (int, error) {
|
|||
}
|
||||
|
||||
func (tun *NativeTun) Name() (string, error) {
|
||||
tun.nameOnce.Do(tun.initNameCache)
|
||||
return tun.nameCache, tun.nameErr
|
||||
}
|
||||
|
||||
func (tun *NativeTun) initNameCache() {
|
||||
tun.nameCache, tun.nameErr = tun.nameSlow()
|
||||
}
|
||||
|
||||
func (tun *NativeTun) nameSlow() (string, error) {
|
||||
sysconn, err := tun.tunFile.SyscallConn()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -276,13 +297,11 @@ func (tun *NativeTun) Name() (string, error) {
|
|||
if errno != 0 {
|
||||
return "", errors.New("failed to get name of TUN device: " + errno.Error())
|
||||
}
|
||||
nullStr := ifr[:]
|
||||
i := bytes.IndexByte(nullStr, 0)
|
||||
if i != -1 {
|
||||
nullStr = nullStr[:i]
|
||||
name := ifr[:]
|
||||
if i := bytes.IndexByte(name, 0); i != -1 {
|
||||
name = name[:i]
|
||||
}
|
||||
tun.name = string(nullStr)
|
||||
return tun.name, nil
|
||||
return string(name), nil
|
||||
}
|
||||
|
||||
func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
|
||||
|
@ -402,16 +421,15 @@ func CreateTUNFromFile(file *os.File, mtu int) (Device, error) {
|
|||
statusListenersShutdown: make(chan struct{}),
|
||||
nopi: false,
|
||||
}
|
||||
var err error
|
||||
|
||||
_, err = tun.Name()
|
||||
name, err := tun.Name()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// start event listener
|
||||
|
||||
tun.index, err = getIFIndex(tun.name)
|
||||
tun.index, err = getIFIndex(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue