func (UserExecer) ExecAsUser(uid, gid int, workDir, programName string, args ...string) error { if _, _, errNo := syscall.RawSyscall(syscall.SYS_SETGID, uintptr(gid), 0, 0); errNo != 0 { return fmt.Errorf("system: setgid: %s", errNo.Error()) } if err := syscall.Setgroups([]int{}); err != nil { return fmt.Errorf("system: setgroups: %s", err) } if _, _, errNo := syscall.RawSyscall(syscall.SYS_SETUID, uintptr(uid), 0, 0); errNo != 0 { return fmt.Errorf("system: setuid: %s", errNo.Error()) } if workDir == "" { return errors.New("system: working directory is not provided.") } if err := os.MkdirAll(workDir, 0755); err != nil { return fmt.Errorf("system: %s", err) } if err := os.Chdir(workDir); err != nil { return fmt.Errorf("system: invalid working directory: %s", workDir) } programPath, err := exec.LookPath(programName) if err != nil { return fmt.Errorf("system: program '%s' was not found in $PATH: %s", programName, err) } if err := syscall.Exec(programPath, append([]string{programName}, args...), os.Environ()); err != nil { return fmt.Errorf("system: exec of %s: %s", programName, err) } return nil }
// SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(u string) error { uid, gid, suppGids, home, err := user.GetUserGroupSupplementaryHome(u, syscall.Getuid(), syscall.Getgid(), "/") if err != nil { return fmt.Errorf("get supplementary groups %s", err) } if err := syscall.Setgroups(suppGids); err != nil { return fmt.Errorf("setgroups %s", err) } if err := syscall.Setgid(gid); err != nil { return fmt.Errorf("setgid %s", err) } if err := syscall.Setuid(uid); err != nil { return fmt.Errorf("setuid %s", err) } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", home); err != nil { return fmt.Errorf("set HOME %s", err) } } return nil }
func DropPrivileges(username string) error { userInfo, err := user.Lookup(username) if err != nil { return err } uid, err := strconv.Atoi(userInfo.Uid) if err != nil { return err } gid, err := strconv.Atoi(userInfo.Gid) if err != nil { return err } // TODO: should set secondary groups too err = syscall.Setgroups([]int{gid}) if err != nil { return err } err = syscall.Setgid(gid) if err != nil { return err } err = syscall.Setuid(uid) if err != nil { return err } return nil }
// SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(u string) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdPath, err := user.GetPasswdPath() if err != nil { return err } groupPath, err := user.GetGroupPath() if err != nil { return err } execUser, err := user.GetExecUserPath(u, &defaultExecUser, passwdPath, groupPath) if err != nil { return fmt.Errorf("get supplementary groups %s", err) } // if not root - check uid/gid by hand if seccomp is not working if syscall.Geteuid() > 0 && (execUser.Uid <= MIN_UID || execUser.Gid <= MIN_GID) { return fmt.Errorf("Invalid UID or GID") } // set supplementary groups if err := syscall.Setgroups(execUser.Sgids); err != nil { return fmt.Errorf("setgroups %s", err) } // set gid if err := system.Setgid(execUser.Gid); err != nil { return fmt.Errorf("setgid %s", err) } // check if setgid is successfull if syscall.Getgid() != execUser.Gid { return fmt.Errorf("setgid failed") } // set uid if err := system.Setuid(execUser.Uid); err != nil { return fmt.Errorf("setuid %s", err) } // check if setuid is successful if syscall.Getuid() != execUser.Uid { return fmt.Errorf("setuid failed") } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return fmt.Errorf("set HOME %s", err) } } return nil }
// setupUser changes the groups, gid, and uid for the user inside the container func setupUser(config *initConfig) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdPath, err := user.GetPasswdPath() if err != nil { return err } groupPath, err := user.GetGroupPath() if err != nil { return err } execUser, err := user.GetExecUserPath(config.User, &defaultExecUser, passwdPath, groupPath) if err != nil { return err } var addGroups []int if len(config.Config.AdditionalGroups) > 0 { addGroups, err = user.GetAdditionalGroupsPath(config.Config.AdditionalGroups, groupPath) if err != nil { return err } } // change the permissions on the STDIO of the current process so that when the user // is changed for the container, it's STDIO of the process matches the user. for _, fd := range []uintptr{ os.Stdin.Fd(), os.Stderr.Fd(), os.Stdout.Fd(), } { if err := syscall.Fchown(int(fd), execUser.Uid, execUser.Gid); err != nil { return err } } suppGroups := append(execUser.Sgids, addGroups...) if err := syscall.Setgroups(suppGroups); err != nil { return err } if err := system.Setgid(execUser.Gid); err != nil { return err } if err := system.Setuid(execUser.Uid); err != nil { return err } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return err } } return nil }
// setupUser changes the groups, gid, and uid for the user inside the container func setupUser(config *initConfig) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdPath, err := user.GetPasswdPath() if err != nil { return err } groupPath, err := user.GetGroupPath() if err != nil { return err } execUser, err := user.GetExecUserPath(config.User, &defaultExecUser, passwdPath, groupPath) if err != nil { return err } var addGroups []int if len(config.Config.AdditionalGroups) > 0 { addGroups, err = user.GetAdditionalGroupsPath(config.Config.AdditionalGroups, groupPath) if err != nil { return err } } // before we change to the container's user make sure that the processes STDIO // is correctly owned by the user that we are switching to. if err := fixStdioPermissions(execUser); err != nil { return err } suppGroups := append(execUser.Sgids, addGroups...) if err := syscall.Setgroups(suppGroups); err != nil { return err } if err := system.Setgid(execUser.Gid); err != nil { return err } if err := system.Setuid(execUser.Uid); err != nil { return err } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return err } } return nil }
func MaybeBecomeChildProcess() { lrs := os.Getenv("_RUNSIT_LAUNCH_INFO") if lrs == "" { return } defer os.Exit(2) // should never make it this far, though lr := new(LaunchRequest) d := gob.NewDecoder(base64.NewDecoder(base64.StdEncoding, strings.NewReader(lrs))) err := d.Decode(lr) if err != nil { log.Fatalf("Failed to decode LaunchRequest in child: %v", err) } if lr.NumFiles != 0 { var lim syscall.Rlimit if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil { log.Fatalf("failed to get NOFILE rlimit: %v", err) } noFile := rlim_t(lr.NumFiles) lim.Cur = noFile lim.Max = noFile if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil { log.Fatalf("failed to set NOFILE rlimit: %v", err) } } if lr.Gid != 0 { if err := syscall.Setgid(lr.Gid); err != nil { log.Fatalf("failed to Setgid(%d): %v", lr.Gid, err) } } if len(lr.Gids) != 0 { if err := syscall.Setgroups(lr.Gids); err != nil { log.Printf("setgroups: %v", err) } } if lr.Uid != 0 { if err := syscall.Setuid(lr.Uid); err != nil { log.Fatalf("failed to Setuid(%d): %v", lr.Uid, err) } } if lr.Path != "" { err = os.Chdir(lr.Dir) if err != nil { log.Fatalf("failed to chdir to %q: %v", lr.Dir, err) } } err = syscall.Exec(lr.Path, lr.Argv, lr.Env) log.Fatalf("failed to exec %q: %v", lr.Path, err) }
// setupUser changes the groups, gid, and uid for the user inside the container func setupUser(config *initConfig) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdPath, err := user.GetPasswdPath() if err != nil { return err } groupPath, err := user.GetGroupPath() if err != nil { return err } execUser, err := user.GetExecUserPath(config.User, &defaultExecUser, passwdPath, groupPath) if err != nil { return err } var addGroups []int if len(config.Config.AdditionalGroups) > 0 { addGroups, err = user.GetAdditionalGroupsPath(config.Config.AdditionalGroups, groupPath) if err != nil { return err } } suppGroups := append(execUser.Sgids, addGroups...) if err := syscall.Setgroups(suppGroups); err != nil { return err } if err := system.Setgid(execUser.Gid); err != nil { return err } if err := system.Setuid(execUser.Uid); err != nil { return err } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return err } } return nil }
// SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(container *libcontainer.Config) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdPath, err := user.GetPasswdPath() if err != nil { return err } groupPath, err := user.GetGroupPath() if err != nil { return err } execUser, err := user.GetExecUserPath(container.User, &defaultExecUser, passwdPath, groupPath) if err != nil { return fmt.Errorf("get supplementary groups %s", err) } suppGroups := append(execUser.Sgids, container.AdditionalGroups...) if err := syscall.Setgroups(suppGroups); err != nil { return fmt.Errorf("setgroups %s", err) } if err := system.Setgid(execUser.Gid); err != nil { return fmt.Errorf("setgid %s", err) } if err := system.Setuid(execUser.Uid); err != nil { return fmt.Errorf("setuid %s", err) } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return fmt.Errorf("set HOME %s", err) } } return nil }
func changeUser(name string) error { user, err := user.Lookup(name) if err != nil { return err } uid, err := strconv.Atoi(user.Uid) if err != nil { return err } gid, err := strconv.Atoi(user.Gid) if err = syscall.Setgroups([]int{gid}); err != nil { return err } if err = syscall.Setuid(uid); err != nil { return err } return nil }
// SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(u string) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdFile, err := user.GetPasswdFile() if err != nil { return err } groupFile, err := user.GetGroupFile() if err != nil { return err } execUser, err := user.GetExecUserFile(u, &defaultExecUser, passwdFile, groupFile) if err != nil { return fmt.Errorf("get supplementary groups %s", err) } if err := syscall.Setgroups(execUser.Sgids); err != nil { return fmt.Errorf("setgroups %s", err) } if err := system.Setgid(execUser.Gid); err != nil { return fmt.Errorf("setgid %s", err) } if err := system.Setuid(execUser.Uid); err != nil { return fmt.Errorf("setuid %s", err) } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return fmt.Errorf("set HOME %s", err) } } return nil }
// SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(u string) error { uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid()) if err != nil { return fmt.Errorf("get supplementary groups %s", err) } if err := syscall.Setgroups(suppGids); err != nil { return fmt.Errorf("setgroups %s", err) } if err := syscall.Setgid(gid); err != nil { return fmt.Errorf("setgid %s", err) } if err := syscall.Setuid(uid); err != nil { return fmt.Errorf("setuid %s", err) } return nil }
// Takes care of dropping privileges to the desired user func changeUser(args *execdriver.InitArgs) error { uid, gid, suppGids, err := user.GetUserGroupSupplementary( args.User, syscall.Getuid(), syscall.Getgid(), ) if err != nil { return err } if err := syscall.Setgroups(suppGids); err != nil { return fmt.Errorf("Setgroups failed: %v", err) } if err := syscall.Setgid(gid); err != nil { return fmt.Errorf("Setgid failed: %v", err) } if err := syscall.Setuid(uid); err != nil { return fmt.Errorf("Setuid failed: %v", err) } return nil }
// setupUser changes the groups, gid, and uid for the user inside the container // copy from libcontainer, cause not it's private func setupUser(userSpec string) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } passwdPath, err := user.GetPasswdPath() if err != nil { return err } groupPath, err := user.GetGroupPath() if err != nil { return err } execUser, err := user.GetExecUserPath(userSpec, &defaultExecUser, passwdPath, groupPath) if err != nil { return err } if err := syscall.Setgroups(execUser.Sgids); err != nil { return err } if err := system.Setgid(execUser.Gid); err != nil { return err } if err := system.Setuid(execUser.Uid); err != nil { return err } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return err } } return nil }
// SetupUser changes the groups, gid, and uid for the user inside the container func SetupUser(u string) error { // Set up defaults. defaultExecUser := user.ExecUser{ Uid: syscall.Getuid(), Gid: syscall.Getgid(), Home: "/", } execUser, err := getUser(u, &defaultExecUser) if err != nil { return err } if err := syscall.Setgroups(execUser.Sgids); err != nil { return fmt.Errorf("setgroups %s", err) } if err := system.Setgid(execUser.Gid); err != nil { return fmt.Errorf("setgid %s", err) } if err := system.Setuid(execUser.Uid); err != nil { return fmt.Errorf("setuid %s", err) } // if we didn't get HOME already, set it based on the user's HOME if envHome := os.Getenv("HOME"); envHome == "" { if err := os.Setenv("HOME", execUser.Home); err != nil { return fmt.Errorf("set HOME %s", err) } } os.Setenv("USER", u) return nil }
func Setgroups(gids []int) error { return syscall.Setgroups(gids) }
func unpackAndDropPrivs(snapFile, targetDir, rootDir string) error { d, err := clickdeb.Open(snapFile) if err != nil { return err } defer d.Close() if helpers.ShouldDropPrivs() { var dropPrivsUser string // first find out what user to use passFile := passwdFile(rootDir, "passwd") for _, dropPrivsUser = range dropPrivsUsers { _, err := readUID(dropPrivsUser, passFile) if err == nil { break } } // then get uid/gid uid, err := readUID(dropPrivsUser, passFile) if err != nil { return err } groupFile := passwdFile(rootDir, "group") gid, err := readUID(dropPrivsUser, groupFile) if err != nil { return err } if err := os.MkdirAll(targetDir, 0755); err != nil { return err } if err := os.Chown(targetDir, uid, gid); err != nil { return err } // Setuid and Setgid only apply to the current Linux thread, so make // sure we don't get moved. runtime.LockOSThread() // run prctl(PR_SET_NO_NEW_PRIVS) rc := C.prctl_no_new_privs() if rc < 0 { return fmt.Errorf("prctl(PR_SET_NO_NEW_PRIVS) failed with %v", rc) } if err := syscall.Setgroups([]int{gid}); err != nil { return fmt.Errorf("Setgroups([]{%d}) call failed: %v", gid, err) } if err := setgid(gid); err != nil { return fmt.Errorf("Setgid(%d) call failed: %v", gid, err) } if err := setuid(uid); err != nil { return fmt.Errorf("Setuid(%d) call failed: %v", uid, err) } // extra paranoia if syscall.Getuid() != uid || syscall.Getgid() != gid { return fmt.Errorf("Dropping privileges failed, uid is %v, gid is %v", syscall.Getuid(), syscall.Getgid()) } } return d.UnpackAll(targetDir) }
// Activates the mitigation measurements. func Activate(uid int, gid int, path string) { if !CanActivate() { panic("Cannot activate mitigation measurements!") } // chroot directory err := syscall.Chroot(path) if err != nil { panic(err) } // change directory to new / err = syscall.Chdir("/") if err != nil { panic(err) } // drop all other groups err = syscall.Setgroups([]int{gid}) if err != nil { panic(err) } // verify the empty group list gids, err := syscall.Getgroups() if err != nil { panic("Could not read groups!") } if len(gids) > 1 { panic("Could not drop groups!") } else if len(gids) == 1 { if gids[0] != gid { panic("Could not drop foreign groups!") } } // change group err = syscall.Setgid(gid) if err != nil { panic(err) } // verify the group change ngid := syscall.Getgid() if ngid != gid { panic("Could not change group id!") } // change user err = syscall.Setuid(uid) if err != nil { panic(err) } // verify the user change nuid := syscall.Getuid() if nuid != uid { panic("Could not change user id!") } // now drop all environment variables os.Clearenv() }