mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
forkexec: initial support for clone3
This commit is contained in:
parent
f6f057edf9
commit
3d8333e952
@ -185,6 +185,8 @@ type Environment interface {
|
||||
|
||||
- 6.1: `pids.peak` in cgroup v2
|
||||
- 5.19: `memory.peak` in cgroup v2
|
||||
- 5.7: `clone3` with `CLONE_INTO_CGROUP`
|
||||
- 5.3: `clone3`
|
||||
- 4.15: cgroup v2 (also need support in the Linux distribution)
|
||||
- 4.14: SECCOMP_RET_KILL_PROCESS
|
||||
- 4.6: CLONE_NEWCGROUP
|
||||
|
||||
17
pkg/forkexec/clone3_linux.go
Normal file
17
pkg/forkexec/clone3_linux.go
Normal file
@ -0,0 +1,17 @@
|
||||
package forkexec
|
||||
|
||||
// cloneArgs holds arguments for clone3 Linux syscall.
|
||||
// from src/syscall/exec_linux.go:196
|
||||
type cloneArgs struct {
|
||||
flags uint64 // Flags bit mask
|
||||
pidFD uint64 // Where to store PID file descriptor (int *)
|
||||
childTID uint64 // Where to store child TID, in child's memory (pid_t *)
|
||||
parentTID uint64 // Where to store child TID, in parent's memory (pid_t *)
|
||||
exitSignal uint64 // Signal to deliver to parent on child termination
|
||||
stack uint64 // Pointer to lowest byte of stack
|
||||
stackSize uint64 // Size of stack
|
||||
tls uint64 // Location of new TLS
|
||||
setTID uint64 // Pointer to a pid_t array (since Linux 5.5)
|
||||
setTIDSize uint64 // Number of elements in set_tid (since Linux 5.5)
|
||||
cgroup uint64 // File descriptor for target cgroup of child (since Linux 5.7)
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package forkexec
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
@ -11,9 +12,21 @@ import (
|
||||
//
|
||||
//go:norace
|
||||
func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, hostname, domainname, pivotRoot *byte, p [2]int) (r1 uintptr, err1 syscall.Errno) {
|
||||
var (
|
||||
clone3 *cloneArgs
|
||||
)
|
||||
// similar to exec_linux, avoid side effect by shuffling around
|
||||
fd, nextfd := prepareFds(r.Files)
|
||||
|
||||
// use clone3 if cgroupFd specified
|
||||
if r.CgroupFd > 0 {
|
||||
clone3 = &cloneArgs{
|
||||
flags: uint64(r.CloneFlags) | unix.CLONE_INTO_CGROUP,
|
||||
exitSignal: uint64(syscall.SIGCHLD),
|
||||
cgroup: uint64(r.CgroupFd),
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire the fork lock so that no other threads
|
||||
// create new fds that are not yet close-on-exec
|
||||
// before we fork.
|
||||
@ -24,7 +37,16 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
|
||||
beforeFork()
|
||||
|
||||
// UnshareFlags (new namespaces) is activated by clone syscall
|
||||
if clone3 != nil {
|
||||
r1, _, err1 = syscall.RawSyscall6(unix.SYS_CLONE3, uintptr(unsafe.Pointer(clone3)), unsafe.Sizeof(*clone3), 0, 0, 0, 0)
|
||||
} else {
|
||||
if runtime.GOARCH == "s390x" {
|
||||
// On Linux/s390, the first two arguments of clone(2) are swapped.
|
||||
r1, _, err1 = syscall.RawSyscall6(syscall.SYS_CLONE, 0, uintptr(syscall.SIGCHLD)|(r.CloneFlags&UnshareFlags), 0, 0, 0, 0)
|
||||
} else {
|
||||
r1, _, err1 = syscall.RawSyscall6(syscall.SYS_CLONE, uintptr(syscall.SIGCHLD)|(r.CloneFlags&UnshareFlags), 0, 0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
if err1 != 0 || r1 != 0 {
|
||||
// in parent process, immediate return
|
||||
return
|
||||
|
||||
@ -61,6 +61,9 @@ type Runner struct {
|
||||
UIDMappings []syscall.SysProcIDMap
|
||||
GIDMappings []syscall.SysProcIDMap
|
||||
|
||||
// CgroupFd to use when clone3 with CLONE_INTO_CGROUP with kernel >=5.7 and cgroup v2
|
||||
CgroupFd uintptr
|
||||
|
||||
// Credential holds user and group identities to be assumed
|
||||
// by a child process started by StartProcess.
|
||||
Credential *syscall.Credential
|
||||
|
||||
Loading…
Reference in New Issue
Block a user