*: fix typos

This commit is contained in:
criyle 2024-02-03 16:19:58 +00:00
parent 231f3cb58f
commit ed93876f8c
19 changed files with 85 additions and 75 deletions

View File

@ -41,8 +41,8 @@ Default file access syscall check:
### linux namespace + cgroup ### linux namespace + cgroup
1. Unshare & bind mount rootfs based on hostfs (elimilated ptrace) 1. Unshare & bind mount rootfs based on hostfs (eliminated ptrace)
2. Use Linux Control Groups to limit & acct CPU & memory (elimilate wait4.rusage) 2. Use Linux Control Groups to limit & acct CPU & memory (eliminated wait4.rusage)
3. Container tech with execveat memfd, sethostname, setdomainname 3. Container tech with execveat memfd, sethostname, setdomainname
## Design ## Design
@ -156,7 +156,7 @@ type Environment interface {
- seccomp: provides seccomp type definition - seccomp: provides seccomp type definition
- libseccomp: provides utility function that wrappers libseccomp - libseccomp: provides utility function that wrappers libseccomp
- forkexec: fork-exec provides mount, unshare, ptrace, seccomp, capset before exec - forkexec: fork-exec provides mount, unshare, ptrace, seccomp, capset before exec
- memfd: read regular file and creates a seaed memfd for its contents - memfd: read regular file and creates a sealed memfd for its contents
- unixsocket: send / recv oob msg from a unix socket - unixsocket: send / recv oob msg from a unix socket
- cgroup: creates cgroup directories and collects resource usage / limits - cgroup: creates cgroup directories and collects resource usage / limits
- mount: provides utility function that wrappers mount syscall - mount: provides utility function that wrappers mount syscall

View File

@ -1,44 +1,52 @@
// Package container provides pre-forked container environment to // Package container provides pre-forked container environment to
// run programs in isolated Linux namespaces. // run programs in isolated Linux namespaces.
// //
// Overview // # Overview
// //
// It creates container within unshared container and communicate // It creates container within unshared container and communicate
// with host process using unix socket with // with host process using unix socket with
// oob for fd / pid and commands encoded by gob. // oob for fd / pid and commands encoded by gob.
// //
// Protocol // # Protocol
// //
// Host to container communication protocol is single threaded and always initiated by // Host to container communication protocol is single threaded and always initiated by
// the host: // the host:
// //
// - ping (alive check): // ## ping (alive check)
// - reply: pong
// //
// - conf (set configuration): // - send: ping
// - reply pong // - reply: pong
// //
// - open (open files in given mode inside container): // ## conf (set configuration)
// - send: []OpenCmd
// - reply: "success", file fds / "error"
// //
// - delete (unlink file / rmdir dir inside container): // - send: conf
// - send: path // - reply:
// - reply: "finished" / "error"
// //
// - reset (clean up container for later use (clear workdir / tmp)): // ## open (open files in given mode inside container):
// - send:
// - reply: "success"
// //
// - execve: (execute file inside container): // - send: []OpenCmd
// - send: argv, env, rLimits, fds // - reply: "success", file fds / "error"
// - reply: //
// - success: "success", pid // ## delete (unlink file / rmdir dir inside container):
// - failed: "failed" //
// - send (success): "init_finished" (as cmd) // - send: path
// - reply: "finished" / send: "kill" (as cmd) // - reply: "finished" / "error"
// - send: "kill" (as cmd) / reply: "finished" //
// - reply: // ## reset (clean up container for later use (clear workdir / tmp)):
//
// - send:
// - reply: "success"
//
// ## execve: (execute file inside container):
//
// - send: argv, env, rLimits, fds
// - reply:
// - success: "success", pid
// - failed: "failed"
// - send (success): "init_finished" (as cmd)
// - reply: "finished" / send: "kill" (as cmd)
// - send: "kill" (as cmd) / reply: "finished"
// - reply:
// //
// Any socket related error will cause the container exit with all process inside container // Any socket related error will cause the container exit with all process inside container
package container package container

View File

@ -8,7 +8,7 @@ import (
"github.com/criyle/go-sandbox/pkg/unixsocket" "github.com/criyle/go-sandbox/pkg/unixsocket"
) )
// 16k buffsize // 16k buffer size
const bufferSize = 16 << 10 const bufferSize = 16 << 10
type socket struct { type socket struct {
@ -17,18 +17,18 @@ type socket struct {
buff []byte buff []byte
decoder *gob.Decoder decoder *gob.Decoder
recvBuff bufferRotater recvBuff bufferRotator
encoder *gob.Encoder encoder *gob.Encoder
sendBuff bytes.Buffer sendBuff bytes.Buffer
} }
// bufferRotater replace the underlying Buffers to avoid allocation // bufferRotator replace the underlying Buffers to avoid allocation
type bufferRotater struct { type bufferRotator struct {
*bytes.Buffer *bytes.Buffer
} }
func (b *bufferRotater) Rotate(buffer *bytes.Buffer) { func (b *bufferRotator) Rotate(buffer *bytes.Buffer) {
b.Buffer = buffer b.Buffer = buffer
} }

6
go.mod
View File

@ -3,9 +3,9 @@ module github.com/criyle/go-sandbox
go 1.21 go 1.21
require ( require (
github.com/elastic/go-seccomp-bpf v1.3.0 github.com/elastic/go-seccomp-bpf v1.4.0
golang.org/x/net v0.18.0 golang.org/x/net v0.20.0
golang.org/x/sys v0.14.0 golang.org/x/sys v0.16.0
) )
require github.com/stretchr/testify v1.8.4 // indirect require github.com/stretchr/testify v1.8.4 // indirect

12
go.sum
View File

@ -1,14 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elastic/go-seccomp-bpf v1.3.0 h1:e6teyX946lvPOnZERSYRrMYmsjxaQcWhoiGTsxLu3Lc= github.com/elastic/go-seccomp-bpf v1.4.0 h1:6y3lYrEHrLH9QzUgOiK8WDqmPaMnnB785WxibCNIOH4=
github.com/elastic/go-seccomp-bpf v1.3.0/go.mod h1:wIMxjTbKpWGQk4CV9WltlG6haB4brjSH/dvAohBPM1I= github.com/elastic/go-seccomp-bpf v1.4.0/go.mod h1:wIMxjTbKpWGQk4CV9WltlG6haB4brjSH/dvAohBPM1I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -36,7 +36,7 @@ type Cgroup interface {
// SetCPUBandwidth sets the cpu bandwidth. Times in ns // SetCPUBandwidth sets the cpu bandwidth. Times in ns
SetCPUBandwidth(quota, period uint64) error SetCPUBandwidth(quota, period uint64) error
// SetCpusetCpus sets the availabile cpu to use (cpuset.cpus). // SetCpusetCpus sets the available cpu to use (cpuset.cpus).
SetCPUSet([]byte) error SetCPUSet([]byte) error
// SetMemoryLimit sets memory.limit_in_bytes // SetMemoryLimit sets memory.limit_in_bytes

View File

@ -1,13 +1,14 @@
// Package cgroup provices builder to create cgroup // Package cgroup provides builder to create cgroup
// under systemd defined mount path (i.e.,sys/fs/cgroup) including v1 and // under systemd defined mount path (i.e.,sys/fs/cgroup) including v1 and
// v2 implementation. // v2 implementation.
// //
// Available cgroup controller: // Available cgroup controller:
// cpu //
// cpuset // cpu
// cpuacct // cpuset
// memory // cpuacct
// pids // memory
// pids
// //
// Current not available: devices, freezer, net_cls, blkio, perf_event, net_prio, huge_tlb, rdma // Current not available: devices, freezer, net_cls, blkio, perf_event, net_prio, huge_tlb, rdma
package cgroup package cgroup

View File

@ -105,7 +105,7 @@ func DetectType() CgroupType {
// if /sys/fs/cgroup is mounted as CGROUPV2 or TMPFS (V1) // if /sys/fs/cgroup is mounted as CGROUPV2 or TMPFS (V1)
var st unix.Statfs_t var st unix.Statfs_t
if err := unix.Statfs(basePath, &st); err != nil { if err := unix.Statfs(basePath, &st); err != nil {
// ignore errors, defalting to CgroupV1 // ignore errors, defaulting to CgroupV1
return CgroupTypeV1 return CgroupTypeV1
} }
if st.Type == unix.CGROUP2_SUPER_MAGIC { if st.Type == unix.CGROUP2_SUPER_MAGIC {

View File

@ -264,7 +264,7 @@ func copyCgroupPropertyFromParent(path, name string) error {
if len(bytes.TrimSpace(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 recursion
if err := copyCgroupPropertyFromParent(filepath.Dir(path), name); err != nil { if err := copyCgroupPropertyFromParent(filepath.Dir(path), name); err != nil {
return err return err
} }

View File

@ -238,7 +238,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
} }
} }
// pivit_root // pivot_root
if pivotRoot != nil { if pivotRoot != nil {
// mkdir("old_root") // mkdir("old_root")
_, _, err1 = syscall.RawSyscall(syscall.SYS_MKDIRAT, uintptr(_AT_FDCWD), uintptr(unsafe.Pointer(&oldRoot[0])), 0755) _, _, err1 = syscall.RawSyscall(syscall.SYS_MKDIRAT, uintptr(_AT_FDCWD), uintptr(unsafe.Pointer(&oldRoot[0])), 0755)
@ -462,7 +462,7 @@ func forkAndExecInChild(r *Runner, argv0 *byte, argv, env []*byte, workdir, host
// 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
// forks but not execve yet (time consuming for setting up mounting points), the forked // forks but not execve yet (time consuming for setting up mounting points), the forked
// process is still holding the fd of the copyied executable fd. However, we don't // process is still holding the fd of the copied executable fd. However, we don't
// want to have different logic to lock the container creation // want to have different logic to lock the container creation
for range [50]struct{}{} { for range [50]struct{}{} {
if err1 != syscall.ETXTBSY { if err1 != syscall.ETXTBSY {

View File

@ -14,7 +14,7 @@ type Runner struct {
// POSIX Resource limit set by set rlimit // POSIX Resource limit set by set rlimit
RLimits []rlimit.RLimit RLimits []rlimit.RLimit
// file disriptors map for new process, from 0 to len - 1 // file descriptors map for new process, from 0 to len - 1
Files []uintptr Files []uintptr
// work path set by chdir(dir) (current working directory for child) // work path set by chdir(dir) (current working directory for child)
@ -24,7 +24,7 @@ type Runner struct {
// sandbox profile defines the sandbox profile for sandbox_init syscall // sandbox profile defines the sandbox profile for sandbox_init syscall
SandboxProfile string SandboxProfile string
// Parent and child process with sync sataus through a socket pair. // Parent and child process with sync status through a socket pair.
// SyncFunc will invoke with the child pid. If SyncFunc return some error, // SyncFunc will invoke with the child pid. If SyncFunc return some error,
// parent will signal child to stop and report the error // parent will signal child to stop and report the error
// SyncFunc is called right before execve, thus it could track cpu more accurately // SyncFunc is called right before execve, thus it could track cpu more accurately

View File

@ -21,7 +21,7 @@ type Runner struct {
// POSIX Resource limit set by set rlimit // POSIX Resource limit set by set rlimit
RLimits []rlimit.RLimit RLimits []rlimit.RLimit
// file disriptors map for new process, from 0 to len - 1 // file descriptors map for new process, from 0 to len - 1
Files []uintptr Files []uintptr
// work path set by chdir(dir) (current working directory for child) // work path set by chdir(dir) (current working directory for child)
@ -65,7 +65,7 @@ type Runner struct {
// by a child process started by StartProcess. // by a child process started by StartProcess.
Credential *syscall.Credential Credential *syscall.Credential
// Parent and child process with sync sataus through a socket pair. // Parent and child process with sync status through a socket pair.
// SyncFunc will invoke with the child pid. If SyncFunc return some error, // SyncFunc will invoke with the child pid. If SyncFunc return some error,
// parent will signal child to stop and report the error // parent will signal child to stop and report the error
// SyncFunc is called right before execve, thus it could track cpu more accurately // SyncFunc is called right before execve, thus it could track cpu more accurately

View File

@ -1,3 +1,3 @@
// Package ptracer provides platfirm independent ptrace pooling loop // Package ptracer provides platform independent ptrace pooling loop
// interface to trace program syscalls on Linux. // interface to trace program syscalls on Linux.
package ptracer package ptracer

View File

@ -8,7 +8,7 @@ type TraceAction int
const ( const (
// TraceAllow does not do anything // TraceAllow does not do anything
TraceAllow TraceAction = iota TraceAllow TraceAction = iota
// TraceBan skippes the syscall and set the return code specified by SetReturnCode // TraceBan skips the syscall and set the return code specified by SetReturnCode
TraceBan TraceBan
// TraceKill referred as dangerous action have been detected // TraceKill referred as dangerous action have been detected
TraceKill TraceKill

View File

@ -34,7 +34,7 @@ func (t *Tracer) trace(c context.Context, pgid int) (result runner.Result) {
cc, cancel := context.WithCancel(c) cc, cancel := context.WithCancel(c)
defer cancel() defer cancel()
// handle cancelation // handle cancellation
go func() { go func() {
<-cc.Done() <-cc.Done()
killAll(pgid) killAll(pgid)

View File

@ -1,33 +1,34 @@
// Package runner provides common interface for program runner together with // Package runner provides common interface for program runner together with
// common types including Result, Limit, Size and Status. // common types including Result, Limit, Size and Status.
// //
// Status // # Status
// //
// Status defines the program running result status including // Status defines the program running result status including
// Normal
// Program Error
// Resource Limit Exceeded (Time / Memory / Output)
// Unauthorized Access (Disallowed Syscall)
// Runtime Error (Signaled / Nonzero Exit Status)
// Program Runner Error
// //
// Size // Normal
// Program Error
// Resource Limit Exceeded (Time / Memory / Output)
// Unauthorized Access (Disallowed Syscall)
// Runtime Error (Signaled / Nonzero Exit Status)
// Program Runner Error
//
// # Size
// //
// Size defines size in bytes, underlying type is uint64 so it // Size defines size in bytes, underlying type is uint64 so it
// is effective to store up to EiB of size // is effective to store up to EiB of size
// //
// Limit // # Limit
// //
// Limit defines Time & Memory restriction on program runner // Limit defines Time & Memory restriction on program runner
// //
// Result // # Result
// //
// Result defines program running result including // Result defines program running result including
// Status, ExitStatus, Detailed Error, Time, Memory, // Status, ExitStatus, Detailed Error, Time, Memory,
// SetupTime and RunningTime (in real clock) // SetupTime and RunningTime (in real clock)
// //
// Runner // # Runner
// //
// General interface to run a program, including a context // General interface to run a program, including a context
// for canclation // for cancellation
package runner package runner

View File

@ -20,7 +20,7 @@ type Runner struct {
// fexecve // fexecve
ExecFile uintptr ExecFile uintptr
// file disriptors for new process, from 0 to len - 1 // file descriptors for new process, from 0 to len - 1
Files []uintptr Files []uintptr
// Resource limit set by set rlimit // Resource limit set by set rlimit
@ -45,7 +45,7 @@ type Runner struct {
SyncFunc func(pid int) error SyncFunc func(pid int) error
} }
// BanRet defines the return value for a syscall ban acction // BanRet defines the return value for a syscall ban action
var BanRet = syscall.EACCES var BanRet = syscall.EACCES
// Handler defines the action when a file access encountered // Handler defines the action when a file access encountered

View File

@ -6,7 +6,7 @@ import (
) )
// Size stores number of byte for the object. E.g. Memory. // Size stores number of byte for the object. E.g. Memory.
// Maximun size is bounded by 64-bit limit // Maximum size is bounded by 64-bit limit
type Size uint64 type Size uint64
// String stringer interface for print // String stringer interface for print

View File

@ -19,7 +19,7 @@ type Runner struct {
// workdir is the current dir after unshare mount namespaces // workdir is the current dir after unshare mount namespaces
WorkDir string WorkDir string
// file disriptors for new process, from 0 to len - 1 // file descriptors for new process, from 0 to len - 1
Files []uintptr Files []uintptr
// Resource limit set by set rlimit // Resource limit set by set rlimit