func childMain() error { var err error pipe := os.NewFile(uintptr(3), "pipe") if pipe != nil { defer pipe.Close() if err == nil { pipe.Write([]byte{DaemonSuccess}) } else { pipe.Write([]byte{DaemonFailure}) } } signal.Ignore(syscall.SIGCHLD) syscall.Close(0) syscall.Close(1) syscall.Close(2) syscall.Setsid() syscall.Umask(022) // syscall.Chdir("/") return nil }
func doChildDaemon() { sid, err := syscall.Setsid() if sid < 0 || err != nil { log.Println("Error setting sid ", err) os.Exit(-1) } }
func PreRunService() { fmt.Println("Starting server!") ret, _, errNo := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errNo != 0 { panic(errors.New(fmt.Sprintf("Fork failed err: %d ", errNo))) } else { return } switch ret { case 0: break default: os.Exit(0) } sid, err := syscall.Setsid() utilities.CheckError(err) if sid == -1 { os.Exit(-1) } router := mux.NewRouter().StrictSlash(true) router.HandleFunc("/", Index) router.HandleFunc("/ls", GetFileList) router.HandleFunc("/file", GetFile) router.HandleFunc("/tunnel", GetTunnel) defer log.Fatal(http.ListenAndServe(":5922", router)) fmt.Println("WTF!") }
// func Reborn daemonize process. Function Reborn calls ForkExec // in the parent process and terminates him. In the child process, // function sets umask, work dir and calls Setsid. Function sets // for child process environment variable _GO_DAEMON=1 - the mark, // might used for debug. func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { // parent process - fork and exec var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := prepareCommand(path) if err = cmd.Start(); err != nil { return } os.Exit(0) } // child process - daemon syscall.Umask(int(umask)) if len(workDir) != 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() // Do not required redirect std // to /dev/null, this work was // done function ForkExec return }
func Daemonize() (e error) { // var ret, err uintptr ret, _, err := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { return fmt.Errorf("fork error: %d", err) } if ret != 0 { // Parent os.Exit(0) } // We are now child if err, _ := syscall.Setsid(); err < 0 { return fmt.Errorf("setsid error: %d", err) } os.Chdir("/") f, e := os.OpenFile(os.DevNull, os.O_RDWR, 0) if e != nil { return } fd := int(f.Fd()) syscall.Dup2(fd, int(os.Stdin.Fd())) syscall.Dup2(fd, int(os.Stdout.Fd())) syscall.Dup2(fd, int(os.Stderr.Fd())) return nil }
func daemon(nochdir, noclose int) int { var ret, ret2 uintptr var err syscall.Errno darwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return 0 } // fork off the parent process ret, ret2, err = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { return -1 } // failure if ret2 < 0 { os.Exit(-1) } // handle exception for darwin if darwin && ret2 == 1 { ret = 0 } // if we got a good PID, then we call exit the parent process. if ret > 0 { os.Exit(0) } /* Change the file mode mask */ _ = syscall.Umask(0) // create a new SID for the child process s_ret, s_errno := syscall.Setsid() if s_errno != nil { log.Printf("Error: syscall.Setsid errno: %d", s_errno) } if s_ret < 0 { return -1 } if nochdir == 0 { os.Chdir("/") } if noclose == 0 { f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } } return 0 }
func daemon(nochdir, noclose int) int { var ret uintptr var err syscall.Errno ret, _, err = syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { return -1 } switch ret { case 0: break default: os.Exit(0) } pid, _ := syscall.Setsid() if pid == -1 { return -1 } if nochdir == 0 { os.Chdir("/") } if noclose == 0 { f, e := os.Open("/dev/null") if e == nil { fd := int(f.Fd()) syscall.Dup2(fd, int(os.Stdin.Fd())) syscall.Dup2(fd, int(os.Stdout.Fd())) syscall.Dup2(fd, int(os.Stderr.Fd())) } } return 0 }
func (this torUtil) SetDaemonMode(nochdir, noclose int) int { if syscall.Getppid() == 1 { return 0 } ret, ret2, err := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { return -1 } if ret2 < 0 { os.Exit(-1) } if ret > 0 { os.Exit(0) } syscall.Umask(0) s_ret, s_errno := syscall.Setsid() if s_ret < 0 { return -1 } if nochdir == 0 { os.Chdir("/") } if noclose == 0 { f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } } return 0 }
func afterDaemonize(err error) { // Ignore SIGCHLD signal signal.Ignore(syscall.SIGCHLD) // Close STDOUT, STDIN, STDERR syscall.Close(0) syscall.Close(1) syscall.Close(2) // Become the process group leader syscall.Setsid() // // Clear umask syscall.Umask(022) // // chdir for root directory syscall.Chdir("/") // Notify that the child process started successfuly pipe := os.NewFile(uintptr(3), "pipe") if pipe != nil { defer pipe.Close() if err == nil { pipe.Write([]byte{DAEMONIZE_SUCCESS}) } else { pipe.Write([]byte{DAEMONIZE_FAIL}) } } }
// This function wraps application with daemonization. // Returns isDaemon value to distinguish parent and daemonized processes. func Daemonize() (isDaemon bool, err error) { const errLoc = "daemonigo.Daemonize()" isDaemon = os.Getenv(EnvVarName) == EnvVarValue log.Println("IsDaemon: ", isDaemon) if WorkDir != "" { if err = os.Chdir(WorkDir); err != nil { err = fmt.Errorf( "%s: changing working directory failed, reason -> %s", errLoc, err.Error(), ) return } } if isDaemon { oldmask := syscall.Umask(int(Umask)) defer syscall.Umask(oldmask) if _, err = syscall.Setsid(); err != nil { err = fmt.Errorf( "%s: setsid failed, reason -> %s", errLoc, err.Error(), ) return } if pidFile, err = lockPidFile(); err != nil { err = fmt.Errorf( "%s: locking PID file failed, reason -> %s", errLoc, err.Error(), ) } } else { flag.Usage = func() { arr := make([]string, 0, len(actions)) for k, _ := range actions { arr = append(arr, k) } fmt.Fprintf(os.Stderr, "Usage: %s {%s}\n", os.Args[0], strings.Join(arr, "|"), ) flag.PrintDefaults() } if !flag.Parsed() { log.Printf(" flag.Parse\n") flag.Parse() } //fmt.Printf("after flag.Parse\n") //fmt.Printf("flag.Arg(0):%s\n", flag.Arg(0)) //action, exist := actions[flag.Arg(0)] action, exist := actions["daemon"] //fmt.Println("exist:", exist) if exist { action() } else { flag.Usage() } } return }
func _not_work_Fork(closeno bool) (pid int, err error) { // don't run this // not work with go threads // see: http://code.google.com/p/go/issues/detail?id=227 darwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return 0, nil } // fork off the parent process ret, ret2, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return -1, fmt.Errorf("Fork failure: %s", errno) } // failure if ret2 < 0 { return -1, fmt.Errorf("Fork failure") } // handle exception for darwin if darwin && ret2 == 1 { ret = 0 } // if we got a good PID, then we call exit the parent process. if ret > 0 { return 0, nil } // create a new SID for the child process s_ret, s_errno := syscall.Setsid() if s_errno != nil { return -1, fmt.Errorf("Error: syscall.Setsid: %s", s_errno) } if s_ret < 0 { return -1, fmt.Errorf("Error: syscall.Setsid: %s", s_errno) } if closeno { f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := int(f.Fd()) syscall.Dup2(fd, int(os.Stdin.Fd())) syscall.Dup2(fd, int(os.Stdout.Fd())) syscall.Dup2(fd, int(os.Stderr.Fd())) } } return os.Getpid(), nil }
func main() { // create a new session to prevent receiving signals from parent syscall.Setsid() cmd := os.Args[1] args := os.Args[2:] c := exec.Command(cmd, args...) c.Stdout = os.Stdout c.Stderr = os.Stderr c.Start() os.Exit(0) }
func daemon() error { isDarwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return nil } // fork off the parent process ret, ret2, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return errors.New(fmt.Sprintf("fork error! [errno=%d]", errno)) } // failure if ret2 < 0 { os.Exit(1) } // handle exception for darwin if isDarwin && ret2 == 1 { ret = 0 } // if we got a good PID, then we call exit the parent process. if int(ret) > 0 { os.Exit(0) } syscall.Umask(0) // create a new SID for the child process _, err := syscall.Setsid() if err != nil { return err } //os.Chdir("/") f, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return nil }
func (executeLinuxProcForkChildImpl *executeLinuxProcForkChildImpl) Exec(cmdLine string, dir string) error { executeLinuxProc := executeLinuxProcStartProcessImpl{} pid, _, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return syscall.Errno(errno) } if pid > 0 { puid := int(pid) processInfo, _ := os.FindProcess(puid) if nil != processInfo { _, err := processInfo.Wait() if nil != err { log.WriteLog("Error: find process %s", err.Error()) } } return nil } else if pid < 0 { return errors.New("fork error") } // pid1, _, errno1 := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) // if errno1 != 0 { // os.Exit(0) // return errors.New("fork error") // } // if pid1 > 0 { // os.Exit(0) // return nil // } else if pid1 < 0 { // os.Exit(0) // return errors.New("fork error") // } _ = syscall.Umask(0) _, s_errno := syscall.Setsid() if s_errno != nil { log.WriteLog("Error: syscall.Setsid errno: %d", s_errno) } os.Chdir("/") result := executeLinuxProc.Exec(cmdLine, dir) os.Exit(0) return result }
func Daemon(nochdir int) error { signal.Ignore(syscall.SIGINT, syscall.SIGHUP, syscall.SIGPIPE) if syscall.Getppid() == 1 { return nil } ret1, ret2, eno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if eno != 0 || ret2 < 0 { return errors.New("Fork fail") } /* exit parent */ if ret1 > 0 { os.Exit(0) } _ = syscall.Umask(0) ret, err := syscall.Setsid() if ret < 0 || err != nil { return errors.New("Set sid failed") } if nochdir == 0 { err = os.Chdir("/") if err != nil { return errors.New("Chdir failed") } } file, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err == nil { fd := file.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) // syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return nil }
func Daemonize() (int, error) { // create a subprocess pid, err := Fork(false) if err != nil { return -1, err } else if pid > 0 { // return the parent return int(pid), nil } // exit the created one, create the daemon _, err = Fork(true) if err != nil { os.Exit(-1) } //Change the file mode mask _ = syscall.Umask(0) // create a new SID for the child process s_ret, err := syscall.Setsid() if err != nil { os.Exit(-1) } if s_ret < 0 { os.Exit(-1) } os.Chdir("/") f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return 0, nil }
// Daemonizes but doesn't fork. // // The stdin, stdout and, unless keepStderr is specified, stderr fds are // remapped to /dev/null. setsid is called. // // The process changes its current directory to /. // // If you intend to call DropPrivileges, call it after calling this function, // as /dev/null will no longer be available after privileges are dropped. func Daemonize(keepStderr bool) error { null_f, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err != nil { return err } defer null_f.Close() stdin_fd := int(os.Stdin.Fd()) stdout_fd := int(os.Stdout.Fd()) stderr_fd := int(os.Stderr.Fd()) // ... reopen fds 0, 1, 2 as /dev/null ... // Since dup2 closes fds which are already open we needn't close the above fds. // This lets us avoid race conditions. null_fd := int(null_f.Fd()) err = dupfd.Dup2(null_fd, stdin_fd) if err != nil { return err } err = dupfd.Dup2(null_fd, stdout_fd) if err != nil { return err } if !keepStderr { err = dupfd.Dup2(null_fd, stderr_fd) if err != nil { return err } haveStderr = false } // This may fail if we're not root syscall.Setsid() // Daemonize implies Init. return Init() }
func Daemon(chdir bool, clstd bool) (err error) { var ret1, ret2 uintptr var er syscall.Errno darwin := runtime.GOOS == "darwin" if syscall.Getppid() == 1 { return } ret1, ret2, er = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if er != 0 { err = errors.New("daemon fork fail") return } if ret2 < 0 { err = errors.New("fork return fail") os.Exit(-1) } if darwin && ret2 == 1 { ret1 = 0 } if ret1 > 0 { os.Exit(0) } syscall.Umask(0) syscall.Setsid() if chdir { os.Chdir("/") } if clstd { fs, err := os.OpenFile(os.DevNull, os.O_RDWR, 0) if err == nil { fd := fs.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } } return }
func daemonize(server *Server) { pid, err := os.ForkExec("lineupd", []string{}, []string{}, "/var/run", []*os.File{}); if err != nil { server.Logger().Logf("couldn't fork: %s\n", err); os.Exit(1); } server.Logger().Logf("%d->%d\n", os.Getpid(), pid); if (pid < 0) { os.Exit(1); } if (pid > 0) { os.Exit(0); } syscall.Setsid(); for i := 0; i < 3; i++ { syscall.Close(i); } for i := 0; i < 3; i++ { syscall.Open("/dev/null", os.O_RDWR, 0644); } syscall.Umask(027); syscall.Chdir("/var/run"); }
func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := exec.Command(path, os.Args[1:]...) envVar := fmt.Sprintf("%s=%s", envVarName, envVarValue) cmd.Env = append(os.Environ(), envVar) if err = cmd.Start(); err != nil { return } os.Exit(0) } syscall.Umask(int(umask)) if len(workDir) == 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() return }
func childMain() { // 初期化処理があればここに var err error // 子プロセスの起動状態を親プロセスに通知する pipe := os.NewFile(uintptr(3), "pipe") if pipe != nil { defer pipe.Close() if err == nil { pipe.Write([]byte{DAEMON_SUCCESS}) } else { pipe.Write([]byte{DAEMON_FAIL}) } } // SIGCHILDを無視する signal.Ignore(syscall.SIGCHLD) // STDOUT, STDIN, STDERRをクローズ syscall.Close(0) syscall.Close(1) syscall.Close(2) // プロセスグループリーダーになる syscall.Setsid() // Umaskをクリア syscall.Umask(022) // / にchdirする syscall.Chdir("/") // main loop for { time.Sleep(1000 * time.Millisecond) } }
func (l *linuxStandardInit) Init() error { // do not inherit the parent's session keyring sessKeyId, err := keyctl.JoinSessionKeyring("") if err != nil { return err } // make session keyring searcheable // without user ns we need 'UID' search permissions // with user ns we need 'other' search permissions if err := keyctl.ModKeyringPerm(sessKeyId, 0xffffffff, 0x080008); err != nil { return err } // join any namespaces via a path to the namespace fd if provided if err := joinExistingNamespaces(l.config.Config.Namespaces); err != nil { return err } var console *linuxConsole if l.config.Console != "" { console = newConsoleFromPath(l.config.Console) if err := console.dupStdio(); err != nil { return err } } if _, err := syscall.Setsid(); err != nil { return err } if console != nil { if err := system.Setctty(); err != nil { return err } } if err := setupNetwork(l.config); err != nil { return err } if err := setupRoute(l.config.Config); err != nil { return err } if err := setupRlimits(l.config.Config); err != nil { return err } if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil { return err } label.Init() // InitializeMountNamespace() can be executed only for a new mount namespace if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := setupRootfs(l.config.Config, console); err != nil { return err } } if hostname := l.config.Config.Hostname; hostname != "" { if err := syscall.Sethostname([]byte(hostname)); err != nil { return err } } if err := apparmor.ApplyProfile(l.config.Config.AppArmorProfile); err != nil { return err } if err := label.SetProcessLabel(l.config.Config.ProcessLabel); err != nil { return err } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { return err } } for _, path := range l.config.Config.ReadonlyPaths { if err := remountReadonly(path); err != nil { return err } } for _, path := range l.config.Config.MaskPaths { if err := maskFile(path); err != nil { return err } } pdeath, err := system.GetParentDeathSignal() if err != nil { return err } if l.config.Config.NoNewPrivileges { if err := system.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { return err } } // Tell our parent that we're ready to Execv. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. if err := syncParentReady(l.pipe); err != nil { return err } if l.config.Config.Seccomp != nil { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } } if err := finalizeNamespace(l.config); err != nil { return err } // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { return err } // compare the parent from the inital start of the init process and make sure that it did not change. // if the parent changes that means it died and we were reparened to something else so we should // just kill ourself and not cause problems for someone else. if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) }
func Daemon(pfile, lfile string, uid, gid, nochdir, noclose int) int { if syscall.Getppid() == 1 { return 0 } ret, mret, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return -1 } if mret < 0 { os.Exit(-1) } if runtime.GOOS == "darwin" && mret == 1 { ret = 0 } if ret > 0 { os.Exit(0) } _ = syscall.Umask(0) s_ret, err := syscall.Setsid() if err != nil { panic(err) } if s_ret < 0 { return -1 } err = WriteFile(pfile, fmt.Sprintf("%d\n", os.Getpid())) if err != nil { panic(err) } /* err = syscall.Setgid(gid) if err != nil { panic(err) } err = syscall.Setuid(uid) if err != nil { panic(err) } */ if nochdir == 0 { os.Chdir("/") } if noclose == 0 { fp, err := os.OpenFile(lfile, os.O_RDWR|os.O_APPEND, 0) if err != nil { panic(err) } fd := fp.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return 0 }
func (l *linuxStandardInit) Init() error { // join any namespaces via a path to the namespace fd if provided if err := joinExistingNamespaces(l.config.Config.Namespaces); err != nil { return err } var console *linuxConsole if l.config.Console != "" { console = newConsoleFromPath(l.config.Console) if err := console.dupStdio(); err != nil { return err } } if _, err := syscall.Setsid(); err != nil { return err } if console != nil { if err := system.Setctty(); err != nil { return err } } if err := setupNetwork(l.config); err != nil { return err } if err := setupRoute(l.config.Config); err != nil { return err } if err := setupRlimits(l.config.Config); err != nil { return err } label.Init() // InitializeMountNamespace() can be executed only for a new mount namespace if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := setupRootfs(l.config.Config, console); err != nil { return err } } if hostname := l.config.Config.Hostname; hostname != "" { if err := syscall.Sethostname([]byte(hostname)); err != nil { return err } } if err := apparmor.ApplyProfile(l.config.Config.AppArmorProfile); err != nil { return err } if err := label.SetProcessLabel(l.config.Config.ProcessLabel); err != nil { return err } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { return err } } for _, path := range l.config.Config.ReadonlyPaths { if err := remountReadonly(path); err != nil { return err } } for _, path := range l.config.Config.MaskPaths { if err := maskFile(path); err != nil { return err } } pdeath, err := system.GetParentDeathSignal() if err != nil { return err } if l.config.Config.Seccomp != nil { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } } if err := finalizeNamespace(l.config); err != nil { return err } // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { return err } // compare the parent from the inital start of the init process and make sure that it did not change. // if the parent changes that means it died and we were reparened to something else so we should // just kill ourself and not cause problems for someone else. if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) }
func (l *linuxStandardInit) Init() error { // join any namespaces via a path to the namespace fd if provided if err := joinExistingNamespaces(l.config.Config.Namespaces); err != nil { return err } var console *linuxConsole if l.config.Console != "" { console = newConsoleFromPath(l.config.Console) if err := console.dupStdio(); err != nil { return err } } if _, err := syscall.Setsid(); err != nil { return err } if console != nil { if err := system.Setctty(); err != nil { return err } } if err := setupNetwork(l.config); err != nil { return err } if err := setupRoute(l.config.Config); err != nil { return err } if err := setupRlimits(l.config.Config); err != nil { return err } label.Init() // InitializeMountNamespace() can be executed only for a new mount namespace if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := setupRootfs(l.config.Config, console); err != nil { return err } } if hostname := l.config.Config.Hostname; hostname != "" { if err := syscall.Sethostname([]byte(hostname)); err != nil { return err } } if err := apparmor.ApplyProfile(l.config.Config.AppArmorProfile); err != nil { return err } if err := label.SetProcessLabel(l.config.Config.ProcessLabel); err != nil { return err } for _, path := range l.config.Config.ReadonlyPaths { if err := remountReadonly(path); err != nil { return err } } for _, path := range l.config.Config.MaskPaths { if err := maskFile(path); err != nil { return err } } pdeath, err := system.GetParentDeathSignal() if err != nil { return err } if err := finalizeNamespace(l.config); err != nil { return err } // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { return err } // Signal self if parent is already dead. Does nothing if running in a new // PID namespace, as Getppid will always return 0. if syscall.Getppid() == 1 { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) }
func daemon(cmd string, argv []string, pipe int) error { // create a subprocess pid, err := fork(false) if err != nil { return err } else if pid > 0 { go func() { wp, err := syscall.Wait4(int(pid), nil, 0, nil) if err == nil { glog.V(3).Infof("collect child %d", wp) } else { glog.Errorf("error during wait %d: %s", pid, err.Error()) } }() // return the parent return nil } // exit the created one, create the daemon _, err = fork(true) if err != nil { glog.Error("second fork failed: ", err.Error()) os.Exit(-1) } cur := os.Getpid() glog.V(1).Infof("qemu daemon pid %d.", cur) //Change the file mode mask _ = syscall.Umask(0) // create a new SID for the child process s_ret, err := syscall.Setsid() if err != nil { glog.Info("Error: syscall.Setsid errno: ", err.Error()) os.Exit(-1) } if s_ret < 0 { glog.Errorf("setsid return negative value: %d", s_ret) os.Exit(-1) } os.Chdir("/") f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } buf := make([]byte, 4) binary.BigEndian.PutUint32(buf, uint32(cur)) syscall.Write(pipe, buf) syscall.Close(pipe) fds := listFd() for _, fd := range fds { if f, err := strconv.Atoi(fd); err == nil && f > 2 { glog.V(1).Infof("close fd %d", f) syscall.Close(f) } } err = syscall.Exec(cmd, argv, []string{}) if err != nil { glog.Error("fail to exec qemu process") os.Exit(-1) } return nil }
func doChild(rootdir string, progfile string, plan plan, stdin_fd, stdout_fd, stderr_fd [2]int) (error, string) { if os.Getpid() != 1 { return errors.New("not cloned?"), "" } if err := syscall.Dup2(stdin_fd[0], 0); err != nil { return err, "dup2 failed" } syscall.Close(stdin_fd[0]) syscall.Close(stdin_fd[1]) if err := syscall.Dup2(stdout_fd[1], 1); err != nil { return err, "dup2 failed" } syscall.Close(stdout_fd[0]) syscall.Close(stdout_fd[1]) if err := syscall.Dup2(stderr_fd[1], 2); err != nil { return err, "dup2 failed" } syscall.Close(stderr_fd[0]) syscall.Close(stderr_fd[1]) if _, _, err := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGKILL), 0); err != 0 { return error(err), "PR_SET_PDEATHSIG failed" } if err := syscall.Sethostname([]byte("poe-sandbox")); err != nil { return err, "sethostname failed" } mounts := []mountPoint{ {"none", "/", "", syscall.MS_PRIVATE | syscall.MS_REC, ""}, {rootdir, rootdir, "bind", syscall.MS_BIND | syscall.MS_REC, ""}, // { "none", rootdir + "/proc", "proc", syscall.MS_NOSUID | syscall.MS_NOEXEC | syscall.MS_NODEV, "" }, // { "none", rootdir + "/dev", "devtmpfs", syscall.MS_NOSUID | syscall.MS_NOEXEC, "" }, // { "none", rootdir + "/dev/shm", "tmpfs", syscall.MS_NOSUID | syscall.MS_NODEV, "" }, } for _, point := range mounts { if err := syscall.Mount(point.source, point.target, point.fstype, point.flags, point.data); err != nil { return err, fmt.Sprintf("mount '%s' on '%s' (%s) failed", point.source, point.target, point.fstype) } } if err := syscall.Chroot(rootdir); err != nil { return err, "chroot failed" } if _, err := syscall.Setsid(); err != nil { return err, "setsid failed" } pw, err := user.Lookup(username) if err != nil { return err, "getpwnam failed" } uid, err := strconv.Atoi(pw.Uid) if err != nil { return err, "atoi error" } gid, err := strconv.Atoi(pw.Gid) if err != nil { return err, "atoi error" } // TODO: initgroups if err := syscall.Setresgid(gid, gid, gid); err != nil { return err, "setresgid failed" } if err := syscall.Setresuid(uid, uid, uid); err != nil { return err, "setresuid failed" } if err := syscall.Chdir("/tmp"); err != nil { return err, "chdir failed" } // stop os.Stdin.Read(make([]byte, 1)) // be traced if _, _, err := syscall.Syscall(syscall.SYS_PRCTL, PR_SET_NO_NEW_PRIVS, 1, 0); err != 0 { return error(err), "PR_SET_NO_NEW_PRIVS failed" } if err := SetupSeccomp(); err != nil { return err, "seccomp fail" } envp := []string{ "PATH=/opt/bin:/usr/bin", "USER="******"LOGNAME=" + username, } cmdl := make([]string, 0, len(plan.Compiler.Command)+len(plan.Extra)-1) for _, arg := range plan.Compiler.Command { if arg == "PROGRAM" { cmdl = append(cmdl, progfile) } else if arg == "EXTRA" { cmdl = append(cmdl, plan.Extra...) } else { cmdl = append(cmdl, arg) } } if err := syscall.Exec(cmdl[0], cmdl, envp); err != nil { return err, "execve failed" } return errors.New("unreachable"), "" }
// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work. // Move this to libcontainer package. // Init is the init process that first runs inside a new namespace to setup mounts, users, networking, // and other options required for the new container. // The caller of Init function has to ensure that the go runtime is locked to an OS thread // (using runtime.LockOSThread) else system calls like setns called within Init may not work as intended. func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syncPipe *syncpipe.SyncPipe, args []string) (err error) { defer func() { if err != nil { syncPipe.ReportChildError(err) } }() rootfs, err := utils.ResolveRootfs(uncleanRootfs) if err != nil { return err } // clear the current processes env and replace it with the environment // defined on the container if err := LoadContainerEnvironment(container); err != nil { return err } // We always read this as it is a way to sync with the parent as well var networkState *network.NetworkState if err := syncPipe.ReadFromParent(&networkState); err != nil { return err } if consolePath != "" { if err := console.OpenAndDup(consolePath); err != nil { return err } } if _, err := syscall.Setsid(); err != nil { return fmt.Errorf("setsid %s", err) } if consolePath != "" { if err := system.Setctty(); err != nil { return fmt.Errorf("setctty %s", err) } } if err := ipc.Initialize(container.IpcNsPath); err != nil { return fmt.Errorf("setup IPC %s", err) } if err := setupNetwork(container, networkState); err != nil { return fmt.Errorf("setup networking %s", err) } if err := setupRoute(container); err != nil { return fmt.Errorf("setup route %s", err) } label.Init() if err := mount.InitializeMountNamespace(rootfs, consolePath, container.RestrictSys, (*mount.MountConfig)(container.MountConfig)); err != nil { return fmt.Errorf("setup mount namespace %s", err) } if container.Hostname != "" { if err := syscall.Sethostname([]byte(container.Hostname)); err != nil { return fmt.Errorf("sethostname %s", err) } } if err := apparmor.ApplyProfile(container.AppArmorProfile); err != nil { return fmt.Errorf("set apparmor profile %s: %s", container.AppArmorProfile, err) } if err := label.SetProcessLabel(container.ProcessLabel); err != nil { return fmt.Errorf("set process label %s", err) } // TODO: (crosbymichael) make this configurable at the Config level if container.RestrictSys { if err := restrict.Restrict("proc/sys", "proc/sysrq-trigger", "proc/irq", "proc/bus"); err != nil { return err } } pdeathSignal, err := system.GetParentDeathSignal() if err != nil { return fmt.Errorf("get parent death signal %s", err) } if err := FinalizeNamespace(container); err != nil { return fmt.Errorf("finalize namespace %s", err) } // FinalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := RestoreParentDeathSignal(pdeathSignal); err != nil { return fmt.Errorf("restore parent death signal %s", err) } return system.Execv(args[0], args[0:], os.Environ()) }
func Setsid() (int, error) { return syscall.Setsid() }
// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work. // Move this to libcontainer package. // Init is the init process that first runs inside a new namespace to setup mounts, users, networking, // and other options required for the new container. // The caller of Init function has to ensure that the go runtime is locked to an OS thread // (using runtime.LockOSThread) else system calls like setns called within Init may not work as intended. func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, pipe *os.File, args []string) (err error) { defer func() { // if we have an error during the initialization of the container's init then send it back to the // parent process in the form of an initError. if err != nil { // ensure that any data sent from the parent is consumed so it doesn't // receive ECONNRESET when the child writes to the pipe. ioutil.ReadAll(pipe) if err := json.NewEncoder(pipe).Encode(initError{ Message: err.Error(), }); err != nil { panic(err) } } // ensure that this pipe is always closed pipe.Close() }() rootfs, err := utils.ResolveRootfs(uncleanRootfs) if err != nil { return err } // clear the current processes env and replace it with the environment // defined on the container if err := LoadContainerEnvironment(container); err != nil { return err } // We always read this as it is a way to sync with the parent as well var networkState *network.NetworkState if err := json.NewDecoder(pipe).Decode(&networkState); err != nil { return err } // join any namespaces via a path to the namespace fd if provided if err := joinExistingNamespaces(container.Namespaces); err != nil { return err } if consolePath != "" { if err := console.OpenAndDup(consolePath); err != nil { return err } } if _, err := syscall.Setsid(); err != nil { return fmt.Errorf("setsid %s", err) } if consolePath != "" { if err := system.Setctty(); err != nil { return fmt.Errorf("setctty %s", err) } } if err := setupNetwork(container, networkState); err != nil { return fmt.Errorf("setup networking %s", err) } if err := setupRoute(container); err != nil { return fmt.Errorf("setup route %s", err) } if err := setupRlimits(container); err != nil { return fmt.Errorf("setup rlimits %s", err) } label.Init() if err := mount.InitializeMountNamespace(rootfs, consolePath, container.RestrictSys, (*mount.MountConfig)(container.MountConfig)); err != nil { return fmt.Errorf("setup mount namespace %s", err) } if container.Hostname != "" { if err := syscall.Sethostname([]byte(container.Hostname)); err != nil { return fmt.Errorf("unable to sethostname %q: %s", container.Hostname, err) } } if err := apparmor.ApplyProfile(container.AppArmorProfile); err != nil { return fmt.Errorf("set apparmor profile %s: %s", container.AppArmorProfile, err) } if err := label.SetProcessLabel(container.ProcessLabel); err != nil { return fmt.Errorf("set process label %s", err) } // TODO: (crosbymichael) make this configurable at the Config level if container.RestrictSys { if err := restrict.Restrict("proc/sys", "proc/sysrq-trigger", "proc/irq", "proc/bus"); err != nil { return err } } pdeathSignal, err := system.GetParentDeathSignal() if err != nil { return fmt.Errorf("get parent death signal %s", err) } if err := FinalizeNamespace(container); err != nil { return fmt.Errorf("finalize namespace %s", err) } // FinalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := RestoreParentDeathSignal(pdeathSignal); err != nil { return fmt.Errorf("restore parent death signal %s", err) } return system.Execv(args[0], args[0:], os.Environ()) }