open-nomad/client/allocrunner/taskrunner/getter/util_linux.go
Seth Hoenig 2a7c7d85a5
artifact: fix sandbox behavior when destination is shared alloc directory (#15712)
This PR fixes the artifact sandbox (new in Nomad 1.5) to allow downloading
artifacts into the shared 'alloc' directory made available to each task in
a common allocation. Previously we assumed the 'alloc' dir would be mounted
under the 'task' dir, but this is only the case in fs isolation: chroot; in
other modes the alloc dir is elsewhere.
2023-01-09 09:46:32 -06:00

83 lines
1.9 KiB
Go

//go:build linux
package getter
import (
"path/filepath"
"syscall"
"github.com/hashicorp/nomad/helper/users"
"github.com/shoenig/go-landlock"
)
var (
// userUID is the current user's uid
userUID uint32
// userGID is the current user's gid
userGID uint32
)
func init() {
userUID = uint32(syscall.Getuid())
userGID = uint32(syscall.Getgid())
}
// attributes returns the system process attributes to run
// the sandbox process with
func attributes() *syscall.SysProcAttr {
uid, gid := credentials()
return &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
},
}
}
// credentials returns the UID and GID of the user the child process
// will run as. On Linux systems this will be the nobody user if Nomad
// is being run as the root user, or the user Nomad is being run as
// otherwise.
func credentials() (uint32, uint32) {
switch userUID {
case 0:
return users.NobodyIDs()
default:
return userUID, userGID
}
}
// defaultEnvironment is the default minimal environment variables for Linux.
func defaultEnvironment(taskDir string) map[string]string {
tmpDir := filepath.Join(taskDir, "tmp")
return map[string]string{
"PATH": "/usr/local/bin:/usr/bin:/bin",
"TMPDIR": tmpDir,
}
}
// lockdown isolates this process to only be able to write and
// create files in the task's task directory.
// dir - the task directory
//
// Only applies to Linux, when available.
func lockdown(allocDir, taskDir string) error {
// landlock not present in the kernel, do not sandbox
if !landlock.Available() {
return nil
}
paths := []*landlock.Path{
landlock.DNS(),
landlock.Certs(),
landlock.Shared(),
landlock.Dir("/bin", "rx"),
landlock.Dir("/usr/bin", "rx"),
landlock.Dir("/usr/local/bin", "rx"),
landlock.Dir(allocDir, "rwc"),
landlock.Dir(taskDir, "rwc"),
}
locker := landlock.New(paths...)
return locker.Lock(landlock.Mandatory)
}