From bc1d900fa9b85fb3f3b897b487e400feaf422ddc Mon Sep 17 00:00:00 2001 From: jguer Date: Tue, 31 Aug 2021 02:27:25 +0200 Subject: [PATCH] feat(su): deelevate if ran as su using a privilege elevation tool --- install.go | 2 +- pkg/settings/dirs.go | 8 +++++--- pkg/settings/exe/cmd_builder.go | 32 +++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/install.go b/install.go index 3098cafc..2a70dcf8 100644 --- a/install.go +++ b/install.go @@ -176,7 +176,7 @@ func install(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Execu cmdArgs, config.Runtime.Mode, settings.NoConfirm)) } - if len(dp.Aur) > 0 && os.Geteuid() == 0 { + if len(dp.Aur) > 0 && os.Geteuid() == 0 && os.Getenv("SUDO_USER") == "" && os.Getenv("DOAS_USER") == "" { return fmt.Errorf(gotext.Get("refusing to install AUR packages as root, aborting")) } diff --git a/pkg/settings/dirs.go b/pkg/settings/dirs.go index 3d8e409c..4c3b02f1 100644 --- a/pkg/settings/dirs.go +++ b/pkg/settings/dirs.go @@ -33,19 +33,21 @@ func getConfigPath() string { } func getCacheHome() string { - if cacheHome := os.Getenv("XDG_CACHE_HOME"); cacheHome != "" { + uid := os.Geteuid() + + if cacheHome := os.Getenv("XDG_CACHE_HOME"); cacheHome != "" && uid != 0 { if err := initDir(cacheHome); err == nil { return filepath.Join(cacheHome, "yay") } } - if cacheHome := os.Getenv("HOME"); cacheHome != "" { + if cacheHome := os.Getenv("HOME"); cacheHome != "" && uid != 0 { if err := initDir(cacheHome); err == nil { return filepath.Join(cacheHome, ".cache", "yay") } } - return "/tmp" + return os.TempDir() } func initDir(dir string) error { diff --git a/pkg/settings/exe/cmd_builder.go b/pkg/settings/exe/cmd_builder.go index ace2f3ca..f095a972 100644 --- a/pkg/settings/exe/cmd_builder.go +++ b/pkg/settings/exe/cmd_builder.go @@ -5,8 +5,11 @@ import ( "fmt" "os" "os/exec" + "os/user" "path/filepath" + "strconv" "strings" + "syscall" "time" "github.com/leonelquinteros/gotext" @@ -63,6 +66,8 @@ func (c *CmdBuilder) BuildGitCmd(ctx context.Context, dir string, extraArgs ...s cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0") + c.deElevateCommand(cmd) + return cmd } @@ -85,6 +90,8 @@ func (c *CmdBuilder) BuildMakepkgCmd(ctx context.Context, dir string, extraArgs cmd := exec.CommandContext(ctx, c.MakepkgBin, args...) cmd.Dir = dir + c.deElevateCommand(cmd) + return cmd } @@ -92,6 +99,26 @@ func (c *CmdBuilder) SetPacmanDBPath(dbPath string) { c.PacmanDBPath = dbPath } +func (c *CmdBuilder) deElevateCommand(cmd *exec.Cmd) { + if os.Geteuid() != 0 { + return + } + + ogCaller := "" + if caller := os.Getenv("SUDO_USER"); caller != "" { + ogCaller = caller + } else if caller := os.Getenv("DOAS_USER"); caller != "" { + ogCaller = caller + } + + if userFound, err := user.Lookup(ogCaller); err == nil { + cmd.SysProcAttr = &syscall.SysProcAttr{} + uid, _ := strconv.Atoi(userFound.Uid) + gid, _ := strconv.Atoi(userFound.Gid) + cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)} + } +} + func (c *CmdBuilder) buildPrivilegeElevatorCommand(ctx context.Context, ogArgs []string) *exec.Cmd { if c.SudoBin == "su" { return exec.CommandContext(ctx, c.SudoBin, "-c", strings.Join(ogArgs, " ")) @@ -121,7 +148,10 @@ func (c *CmdBuilder) BuildPacmanCmd(ctx context.Context, args *parser.Arguments, if needsRoot { waitLock(c.PacmanDBPath) - return c.buildPrivilegeElevatorCommand(ctx, argArr) + + if os.Geteuid() != 0 { + return c.buildPrivilegeElevatorCommand(ctx, argArr) + } } return exec.CommandContext(ctx, argArr[0], argArr[1:]...)