func main() { flagUsername := flag.String("username", "nobody", "username for the unprivileged child") isChild, r, w, _, err := privsep.MaybeBecomeChild() if err != nil { log.Fatalf("MaybeBecomeChild failed: %s", err) } who := "parent" if isChild { who = "child" } log.Printf("%s: pid=%d uid=%d euid=%d gid=%d egid=%d", who, os.Getpid(), os.Getuid(), os.Geteuid(), os.Getgid(), os.Getegid()) if isChild { child(r, w) return } if os.Getuid() != 0 { log.Print("Warning: this example only works when run as the root user") } _, r, w, err = privsep.CreateChild(*flagUsername, os.Args[0], nil, nil) if err != nil { log.Fatalf("CreateChild failed: %s", err) } parent(r, w) }
func main() { flagUsername := flag.String("username", "nobody", "username for the unprivileged child") isChild, _, _, files, err := privsep.MaybeBecomeChild() if err != nil { log.Fatalf("MaybeBecomeChild failed: %s", err) } who := "parent" if isChild { who = "child" } log.Printf("%s: pid=%d uid=%d euid=%d gid=%d egid=%d", who, os.Getpid(), os.Getuid(), os.Geteuid(), os.Getgid(), os.Getegid()) if isChild { if len(files) < 1 { log.Fatalf("no extra files: %v", files) } l, err := net.FileListener(files[0]) if err != nil { log.Fatalf("FileListener: %s", err) } child(l) return } if os.Getuid() != 0 { log.Print("Warning: this example only works when run as the root user") } addr := "localhost:1111" laddr, err := net.ResolveTCPAddr("tcp", addr) if err != nil { log.Fatalf("resolve %s: %s", addr, err) } l, err := net.ListenTCP("tcp", laddr) if err != nil { log.Fatalf("listen %s: %s", laddr, err) } sock, err := l.File() if err != nil { log.Fatalf("fd: %s", err) } proc, _, _, err := privsep.CreateChild(*flagUsername, os.Args[0], nil, []*os.File{sock}) if err != nil { log.Fatalf("CreateChild failed: %s", err) } sock.Close() // tidy up so child doesn't run forever defer proc.Kill() parent(laddr) }
func main() { var ( flagUsername = flag.String("username", "nobody", "username for the unprivileged child") flagChildren = flag.Int("children", 32, "exit code") flagPause = flag.Duration("pause", 10*time.Second, "time for children to sleep") flagTimeout = flag.Duration("timeout", 5*time.Second, "time for parent to wait") ) isChild, _, _, _, err := privsep.MaybeBecomeChild() if err != nil { log.Fatalf("MaybeBecomeChild failed: %s", err) } if isChild { rand.Seed(int64(time.Now().Nanosecond())) sleep := time.Duration(rand.Float64() * float64(*flagPause)) code := rand.Intn(8) log.Printf("[%d] sleep(%.1fs), exit(%d)", os.Getpid(), sleep.Seconds(), code) time.Sleep(sleep) os.Exit(code) return } if os.Getuid() != 0 { log.Fatal("Error: this example only works when run as the root user") } var procsMu sync.Mutex procs := make(map[interface{}]*os.Process) var wg sync.WaitGroup wg.Add(*flagChildren) for i := 0; i < *flagChildren; i++ { proc, _, _, err := privsep.CreateChild(*flagUsername, os.Args[0], nil, nil) if err != nil { log.Fatalf("CreateChild failed: %s", err) } procsMu.Lock() procs[proc] = proc procsMu.Unlock() go func() { defer wg.Done() status, err := proc.Wait() if err != nil { log.Printf("child %d errored: %s", proc.Pid, err) } procsMu.Lock() delete(procs, proc) procsMu.Unlock() // detailed status information is available by casting to the // appropriate type for the platform if s, ok := status.Sys().(syscall.WaitStatus); ok { log.Printf("child %d exited with code %d", proc.Pid, s.ExitStatus()) } }() } go func() { time.Sleep(*flagTimeout) log.Print("Parent timed out, killing children") procsMu.Lock() defer procsMu.Unlock() for _, proc := range procs { proc.Kill() } }() wg.Wait() }