forkexec: only sync when syncFunc exists

#13
This commit is contained in:
criyle 2025-02-20 21:45:03 +00:00
parent d32acd7591
commit f8361a08a0
3 changed files with 33 additions and 27 deletions

View File

@ -224,13 +224,14 @@ func start() (*runner.Result, error) {
}
}
syncFunc := func(pid int) error {
if cg != nil {
var syncFunc func(pid int) error
if cg != nil {
syncFunc = func(pid int) error {
if err := cg.AddProc(pid); err != nil {
return err
}
return nil
}
return nil
}
if memfile {

View File

@ -351,14 +351,16 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
// Enable Ptrace & sync with parent (since ptrace_me is a blocking operation)
if r.Ptrace && r.Seccomp != nil {
{
r1, _, err1 = syscall.RawSyscall(syscall.SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncWrite, err1)
}
if r.SyncFunc != nil {
r1, _, err1 = syscall.RawSyscall(syscall.SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncWrite, err1)
}
r1, _, err1 = syscall.RawSyscall(syscall.SYS_READ, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncRead, err1)
r1, _, err1 = syscall.RawSyscall(syscall.SYS_READ, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncRead, err1)
}
}
// unshare cgroup namespace
@ -414,14 +416,16 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
// Before exec, sync with parent through pipe (configured as close_on_exec)
if !r.Ptrace || r.Seccomp == nil {
{
r1, _, err1 = syscall.RawSyscall(syscall.SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncWrite, err1)
}
if r.SyncFunc != nil {
r1, _, err1 = syscall.RawSyscall(syscall.SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncWrite, err1)
}
r1, _, err1 = syscall.RawSyscall(syscall.SYS_READ, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncRead, err1)
r1, _, err1 = syscall.RawSyscall(syscall.SYS_READ, uintptr(pipe), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
if r1 == 0 || err1 != 0 {
childExitError(pipe, LocSyncRead, err1)
}
}
// unshare cgroup namespace

View File

@ -65,6 +65,7 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error
err error
unshareUser = r.CloneFlags&unix.CLONE_NEWUSER == unix.CLONE_NEWUSER
childErr ChildError
n int
)
// sync with child
@ -86,24 +87,24 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error
syscall.RawSyscall(syscall.SYS_WRITE, uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2)))
}
n, err := readChildErr(p[0], &childErr)
// child returned error code
if (n != int(unsafe.Sizeof(err2)) && n != int(unsafe.Sizeof(childErr))) || childErr.Err != 0 || err != nil {
childErr.Err = handlePipeError(n, childErr.Err)
goto fail
}
// if syncfunc return error, then fail child immediately
// only sync if there is a syncFunc
if r.SyncFunc != nil {
n, err = readChildErr(p[0], &childErr)
// child returned error code
if (n != int(unsafe.Sizeof(err2)) && n != int(unsafe.Sizeof(childErr))) || childErr.Err != 0 || err != nil {
childErr.Err = handlePipeError(n, childErr.Err)
goto fail
}
if err = r.SyncFunc(int(pid)); err != nil {
goto fail
}
// otherwise, ack child (err1 == 0)
syscall.RawSyscall(syscall.SYS_WRITE, uintptr(p[0]), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)))
}
// otherwise, ack child (err1 == 0)
syscall.RawSyscall(syscall.SYS_WRITE, uintptr(p[0]), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)))
// if stopped before execve by signal SIGSTOP or PTRACE_ME, then do not wait until execve
if r.Ptrace || r.StopBeforeSeccomp {
if r.StopBeforeSeccomp || (r.Seccomp != nil && r.Ptrace) {
// let's wait it in another goroutine to avoid SIGPIPE
go func() {
readChildErr(p[0], &childErr)