veyron/services/mgmt/suidhelper/impl: chown, setuid
Previously, all the setuid helper code has not actually called chown and
setuid when possible. This CL adds the actual root-requiring system calls.
Change-Id: I2966fff6b322611c5fae27a6c3969631f608262c
diff --git a/services/mgmt/suidhelper/impl/args.go b/services/mgmt/suidhelper/impl/args.go
index 3178e1e..2c9da35 100644
--- a/services/mgmt/suidhelper/impl/args.go
+++ b/services/mgmt/suidhelper/impl/args.go
@@ -13,14 +13,15 @@
)
type WorkParameters struct {
- uid uint32
- gid uint32
+ uid int
+ gid int
workspace string
stderrLog string
stdoutLog string
argv0 string
argv []string
envv []string
+ dryrun bool
}
type ArgsSavedForTest struct {
@@ -67,18 +68,18 @@
return fmt.Errorf("--username %s: unknown user", username)
}
- uid, err := strconv.ParseUint(usr.Uid, 0, 32)
+ uid, err := strconv.ParseInt(usr.Uid, 0, 32)
if err != nil {
return fmt.Errorf("user.Lookup() returned an invalid uid %v", usr.Uid)
}
- gid, err := strconv.ParseUint(usr.Gid, 0, 32)
+ gid, err := strconv.ParseInt(usr.Gid, 0, 32)
if err != nil {
return fmt.Errorf("user.Lookup() returned an invalid gid %v", usr.Gid)
}
// Uids less than 501 can be special so we forbid running as them.
- if uint32(uid) < uint32(*flagMinimumUid) {
- return fmt.Errorf("suidhelper does not permit uids less than %d", uint32(*flagMinimumUid))
+ if uid < *flagMinimumUid {
+ return fmt.Errorf("suidhelper does not permit uids less than %d", *flagMinimumUid)
}
// Preserve the arguments for examination by the test harness if executed
@@ -94,10 +95,11 @@
StderrLog: *flagStderrLog,
})
env = append(env, SavedArgs+"="+b.String())
+ wp.dryrun = true
}
- wp.uid = uint32(uid)
- wp.gid = uint32(gid)
+ wp.uid = int(uid)
+ wp.gid = int(gid)
wp.workspace = *flagWorkspace
wp.argv0 = *flagRun
wp.stdoutLog = *flagStdoutLog
diff --git a/services/mgmt/suidhelper/impl/system.go b/services/mgmt/suidhelper/impl/system.go
index d3e9f3c..52d96b3 100644
--- a/services/mgmt/suidhelper/impl/system.go
+++ b/services/mgmt/suidhelper/impl/system.go
@@ -3,27 +3,43 @@
package impl
import (
+ "fmt"
"log"
+ "os"
"syscall"
)
// Chown is only availabe on UNIX platforms so this file has a build
// restriction.
func (hw *WorkParameters) Chown() error {
- // TODO(rjkroege): Insert the actual code to chown in a subsequent CL.
- log.Printf("chown %d %s\n", hw.uid, hw.workspace)
- log.Printf("chown %d %s\n", hw.uid, hw.stdoutLog)
- log.Printf("chown %d %s\n", hw.uid, hw.stderrLog)
+ chown := func(path string) error {
+ if hw.dryrun {
+ log.Printf("[dryrun] os.Chown(%s, %d, %d)", path, hw.uid, hw.gid)
+ return nil
+ }
+ return os.Chown(path, hw.uid, hw.gid)
+ }
+ for _, p := range []string{hw.workspace, hw.stdoutLog, hw.stderrLog} {
+ // TODO(rjkroege): Ensure that the nodemanager can read log entries.
+ if err := chown(p); err != nil {
+ return fmt.Errorf("os.Chown(%s, %d, %d) failed: %v", p, hw.uid, hw.gid, err)
+ }
+ }
return nil
}
func (hw *WorkParameters) Exec() error {
- log.Printf("should be Exec-ing work parameters: %#v\n", hw)
- log.Printf("su %d\n", hw.uid)
- log.Printf("exec %s %v", hw.argv0, hw.argv)
- log.Printf("env: %v", hw.envv)
-
- // TODO(rjkroege): Insert the actual code to change uid in a subsquent CL.
+ if hw.dryrun {
+ log.Printf("[dryrun] syscall.Setuid(%d)", hw.uid)
+ log.Printf("[dryrun] syscall.Setgid(%d)", hw.gid)
+ } else {
+ if err := syscall.Setuid(hw.uid); err != nil {
+ return fmt.Errorf("syscall.Setuid(%d) failed: %v", hw.uid, err)
+ }
+ if err := syscall.Setgid(hw.gid); err != nil {
+ return fmt.Errorf("syscall.Setgid(%d) failed: %v", hw.gid, err)
+ }
+ }
return syscall.Exec(hw.argv0, hw.argv, hw.envv)
}