mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
Backwards compatibility for older kernels >= 3.10
This commit is contained in:
parent
29aefc839b
commit
464c5ac932
11
README.md
11
README.md
@ -179,6 +179,17 @@ type Environment interface {
|
|||||||
|
|
||||||
- config/config.go: all configs toward running specs (similar to UOJ)
|
- config/config.go: all configs toward running specs (similar to UOJ)
|
||||||
|
|
||||||
|
## Kernel Versions
|
||||||
|
|
||||||
|
- 4.14: SECCOMP_RET_KILL_PROCESS
|
||||||
|
- 4.6: CLONE_NEWCGROUP
|
||||||
|
- 3.19: execveat()
|
||||||
|
- 3.17: seccomp, memfd_create
|
||||||
|
- 3.10: CentOS 7
|
||||||
|
- 3.8: CLONE_NEWUSER without CAP_SYS_ADMIN, CAP_SETUID, CAP_SETGID
|
||||||
|
- 3.5: prctl(PR_SET_NO_NEW_PRIVS)
|
||||||
|
- 2.6.36: prlimit64
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
### ForkExec
|
### ForkExec
|
||||||
|
|||||||
@ -25,11 +25,12 @@ import (
|
|||||||
"github.com/criyle/go-sandbox/runner/ptrace"
|
"github.com/criyle/go-sandbox/runner/ptrace"
|
||||||
"github.com/criyle/go-sandbox/runner/ptrace/filehandler"
|
"github.com/criyle/go-sandbox/runner/ptrace/filehandler"
|
||||||
"github.com/criyle/go-sandbox/runner/unshare"
|
"github.com/criyle/go-sandbox/runner/unshare"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
addReadable, addWritable, addRawReadable, addRawWritable arrayFlags
|
addReadable, addWritable, addRawReadable, addRawWritable arrayFlags
|
||||||
allowProc, unsafe, showDetails, useCGroup, memfile, cred bool
|
allowProc, unsafe, showDetails, useCGroup, memfile, cred, nucg bool
|
||||||
timeLimit, realTimeLimit, memoryLimit, outputLimit, stackLimit uint64
|
timeLimit, realTimeLimit, memoryLimit, outputLimit, stackLimit uint64
|
||||||
inputFileName, outputFileName, errorFileName, workPath, runt string
|
inputFileName, outputFileName, errorFileName, workPath, runt string
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ func main() {
|
|||||||
flag.BoolVar(&memfile, "memfd", false, "Use memfd as exec file")
|
flag.BoolVar(&memfile, "memfd", false, "Use memfd as exec file")
|
||||||
flag.StringVar(&runt, "runner", "ptrace", "Runner for the program (ptrace, ns, container)")
|
flag.StringVar(&runt, "runner", "ptrace", "Runner for the program (ptrace, ns, container)")
|
||||||
flag.BoolVar(&cred, "cred", false, "Generate credential for containers (uid=10000)")
|
flag.BoolVar(&cred, "cred", false, "Generate credential for containers (uid=10000)")
|
||||||
|
flag.BoolVar(&nucg, "nucg", false, "don't unshare cgroup")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
args = flag.Args()
|
args = flag.Args()
|
||||||
@ -283,12 +285,17 @@ func start() (*runner.Result, error) {
|
|||||||
stderr = os.Stderr
|
stderr = os.Stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cloneFlag := forkexec.UnshareFlags
|
||||||
|
if nucg {
|
||||||
|
cloneFlag &= ^unix.CLONE_NEWCGROUP
|
||||||
|
}
|
||||||
|
|
||||||
b := container.Builder{
|
b := container.Builder{
|
||||||
Root: root,
|
Root: root,
|
||||||
Mounts: mb.Mounts,
|
Mounts: mb.Mounts,
|
||||||
Stderr: stderr,
|
Stderr: stderr,
|
||||||
CredGenerator: credG,
|
CredGenerator: credG,
|
||||||
CloneFlags: forkexec.UnshareFlags,
|
CloneFlags: uintptr(cloneFlag),
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := b.Build()
|
m, err := b.Build()
|
||||||
|
|||||||
@ -84,7 +84,7 @@ func (c *containerServer) handleExecve(cmd *execCmd, msg *unixsocket.Msg) error
|
|||||||
CTTY: cmd.CTTY,
|
CTTY: cmd.CTTY,
|
||||||
Seccomp: seccomp,
|
Seccomp: seccomp,
|
||||||
|
|
||||||
UnshareCgroupAfterSync: true,
|
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()
|
||||||
|
|||||||
@ -129,6 +129,7 @@ func (b *Builder) Build() (Environment, error) {
|
|||||||
Cred: b.CredGenerator != nil,
|
Cred: b.CredGenerator != nil,
|
||||||
ContainerUID: b.ContainerUID,
|
ContainerUID: b.ContainerUID,
|
||||||
ContainerGID: b.ContainerGID,
|
ContainerGID: b.ContainerGID,
|
||||||
|
UnshareCgroup: b.CloneFlags&unix.CLONE_NEWCGROUP == unix.CLONE_NEWCGROUP,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
c.Destroy()
|
c.Destroy()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -58,9 +58,10 @@ type containerConfig struct {
|
|||||||
ContainerRoot string
|
ContainerRoot string
|
||||||
Mounts []mount.Mount
|
Mounts []mount.Mount
|
||||||
|
|
||||||
Cred bool
|
ContainerUID int
|
||||||
ContainerUID int
|
ContainerGID int
|
||||||
ContainerGID int
|
Cred bool
|
||||||
|
UnshareCgroup bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// reply is the reply message send back to controller
|
// reply is the reply message send back to controller
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cgroup is the combination of sub-cgroups
|
// Cgroup is the combination of sub-cgroups
|
||||||
@ -198,7 +197,7 @@ func copyCgroupPropertyFromParent(path, name string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(strings.TrimSpace(string(b))) > 0 {
|
if len(bytes.TrimSpace(b)) > 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// otherwise copy from parent, first to ensure it is empty by recurssion
|
// otherwise copy from parent, first to ensure it is empty by recurssion
|
||||||
|
|||||||
@ -157,7 +157,7 @@ func benchmarkRun(r *Runner, b *testing.B) {
|
|||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
pid, err := r.Start()
|
pid, err := r.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fail()
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
wait4(pid, b)
|
wait4(pid, b)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -282,14 +282,11 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
|
|||||||
// if execfile fd is specified, call fexecve
|
// if execfile fd is specified, call fexecve
|
||||||
if r.ExecFile > 0 {
|
if r.ExecFile > 0 {
|
||||||
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, r.ExecFile,
|
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, r.ExecFile,
|
||||||
uintptr(unsafe.Pointer(&empty[0])),
|
uintptr(unsafe.Pointer(&empty[0])), uintptr(unsafe.Pointer(&argv[0])),
|
||||||
uintptr(unsafe.Pointer(&argv[0])),
|
|
||||||
uintptr(unsafe.Pointer(&env[0])), unix.AT_EMPTY_PATH, 0)
|
uintptr(unsafe.Pointer(&env[0])), unix.AT_EMPTY_PATH, 0)
|
||||||
} else {
|
} else {
|
||||||
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, uintptr(_AT_FDCWD),
|
_, _, err1 = syscall.RawSyscall(unix.SYS_EXECVE, uintptr(unsafe.Pointer(argv0)),
|
||||||
uintptr(unsafe.Pointer(argv0)),
|
uintptr(unsafe.Pointer(&argv[0])), uintptr(unsafe.Pointer(&env[0])))
|
||||||
uintptr(unsafe.Pointer(&argv[0])),
|
|
||||||
uintptr(unsafe.Pointer(&env[0])), 0, 0)
|
|
||||||
}
|
}
|
||||||
// Fix potential ETXTBSY but with caution (max 50 attempt)
|
// Fix potential ETXTBSY but with caution (max 50 attempt)
|
||||||
// The ETXTBSY happens when we copy the executable into container, another goroutine
|
// The ETXTBSY happens when we copy the executable into container, another goroutine
|
||||||
@ -304,14 +301,11 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
|
|||||||
syscall.RawSyscall(unix.SYS_NANOSLEEP, uintptr(unsafe.Pointer(&etxtbsyRetryInterval)), 0, 0)
|
syscall.RawSyscall(unix.SYS_NANOSLEEP, uintptr(unsafe.Pointer(&etxtbsyRetryInterval)), 0, 0)
|
||||||
if r.ExecFile > 0 {
|
if r.ExecFile > 0 {
|
||||||
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, r.ExecFile,
|
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, r.ExecFile,
|
||||||
uintptr(unsafe.Pointer(&empty[0])),
|
uintptr(unsafe.Pointer(&empty[0])), uintptr(unsafe.Pointer(&argv[0])),
|
||||||
uintptr(unsafe.Pointer(&argv[0])),
|
|
||||||
uintptr(unsafe.Pointer(&env[0])), unix.AT_EMPTY_PATH, 0)
|
uintptr(unsafe.Pointer(&env[0])), unix.AT_EMPTY_PATH, 0)
|
||||||
} else {
|
} else {
|
||||||
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, uintptr(_AT_FDCWD),
|
_, _, err1 = syscall.RawSyscall(unix.SYS_EXECVE, uintptr(unsafe.Pointer(argv0)),
|
||||||
uintptr(unsafe.Pointer(argv0)),
|
uintptr(unsafe.Pointer(&argv[0])), uintptr(unsafe.Pointer(&env[0])))
|
||||||
uintptr(unsafe.Pointer(&argv[0])),
|
|
||||||
uintptr(unsafe.Pointer(&env[0])), 0, 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user