Просмотр исходного кода

Fix: can't use net.FileConn to dup tun fd

Rod Hynes 8 лет назад
Родитель
Сommit
c2759d45c2
3 измененных файлов с 54 добавлено и 5 удалено
  1. 4 5
      psiphon/common/tun/tun.go
  2. 46 0
      psiphon/common/tun/tun_unix.go
  3. 4 0
      psiphon/common/tun/tun_unsupported.go

+ 4 - 5
psiphon/common/tun/tun.go

@@ -1990,19 +1990,18 @@ func newDevice(
 // NewClientDeviceFromFD wraps an existing tun device.
 func NewClientDeviceFromFD(config *ClientConfig) (*Device, error) {
 
-	file := os.NewFile(uintptr(config.TunFD), "")
-
-	// net.FileConn() dups TunFD
-	fileConn, err := net.FileConn(file)
+	dupFD, err := dupCloseOnExec(config.TunFD)
 	if err != nil {
 		return nil, common.ContextError(err)
 	}
 
+	file := os.NewFile(uintptr(dupFD), "")
+
 	MTU := getMTU(config.MTU)
 
 	return &Device{
 		name:           "",
-		deviceIO:       fileConn,
+		deviceIO:       file,
 		inboundBuffer:  makeDeviceInboundBuffer(MTU),
 		outboundBuffer: makeDeviceOutboundBuffer(MTU),
 	}, nil

+ 46 - 0
psiphon/common/tun/tun_unix.go

@@ -0,0 +1,46 @@
+// +build darwin linux
+
+/*
+ * Copyright (c) 2017, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tun
+
+import (
+	"os"
+	"syscall"
+
+	"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) {
+	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)
+	return
+}

+ 4 - 0
psiphon/common/tun/tun_unsupported.go

@@ -70,3 +70,7 @@ func resetNATTables(_ *ServerConfig, _ net.IP) error {
 func routeServerInterface(_ string, _ int) error {
 	return common.ContextError(unsupportedError)
 }
+
+func dupCloseOnExec(_ int) (int, error) {
+	return -1, common.ContextError(unsupportedError)
+}