github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/exec/cli_unix.go (about) 1 //go:build !windows 2 // +build !windows 3 4 package exec 5 6 import ( 7 "os" 8 goexec "os/exec" 9 "os/user" 10 "regexp" 11 "strconv" 12 "syscall" 13 14 "github.com/sirupsen/logrus" 15 ) 16 17 func adjustCmd(cmd *goexec.Cmd, noRootDrop bool, userName, groupName string) error { 18 cmd.SysProcAttr = &syscall.SysProcAttr{} 19 // permissions drop 20 if isRoot() && !noRootDrop && os.Getenv("SUDO_UID") != "" && os.Getenv("SUDO_GID") != "" { 21 creds, err := generateCredentialsDrop() 22 if err != nil { 23 logrus.Errorf("failed to drop permissions, %q", err) 24 } else { 25 cmd.SysProcAttr.Credential = creds 26 } 27 } 28 29 if userName != "" || groupName != "" { 30 creds, err := generateCredentials(userName, groupName) 31 if err != nil { 32 logrus.Errorf("failed to generate credentials: %q", err) 33 } else { 34 cmd.SysProcAttr.Credential = creds 35 } 36 } 37 cmd.SysProcAttr.Setpgid = true 38 return nil 39 } 40 41 func isRoot() bool { 42 u, err := user.Current() 43 return err == nil && u.Username == "root" 44 } 45 46 func generateCredentialsDrop() (*syscall.Credential, error) { 47 sudoUser := os.Getenv("SUDO_USER") 48 sudoUID := os.Getenv("SUDO_UID") 49 sudoGid := os.Getenv("SUDO_GID") 50 51 logrus.Infof("dropping permissions, running command as %q (%s/%s)", sudoUser, sudoUID, sudoGid) 52 53 uid, err := strconv.Atoi(sudoUID) 54 if err != nil { 55 return nil, err 56 } 57 gid, err := strconv.Atoi(sudoGid) 58 if err != nil { 59 return nil, err 60 } 61 62 return &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}, nil 63 } 64 65 var digitCheck = regexp.MustCompile(`^[0-9]+$`) 66 67 func generateCredentials(userName, groupName string) (*syscall.Credential, error) { 68 c := syscall.Credential{} 69 70 var u *user.User 71 var g *user.Group 72 var err error 73 74 if userName != "" { 75 if digitCheck.MatchString(userName) { 76 u, err = user.LookupId(userName) 77 } else { 78 u, err = user.Lookup(userName) 79 } 80 if err != nil { 81 return nil, err 82 } 83 84 uid, _ := strconv.Atoi(u.Uid) 85 c.Uid = uint32(uid) 86 } 87 88 if groupName != "" { 89 if digitCheck.MatchString(groupName) { 90 g, err = user.LookupGroupId(groupName) 91 } else { 92 g, err = user.LookupGroup(groupName) 93 } 94 if err != nil { 95 return nil, err 96 } 97 98 gid, _ := strconv.Atoi(g.Gid) 99 c.Gid = uint32(gid) 100 } 101 102 return &c, nil 103 }