From 6af725ff099e78fab2920f060c127415aa3b1893 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 10 Dec 2016 14:54:06 +0100 Subject: [PATCH] ctlsock: exit early if socket cannot be created; delete on exit Both are achieved by opening the socket from main and passing it to the ctlsock package instead of passing the path. --- cli_args.go | 5 ++++- internal/ctlsock/ctlsock_serve.go | 13 ++++------- mount.go | 37 +++++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/cli_args.go b/cli_args.go index 7301d9a..4d16570 100644 --- a/cli_args.go +++ b/cli_args.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + "net" "os" "strconv" "strings" @@ -23,9 +24,11 @@ type argContainer struct { // Configuration file name override config string notifypid, scryptn int + // Helper variables that are NOT cli options all start with an underscore // _configCustom is true when the user sets a custom config file name. - // This is not a CLI option. _configCustom bool + // _ctlsockFd stores the control socket file descriptor (ctlsock stores the path) + _ctlsockFd net.Listener } var flagSet *flag.FlagSet diff --git a/internal/ctlsock/ctlsock_serve.go b/internal/ctlsock/ctlsock_serve.go index 63515c0..45b1e5b 100644 --- a/internal/ctlsock/ctlsock_serve.go +++ b/internal/ctlsock/ctlsock_serve.go @@ -46,19 +46,14 @@ type ctlSockHandler struct { socket *net.UnixListener } -// CreateAndServe creates an unix socket at "path" and serves incoming -// connections in a new goroutine. -func CreateAndServe(path string, fs Interface) error { - sock, err := net.Listen("unix", path) - if err != nil { - return err - } +// Serve serves incoming connections on "sock". This call blocks so you +// probably want to run it in a new goroutine. +func Serve(sock net.Listener, fs Interface) { handler := ctlSockHandler{ fs: fs, socket: sock.(*net.UnixListener), } - go handler.acceptLoop() - return nil + handler.acceptLoop() } func (ch *ctlSockHandler) acceptLoop() { diff --git a/mount.go b/mount.go index b9bdc40..bd65fc6 100644 --- a/mount.go +++ b/mount.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io/ioutil" "log/syslog" + "net" "os" "os/exec" "os/signal" @@ -50,7 +51,28 @@ func doMount(args *argContainer) int { tlog.Fatal.Printf("Invalid mountpoint: %v", err) os.Exit(ErrExitMountPoint) } - // Get master key + // Open control socket early so we can error out before asking the user + // for the password + if args.ctlsock != "" { + // We must use an absolute path because we cd to / when daemonizing. + // This messes up the delete-on-close logic in the unix socket object. + args.ctlsock, _ = filepath.Abs(args.ctlsock) + var sock net.Listener + sock, err = net.Listen("unix", args.ctlsock) + if err != nil { + tlog.Fatal.Printf("ctlsock: %v", err) + os.Exit(ErrExitMount) + } + args._ctlsockFd = sock + // Close also deletes the socket file + defer func() { + err = sock.Close() + if err != nil { + tlog.Warn.Print(err) + } + }() + } + // Get master key (may prompt for the password) var masterkey []byte var confFile *configfile.ConfFile if args.masterkey != "" { @@ -65,6 +87,7 @@ func doMount(args *argContainer) int { masterkey = make([]byte, cryptocore.KeyLen) } else { // Load master key from config file + // Prompts the user for the password masterkey, confFile = loadConfig(args) printMasterKey(masterkey) } @@ -177,14 +200,10 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF finalFs = fs ctlSockBackend = fs } - if args.ctlsock != "" { - err := ctlsock.CreateAndServe(args.ctlsock, ctlSockBackend) - if err != nil { - // TODO if the socket cannot be created, we should exit BEFORE - // asking the user for the password - tlog.Fatal.Printf("ctlsock: %v", err) - os.Exit(ErrExitMount) - } + // We have opened the socket early so that we cannot fail here after + // asking the user for the password + if args._ctlsockFd != nil { + go ctlsock.Serve(args._ctlsockFd, ctlSockBackend) } pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true} pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)