Browse Source

Fix: tun device should use blocking I/O

Rod Hynes 8 years ago
parent
commit
d785d1218a
2 changed files with 17 additions and 6 deletions
  1. 3 3
      psiphon/common/tun/tun.go
  2. 14 3
      psiphon/common/tun/tun_unix.go

+ 3 - 3
psiphon/common/tun/tun.go

@@ -917,9 +917,9 @@ func GetTransparentDNSResolverIPv4Address() net.IP {
 	return transparentDNSResolverIPv4Address
 }
 
-// GetTransparentDNSResolverIPv4Address returns the static IPv6 address
+// GetTransparentDNSResolverIPv6Address returns the static IPv6 address
 // to use as a DNS resolver when transparent DNS rewriting is desired.
-func GeTransparentDNSResolverIPv6Address() net.IP {
+func GetTransparentDNSResolverIPv6Address() net.IP {
 	return transparentDNSResolverIPv6Address
 }
 
@@ -1989,7 +1989,7 @@ func newDevice(
 // NewClientDeviceFromFD wraps an existing tun device.
 func NewClientDeviceFromFD(config *ClientConfig) (*Device, error) {
 
-	dupFD, err := dupCloseOnExec(config.TunFileDescriptor)
+	dupFD, err := dupFD(config.TunFileDescriptor)
 	if err != nil {
 		return nil, common.ContextError(err)
 	}

+ 14 - 3
psiphon/common/tun/tun_unix.go

@@ -32,15 +32,26 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 )
 
-// dupCloseOnExec is dupCloseOnExecOld from:
-// https://github.com/golang/go/blob/bf0f69220255941196c684f235727fd6dc747b5c/src/net/fd_unix.go#L293
-func dupCloseOnExec(fd int) (newfd int, err error) {
+// dupFD is essentially this function:
+// https://github.com/golang/go/blob/bf0f69220255941196c684f235727fd6dc747b5c/src/net/fd_unix.go#L306
+//
+// dupFD duplicates the file descriptor; sets O_CLOEXEC to avoid leaking
+// to child processes; and sets the mode to blocking for use with os.NewFile.
+func dupFD(fd int) (newfd int, err error) {
+
 	syscall.ForkLock.RLock()
 	defer syscall.ForkLock.RUnlock()
+
 	newfd, err = syscall.Dup(fd)
 	if err != nil {
 		return -1, common.ContextError(os.NewSyscallError("dup", err))
 	}
+
 	syscall.CloseOnExec(newfd)
+
+	if err = syscall.SetNonblock(newfd, false); err != nil {
+		return -1, common.ContextError(os.NewSyscallError("setnonblock", err))
+	}
+
 	return
 }