Backwards compatibility for older kernels >= 3.10

This commit is contained in:
criyle 2021-01-21 00:20:57 -08:00
parent 29aefc839b
commit 464c5ac932
8 changed files with 34 additions and 21 deletions

View File

@ -179,6 +179,17 @@ type Environment interface {
- 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
### ForkExec

View File

@ -25,11 +25,12 @@ import (
"github.com/criyle/go-sandbox/runner/ptrace"
"github.com/criyle/go-sandbox/runner/ptrace/filehandler"
"github.com/criyle/go-sandbox/runner/unshare"
"golang.org/x/sys/unix"
)
var (
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
inputFileName, outputFileName, errorFileName, workPath, runt string
@ -66,6 +67,7 @@ func main() {
flag.BoolVar(&memfile, "memfd", false, "Use memfd as exec file")
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(&nucg, "nucg", false, "don't unshare cgroup")
flag.Parse()
args = flag.Args()
@ -283,12 +285,17 @@ func start() (*runner.Result, error) {
stderr = os.Stderr
}
cloneFlag := forkexec.UnshareFlags
if nucg {
cloneFlag &= ^unix.CLONE_NEWCGROUP
}
b := container.Builder{
Root: root,
Mounts: mb.Mounts,
Stderr: stderr,
CredGenerator: credG,
CloneFlags: forkexec.UnshareFlags,
CloneFlags: uintptr(cloneFlag),
}
m, err := b.Build()

View File

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

View File

@ -129,6 +129,7 @@ func (b *Builder) Build() (Environment, error) {
Cred: b.CredGenerator != nil,
ContainerUID: b.ContainerUID,
ContainerGID: b.ContainerGID,
UnshareCgroup: b.CloneFlags&unix.CLONE_NEWCGROUP == unix.CLONE_NEWCGROUP,
}); err != nil {
c.Destroy()
return nil, err

View File

@ -58,9 +58,10 @@ type containerConfig struct {
ContainerRoot string
Mounts []mount.Mount
Cred bool
ContainerUID int
ContainerGID int
ContainerUID int
ContainerGID int
Cred bool
UnshareCgroup bool
}
// reply is the reply message send back to controller

View File

@ -6,7 +6,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
)
// Cgroup is the combination of sub-cgroups
@ -198,7 +197,7 @@ func copyCgroupPropertyFromParent(path, name string) error {
if err != nil {
return err
}
if len(strings.TrimSpace(string(b))) > 0 {
if len(bytes.TrimSpace(b)) > 0 {
return nil
}
// otherwise copy from parent, first to ensure it is empty by recurssion

View File

@ -157,7 +157,7 @@ func benchmarkRun(r *Runner, b *testing.B) {
for pb.Next() {
pid, err := r.Start()
if err != nil {
b.Fail()
b.Fatal(err)
}
wait4(pid, b)
}

View File

@ -282,14 +282,11 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
// if execfile fd is specified, call fexecve
if r.ExecFile > 0 {
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, r.ExecFile,
uintptr(unsafe.Pointer(&empty[0])),
uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&empty[0])), uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&env[0])), unix.AT_EMPTY_PATH, 0)
} else {
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, uintptr(_AT_FDCWD),
uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&env[0])), 0, 0)
_, _, err1 = syscall.RawSyscall(unix.SYS_EXECVE, uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])), uintptr(unsafe.Pointer(&env[0])))
}
// Fix potential ETXTBSY but with caution (max 50 attempt)
// 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)
if r.ExecFile > 0 {
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, r.ExecFile,
uintptr(unsafe.Pointer(&empty[0])),
uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&empty[0])), uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&env[0])), unix.AT_EMPTY_PATH, 0)
} else {
_, _, err1 = syscall.RawSyscall6(unix.SYS_EXECVEAT, uintptr(_AT_FDCWD),
uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&env[0])), 0, 0)
_, _, err1 = syscall.RawSyscall(unix.SYS_EXECVE, uintptr(unsafe.Pointer(argv0)),
uintptr(unsafe.Pointer(&argv[0])), uintptr(unsafe.Pointer(&env[0])))
}
}