github.com/geofffranks/garden-linux@v0.0.0-20160715111146-26c893169cfa/system/user_execer_linux.go (about)

     1  package system
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  	"runtime"
     9  	"syscall"
    10  )
    11  
    12  func init() {
    13  	runtime.LockOSThread()
    14  }
    15  
    16  type UserExecer struct{}
    17  
    18  func (UserExecer) ExecAsUser(uid, gid int, workDir, programName string, args ...string) error {
    19  	if _, _, errNo := syscall.RawSyscall(syscall.SYS_SETGID, uintptr(gid), 0, 0); errNo != 0 {
    20  		return fmt.Errorf("system: setgid: %s", errNo.Error())
    21  	}
    22  
    23  	if err := syscall.Setgroups([]int{}); err != nil {
    24  		return fmt.Errorf("system: setgroups: %s", err)
    25  	}
    26  
    27  	if _, _, errNo := syscall.RawSyscall(syscall.SYS_SETUID, uintptr(uid), 0, 0); errNo != 0 {
    28  		return fmt.Errorf("system: setuid: %s", errNo.Error())
    29  	}
    30  
    31  	if workDir == "" {
    32  		return errors.New("system: working directory is not provided.")
    33  	}
    34  
    35  	if err := os.MkdirAll(workDir, 0755); err != nil {
    36  		return fmt.Errorf("system: %s", err)
    37  	}
    38  
    39  	if err := os.Chdir(workDir); err != nil {
    40  		return fmt.Errorf("system: invalid working directory: %s", workDir)
    41  	}
    42  
    43  	programPath, err := exec.LookPath(programName)
    44  	if err != nil {
    45  		return fmt.Errorf("system: program '%s' was not found in $PATH: %s", programName, err)
    46  	}
    47  
    48  	if err := syscall.Exec(programPath, append([]string{programName}, args...), os.Environ()); err != nil {
    49  		return fmt.Errorf("system: exec of %s: %s", programName, err)
    50  	}
    51  	return nil
    52  }