container: fix cgroup fd

forkexec: disabled VFORK for now as it is not working properly
#13
This commit is contained in:
criyle 2025-02-20 22:52:26 -05:00
parent 659099a2c0
commit f0dd44f466
4 changed files with 19 additions and 15 deletions

View File

@ -110,7 +110,7 @@ func (c *containerServer) handleExecve(cmd *execCmd, msg unixsocket.Msg) error {
Seccomp: seccomp, Seccomp: seccomp,
CgroupFd: cgroupFd, CgroupFd: cgroupFd,
UnshareCgroupAfterSync: c.UnshareCgroup && !cmd.SyncAfter, UnshareCgroupAfterSync: c.UnshareCgroup,
} }
// starts the runner, error is handled same as wait4 to make communication equal // starts the runner, error is handled same as wait4 to make communication equal
pid, err := r.Start() pid, err := r.Start()

View File

@ -250,7 +250,7 @@ func (b *Builder) startContainer() (*container, error) {
unix.CAP_SYS_ADMIN, unix.CAP_SYS_ADMIN,
unix.CAP_SYS_RESOURCE, unix.CAP_SYS_RESOURCE,
}, },
Pdeathsig: syscall.SIGTERM, Pdeathsig: syscall.SIGKILL,
}, },
} }
if err = r.Start(); err != nil { if err = r.Start(); err != nil {

View File

@ -72,6 +72,7 @@ func (c *container) Execve(ctx context.Context, param ExecveParam) runner.Result
FdExec: param.ExecFile > 0, FdExec: param.ExecFile > 0,
CTTY: param.CTTY, CTTY: param.CTTY,
SyncAfter: param.SyncAfterExec, SyncAfter: param.SyncAfterExec,
FdCgroup: param.CgroupFD > 0,
} }
cm := cmd{ cm := cmd{
Cmd: cmdExecve, Cmd: cmdExecve,

View File

@ -5,22 +5,32 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/criyle/go-sandbox/pkg/rlimit"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
// Reference to src/syscall/exec_linux.go // Reference to src/syscall/exec_linux.go
// //
//go:noinline
//go:norace //go:norace
//go:nocheckptr
func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, hostname, domainname, pivotRoot *byte, p [2]int) (r1 uintptr, err1 syscall.Errno) { func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, hostname, domainname, pivotRoot *byte, p [2]int) (r1 uintptr, err1 syscall.Errno) {
var ( var (
clone3 *cloneArgs clone3 *cloneArgs
pid uintptr
err2 syscall.Errno
unshareUser = r.CloneFlags&unix.CLONE_NEWUSER == unix.CLONE_NEWUSER
i int
rlim rlimit.RLimit
) )
pipe := p[1]
// similar to exec_linux, avoid side effect by shuffling around // similar to exec_linux, avoid side effect by shuffling around
fd, nextfd := prepareFds(r.Files) fd, nextfd := prepareFds(r.Files)
flag := r.CloneFlags & UnshareFlags flag := r.CloneFlags & UnshareFlags
if r.SyncFunc == nil && !(r.StopBeforeSeccomp || (r.Seccomp != nil && r.Ptrace)) && flag|syscall.CLONE_NEWUSER != syscall.CLONE_NEWUSER { if r.SyncFunc == nil && !(r.StopBeforeSeccomp || (r.Seccomp != nil && r.Ptrace)) && flag&syscall.CLONE_NEWUSER != syscall.CLONE_NEWUSER {
flag |= syscall.CLONE_VM | syscall.CLONE_VFORK // flag |= syscall.CLONE_VM | syscall.CLONE_VFORK
} }
// use clone3 if cgroupFd specified // use clone3 if cgroupFd specified
@ -62,13 +72,6 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
afterForkInChild() afterForkInChild()
// Notice: cannot call any GO functions beyond this point // Notice: cannot call any GO functions beyond this point
pipe := p[1]
var (
pid uintptr
err2 syscall.Errno
unshareUser = r.CloneFlags&unix.CLONE_NEWUSER == unix.CLONE_NEWUSER
)
// Close write end of pipe // Close write end of pipe
if _, _, err1 = syscall.RawSyscall(syscall.SYS_CLOSE, uintptr(p[0]), 0, 0); err1 != 0 { if _, _, err1 = syscall.RawSyscall(syscall.SYS_CLOSE, uintptr(p[0]), 0, 0); err1 != 0 {
childExitError(pipe, LocCloseWrite, err1) childExitError(pipe, LocCloseWrite, err1)
@ -154,7 +157,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
r.ExecFile = uintptr(nextfd) r.ExecFile = uintptr(nextfd)
nextfd++ nextfd++
} }
for i := 0; i < len(fd); i++ { for i = 0; i < len(fd); i++ {
if fd[i] >= 0 && fd[i] < int(i) { if fd[i] >= 0 && fd[i] < int(i) {
// Avoid fd rewrite // Avoid fd rewrite
for nextfd == pipe || (r.ExecFile > 0 && nextfd == int(r.ExecFile)) { for nextfd == pipe || (r.ExecFile > 0 && nextfd == int(r.ExecFile)) {
@ -170,7 +173,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
} }
} }
// Pass 2: fd[i] => i // Pass 2: fd[i] => i
for i := 0; i < len(fd); i++ { for i = 0; i < len(fd); i++ {
if fd[i] == -1 { if fd[i] == -1 {
syscall.RawSyscall(syscall.SYS_CLOSE, uintptr(i), 0, 0) syscall.RawSyscall(syscall.SYS_CLOSE, uintptr(i), 0, 0)
continue continue
@ -324,7 +327,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
} }
// Set limit // Set limit
for i, rlim := range r.RLimits { for i, rlim = range r.RLimits {
// prlimit instead of setrlimit to avoid 32-bit limitation (linux > 3.2) // prlimit instead of setrlimit to avoid 32-bit limitation (linux > 3.2)
_, _, err1 = syscall.RawSyscall6(syscall.SYS_PRLIMIT64, 0, uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0, 0, 0) _, _, err1 = syscall.RawSyscall6(syscall.SYS_PRLIMIT64, 0, uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0, 0, 0)
if err1 != 0 { if err1 != 0 {