From 70c16fde4c908414f6af53c3193a89fa296ef732 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 24 May 2017 19:57:45 +0200 Subject: main: replace paniclog with logger(1) Instead of redirecting stdout and stderr to /tmp/gocryptfs_paniclog, where it is hard to find, redirect them to a newly spawned logger(1) instance that forwards the messages to syslog. See https://github.com/rfjakob/gocryptfs/issues/109 for an example where the paniclog was lost due to a reboot. Also, instead of closing stdin, redirect it to /dev/null, like most daemons seem to do. --- mount.go | 87 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/mount.go b/mount.go index 5a28640..c10f90b 100644 --- a/mount.go +++ b/mount.go @@ -2,7 +2,7 @@ package main import ( "encoding/json" - "io/ioutil" + "fmt" "log/syslog" "net" "os" @@ -107,7 +107,6 @@ func doMount(args *argContainer) int { // Initialize FUSE server srv := initFuseFrontend(masterkey, args, confFile) tlog.Info.Println(tlog.ColorGreen + "Filesystem mounted and ready." + tlog.ColorReset) - var paniclog *os.File // We have been forked into the background, as evidenced by the set // "notifypid". if args.notifypid > 0 { @@ -115,38 +114,13 @@ func doMount(args *argContainer) int { os.Chdir("/") // Switch to syslog if !args.nosyslog { - paniclog, err = ioutil.TempFile("", "gocryptfs_paniclog.") - if err != nil { - tlog.Warn.Printf("Failed to create paniclog: %v."+ - " Carrying on, but fatal errors will not be logged.", err) - } // Switch all of our logs and the generic logger to syslog tlog.Info.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_INFO) tlog.Debug.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_DEBUG) tlog.Warn.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_WARNING) tlog.SwitchLoggerToSyslog(syslog.LOG_USER | syslog.LOG_WARNING) - // Daemons should close all fds (and we don't want to get killed by - // SIGPIPE if any of those get closed on the other end) - os.Stdin.Close() - // Redirect stdout and stderr to /tmp/gocryptfs_paniclog.NNNNNN - // instead of closing them so users have a chance to get the - // backtrace on a panic. - // https://github.com/golang/go/issues/325#issuecomment-66049178 - if paniclog != nil { - err = syscall.Dup2(int(paniclog.Fd()), 1) - if err != nil { - tlog.Warn.Printf("paniclog stdout dup error: %v\n", err) - } - syscall.Dup2(int(paniclog.Fd()), 2) - if err != nil { - tlog.Warn.Printf("paniclog stderr dup error: %v\n", err) - } - // No need for the extra FD anymore, we have copies in Stdout and Stderr - err = paniclog.Close() - if err != nil { - tlog.Warn.Printf("paniclog close error: %v\n", err) - } - } + // Daemons should redirect stdin, stdout and stderr + redirectStdFds() } // Disconnect from the controlling terminal by creating a new session. // This prevents us from getting SIGINT when the user presses Ctrl-C @@ -167,23 +141,50 @@ func doMount(args *argContainer) int { handleSigint(srv, args.mountpoint) // Jump into server loop. Returns when it gets an umount request from the kernel. srv.Serve() - // Delete empty paniclogs - if paniclog != nil { - // The paniclog FD is saved in Stdout and Stderr - fi, err := os.Stderr.Stat() - if err != nil { - tlog.Warn.Printf("paniclog fstat error: %v", err) - } else if fi.Size() > 0 { - tlog.Warn.Printf("paniclog at %q is not empty (size %d). Not deleting it.", - paniclog.Name(), fi.Size()) - return exitcodes.PanicLogNotEmpty - } else { - syscall.Unlink(paniclog.Name()) - } - } return 0 } +// redirectStdFds redirects stderr and stdout to syslog; stdin to /dev/null +func redirectStdFds() { + // stderr and stdout + pr, pw, err := os.Pipe() + if err != nil { + tlog.Warn.Printf("redirectStdFds: could not create pipe: %v\n", err) + return + } + tag := fmt.Sprintf("gocryptfs-%d-logger", os.Getpid()) + cmd := exec.Command("logger", "-t", tag) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = pr + err = cmd.Start() + if err != nil { + tlog.Warn.Printf("redirectStdFds: could not start logger: %v\n", err) + } + pr.Close() + err = syscall.Dup2(int(pw.Fd()), 1) + if err != nil { + tlog.Warn.Printf("redirectStdFds: stdout dup error: %v\n", err) + } + syscall.Dup2(int(pw.Fd()), 2) + if err != nil { + tlog.Warn.Printf("redirectStdFds: stderr dup error: %v\n", err) + } + pw.Close() + + // stdin + nullFd, err := os.Open("/dev/null") + if err != nil { + tlog.Warn.Printf("redirectStdFds: could not open /dev/null: %v\n", err) + return + } + err = syscall.Dup2(int(nullFd.Fd()), 0) + if err != nil { + tlog.Warn.Printf("redirectStdFds: stdin dup error: %v\n", err) + } + nullFd.Close() +} + // setOpenFileLimit tries to increase the open file limit to 4096 (the default hard // limit on Linux). func setOpenFileLimit() { -- cgit v1.2.3