Skip to content

Commit 08948ef

Browse files
committed
implements permissions drop in pyroscope exec
1 parent 7cb7932 commit 08948ef

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

pkg/cli/cli.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,9 @@ func Start(cfg *config.Config) error {
280280
return convert.Cli(cfg, args)
281281
}
282282
execCmd.Exec = func(_ context.Context, args []string) error {
283-
if l, err := logrus.ParseLevel(cfg.Exec.LogLevel); err == nil {
283+
if cfg.Exec.NoLogging {
284+
logrus.SetLevel(logrus.PanicLevel)
285+
} else if l, err := logrus.ParseLevel(cfg.Exec.LogLevel); err == nil {
284286
logrus.SetLevel(l)
285287
}
286288
if len(args) == 0 {

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ type Exec struct {
8282
UpstreamThreads int `def:"4" desc:"number of upload threads"`
8383
UpstreamRequestTimeout time.Duration `def:"10s" desc:"profile upload timeout"`
8484
NoLogging bool `def:"false" desc:"disables logging from pyroscope"`
85+
NoRootDrop bool `def:"false" desc:"disables permissions drop when ran under root. use this one if you want to run your command as root"`
8586
}
8687

8788
func calculateMaxDepth(min, max time.Duration, multiplier int) int {

pkg/exec/cli.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os/user"
99
"path"
1010
"runtime"
11+
"strconv"
1112
"strings"
1213
"syscall"
1314
"time"
@@ -67,6 +68,17 @@ func Cli(cfg *config.Config, args []string) error {
6768
cmd.Stdout = os.Stdout
6869
cmd.Stdin = os.Stdin
6970
cmd.SysProcAttr = &syscall.SysProcAttr{}
71+
72+
// permissions drop
73+
if isRoot() && !cfg.Exec.NoRootDrop && os.Getenv("SUDO_UID") != "" && os.Getenv("SUDO_GID") != "" {
74+
creds, err := generateCredentialsDrop()
75+
if err != nil {
76+
logrus.Errorf("failed to drop permissions, %q", err)
77+
} else {
78+
cmd.SysProcAttr.Credential = creds
79+
}
80+
}
81+
7082
cmd.SysProcAttr.Setpgid = true
7183
err := cmd.Start()
7284
if err != nil {
@@ -103,7 +115,7 @@ func Cli(cfg *config.Config, args []string) error {
103115
func waitForProcessToExit(cmd *exec.Cmd) {
104116
sigc := make(chan struct{})
105117

106-
go func(){
118+
go func() {
107119
cmd.Wait()
108120
}()
109121

@@ -135,7 +147,7 @@ func performChecks(spyName string) error {
135147

136148
if runtime.GOOS == "darwin" {
137149
if !isRoot() {
138-
logrus.Error("on macOS you're required to run the agent with sudo")
150+
logrus.Fatal("on macOS you're required to run the agent with sudo")
139151
}
140152
}
141153

@@ -173,10 +185,29 @@ func armMessage() string {
173185
return ""
174186
}
175187

176-
func generateSeed(args []string) string{
188+
func generateSeed(args []string) string {
177189
path, err := os.Getwd()
178190
if err != nil {
179191
path = "<unknown>"
180192
}
181193
return path + "|" + strings.Join(args, "&")
182194
}
195+
196+
func generateCredentialsDrop() (*syscall.Credential, error) {
197+
sudoUser := os.Getenv("SUDO_USER")
198+
sudoUid := os.Getenv("SUDO_UID")
199+
sudoGid := os.Getenv("SUDO_GID")
200+
201+
logrus.Infof("dropping permissions, running command as %q (%s/%s)", sudoUser, sudoUid, sudoGid)
202+
203+
uid, err := strconv.Atoi(sudoUid)
204+
if err != nil {
205+
return nil, err
206+
}
207+
gid, err := strconv.Atoi(sudoGid)
208+
if err != nil {
209+
return nil, err
210+
}
211+
212+
return &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}, nil
213+
}

0 commit comments

Comments
 (0)