diff options
| author | Sebastian Lackner | 2019-01-05 15:44:32 +0100 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2019-01-05 16:12:16 +0100 | 
| commit | 7e05e809b7579ad0473fff6ce466c19d417d4e93 (patch) | |
| tree | f4ba0f8b29c2a1ac7595b544a335db3aa32d75ed | |
| parent | ad15ad99856f90f3a72be4bd22ce44338645c963 (diff) | |
main: Run 'ensure fds' code early during the program startup.
The files are apparently processed in alphabetic order, so cli_args.go is
processed before main.go. In order to run before the go-fuse imports, put
the 'ensure fds' code in a separate package. Debug messages are omitted
to avoid additional imports (that might contain other code messing up our
file descriptors).
| -rw-r--r-- | cli_args.go | 5 | ||||
| -rw-r--r-- | internal/ensurefds012/ensurefds012.go | 52 | ||||
| -rw-r--r-- | internal/fusefrontend/dircache.go | 4 | ||||
| -rw-r--r-- | main.go | 25 | 
4 files changed, 61 insertions, 25 deletions
| diff --git a/cli_args.go b/cli_args.go index b3f2834..a4da85c 100644 --- a/cli_args.go +++ b/cli_args.go @@ -1,5 +1,10 @@  package main +// Should be initialized before anything else. +// This import line MUST be in the alphabitcally first source code file of +// package main! +import _ "github.com/rfjakob/gocryptfs/internal/ensurefds012" +  import (  	"flag"  	"fmt" diff --git a/internal/ensurefds012/ensurefds012.go b/internal/ensurefds012/ensurefds012.go new file mode 100644 index 0000000..7872eb2 --- /dev/null +++ b/internal/ensurefds012/ensurefds012.go @@ -0,0 +1,52 @@ +package ensurefds012 + +// Package ensurefds012 ensures that file descriptors 0,1,2 are open. It opens +// multiple copies of /dev/null as required. +// The Go stdlib as well as the gocryptfs code rely on the fact that +// fds 0,1,2 are always open. +// +// Use like this: +// +//   import _ "github.com/rfjakob/gocryptfs/internal/ensurefds012" +// +// The import line MUST be in the alphabitcally first source code file of +// package main! +// +// You can test if it works as expected by inserting a long sleep into main, +// startings gocryptfs with all fds closed like this, +// +//   $ ./gocryptfs 0<&- 1>&- 2>&- +// +// and then checking the open fds. It should look like this: +// +//   $ ls -l /proc/$(pgrep gocryptfs)/fd +//   total 0 +//   lrwx------. 1 jakob jakob 64 Jan  5 15:54 0 -> /dev/null +//   lrwx------. 1 jakob jakob 64 Jan  5 15:54 1 -> /dev/null +//   lrwx------. 1 jakob jakob 64 Jan  5 15:54 2 -> /dev/null +//   l-wx------. 1 jakob jakob 64 Jan  5 15:54 3 -> /dev/null +//   lrwx------. 1 jakob jakob 64 Jan  5 15:54 4 -> 'anon_inode:[eventpoll]' +// +// See https://github.com/rfjakob/gocryptfs/issues/320 for details. + +import ( +	"os" +	"syscall" + +	"github.com/rfjakob/gocryptfs/internal/exitcodes" +) + +func init() { +	fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0) +	if err != nil { +		os.Exit(exitcodes.DevNull) +	} +	for fd <= 2 { +		fd, err = syscall.Dup(fd) +		if err != nil { +			os.Exit(exitcodes.DevNull) +		} +	} +	// Close excess fd (usually fd 3) +	syscall.Close(fd) +} diff --git a/internal/fusefrontend/dircache.go b/internal/fusefrontend/dircache.go index 6d0d570..68fd99c 100644 --- a/internal/fusefrontend/dircache.go +++ b/internal/fusefrontend/dircache.go @@ -35,6 +35,8 @@ type dirCacheEntryStruct struct {  func (e *dirCacheEntryStruct) Clear() {  	// An earlier clear may have already closed the fd, or the cache  	// has never been filled (fd is 0 in that case). +	// Note: package ensurefds012, imported from main, guarantees that dirCache +	// can never get fds 0,1,2.  	if e.fd > 0 {  		err := syscall.Close(e.fd)  		if err != nil { @@ -72,6 +74,8 @@ func (d *dirCacheStruct) Clear() {  // Store the entry in the cache. The passed "fd" will be Dup()ed, and the caller  // can close their copy at will.  func (d *dirCacheStruct) Store(dirRelPath string, fd int, iv []byte) { +	// Note: package ensurefds012, imported from main, guarantees that dirCache +	// can never get fds 0,1,2.  	if fd <= 0 || len(iv) != nametransform.DirIVLen {  		log.Panicf("Store sanity check failed: fd=%d len=%d", fd, len(iv))  	} @@ -8,7 +8,6 @@ import (  	"runtime"  	"strconv"  	"strings" -	"syscall"  	"github.com/hanwen/go-fuse/fuse" @@ -150,7 +149,6 @@ func printVersion() {  }  func main() { -	ensureStdFds()  	mxp := runtime.GOMAXPROCS(0)  	if mxp < 4 {  		// On a 2-core machine, setting maxprocs to 4 gives 10% better performance @@ -330,26 +328,3 @@ func main() {  		os.Exit(0)  	}  } - -// ensureStdFds ensures that file descriptors 0,1,2 are open. The Go stdlib, -// as well as the gocryptfs code, relies on the fact that fds 0,1,2 are always -// open. -// See https://github.com/rfjakob/gocryptfs/issues/320 for details. -// -// This function should be called as the first thing from main(). -func ensureStdFds() { -	fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0) -	if err != nil { -		tlog.Fatal.Printf("ensureStdFds: open /dev/null failed: %v", err) -		os.Exit(exitcodes.DevNull) -	} -	for fd <= 2 { -		fd, err = syscall.Dup(fd) -		if err != nil { -			tlog.Fatal.Printf("ensureStdFds: dup failed: %v", err) -			os.Exit(exitcodes.DevNull) -		} -	} -	// Close excess fd (usually fd 3) -	syscall.Close(fd) -} | 
