diff --git a/pkg/config/config.go b/pkg/config/config.go index 7aa6d2d479..108cdbc322 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -87,6 +87,8 @@ type Exec struct { NoLogging bool `def:"false" desc:"disables logging from pyroscope"` NoRootDrop bool `def:"false" desc:"disables permissions drop when ran under root. use this one if you want to run your command as root"` Pid int `def:"0" desc:"PID of the process you want to profile. Pass -1 to profile the whole system (only supported by ebpfspy)"` + UserName string `def:"" desc:"starts process under specified user name"` + GroupName string `def:"" desc:"starts process under specified group name"` PyspyBlocking bool `def:"false" desc:"enables blocking mode for pyspy"` } diff --git a/pkg/exec/cli.go b/pkg/exec/cli.go index 0d075571ee..5a178d1547 100644 --- a/pkg/exec/cli.go +++ b/pkg/exec/cli.go @@ -7,6 +7,7 @@ import ( "os/exec" "os/user" "path" + "regexp" "strconv" "strings" "syscall" @@ -106,6 +107,15 @@ func Cli(cfg *config.Config, args []string) error { } } + if cfg.Exec.UserName != "" || cfg.Exec.GroupName != "" { + creds, err := generateCredentials(cfg.Exec.UserName, cfg.Exec.GroupName) + if err != nil { + logrus.Errorf("failed to generate credentials: %q", err) + } else { + cmd.SysProcAttr.Credential = creds + } + } + cmd.SysProcAttr.Setpgid = true err := cmd.Start() if err != nil { @@ -137,9 +147,7 @@ func Cli(cfg *config.Config, args []string) error { sess := agent.NewSession(u, cfg.Exec.ApplicationName, spyName, 100, 10*time.Second, pid, cfg.Exec.DetectSubprocesses) sess.Logger = logrus.StandardLogger() - logrus.Debug("sess created") err = sess.Start() - logrus.Debug("sess started") if err != nil { logrus.Errorf("error when starting session: %q", err) } @@ -263,3 +271,43 @@ func generateCredentialsDrop() (*syscall.Credential, error) { return &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}, nil } + +var digitCheck = regexp.MustCompile(`^[0-9]+$`) + +func generateCredentials(userName, groupName string) (*syscall.Credential, error) { + c := syscall.Credential{} + + var u *user.User + var g *user.Group + var err error + + if userName != "" { + if digitCheck.MatchString(userName) { + u, err = user.LookupId(userName) + } else { + u, err = user.Lookup(userName) + } + if err != nil { + return nil, err + } + + uid, _ := strconv.Atoi(u.Uid) + c.Uid = uint32(uid) + } + + if groupName != "" { + if digitCheck.MatchString(groupName) { + g, err = user.LookupGroupId(groupName) + } else { + g, err = user.LookupGroup(groupName) + } + if err != nil { + return nil, err + } + + gid, _ := strconv.Atoi(g.Gid) + c.Gid = uint32(gid) + } + + return &c, nil +}