13// Fork and exec as unprivileged user.
15// We don't use just setuid because it is hard to guarantee that no other
16// privileged go worker processes have been started before we get here. E.g. init
17// functions in packages can start goroutines.
18func ForkExecUnprivileged() {
19 prog, err := os.Executable()
21 pkglog.Fatalx("finding executable for exec", err)
24 files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
26 for addr, f := range passedListeners {
27 files = append(files, f)
28 addrs = append(addrs, addr)
31 for path, fl := range passedFiles {
32 for _, f := range fl {
33 files = append(files, f)
34 paths = append(paths, path)
38 env = append(env, "MOX_SOCKETS="+strings.Join(addrs, ","), "MOX_FILES="+strings.Join(paths, ","))
40 p, err := os.StartProcess(prog, os.Args, &os.ProcAttr{
43 Sys: &syscall.SysProcAttr{
44 Credential: &syscall.Credential{
51 pkglog.Fatalx("fork and exec", err)
55 // If we get a interrupt/terminate signal, pass it on to the child. For interrupt,
56 // the child probably already got it.
57 // todo: see if we tie up child and root process so a kill -9 of the root process
58 // kills the child process too.
59 sigc := make(chan os.Signal, 1)
60 signal.Notify(sigc, os.Interrupt, syscall.SIGTERM)
68 pkglog.Fatalx("wait", err)
71 pkglog.Print("stopping after child exit", slog.Int("exitcode", code))