sandbox/seccomp: import dot for syscall
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 1m55s
Test / Sandbox (race detector) (push) Successful in 3m7s
Test / Planterette (push) Successful in 3m31s
Test / Hakurei (race detector) (push) Successful in 4m19s
Test / Hakurei (push) Successful in 1m57s
Test / Flake checks (push) Successful in 1m11s
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 1m55s
Test / Sandbox (race detector) (push) Successful in 3m7s
Test / Planterette (push) Successful in 3m31s
Test / Hakurei (race detector) (push) Successful in 4m19s
Test / Hakurei (push) Successful in 1m57s
Test / Flake checks (push) Successful in 1m11s
This significantly increases readability in some places. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
69bd581af7
commit
a6887f7253
@ -11,7 +11,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
. "syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/hakurei/sandbox/seccomp"
|
"git.gensokyo.uk/security/hakurei/sandbox/seccomp"
|
||||||
@ -119,11 +119,9 @@ func (p *Container) Start() error {
|
|||||||
ctx, cancel := context.WithCancel(p.ctx)
|
ctx, cancel := context.WithCancel(p.ctx)
|
||||||
p.cancel = cancel
|
p.cancel = cancel
|
||||||
|
|
||||||
var cloneFlags uintptr = syscall.CLONE_NEWIPC |
|
var cloneFlags uintptr = CLONE_NEWIPC | CLONE_NEWUTS | CLONE_NEWCGROUP
|
||||||
syscall.CLONE_NEWUTS |
|
|
||||||
syscall.CLONE_NEWCGROUP
|
|
||||||
if p.Flags&FAllowNet == 0 {
|
if p.Flags&FAllowNet == 0 {
|
||||||
cloneFlags |= syscall.CLONE_NEWNET
|
cloneFlags |= CLONE_NEWNET
|
||||||
}
|
}
|
||||||
|
|
||||||
// map to overflow id to work around ownership checks
|
// map to overflow id to work around ownership checks
|
||||||
@ -146,17 +144,13 @@ func (p *Container) Start() error {
|
|||||||
if p.Cancel != nil {
|
if p.Cancel != nil {
|
||||||
p.cmd.Cancel = func() error { return p.Cancel(p.cmd) }
|
p.cmd.Cancel = func() error { return p.Cancel(p.cmd) }
|
||||||
} else {
|
} else {
|
||||||
p.cmd.Cancel = func() error { return p.cmd.Process.Signal(syscall.SIGTERM) }
|
p.cmd.Cancel = func() error { return p.cmd.Process.Signal(SIGTERM) }
|
||||||
}
|
}
|
||||||
p.cmd.Dir = "/"
|
p.cmd.Dir = "/"
|
||||||
p.cmd.SysProcAttr = &syscall.SysProcAttr{
|
p.cmd.SysProcAttr = &SysProcAttr{
|
||||||
Setsid: p.Flags&FAllowTTY == 0,
|
Setsid: p.Flags&FAllowTTY == 0,
|
||||||
Pdeathsig: syscall.SIGKILL,
|
Pdeathsig: SIGKILL,
|
||||||
|
Cloneflags: cloneFlags | CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS,
|
||||||
Cloneflags: cloneFlags |
|
|
||||||
syscall.CLONE_NEWUSER |
|
|
||||||
syscall.CLONE_NEWPID |
|
|
||||||
syscall.CLONE_NEWNS,
|
|
||||||
|
|
||||||
// remain privileged for setup
|
// remain privileged for setup
|
||||||
AmbientCaps: []uintptr{CAP_SYS_ADMIN, CAP_SETPCAP},
|
AmbientCaps: []uintptr{CAP_SYS_ADMIN, CAP_SETPCAP},
|
||||||
@ -194,7 +188,7 @@ func (p *Container) Serve() error {
|
|||||||
|
|
||||||
if p.Path != "" && !path.IsAbs(p.Path) {
|
if p.Path != "" && !path.IsAbs(p.Path) {
|
||||||
p.cancel()
|
p.cancel()
|
||||||
return msg.WrapErr(syscall.EINVAL,
|
return msg.WrapErr(EINVAL,
|
||||||
fmt.Sprintf("invalid executable path %q", p.Path))
|
fmt.Sprintf("invalid executable path %q", p.Path))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +197,7 @@ func (p *Container) Serve() error {
|
|||||||
p.Path = os.Getenv("SHELL")
|
p.Path = os.Getenv("SHELL")
|
||||||
if !path.IsAbs(p.Path) {
|
if !path.IsAbs(p.Path) {
|
||||||
p.cancel()
|
p.cancel()
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE,
|
||||||
"no command specified and $SHELL is invalid")
|
"no command specified and $SHELL is invalid")
|
||||||
}
|
}
|
||||||
p.name = path.Base(p.Path)
|
p.name = path.Base(p.Path)
|
||||||
@ -220,8 +214,8 @@ func (p *Container) Serve() error {
|
|||||||
err := setup.Encode(
|
err := setup.Encode(
|
||||||
&initParams{
|
&initParams{
|
||||||
p.Params,
|
p.Params,
|
||||||
syscall.Getuid(),
|
Getuid(),
|
||||||
syscall.Getgid(),
|
Getgid(),
|
||||||
len(p.ExtraFiles),
|
len(p.ExtraFiles),
|
||||||
msg.IsVerbose(),
|
msg.IsVerbose(),
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
. "syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/hakurei/sandbox/seccomp"
|
"git.gensokyo.uk/security/hakurei/sandbox/seccomp"
|
||||||
@ -97,9 +97,9 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
oldmask := syscall.Umask(0)
|
oldmask := Umask(0)
|
||||||
if params.Hostname != "" {
|
if params.Hostname != "" {
|
||||||
if err := syscall.Sethostname([]byte(params.Hostname)); err != nil {
|
if err := Sethostname([]byte(params.Hostname)); err != nil {
|
||||||
log.Fatalf("cannot set hostname: %v", err)
|
log.Fatalf("cannot set hostname: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,9 +107,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
// cache sysctl before pivot_root
|
// cache sysctl before pivot_root
|
||||||
LastCap()
|
LastCap()
|
||||||
|
|
||||||
if err := syscall.Mount("", "/", "",
|
if err := Mount("", "/", "", MS_SILENT|MS_SLAVE|MS_REC, ""); err != nil {
|
||||||
syscall.MS_SILENT|syscall.MS_SLAVE|syscall.MS_REC,
|
|
||||||
""); err != nil {
|
|
||||||
log.Fatalf("cannot make / rslave: %v", err)
|
log.Fatalf("cannot make / rslave: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,9 +124,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.Mount("rootfs", basePath, "tmpfs",
|
if err := Mount("rootfs", basePath, "tmpfs", MS_NODEV|MS_NOSUID, ""); err != nil {
|
||||||
syscall.MS_NODEV|syscall.MS_NOSUID,
|
|
||||||
""); err != nil {
|
|
||||||
log.Fatalf("cannot mount intermediate root: %v", err)
|
log.Fatalf("cannot mount intermediate root: %v", err)
|
||||||
}
|
}
|
||||||
if err := os.Chdir(basePath); err != nil {
|
if err := os.Chdir(basePath); err != nil {
|
||||||
@ -138,9 +134,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
if err := os.Mkdir(sysrootDir, 0755); err != nil {
|
if err := os.Mkdir(sysrootDir, 0755); err != nil {
|
||||||
log.Fatalf("%v", err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
if err := syscall.Mount(sysrootDir, sysrootDir, "",
|
if err := Mount(sysrootDir, sysrootDir, "", MS_SILENT|MS_MGC_VAL|MS_BIND|MS_REC, ""); err != nil {
|
||||||
syscall.MS_SILENT|syscall.MS_MGC_VAL|syscall.MS_BIND|syscall.MS_REC,
|
|
||||||
""); err != nil {
|
|
||||||
log.Fatalf("cannot bind sysroot: %v", err)
|
log.Fatalf("cannot bind sysroot: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +142,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
log.Fatalf("%v", err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
// pivot_root uncovers basePath in hostDir
|
// pivot_root uncovers basePath in hostDir
|
||||||
if err := syscall.PivotRoot(basePath, hostDir); err != nil {
|
if err := PivotRoot(basePath, hostDir); err != nil {
|
||||||
log.Fatalf("cannot pivot into intermediate root: %v", err)
|
log.Fatalf("cannot pivot into intermediate root: %v", err)
|
||||||
}
|
}
|
||||||
if err := os.Chdir("/"); err != nil {
|
if err := os.Chdir("/"); err != nil {
|
||||||
@ -167,19 +161,17 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup requiring host root complete at this point
|
// setup requiring host root complete at this point
|
||||||
if err := syscall.Mount(hostDir, hostDir, "",
|
if err := Mount(hostDir, hostDir, "", MS_SILENT|MS_REC|MS_PRIVATE, ""); err != nil {
|
||||||
syscall.MS_SILENT|syscall.MS_REC|syscall.MS_PRIVATE,
|
|
||||||
""); err != nil {
|
|
||||||
log.Fatalf("cannot make host root rprivate: %v", err)
|
log.Fatalf("cannot make host root rprivate: %v", err)
|
||||||
}
|
}
|
||||||
if err := syscall.Unmount(hostDir, syscall.MNT_DETACH); err != nil {
|
if err := Unmount(hostDir, MNT_DETACH); err != nil {
|
||||||
log.Fatalf("cannot unmount host root: %v", err)
|
log.Fatalf("cannot unmount host root: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var fd int
|
var fd int
|
||||||
if err := IgnoringEINTR(func() (err error) {
|
if err := IgnoringEINTR(func() (err error) {
|
||||||
fd, err = syscall.Open("/", syscall.O_DIRECTORY|syscall.O_RDONLY, 0)
|
fd, err = Open("/", O_DIRECTORY|O_RDONLY, 0)
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Fatalf("cannot open intermediate root: %v", err)
|
log.Fatalf("cannot open intermediate root: %v", err)
|
||||||
@ -188,36 +180,36 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
log.Fatalf("%v", err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.PivotRoot(".", "."); err != nil {
|
if err := PivotRoot(".", "."); err != nil {
|
||||||
log.Fatalf("cannot pivot into sysroot: %v", err)
|
log.Fatalf("cannot pivot into sysroot: %v", err)
|
||||||
}
|
}
|
||||||
if err := syscall.Fchdir(fd); err != nil {
|
if err := Fchdir(fd); err != nil {
|
||||||
log.Fatalf("cannot re-enter intermediate root: %v", err)
|
log.Fatalf("cannot re-enter intermediate root: %v", err)
|
||||||
}
|
}
|
||||||
if err := syscall.Unmount(".", syscall.MNT_DETACH); err != nil {
|
if err := Unmount(".", MNT_DETACH); err != nil {
|
||||||
log.Fatalf("cannot unmount intemediate root: %v", err)
|
log.Fatalf("cannot unmount intemediate root: %v", err)
|
||||||
}
|
}
|
||||||
if err := os.Chdir("/"); err != nil {
|
if err := os.Chdir("/"); err != nil {
|
||||||
log.Fatalf("%v", err)
|
log.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.Close(fd); err != nil {
|
if err := Close(fd); err != nil {
|
||||||
log.Fatalf("cannot close intermediate root: %v", err)
|
log.Fatalf("cannot close intermediate root: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, errno := syscall.Syscall(PR_SET_NO_NEW_PRIVS, 1, 0, 0); errno != 0 {
|
if _, _, errno := Syscall(PR_SET_NO_NEW_PRIVS, 1, 0, 0); errno != 0 {
|
||||||
log.Fatalf("prctl(PR_SET_NO_NEW_PRIVS): %v", errno)
|
log.Fatalf("prctl(PR_SET_NO_NEW_PRIVS): %v", errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0); errno != 0 {
|
if _, _, errno := Syscall(SYS_PRCTL, PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0); errno != 0 {
|
||||||
log.Fatalf("cannot clear the ambient capability set: %v", errno)
|
log.Fatalf("cannot clear the ambient capability set: %v", errno)
|
||||||
}
|
}
|
||||||
for i := uintptr(0); i <= LastCap(); i++ {
|
for i := uintptr(0); i <= LastCap(); i++ {
|
||||||
if params.Privileged && i == CAP_SYS_ADMIN {
|
if params.Privileged && i == CAP_SYS_ADMIN {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_CAPBSET_DROP, i, 0); errno != 0 {
|
if _, _, errno := Syscall(SYS_PRCTL, PR_CAPBSET_DROP, i, 0); errno != 0 {
|
||||||
log.Fatalf("cannot drop capability from bonding set: %v", errno)
|
log.Fatalf("cannot drop capability from bonding set: %v", errno)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +218,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
if params.Privileged {
|
if params.Privileged {
|
||||||
keep[capToIndex(CAP_SYS_ADMIN)] |= capToMask(CAP_SYS_ADMIN)
|
keep[capToIndex(CAP_SYS_ADMIN)] |= capToMask(CAP_SYS_ADMIN)
|
||||||
|
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_SYS_ADMIN); errno != 0 {
|
if _, _, errno := Syscall(SYS_PRCTL, PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_SYS_ADMIN); errno != 0 {
|
||||||
log.Fatalf("cannot raise CAP_SYS_ADMIN: %v", errno)
|
log.Fatalf("cannot raise CAP_SYS_ADMIN: %v", errno)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,7 +238,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
// setup fd is placed before all extra files
|
// setup fd is placed before all extra files
|
||||||
extraFiles[i] = os.NewFile(uintptr(offsetSetup+i), "extra file "+strconv.Itoa(i))
|
extraFiles[i] = os.NewFile(uintptr(offsetSetup+i), "extra file "+strconv.Itoa(i))
|
||||||
}
|
}
|
||||||
syscall.Umask(oldmask)
|
Umask(oldmask)
|
||||||
|
|
||||||
cmd := exec.Command(params.Path)
|
cmd := exec.Command(params.Path)
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
@ -267,7 +259,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
|
|
||||||
type winfo struct {
|
type winfo struct {
|
||||||
wpid int
|
wpid int
|
||||||
wstatus syscall.WaitStatus
|
wstatus WaitStatus
|
||||||
}
|
}
|
||||||
info := make(chan winfo, 1)
|
info := make(chan winfo, 1)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -276,7 +268,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
wpid = -2
|
wpid = -2
|
||||||
wstatus syscall.WaitStatus
|
wstatus WaitStatus
|
||||||
)
|
)
|
||||||
|
|
||||||
// keep going until no child process is left
|
// keep going until no child process is left
|
||||||
@ -289,12 +281,12 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
info <- winfo{wpid, wstatus}
|
info <- winfo{wpid, wstatus}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = syscall.EINTR
|
err = EINTR
|
||||||
for errors.Is(err, syscall.EINTR) {
|
for errors.Is(err, EINTR) {
|
||||||
wpid, err = syscall.Wait4(-1, &wstatus, 0, nil)
|
wpid, err = Wait4(-1, &wstatus, 0, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !errors.Is(err, syscall.ECHILD) {
|
if !errors.Is(err, ECHILD) {
|
||||||
log.Println("unexpected wait4 response:", err)
|
log.Println("unexpected wait4 response:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +295,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
|
|
||||||
// handle signals to dump withheld messages
|
// handle signals to dump withheld messages
|
||||||
sig := make(chan os.Signal, 2)
|
sig := make(chan os.Signal, 2)
|
||||||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sig, SIGINT, SIGTERM)
|
||||||
|
|
||||||
// closed after residualProcessTimeout has elapsed after initial process death
|
// closed after residualProcessTimeout has elapsed after initial process death
|
||||||
timeout := make(chan struct{})
|
timeout := make(chan struct{})
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
. "syscall"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/hakurei/sandbox/vfs"
|
"git.gensokyo.uk/security/hakurei/sandbox/vfs"
|
||||||
)
|
)
|
||||||
@ -17,8 +17,7 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
|
|||||||
msg.Verbosef("resolved %q on %q flags %#x", source, target, flags)
|
msg.Verbosef("resolved %q on %q flags %#x", source, target, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.Mount(source, target, "",
|
if err := Mount(source, target, "", MS_SILENT|MS_BIND|flags&MS_REC, ""); err != nil {
|
||||||
syscall.MS_SILENT|syscall.MS_BIND|flags&syscall.MS_REC, ""); err != nil {
|
|
||||||
return wrapErrSuffix(err,
|
return wrapErrSuffix(err,
|
||||||
fmt.Sprintf("cannot mount %q on %q:", source, target))
|
fmt.Sprintf("cannot mount %q on %q:", source, target))
|
||||||
}
|
}
|
||||||
@ -38,7 +37,7 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
|
|||||||
{
|
{
|
||||||
var destFd int
|
var destFd int
|
||||||
if err := IgnoringEINTR(func() (err error) {
|
if err := IgnoringEINTR(func() (err error) {
|
||||||
destFd, err = syscall.Open(targetFinal, O_PATH|syscall.O_CLOEXEC, 0)
|
destFd, err = Open(targetFinal, O_PATH|O_CLOEXEC, 0)
|
||||||
return
|
return
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return wrapErrSuffix(err,
|
return wrapErrSuffix(err,
|
||||||
@ -46,7 +45,7 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
|
|||||||
}
|
}
|
||||||
if v, err := os.Readlink(p.fd(destFd)); err != nil {
|
if v, err := os.Readlink(p.fd(destFd)); err != nil {
|
||||||
return wrapErrSelf(err)
|
return wrapErrSelf(err)
|
||||||
} else if err = syscall.Close(destFd); err != nil {
|
} else if err = Close(destFd); err != nil {
|
||||||
return wrapErrSuffix(err,
|
return wrapErrSuffix(err,
|
||||||
fmt.Sprintf("cannot close %q:", targetFinal))
|
fmt.Sprintf("cannot close %q:", targetFinal))
|
||||||
} else {
|
} else {
|
||||||
@ -54,11 +53,11 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mf := syscall.MS_NOSUID | flags&syscall.MS_NODEV | flags&syscall.MS_RDONLY
|
mf := MS_NOSUID | flags&MS_NODEV | flags&MS_RDONLY
|
||||||
return hostProc.mountinfo(func(d *vfs.MountInfoDecoder) error {
|
return hostProc.mountinfo(func(d *vfs.MountInfoDecoder) error {
|
||||||
n, err := d.Unfold(targetKFinal)
|
n, err := d.Unfold(targetKFinal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, syscall.ESTALE) {
|
if errors.Is(err, ESTALE) {
|
||||||
return msg.WrapErr(err,
|
return msg.WrapErr(err,
|
||||||
fmt.Sprintf("mount point %q never appeared in mountinfo", targetKFinal))
|
fmt.Sprintf("mount point %q never appeared in mountinfo", targetKFinal))
|
||||||
}
|
}
|
||||||
@ -69,13 +68,13 @@ func (p *procPaths) bindMount(source, target string, flags uintptr, eq bool) err
|
|||||||
if err = remountWithFlags(n, mf); err != nil {
|
if err = remountWithFlags(n, mf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if flags&syscall.MS_REC == 0 {
|
if flags&MS_REC == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for cur := range n.Collective() {
|
for cur := range n.Collective() {
|
||||||
err = remountWithFlags(cur, mf)
|
err = remountWithFlags(cur, mf)
|
||||||
if err != nil && !errors.Is(err, syscall.EACCES) {
|
if err != nil && !errors.Is(err, EACCES) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,9 +90,8 @@ func remountWithFlags(n *vfs.MountInfoNode, mf uintptr) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if kf&mf != mf {
|
if kf&mf != mf {
|
||||||
return wrapErrSuffix(syscall.Mount("none", n.Clean, "",
|
return wrapErrSuffix(
|
||||||
syscall.MS_SILENT|syscall.MS_BIND|syscall.MS_REMOUNT|kf|mf,
|
Mount("none", n.Clean, "", MS_SILENT|MS_BIND|MS_REMOUNT|kf|mf, ""),
|
||||||
""),
|
|
||||||
fmt.Sprintf("cannot remount %q:", n.Clean))
|
fmt.Sprintf("cannot remount %q:", n.Clean))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -108,8 +106,8 @@ func mountTmpfs(fsname, name string, size int, perm os.FileMode) error {
|
|||||||
if size > 0 {
|
if size > 0 {
|
||||||
opt += fmt.Sprintf(",size=%d", size)
|
opt += fmt.Sprintf(",size=%d", size)
|
||||||
}
|
}
|
||||||
return wrapErrSuffix(syscall.Mount(fsname, target, "tmpfs",
|
return wrapErrSuffix(
|
||||||
syscall.MS_NOSUID|syscall.MS_NODEV, opt),
|
Mount(fsname, target, "tmpfs", MS_NOSUID|MS_NODEV, opt),
|
||||||
fmt.Sprintf("cannot mount tmpfs on %q:", name))
|
fmt.Sprintf("cannot mount tmpfs on %q:", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
. "syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,8 +46,7 @@ const (
|
|||||||
|
|
||||||
func (b *BindMountOp) early(*Params) error {
|
func (b *BindMountOp) early(*Params) error {
|
||||||
if !path.IsAbs(b.Source) {
|
if !path.IsAbs(b.Source) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", b.Source))
|
||||||
fmt.Sprintf("path %q is not absolute", b.Source))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, err := filepath.EvalSymlinks(b.Source); err != nil {
|
if v, err := filepath.EvalSymlinks(b.Source); err != nil {
|
||||||
@ -66,14 +65,13 @@ func (b *BindMountOp) apply(*Params) error {
|
|||||||
if b.SourceFinal == "\x00" {
|
if b.SourceFinal == "\x00" {
|
||||||
if b.Flags&BindOptional == 0 {
|
if b.Flags&BindOptional == 0 {
|
||||||
// unreachable
|
// unreachable
|
||||||
return syscall.EBADE
|
return EBADE
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !path.IsAbs(b.SourceFinal) || !path.IsAbs(b.Target) {
|
if !path.IsAbs(b.SourceFinal) || !path.IsAbs(b.Target) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, "path is not absolute")
|
||||||
"path is not absolute")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source := toHost(b.SourceFinal)
|
source := toHost(b.SourceFinal)
|
||||||
@ -91,12 +89,12 @@ func (b *BindMountOp) apply(*Params) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var flags uintptr = syscall.MS_REC
|
var flags uintptr = MS_REC
|
||||||
if b.Flags&BindWritable == 0 {
|
if b.Flags&BindWritable == 0 {
|
||||||
flags |= syscall.MS_RDONLY
|
flags |= MS_RDONLY
|
||||||
}
|
}
|
||||||
if b.Flags&BindDevice == 0 {
|
if b.Flags&BindDevice == 0 {
|
||||||
flags |= syscall.MS_NODEV
|
flags |= MS_NODEV
|
||||||
}
|
}
|
||||||
|
|
||||||
return hostProc.bindMount(source, target, flags, b.SourceFinal == b.Target)
|
return hostProc.bindMount(source, target, flags, b.SourceFinal == b.Target)
|
||||||
@ -125,16 +123,14 @@ func (p MountProcOp) apply(params *Params) error {
|
|||||||
v := string(p)
|
v := string(p)
|
||||||
|
|
||||||
if !path.IsAbs(v) {
|
if !path.IsAbs(v) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", v))
|
||||||
fmt.Sprintf("path %q is not absolute", v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target := toSysroot(v)
|
target := toSysroot(v)
|
||||||
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
|
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
|
||||||
return wrapErrSelf(err)
|
return wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
return wrapErrSuffix(syscall.Mount("proc", target, "proc",
|
return wrapErrSuffix(Mount("proc", target, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, ""),
|
||||||
syscall.MS_NOSUID|syscall.MS_NOEXEC|syscall.MS_NODEV, ""),
|
|
||||||
fmt.Sprintf("cannot mount proc on %q:", v))
|
fmt.Sprintf("cannot mount proc on %q:", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +152,7 @@ func (d MountDevOp) apply(params *Params) error {
|
|||||||
v := string(d)
|
v := string(d)
|
||||||
|
|
||||||
if !path.IsAbs(v) {
|
if !path.IsAbs(v) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", v))
|
||||||
fmt.Sprintf("path %q is not absolute", v))
|
|
||||||
}
|
}
|
||||||
target := toSysroot(v)
|
target := toSysroot(v)
|
||||||
|
|
||||||
@ -204,8 +199,7 @@ func (d MountDevOp) apply(params *Params) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.Mount("devpts", devPtsPath, "devpts",
|
if err := Mount("devpts", devPtsPath, "devpts", MS_NOSUID|MS_NOEXEC,
|
||||||
syscall.MS_NOSUID|syscall.MS_NOEXEC,
|
|
||||||
"newinstance,ptmxmode=0666,mode=620"); err != nil {
|
"newinstance,ptmxmode=0666,mode=620"); err != nil {
|
||||||
return wrapErrSuffix(err,
|
return wrapErrSuffix(err,
|
||||||
fmt.Sprintf("cannot mount devpts on %q:", devPtsPath))
|
fmt.Sprintf("cannot mount devpts on %q:", devPtsPath))
|
||||||
@ -213,10 +207,7 @@ func (d MountDevOp) apply(params *Params) error {
|
|||||||
|
|
||||||
if params.Flags&FAllowTTY != 0 {
|
if params.Flags&FAllowTTY != 0 {
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
if _, _, errno := syscall.Syscall(
|
if _, _, errno := Syscall(SYS_IOCTL, 1, TIOCGWINSZ, uintptr(unsafe.Pointer(&buf[0]))); errno == 0 {
|
||||||
syscall.SYS_IOCTL, 1, syscall.TIOCGWINSZ,
|
|
||||||
uintptr(unsafe.Pointer(&buf[0])),
|
|
||||||
); errno == 0 {
|
|
||||||
consolePath := toSysroot(path.Join(v, "console"))
|
consolePath := toSysroot(path.Join(v, "console"))
|
||||||
if err := ensureFile(consolePath, 0444, params.ParentPerm); err != nil {
|
if err := ensureFile(consolePath, 0444, params.ParentPerm); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -255,16 +246,14 @@ func (m MountMqueueOp) apply(params *Params) error {
|
|||||||
v := string(m)
|
v := string(m)
|
||||||
|
|
||||||
if !path.IsAbs(v) {
|
if !path.IsAbs(v) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", v))
|
||||||
fmt.Sprintf("path %q is not absolute", v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target := toSysroot(v)
|
target := toSysroot(v)
|
||||||
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
|
if err := os.MkdirAll(target, params.ParentPerm); err != nil {
|
||||||
return wrapErrSelf(err)
|
return wrapErrSelf(err)
|
||||||
}
|
}
|
||||||
return wrapErrSuffix(syscall.Mount("mqueue", target, "mqueue",
|
return wrapErrSuffix(Mount("mqueue", target, "mqueue", MS_NOSUID|MS_NOEXEC|MS_NODEV, ""),
|
||||||
syscall.MS_NOSUID|syscall.MS_NOEXEC|syscall.MS_NODEV, ""),
|
|
||||||
fmt.Sprintf("cannot mount mqueue on %q:", v))
|
fmt.Sprintf("cannot mount mqueue on %q:", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,12 +277,10 @@ type MountTmpfsOp struct {
|
|||||||
func (t *MountTmpfsOp) early(*Params) error { return nil }
|
func (t *MountTmpfsOp) early(*Params) error { return nil }
|
||||||
func (t *MountTmpfsOp) apply(*Params) error {
|
func (t *MountTmpfsOp) apply(*Params) error {
|
||||||
if !path.IsAbs(t.Path) {
|
if !path.IsAbs(t.Path) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", t.Path))
|
||||||
fmt.Sprintf("path %q is not absolute", t.Path))
|
|
||||||
}
|
}
|
||||||
if t.Size < 0 || t.Size > math.MaxUint>>1 {
|
if t.Size < 0 || t.Size > math.MaxUint>>1 {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("size %d out of bounds", t.Size))
|
||||||
fmt.Sprintf("size %d out of bounds", t.Size))
|
|
||||||
}
|
}
|
||||||
return mountTmpfs("tmpfs", t.Path, t.Size, t.Perm)
|
return mountTmpfs("tmpfs", t.Path, t.Size, t.Perm)
|
||||||
}
|
}
|
||||||
@ -315,8 +302,7 @@ func (l *SymlinkOp) early(*Params) error {
|
|||||||
if strings.HasPrefix(l[0], "*") {
|
if strings.HasPrefix(l[0], "*") {
|
||||||
l[0] = l[0][1:]
|
l[0] = l[0][1:]
|
||||||
if !path.IsAbs(l[0]) {
|
if !path.IsAbs(l[0]) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", l[0]))
|
||||||
fmt.Sprintf("path %q is not absolute", l[0]))
|
|
||||||
}
|
}
|
||||||
if name, err := os.Readlink(l[0]); err != nil {
|
if name, err := os.Readlink(l[0]); err != nil {
|
||||||
return wrapErrSelf(err)
|
return wrapErrSelf(err)
|
||||||
@ -329,8 +315,7 @@ func (l *SymlinkOp) early(*Params) error {
|
|||||||
func (l *SymlinkOp) apply(params *Params) error {
|
func (l *SymlinkOp) apply(params *Params) error {
|
||||||
// symlink target is an arbitrary path value, so only validate link name here
|
// symlink target is an arbitrary path value, so only validate link name here
|
||||||
if !path.IsAbs(l[1]) {
|
if !path.IsAbs(l[1]) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", l[1]))
|
||||||
fmt.Sprintf("path %q is not absolute", l[1]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target := toSysroot(l[1])
|
target := toSysroot(l[1])
|
||||||
@ -362,8 +347,7 @@ type MkdirOp struct {
|
|||||||
func (m *MkdirOp) early(*Params) error { return nil }
|
func (m *MkdirOp) early(*Params) error { return nil }
|
||||||
func (m *MkdirOp) apply(*Params) error {
|
func (m *MkdirOp) apply(*Params) error {
|
||||||
if !path.IsAbs(m.Path) {
|
if !path.IsAbs(m.Path) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", m.Path))
|
||||||
fmt.Sprintf("path %q is not absolute", m.Path))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(toSysroot(m.Path), m.Perm); err != nil {
|
if err := os.MkdirAll(toSysroot(m.Path), m.Perm); err != nil {
|
||||||
@ -391,8 +375,7 @@ type TmpfileOp struct {
|
|||||||
func (t *TmpfileOp) early(*Params) error { return nil }
|
func (t *TmpfileOp) early(*Params) error { return nil }
|
||||||
func (t *TmpfileOp) apply(params *Params) error {
|
func (t *TmpfileOp) apply(params *Params) error {
|
||||||
if !path.IsAbs(t.Path) {
|
if !path.IsAbs(t.Path) {
|
||||||
return msg.WrapErr(syscall.EBADE,
|
return msg.WrapErr(EBADE, fmt.Sprintf("path %q is not absolute", t.Path))
|
||||||
fmt.Sprintf("path %q is not absolute", t.Path))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmpPath string
|
var tmpPath string
|
||||||
@ -414,7 +397,7 @@ func (t *TmpfileOp) apply(params *Params) error {
|
|||||||
} else if err = hostProc.bindMount(
|
} else if err = hostProc.bindMount(
|
||||||
tmpPath,
|
tmpPath,
|
||||||
target,
|
target,
|
||||||
syscall.MS_RDONLY|syscall.MS_NODEV,
|
MS_RDONLY|MS_NODEV,
|
||||||
false,
|
false,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
|
Loading…
x
Reference in New Issue
Block a user