package main // #include // #include import "C" import ( "log" "os" "os/exec" "os/signal" "os/user" "strconv" "syscall" "golang.org/x/sys/unix" ) func runAsRoot() { cmd := exec.Command("whoami") uid := 0 unprivUser := "nobody" lu, err := user.Lookup(unprivUser) if err != nil { log.Fatalf("Error: Unable to lookup user '%s': %v", unprivUser, err) } unprivUid, err := strconv.Atoi(lu.Uid) if err != nil { log.Fatalf("Error: %v", err) } log.Printf("Calling setreuid") ret, errno := C.setreuid(C.uid_t(unprivUid), C.uid_t(uid)) if ret != 0 { log.Fatalf("Error: returned %d, errno: %v", ret, errno) } euid := unix.Geteuid() if euid != uid { log.Fatalf("Error: euid %d, should be %d", euid, uid) } log.Printf("Running command") stdoutStderr, err := cmd.CombinedOutput() if err != nil { log.Fatal(err) } log.Printf("%s", stdoutStderr) log.Printf("Command complete") return } func main() { log.SetFlags(log.Lshortfile) unprivUser := "nobody" lu, err := user.Lookup(unprivUser) if err != nil { log.Fatalf("Error: Unable to lookup user '%s': %v", unprivUser, err) } uid, err := strconv.Atoi(lu.Uid) if err != nil { log.Fatalf("Error: %v", err) } ret, errno := C.setreuid(C.uid_t(0), C.uid_t(uid)) if ret != 0 { log.Fatalf("Error: returned %d, errno: %v", ret, errno) } euid := unix.Geteuid() if euid != uid { log.Fatalf("Error: euid %d, should be %d", euid, uid) } go func() { runAsRoot() }() sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt, syscall.SIGTERM) <-sigs }