Skip to content

Instantly share code, notes, and snippets.

@tehmoon
Last active April 10, 2018 01:39
Show Gist options
  • Save tehmoon/ef80dbce20040ad77d1ec0edb3a94465 to your computer and use it in GitHub Desktop.
Save tehmoon/ef80dbce20040ad77d1ec0edb3a94465 to your computer and use it in GitHub Desktop.
Drop privileges Go
package main
// From https://play.golang.org/p/dXBizm4xl3
import (
"io"
"fmt"
"net"
"net/http"
"os"
"os/exec"
"syscall"
)
func main() {
if os.Getuid() == 0 {
fmt.Println("Dropping privileges...")
cmd, r, w, err := drop()
if err != nil {
fmt.Println("Failed to drop privileges:", err)
os.Exit(1)
}
go func() {
io.Copy(os.Stdout, r)
}()
go func() {
io.Copy(w, os.Stdin)
}()
cmd.Wait()
os.Exit(1)
}
l, err := net.FileListener(os.NewFile(3, "[socket]"))
if err != nil {
// Yell into the void.
fmt.Println("Failed to listen on FD 3:", err)
os.Exit(1)
}
// r := os.NewFile(4, "reader")
w := os.NewFile(5, "writer")
http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "here!")
fmt.Fprintf(resp, "I am process %d running as %d/%d", os.Getpid(), os.Getuid(), os.Getgid())
}))
}
func drop() (*exec.Cmd, *os.File, *os.File, error) {
l, err := net.Listen("tcp", ":80")
if err != nil {
return nil, nil, nil, err
}
f, err := l.(*net.TCPListener).File()
if err != nil {
return nil, nil, nil, err
}
r1, w1, err := os.Pipe()
if err != nil {
return nil, nil, nil, err
}
r2, w2, err := os.Pipe()
if err != nil {
return nil, nil, nil, err
}
cmd := exec.Command(os.Args[0])
cmd.ExtraFiles = []*os.File{f, r1, w2}
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: 65534,
Gid: 65534,
},
Setsid: true,
}
if err := cmd.Start(); err != nil {
return nil, nil, nil, err
}
fmt.Printf("Spawned process %d, exiting\n", cmd.Process.Pid)
return cmd, r2, w1, nil
// cmd.Process.Release()
// os.Exit(0)
// return nil /* unreachable */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment