//go:build linux package main import ( "fmt" "net" "os" "strconv" "strings" "syscall" ) // peerCred returns the uid and pid of the process on the other end of a unix socket (kernel-verified). func peerCred(c net.Conn) (uid, pid int, err error) { uc, ok := c.(*net.UnixConn) if !ok { return -1, 0, fmt.Errorf("not a unix connection") } raw, err := uc.SyscallConn() if err != nil { return -1, 0, err } uid = -1 var gerr error raw.Control(func(fd uintptr) { cred, err := syscall.GetsockoptUcred(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERCRED) if err != nil { gerr = err return } uid, pid = int(cred.Uid), int(cred.Pid) }) return uid, pid, gerr } // peerExe is the program the process runs (a replaced program shows as "... (deleted)": the name is what matters). func peerExe(pid int) (string, error) { p, err := os.Readlink("/proc/" + strconv.Itoa(pid) + "/exe") return strings.TrimSuffix(p, " (deleted)"), err }