2022-12-07 22:02:25 +00:00
|
|
|
//go:build linux
|
|
|
|
|
|
|
|
package getter
|
|
|
|
|
|
|
|
import (
|
2023-01-26 19:07:40 +00:00
|
|
|
"os"
|
2022-12-07 22:02:25 +00:00
|
|
|
"path/filepath"
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
"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
|
2023-03-08 21:58:43 +00:00
|
|
|
// will run as - for now this is always the same user the Nomad agent is
|
|
|
|
// running as.
|
2022-12-07 22:02:25 +00:00
|
|
|
func credentials() (uint32, uint32) {
|
2023-03-08 21:58:43 +00:00
|
|
|
return userUID, userGID
|
2022-12-07 22:02:25 +00:00
|
|
|
}
|
|
|
|
|
2022-12-09 21:46:07 +00:00
|
|
|
// defaultEnvironment is the default minimal environment variables for Linux.
|
|
|
|
func defaultEnvironment(taskDir string) map[string]string {
|
2022-12-07 22:02:25 +00:00
|
|
|
tmpDir := filepath.Join(taskDir, "tmp")
|
2022-12-09 21:46:07 +00:00
|
|
|
return map[string]string{
|
|
|
|
"PATH": "/usr/local/bin:/usr/bin:/bin",
|
|
|
|
"TMPDIR": tmpDir,
|
2022-12-07 22:02:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2023-01-09 15:46:32 +00:00
|
|
|
func lockdown(allocDir, taskDir string) error {
|
2022-12-07 22:02:25 +00:00
|
|
|
// 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"),
|
2023-01-09 15:46:32 +00:00
|
|
|
landlock.Dir(allocDir, "rwc"),
|
|
|
|
landlock.Dir(taskDir, "rwc"),
|
2022-12-07 22:02:25 +00:00
|
|
|
}
|
2023-01-26 19:07:40 +00:00
|
|
|
paths = append(paths, systemVersionControlGlobalConfigs()...)
|
2022-12-07 22:02:25 +00:00
|
|
|
locker := landlock.New(paths...)
|
|
|
|
return locker.Lock(landlock.Mandatory)
|
|
|
|
}
|
2023-01-26 19:07:40 +00:00
|
|
|
|
|
|
|
func systemVersionControlGlobalConfigs() []*landlock.Path {
|
|
|
|
const (
|
|
|
|
gitGlobalFile = "/etc/gitconfig" // https://git-scm.com/docs/git-config#SCOPES
|
|
|
|
hgGlobalFile = "/etc/mercurial/hgrc" // https://www.mercurial-scm.org/doc/hgrc.5.html#files
|
|
|
|
hgGlobalDir = "/etc/mercurial/hgrc.d" // https://www.mercurial-scm.org/doc/hgrc.5.html#files
|
|
|
|
)
|
|
|
|
return loadVersionControlGlobalConfigs(gitGlobalFile, hgGlobalFile, hgGlobalDir)
|
|
|
|
}
|
|
|
|
|
|
|
|
func loadVersionControlGlobalConfigs(gitGlobalFile, hgGlobalFile, hgGlobalDir string) []*landlock.Path {
|
|
|
|
exists := func(p string) bool {
|
|
|
|
_, err := os.Stat(p)
|
|
|
|
return err == nil
|
|
|
|
}
|
|
|
|
result := make([]*landlock.Path, 0, 3)
|
|
|
|
if exists(gitGlobalFile) {
|
|
|
|
result = append(result, landlock.File(gitGlobalFile, "r"))
|
|
|
|
}
|
|
|
|
if exists(hgGlobalFile) {
|
|
|
|
result = append(result, landlock.File(hgGlobalFile, "r"))
|
|
|
|
}
|
|
|
|
if exists(hgGlobalDir) {
|
|
|
|
result = append(result, landlock.Dir(hgGlobalDir, "r"))
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|