mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
normalize naming schema
This commit is contained in:
parent
ebab7514d1
commit
7b06ce65ac
16
README.md
16
README.md
@ -54,21 +54,21 @@ Default file access syscall check:
|
||||
|
||||
## Packages
|
||||
|
||||
- tracer: ptrace tracer and provides syscall trap filter context
|
||||
- deamon: creates pre-forked container to run programs inside
|
||||
- runprogram: wrapper to call forkexec and trecer
|
||||
- rununshared: wrapper to call forkexec and unshared namespaces
|
||||
- runconfig: defines arch & language specified trace condition for seccomp and ptrace
|
||||
- types: general runtime specs
|
||||
- specs: provides general res / result data structures
|
||||
- runner: interface to run program
|
||||
- config: defines arch & language specified trace condition for seccomp and ptrace
|
||||
- ptrace: wrapper to call forkexec and ptracer
|
||||
- unshare: wrapper to call forkexec and unshared namespaces
|
||||
- ptracer: ptrace tracer and provides syscall trap filter context
|
||||
- types: provides general res / result data structures
|
||||
|
||||
## Executable
|
||||
|
||||
- run_program: safely run program by unshare / ptrace / pre-forked containers
|
||||
- runprog: safely run program by unshare / ptrace / pre-forked containers
|
||||
|
||||
## Configurations
|
||||
|
||||
- run_program/config.go: all configs toward running specs
|
||||
- run/config/config.go: all configs toward running specs
|
||||
|
||||
## Benchmarks (docker desktop amd64 / native arm64)
|
||||
|
||||
|
||||
@ -12,10 +12,11 @@ import (
|
||||
"github.com/criyle/go-sandbox/pkg/cgroup"
|
||||
"github.com/criyle/go-sandbox/pkg/memfd"
|
||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||
"github.com/criyle/go-sandbox/runconfig"
|
||||
"github.com/criyle/go-sandbox/runprogram"
|
||||
"github.com/criyle/go-sandbox/rununshared"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/runner"
|
||||
"github.com/criyle/go-sandbox/runner/config"
|
||||
"github.com/criyle/go-sandbox/runner/ptrace"
|
||||
"github.com/criyle/go-sandbox/runner/unshare"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -33,11 +34,6 @@ var (
|
||||
args []string
|
||||
)
|
||||
|
||||
// Runner can be ptraced runner or namespaced runner
|
||||
type Runner interface {
|
||||
Start(<-chan struct{}) (<-chan specs.TraceResult, error)
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] <args>\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
@ -104,28 +100,28 @@ func main() {
|
||||
defer f.Close()
|
||||
}
|
||||
|
||||
rt, err := run()
|
||||
rt, err := start()
|
||||
if rt == nil {
|
||||
rt = &specs.TraceResult{
|
||||
TraceStatus: specs.TraceCodeFatal,
|
||||
rt = &types.Result{
|
||||
Status: types.StatusFatal,
|
||||
}
|
||||
}
|
||||
if err == nil && rt.TraceStatus != specs.TraceCodeNormal {
|
||||
err = rt.TraceStatus
|
||||
if err == nil && rt.Status != types.StatusNormal {
|
||||
err = rt.Status
|
||||
}
|
||||
if err != nil {
|
||||
debug(err)
|
||||
c, ok := err.(specs.TraceCode)
|
||||
c, ok := err.(types.Status)
|
||||
if !ok {
|
||||
c = specs.TraceCodeFatal
|
||||
c = types.StatusFatal
|
||||
}
|
||||
// Handle fatal error from trace
|
||||
fmt.Fprintf(f, "%d %d %d %d\n", int(c), rt.UserTime, rt.UserMem, rt.ExitCode)
|
||||
if c == specs.TraceCodeFatal {
|
||||
fmt.Fprintf(f, "%d %d %d %d\n", int(c), rt.UserTime, rt.UserMem, rt.ExitStatus)
|
||||
if c == types.StatusFatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(f, "%d %d %d %d\n", 0, rt.UserTime, rt.UserMem, rt.ExitCode)
|
||||
fmt.Fprintf(f, "%d %d %d %d\n", 0, rt.UserTime, rt.UserMem, rt.ExitStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,22 +130,22 @@ type deamonRunner struct {
|
||||
*deamon.ExecveParam
|
||||
}
|
||||
|
||||
func (r *deamonRunner) Start(done <-chan struct{}) (<-chan specs.TraceResult, error) {
|
||||
func (r *deamonRunner) Start(done <-chan struct{}) (<-chan types.Result, error) {
|
||||
return r.Master.Execve(done, r.ExecveParam)
|
||||
}
|
||||
|
||||
func run() (*specs.TraceResult, error) {
|
||||
func start() (*types.Result, error) {
|
||||
var (
|
||||
runner Runner
|
||||
runner runner.Runner
|
||||
cg *cgroup.CGroup
|
||||
err error
|
||||
execFile uintptr
|
||||
rt specs.TraceResult
|
||||
rt types.Result
|
||||
)
|
||||
|
||||
addRead := runconfig.GetExtraSet(addReadable, addRawReadable)
|
||||
addWrite := runconfig.GetExtraSet(addWritable, addRawWritable)
|
||||
h := runconfig.GetConf(pType, workPath, args, addRead, addWrite, allowProc, showDetails)
|
||||
addRead := config.GetExtraSet(addReadable, addRawReadable)
|
||||
addWrite := config.GetExtraSet(addWritable, addRawWritable)
|
||||
h := config.GetConf(pType, workPath, args, addRead, addWrite, allowProc, showDetails)
|
||||
|
||||
if useCGroup {
|
||||
cg, err = cgroup.NewCGroup("run_program")
|
||||
@ -245,21 +241,20 @@ func run() (*specs.TraceResult, error) {
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
runner = &rununshared.RunUnshared{
|
||||
runner = &unshare.Runner{
|
||||
Args: h.Args,
|
||||
Env: []string{pathEnv},
|
||||
ExecFile: execFile,
|
||||
WorkDir: "/w",
|
||||
Files: fds,
|
||||
RLimits: rlims,
|
||||
ResLimits: specs.ResLimit{
|
||||
ResLimits: types.Limit{
|
||||
TimeLimit: timeLimit * 1e3,
|
||||
RealTimeLimit: realTimeLimit * 1e3,
|
||||
MemoryLimit: memoryLimit << 10,
|
||||
},
|
||||
SyscallAllowed: h.SyscallAllow,
|
||||
Root: root,
|
||||
Mounts: rununshared.GetDefaultMounts(root, []rununshared.AddBind{
|
||||
Mounts: unshare.GetDefaultMounts(root, []unshare.AddBind{
|
||||
{
|
||||
Source: workPath,
|
||||
Target: "w",
|
||||
@ -271,15 +266,14 @@ func run() (*specs.TraceResult, error) {
|
||||
DomainName: "run_program",
|
||||
}
|
||||
} else {
|
||||
runner = &runprogram.RunProgram{
|
||||
runner = &ptrace.Runner{
|
||||
Args: h.Args,
|
||||
Env: []string{pathEnv},
|
||||
ExecFile: execFile,
|
||||
WorkDir: workPath,
|
||||
RLimits: rlims,
|
||||
TraceLimit: specs.ResLimit{
|
||||
TraceLimit: types.Limit{
|
||||
TimeLimit: timeLimit * 1e3,
|
||||
RealTimeLimit: realTimeLimit * 1e3,
|
||||
MemoryLimit: memoryLimit << 10,
|
||||
},
|
||||
Files: fds,
|
||||
@ -309,7 +303,7 @@ func run() (*specs.TraceResult, error) {
|
||||
case <-sig:
|
||||
close(done)
|
||||
rt = <-s
|
||||
rt.TraceStatus = specs.TraceCodeFatal
|
||||
rt.Status = types.StatusFatal
|
||||
|
||||
case <-tC:
|
||||
close(done)
|
||||
@ -320,8 +314,8 @@ func run() (*specs.TraceResult, error) {
|
||||
eTime := time.Now()
|
||||
|
||||
if rt.SetUpTime == 0 {
|
||||
rt.SetUpTime = int64(rTime.Sub(sTime))
|
||||
rt.RunningTime = int64(eTime.Sub(rTime))
|
||||
rt.SetUpTime = rTime.Sub(sTime)
|
||||
rt.RunningTime = eTime.Sub(rTime)
|
||||
}
|
||||
|
||||
debug("results:", rt, err)
|
||||
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/forkexec"
|
||||
"github.com/criyle/go-sandbox/pkg/unixsocket"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// ContainerInit is called for container init process
|
||||
@ -231,19 +231,19 @@ loop:
|
||||
break loop
|
||||
|
||||
case wstatus.Signaled():
|
||||
var status specs.TraceCode
|
||||
var status types.Status
|
||||
switch wstatus.Signal() {
|
||||
// kill signal treats as TLE
|
||||
case syscall.SIGXCPU, syscall.SIGKILL:
|
||||
status = specs.TraceCodeTLE
|
||||
status = types.StatusTLE
|
||||
case syscall.SIGXFSZ:
|
||||
status = specs.TraceCodeOLE
|
||||
status = types.StatusOLE
|
||||
case syscall.SIGSYS:
|
||||
status = specs.TraceCodeBan
|
||||
status = types.StatusBan
|
||||
default:
|
||||
status = specs.TraceCodeRE
|
||||
status = types.StatusRE
|
||||
}
|
||||
reply := Reply{TraceStatus: status}
|
||||
reply := Reply{Status: status}
|
||||
sendReply(s, &reply, nil)
|
||||
break loop
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ Any socket related error will cause the deamon exit (with all process inside con
|
||||
|
||||
import (
|
||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// Cmd is the control message send into deamon
|
||||
@ -52,5 +52,5 @@ type Cmd struct {
|
||||
type Reply struct {
|
||||
Error string // empty if no error
|
||||
ExitStatus int // waitpid exit status
|
||||
TraceStatus specs.TraceCode // TraceCode
|
||||
Status types.Status // return status
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/pkg/unixsocket"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// ExecveParam is parameters to run process inside container
|
||||
@ -23,7 +23,7 @@ type ExecveParam struct {
|
||||
|
||||
// Execve runs process inside container
|
||||
// accepts done for cancelation
|
||||
func (m *Master) Execve(done <-chan struct{}, param *ExecveParam) (<-chan specs.TraceResult, error) {
|
||||
func (m *Master) Execve(done <-chan struct{}, param *ExecveParam) (<-chan types.Result, error) {
|
||||
var files []int
|
||||
if param.ExecFile > 0 {
|
||||
files = append(files, int(param.ExecFile))
|
||||
@ -60,16 +60,16 @@ func (m *Master) Execve(done <-chan struct{}, param *ExecveParam) (<-chan specs.
|
||||
return nil, fmt.Errorf("execve: ok failed(%v)", err)
|
||||
}
|
||||
// make sure goroutine not leaked (blocked) even if result is not consumed
|
||||
wait := make(chan specs.TraceResult, 1)
|
||||
wait := make(chan types.Result, 1)
|
||||
waitDone := make(chan struct{})
|
||||
// Wait
|
||||
go func() {
|
||||
defer close(wait)
|
||||
reply2, _, _ := m.recvReply()
|
||||
close(waitDone)
|
||||
wait <- specs.TraceResult{
|
||||
ExitCode: reply2.ExitStatus,
|
||||
TraceStatus: reply2.TraceStatus,
|
||||
wait <- types.Result{
|
||||
ExitStatus: reply2.ExitStatus,
|
||||
Status: reply2.Status,
|
||||
}
|
||||
// done signal (should recv after kill)
|
||||
m.recvReply()
|
||||
|
||||
2
go.mod
2
go.mod
@ -4,5 +4,5 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/seccomp/libseccomp-golang v0.9.1
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456
|
||||
golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad
|
||||
)
|
||||
|
||||
4
go.sum
4
go.sum
@ -1,4 +1,4 @@
|
||||
github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad h1:cCejgArrk10gX6kFqjWeLwXD7aVMqWoRpyUCaaJSggc=
|
||||
golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||
)
|
||||
|
||||
// Runner is the RunProgramConfig including the exec path, argv
|
||||
// Runner is the runptraceConfig including the exec path, argv
|
||||
// and resource limits. It creates tracee for ptrace-based tracer.
|
||||
// It can also create unshared process in another namespace
|
||||
type Runner struct {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"os"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
unix "golang.org/x/sys/unix"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
@ -1,4 +1,4 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
// TraceAction defines the action returned by TraceHandle
|
||||
type TraceAction int
|
||||
@ -1,11 +1,12 @@
|
||||
package tracer
|
||||
package ptracer
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
unix "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// MsgDisallow, Msghandle defines the action needed when traped by
|
||||
@ -16,9 +17,9 @@ const (
|
||||
)
|
||||
|
||||
// Trace starts new goroutine and trace runner with ptrace
|
||||
func Trace(done <-chan struct{}, handler Handler, runner Runner, limits specs.ResLimit) (<-chan specs.TraceResult, error) {
|
||||
func Trace(done <-chan struct{}, handler Handler, runner Runner, limits types.Limit) (<-chan types.Result, error) {
|
||||
var err error
|
||||
result := make(chan specs.TraceResult, 1)
|
||||
result := make(chan types.Result, 1)
|
||||
start := make(chan struct{})
|
||||
finish := make(chan struct{})
|
||||
|
||||
@ -40,7 +41,7 @@ func Trace(done <-chan struct{}, handler Handler, runner Runner, limits specs.Re
|
||||
// TraceRun start and traces all child process by runner in the calling goroutine
|
||||
// parameter done used to cancel work, start is used notify child starts
|
||||
func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
handler Handler, runner Runner, limits specs.ResLimit) (result specs.TraceResult, err error) {
|
||||
handler Handler, runner Runner, limits types.Limit) (result types.Result, err error) {
|
||||
var (
|
||||
wstatus unix.WaitStatus // wait4 wait status
|
||||
rusage unix.Rusage // wait4 rusage
|
||||
@ -61,7 +62,7 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
handler.Debug("tracer started: ", pgid, err)
|
||||
if err != nil {
|
||||
handler.Debug("start tracee failed: ", err)
|
||||
result.TraceStatus = specs.TraceCodeRE
|
||||
result.Status = types.StatusRE
|
||||
return result, err
|
||||
}
|
||||
|
||||
@ -83,17 +84,17 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
// also ensure processes was well terminated
|
||||
defer func() {
|
||||
if tle {
|
||||
err = specs.TraceCodeTLE
|
||||
err = types.StatusTLE
|
||||
}
|
||||
if err2 := recover(); err2 != nil {
|
||||
handler.Debug(err2)
|
||||
err = specs.TraceCodeFatal
|
||||
err = types.StatusFatal
|
||||
}
|
||||
// kill all tracee upon return
|
||||
killAll(pgid)
|
||||
collectZombie(pgid)
|
||||
result.SetUpTime = fTime.Sub(sTime).Nanoseconds()
|
||||
result.RunningTime = time.Since(fTime).Nanoseconds()
|
||||
result.SetUpTime = fTime.Sub(sTime)
|
||||
result.RunningTime = time.Since(fTime)
|
||||
}()
|
||||
|
||||
// trace unixs
|
||||
@ -107,11 +108,11 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
}
|
||||
if err != nil {
|
||||
handler.Debug("wait4 failed: ", err)
|
||||
return result, specs.TraceCodeFatal
|
||||
return result, types.StatusFatal
|
||||
}
|
||||
handler.Debug("------ ", pid, " ------")
|
||||
|
||||
status := specs.TraceCodeNormal
|
||||
status := types.StatusNormal
|
||||
if pid == pgid {
|
||||
// update resource usage and check against limits
|
||||
userTime := uint64(rusage.Utime.Sec*1e3 + rusage.Utime.Usec/1e3) // ms
|
||||
@ -119,17 +120,17 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
|
||||
// check tle / mle
|
||||
if userTime > limits.TimeLimit {
|
||||
status = specs.TraceCodeTLE
|
||||
status = types.StatusTLE
|
||||
}
|
||||
if userMem > limits.MemoryLimit {
|
||||
status = specs.TraceCodeMLE
|
||||
status = types.StatusMLE
|
||||
}
|
||||
result = specs.TraceResult{
|
||||
result = types.Result{
|
||||
Status: status,
|
||||
UserTime: userTime,
|
||||
UserMem: userMem,
|
||||
TraceStatus: status,
|
||||
}
|
||||
if status != specs.TraceCodeNormal {
|
||||
if status != types.StatusNormal {
|
||||
return result, status
|
||||
}
|
||||
}
|
||||
@ -141,11 +142,11 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
handler.Debug("process exited: ", pid, wstatus.ExitStatus())
|
||||
if pid == pgid {
|
||||
if execved {
|
||||
result.ExitCode = wstatus.ExitStatus()
|
||||
result.ExitStatus = wstatus.ExitStatus()
|
||||
return result, nil
|
||||
}
|
||||
result.TraceStatus = specs.TraceCodeFatal
|
||||
return result, specs.TraceCodeFatal
|
||||
result.Status = types.StatusFatal
|
||||
return result, types.StatusFatal
|
||||
}
|
||||
|
||||
case wstatus.Signaled():
|
||||
@ -155,15 +156,15 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
delete(traced, pid)
|
||||
switch sig {
|
||||
case unix.SIGXCPU, unix.SIGKILL:
|
||||
status = specs.TraceCodeTLE
|
||||
status = types.StatusTLE
|
||||
case unix.SIGXFSZ:
|
||||
status = specs.TraceCodeOLE
|
||||
status = types.StatusOLE
|
||||
case unix.SIGSYS:
|
||||
status = specs.TraceCodeBan
|
||||
status = types.StatusBan
|
||||
default:
|
||||
status = specs.TraceCodeRE
|
||||
status = types.StatusRE
|
||||
}
|
||||
result.TraceStatus = status
|
||||
result.Status = status
|
||||
return result, status
|
||||
}
|
||||
unix.PtraceCont(pid, int(sig))
|
||||
@ -176,7 +177,7 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
// Ptrace set option valid if the tracee is stopped
|
||||
err = setPtraceOption(pid)
|
||||
if err != nil {
|
||||
result.TraceStatus = specs.TraceCodeFatal
|
||||
result.Status = types.StatusFatal
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
@ -189,7 +190,7 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
// give the customized handle for syscall
|
||||
err := handleTrap(handler, pid)
|
||||
if err != nil {
|
||||
result.TraceStatus = specs.TraceCodeBan
|
||||
result.Status = types.StatusBan
|
||||
return result, err
|
||||
}
|
||||
} else {
|
||||
@ -218,12 +219,12 @@ func TraceRun(done <-chan struct{}, start chan<- struct{},
|
||||
// check if cpu rlimit hit
|
||||
switch stopSig {
|
||||
case unix.SIGXCPU:
|
||||
status = specs.TraceCodeTLE
|
||||
status = types.StatusTLE
|
||||
case unix.SIGXFSZ:
|
||||
status = specs.TraceCodeOLE
|
||||
status = types.StatusOLE
|
||||
}
|
||||
if status != specs.TraceCodeNormal {
|
||||
result.TraceStatus = status
|
||||
if status != types.StatusNormal {
|
||||
result.Status = status
|
||||
return result, status
|
||||
}
|
||||
// Likely encountered SIGSEGV (segment violation)
|
||||
@ -272,7 +273,7 @@ func handleTrap(handler Handler, pid int) error {
|
||||
return ctx.skipSyscall()
|
||||
|
||||
case TraceKill:
|
||||
return specs.TraceCodeBan
|
||||
return types.StatusBan
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// This file includes configs for the run program settings
|
||||
|
||||
@ -105,7 +105,7 @@ var (
|
||||
|
||||
// config for different type of program
|
||||
// workpath and arg0 have additional read / stat permission
|
||||
runprogramConfig = map[string]ProgramConfig{
|
||||
runptraceConfig = map[string]ProgramConfig{
|
||||
"python2.7": ProgramConfig{
|
||||
Syscall: SyscallConfig{
|
||||
ExtraAllow: []string{
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// This file includes configs for the run program settings
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// This file includes configs for the run program settings
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// This file includes configs for the run program settings
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// GetConf return file access check set, syscall counter, allow and traced syscall arrays and new args
|
||||
func GetConf(pType, workPath string, args, addRead, addWrite []string, allowProc, showDetails bool) *Handler {
|
||||
@ -18,7 +18,7 @@ func GetConf(pType, workPath string, args, addRead, addWrite []string, allowProc
|
||||
fs.Readable.AddRange(addRead, workPath)
|
||||
fs.Writable.AddRange(addWrite, workPath)
|
||||
|
||||
if c, o := runprogramConfig[pType]; o {
|
||||
if c, o := runptraceConfig[pType]; o {
|
||||
allow = append(allow, c.Syscall.ExtraAllow...)
|
||||
trace = append(trace, c.Syscall.ExtraBan...)
|
||||
sc.AddRange(c.Syscall.ExtraCount)
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// ProgramConfig defines the extra config apply to program type
|
||||
type ProgramConfig struct {
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
@ -1,13 +1,13 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/criyle/go-sandbox/runprogram"
|
||||
"github.com/criyle/go-sandbox/runner/ptrace"
|
||||
)
|
||||
|
||||
// Handler defines file access restricted handler to call the runprogram
|
||||
// Handler defines file access restricted handler to call the ptrace
|
||||
// safe runner
|
||||
type Handler struct {
|
||||
SyscallAllow, SyscallTrace, Args []string
|
||||
@ -17,51 +17,51 @@ type Handler struct {
|
||||
}
|
||||
|
||||
// CheckRead checks whether the file have read permission
|
||||
func (h *Handler) CheckRead(fn string) runprogram.TraceAction {
|
||||
func (h *Handler) CheckRead(fn string) ptrace.TraceAction {
|
||||
if !h.FileSet.IsReadableFile(fn) {
|
||||
return h.onDgsFileDetect(fn)
|
||||
}
|
||||
return runprogram.TraceAllow
|
||||
return ptrace.TraceAllow
|
||||
}
|
||||
|
||||
// CheckWrite checks whether the file have write permission
|
||||
func (h *Handler) CheckWrite(fn string) runprogram.TraceAction {
|
||||
func (h *Handler) CheckWrite(fn string) ptrace.TraceAction {
|
||||
if !h.FileSet.IsWritableFile(fn) {
|
||||
return h.onDgsFileDetect(fn)
|
||||
}
|
||||
return runprogram.TraceAllow
|
||||
return ptrace.TraceAllow
|
||||
}
|
||||
|
||||
// CheckStat checks whether the file have stat permission
|
||||
func (h *Handler) CheckStat(fn string) runprogram.TraceAction {
|
||||
func (h *Handler) CheckStat(fn string) ptrace.TraceAction {
|
||||
if !h.FileSet.IsStatableFile(fn) {
|
||||
return h.onDgsFileDetect(fn)
|
||||
}
|
||||
return runprogram.TraceAllow
|
||||
return ptrace.TraceAllow
|
||||
}
|
||||
|
||||
// CheckSyscall checks syscalls other than allowed and traced agianst the
|
||||
// SyscallCounter
|
||||
func (h *Handler) CheckSyscall(syscallName string) runprogram.TraceAction {
|
||||
func (h *Handler) CheckSyscall(syscallName string) ptrace.TraceAction {
|
||||
// if it is traced, then try to count syscall
|
||||
if inside, allow := h.SyscallCounter.Check(syscallName); inside {
|
||||
if allow {
|
||||
return runprogram.TraceAllow
|
||||
return ptrace.TraceAllow
|
||||
}
|
||||
return runprogram.TraceKill
|
||||
return ptrace.TraceKill
|
||||
}
|
||||
// if it is traced but not counted, it should be soft banned
|
||||
return runprogram.TraceBan
|
||||
return ptrace.TraceBan
|
||||
}
|
||||
|
||||
// onDgsFileDetect soft ban file if in soft ban set
|
||||
// otherwise stops the trace process
|
||||
func (h *Handler) onDgsFileDetect(name string) runprogram.TraceAction {
|
||||
func (h *Handler) onDgsFileDetect(name string) ptrace.TraceAction {
|
||||
if h.FileSet.IsSoftBanFile(name) {
|
||||
return runprogram.TraceBan
|
||||
return ptrace.TraceBan
|
||||
}
|
||||
h.print("Dangerous fileopen: ", name)
|
||||
return runprogram.TraceKill
|
||||
return ptrace.TraceKill
|
||||
}
|
||||
|
||||
// print is used to print debug information
|
||||
@ -1,4 +1,4 @@
|
||||
package runconfig
|
||||
package config
|
||||
|
||||
// SyscallCounter defines a count-down for each each syscall occurs
|
||||
type SyscallCounter map[string]int
|
||||
@ -1,4 +1,4 @@
|
||||
package runprogram
|
||||
package ptrace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -8,8 +8,8 @@ import (
|
||||
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
|
||||
"github.com/criyle/go-sandbox/tracer"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/ptracer"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
type tracerHandler struct {
|
||||
@ -23,11 +23,11 @@ func (h *tracerHandler) Debug(v ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *tracerHandler) getString(ctx *tracer.Context, addr uint) string {
|
||||
func (h *tracerHandler) getString(ctx *ptracer.Context, addr uint) string {
|
||||
return absPath(ctx.Pid, ctx.GetString(uintptr(addr)))
|
||||
}
|
||||
|
||||
func (h *tracerHandler) checkOpen(ctx *tracer.Context, addr uint, flags uint) TraceAction {
|
||||
func (h *tracerHandler) checkOpen(ctx *ptracer.Context, addr uint, flags uint) TraceAction {
|
||||
fn := h.getString(ctx, addr)
|
||||
isReadOnly := (flags&syscall.O_ACCMODE == syscall.O_RDONLY) &&
|
||||
(flags&syscall.O_CREAT == 0) &&
|
||||
@ -41,25 +41,25 @@ func (h *tracerHandler) checkOpen(ctx *tracer.Context, addr uint, flags uint) Tr
|
||||
return h.Handler.CheckWrite(fn)
|
||||
}
|
||||
|
||||
func (h *tracerHandler) checkRead(ctx *tracer.Context, addr uint) TraceAction {
|
||||
func (h *tracerHandler) checkRead(ctx *ptracer.Context, addr uint) TraceAction {
|
||||
fn := h.getString(ctx, addr)
|
||||
h.Debug("check read: ", fn)
|
||||
return h.Handler.CheckRead(fn)
|
||||
}
|
||||
|
||||
func (h *tracerHandler) checkWrite(ctx *tracer.Context, addr uint) TraceAction {
|
||||
func (h *tracerHandler) checkWrite(ctx *ptracer.Context, addr uint) TraceAction {
|
||||
fn := h.getString(ctx, addr)
|
||||
h.Debug("check write: ", fn)
|
||||
return h.Handler.CheckWrite(fn)
|
||||
}
|
||||
|
||||
func (h *tracerHandler) checkStat(ctx *tracer.Context, addr uint) TraceAction {
|
||||
func (h *tracerHandler) checkStat(ctx *ptracer.Context, addr uint) TraceAction {
|
||||
fn := h.getString(ctx, addr)
|
||||
h.Debug("check stat: ", fn)
|
||||
return h.Handler.CheckStat(fn)
|
||||
}
|
||||
|
||||
func (h *tracerHandler) Handle(ctx *tracer.Context) tracer.TraceAction {
|
||||
func (h *tracerHandler) Handle(ctx *ptracer.Context) ptracer.TraceAction {
|
||||
var (
|
||||
action TraceAction
|
||||
syscallNo = ctx.SyscallNo()
|
||||
@ -108,30 +108,30 @@ func (h *tracerHandler) Handle(ctx *tracer.Context) tracer.TraceAction {
|
||||
|
||||
switch action {
|
||||
case TraceAllow:
|
||||
return tracer.TraceAllow
|
||||
return ptracer.TraceAllow
|
||||
case TraceBan:
|
||||
h.Debug("<soft ban syscall>")
|
||||
return softBanSyscall(ctx)
|
||||
default:
|
||||
return tracer.TraceKill
|
||||
return ptracer.TraceKill
|
||||
}
|
||||
}
|
||||
|
||||
func (h *tracerHandler) GetSyscallName(ctx *tracer.Context) (string, error) {
|
||||
func (h *tracerHandler) GetSyscallName(ctx *ptracer.Context) (string, error) {
|
||||
syscallNo := ctx.SyscallNo()
|
||||
return libseccomp.ScmpSyscall(syscallNo).GetName()
|
||||
}
|
||||
|
||||
func (h *tracerHandler) HandlerDisallow(name string) error {
|
||||
if !h.Unsafe {
|
||||
return specs.TraceCodeBan
|
||||
return types.StatusBan
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func softBanSyscall(ctx *tracer.Context) tracer.TraceAction {
|
||||
func softBanSyscall(ctx *ptracer.Context) ptracer.TraceAction {
|
||||
ctx.SetReturnValue(-int(BanRet))
|
||||
return tracer.TraceBan
|
||||
return ptracer.TraceBan
|
||||
}
|
||||
|
||||
func getFileMode(flags uint) string {
|
||||
@ -1,16 +1,16 @@
|
||||
package runprogram
|
||||
package ptrace
|
||||
|
||||
import (
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/forkexec"
|
||||
"github.com/criyle/go-sandbox/pkg/seccomp"
|
||||
"github.com/criyle/go-sandbox/tracer"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/ptracer"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// Start starts the tracing process
|
||||
func (r *RunProgram) Start(done <-chan struct{}) (<-chan specs.TraceResult, error) {
|
||||
func (r *Runner) Start(done <-chan struct{}) (<-chan types.Result, error) {
|
||||
// build seccomp filter
|
||||
filter, err := buildFilter(r.ShowDetails, r.SyscallAllowed, r.SyscallTraced)
|
||||
if err != nil {
|
||||
@ -42,7 +42,7 @@ func (r *RunProgram) Start(done <-chan struct{}) (<-chan specs.TraceResult, erro
|
||||
Unsafe: r.Unsafe,
|
||||
Handler: r.Handler,
|
||||
}
|
||||
return tracer.Trace(done, th, ch, specs.ResLimit(r.TraceLimit))
|
||||
return ptracer.Trace(done, th, ch, types.Limit(r.TraceLimit))
|
||||
}
|
||||
|
||||
// build filter builds the libseccomp filter according to the allow, trace and show details
|
||||
@ -51,9 +51,9 @@ func buildFilter(showDetails bool, allow, trace []string) (*libseccomp.ScmpFilte
|
||||
var defaultAction libseccomp.ScmpAction
|
||||
// if debug, allow all syscalls and output what was blocked
|
||||
if showDetails {
|
||||
defaultAction = libseccomp.ActTrace.SetReturnCode(tracer.MsgDisallow)
|
||||
defaultAction = libseccomp.ActTrace.SetReturnCode(ptracer.MsgDisallow)
|
||||
} else {
|
||||
defaultAction = libseccomp.ActKill
|
||||
}
|
||||
return seccomp.BuildFilter(defaultAction, libseccomp.ActTrace.SetReturnCode(tracer.MsgHandle), allow, trace)
|
||||
return seccomp.BuildFilter(defaultAction, libseccomp.ActTrace.SetReturnCode(ptracer.MsgHandle), allow, trace)
|
||||
}
|
||||
@ -1,14 +1,14 @@
|
||||
package runprogram
|
||||
package ptrace
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// RunProgram defines the spec to run a program safely
|
||||
type RunProgram struct {
|
||||
// Runner defines the spec to run a program safely by ptracer
|
||||
type Runner struct {
|
||||
// argv and env for the child process
|
||||
// work path set by setcwd (current working directory for child)
|
||||
Args []string
|
||||
@ -25,7 +25,7 @@ type RunProgram struct {
|
||||
RLimits rlimit.RLimits
|
||||
|
||||
// Res limit enforced by tracer
|
||||
TraceLimit specs.ResLimit
|
||||
TraceLimit types.Limit
|
||||
|
||||
// Allowed / Traced syscall names
|
||||
// Notice: file access syscalls should be traced
|
||||
8
runner/runner.go
Normal file
8
runner/runner.go
Normal file
@ -0,0 +1,8 @@
|
||||
package runner
|
||||
|
||||
import "github.com/criyle/go-sandbox/types"
|
||||
|
||||
// Runner interface defines method to start running
|
||||
type Runner interface {
|
||||
Start(<-chan struct{}) (<-chan types.Result, error)
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
package rununshared
|
||||
package unshare
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/mount"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/mount"
|
||||
)
|
||||
|
||||
// AddBind is the additional bind mounts besides the default one
|
||||
@ -1,15 +1,16 @@
|
||||
package rununshared
|
||||
package unshare
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/forkexec"
|
||||
"github.com/criyle/go-sandbox/pkg/seccomp"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
libseccomp "github.com/seccomp/libseccomp-golang"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/criyle/go-sandbox/pkg/forkexec"
|
||||
"github.com/criyle/go-sandbox/pkg/seccomp"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -18,7 +19,7 @@ const (
|
||||
)
|
||||
|
||||
// Start starts the unshared process
|
||||
func (r *RunUnshared) Start(done <-chan struct{}) (<-chan specs.TraceResult, error) {
|
||||
func (r *Runner) Start(done <-chan struct{}) (<-chan types.Result, error) {
|
||||
filter, err := seccomp.BuildFilter(libseccomp.ActKill, libseccomp.ActTrap, r.SyscallAllowed, []string{})
|
||||
if err != nil {
|
||||
println(err)
|
||||
@ -51,7 +52,7 @@ func (r *RunUnshared) Start(done <-chan struct{}) (<-chan specs.TraceResult, err
|
||||
SyncFunc: r.SyncFunc,
|
||||
}
|
||||
|
||||
result := make(chan specs.TraceResult, 1)
|
||||
result := make(chan types.Result, 1)
|
||||
start := make(chan struct{})
|
||||
finish := make(chan struct{})
|
||||
|
||||
@ -71,13 +72,13 @@ func (r *RunUnshared) Start(done <-chan struct{}) (<-chan specs.TraceResult, err
|
||||
}
|
||||
|
||||
// Trace tracks child processes
|
||||
func (r *RunUnshared) Trace(done <-chan struct{}, start chan<- struct{},
|
||||
runner *forkexec.Runner) (result specs.TraceResult, err error) {
|
||||
func (r *Runner) Trace(done <-chan struct{}, start chan<- struct{},
|
||||
runner *forkexec.Runner) (result types.Result, err error) {
|
||||
var (
|
||||
wstatus unix.WaitStatus // wait4 wait status
|
||||
rusage unix.Rusage // wait4 rusage
|
||||
tle = false
|
||||
status = specs.TraceCodeNormal
|
||||
status = types.StatusNormal
|
||||
sTime = time.Now() // start time
|
||||
fTime time.Time // finish time for setup
|
||||
)
|
||||
@ -86,7 +87,7 @@ func (r *RunUnshared) Trace(done <-chan struct{}, start chan<- struct{},
|
||||
pgid, err := runner.Start()
|
||||
r.println("Starts: ", pgid, err)
|
||||
if err != nil {
|
||||
result.TraceStatus = specs.TraceCodeRE
|
||||
result.Status = types.StatusRE
|
||||
return result, err
|
||||
}
|
||||
|
||||
@ -106,13 +107,13 @@ func (r *RunUnshared) Trace(done <-chan struct{}, start chan<- struct{},
|
||||
|
||||
defer func() {
|
||||
if tle {
|
||||
err = specs.TraceCodeTLE
|
||||
err = types.StatusTLE
|
||||
}
|
||||
// kill all tracee upon return
|
||||
killAll(pgid)
|
||||
collectZombie(pgid)
|
||||
result.SetUpTime = fTime.Sub(sTime).Nanoseconds()
|
||||
result.RunningTime = time.Since(fTime).Nanoseconds()
|
||||
result.SetUpTime = fTime.Sub(sTime)
|
||||
result.RunningTime = time.Since(fTime)
|
||||
}()
|
||||
|
||||
fTime = time.Now()
|
||||
@ -120,7 +121,7 @@ func (r *RunUnshared) Trace(done <-chan struct{}, start chan<- struct{},
|
||||
_, err := unix.Wait4(pgid, &wstatus, 0, &rusage)
|
||||
r.println("wait4: ", wstatus)
|
||||
if err != nil {
|
||||
return result, specs.TraceCodeFatal
|
||||
return result, types.StatusFatal
|
||||
}
|
||||
|
||||
// update resource usage and check against limits
|
||||
@ -129,37 +130,37 @@ func (r *RunUnshared) Trace(done <-chan struct{}, start chan<- struct{},
|
||||
|
||||
// check tle / mle
|
||||
if userTime > r.ResLimits.TimeLimit {
|
||||
status = specs.TraceCodeTLE
|
||||
status = types.StatusTLE
|
||||
}
|
||||
if userMem > r.ResLimits.MemoryLimit {
|
||||
status = specs.TraceCodeMLE
|
||||
status = types.StatusMLE
|
||||
}
|
||||
result = specs.TraceResult{
|
||||
result = types.Result{
|
||||
Status: status,
|
||||
UserTime: userTime,
|
||||
UserMem: userMem,
|
||||
TraceStatus: status,
|
||||
}
|
||||
if status != specs.TraceCodeNormal {
|
||||
if status != types.StatusNormal {
|
||||
return result, status
|
||||
}
|
||||
|
||||
switch {
|
||||
case wstatus.Exited():
|
||||
result.ExitCode = wstatus.ExitStatus()
|
||||
result.ExitStatus = wstatus.ExitStatus()
|
||||
return result, nil
|
||||
case wstatus.Signaled():
|
||||
sig := wstatus.Signal()
|
||||
switch sig {
|
||||
case unix.SIGXCPU, unix.SIGKILL:
|
||||
status = specs.TraceCodeTLE
|
||||
status = types.StatusTLE
|
||||
case unix.SIGXFSZ:
|
||||
status = specs.TraceCodeOLE
|
||||
status = types.StatusOLE
|
||||
case unix.SIGSYS:
|
||||
status = specs.TraceCodeBan
|
||||
status = types.StatusBan
|
||||
default:
|
||||
status = specs.TraceCodeRE
|
||||
status = types.StatusRE
|
||||
}
|
||||
result.TraceStatus = status
|
||||
result.Status = status
|
||||
return result, status
|
||||
}
|
||||
}
|
||||
@ -182,7 +183,7 @@ func collectZombie(pgid int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RunUnshared) println(v ...interface{}) {
|
||||
func (r *Runner) println(v ...interface{}) {
|
||||
if r.ShowDetails {
|
||||
fmt.Fprintln(os.Stderr, v...)
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
package rununshared
|
||||
package unshare
|
||||
|
||||
import (
|
||||
"github.com/criyle/go-sandbox/pkg/mount"
|
||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||
"github.com/criyle/go-sandbox/types/specs"
|
||||
"github.com/criyle/go-sandbox/types"
|
||||
)
|
||||
|
||||
// RunUnshared runs program in unshared namespaces
|
||||
type RunUnshared struct {
|
||||
// Runner runs program in unshared namespaces
|
||||
type Runner struct {
|
||||
// argv and env for the child process
|
||||
Args []string
|
||||
Env []string
|
||||
@ -25,7 +25,7 @@ type RunUnshared struct {
|
||||
RLimits rlimit.RLimits
|
||||
|
||||
// Resource limit enforced by tracer
|
||||
ResLimits specs.ResLimit
|
||||
ResLimits types.Limit
|
||||
|
||||
// Allowed syscall names
|
||||
SyscallAllowed []string
|
||||
@ -1,59 +0,0 @@
|
||||
package specs
|
||||
|
||||
// TraceCode is the error type
|
||||
type TraceCode int
|
||||
|
||||
// Different end condtion
|
||||
const (
|
||||
TraceCodeNormal TraceCode = iota // 0
|
||||
TraceCodeInvalid // 1
|
||||
TraceCodeRE // 2
|
||||
TraceCodeMLE // 3
|
||||
TraceCodeTLE // 4
|
||||
TraceCodeOLE // 5
|
||||
TraceCodeBan // 6
|
||||
TraceCodeFatal // 7
|
||||
)
|
||||
|
||||
func (t TraceCode) Error() string {
|
||||
switch t {
|
||||
case TraceCodeNormal:
|
||||
return ""
|
||||
case TraceCodeRE:
|
||||
return "runtime error"
|
||||
case TraceCodeTLE:
|
||||
return "time limit exceeded"
|
||||
case TraceCodeMLE:
|
||||
return "memory limit exceeded"
|
||||
case TraceCodeOLE:
|
||||
return "output limit exceeded"
|
||||
case TraceCodeBan:
|
||||
return "syscall banned"
|
||||
case TraceCodeFatal:
|
||||
return "handle failed"
|
||||
default:
|
||||
return "invalid"
|
||||
}
|
||||
}
|
||||
|
||||
// TraceStat is the time usages in ns
|
||||
type TraceStat struct {
|
||||
SetUpTime int64
|
||||
RunningTime int64
|
||||
}
|
||||
|
||||
// TraceResult is the result returned by strat trace
|
||||
type TraceResult struct {
|
||||
UserTime uint64 // used user CPU time (in ms)
|
||||
UserMem uint64 // used user memory (in kb)
|
||||
ExitCode int // exit code
|
||||
TraceStatus TraceCode // the final status for the process
|
||||
TraceStat // collects time for the process
|
||||
}
|
||||
|
||||
// ResLimit represents the resource limit for traced process
|
||||
type ResLimit struct {
|
||||
TimeLimit uint64 // user CPU time limit (in ms)
|
||||
RealTimeLimit uint64 // sig_kill will force the process to exit after this limit (in ms)
|
||||
MemoryLimit uint64 // user memory limit (in kB)
|
||||
}
|
||||
41
types/status.go
Normal file
41
types/status.go
Normal file
@ -0,0 +1,41 @@
|
||||
package types
|
||||
|
||||
// Status is the result Status
|
||||
type Status int
|
||||
|
||||
// Different end condtion
|
||||
const (
|
||||
StatusNormal Status = iota // 0
|
||||
StatusInvalid // 1
|
||||
StatusRE // 2
|
||||
StatusMLE // 3
|
||||
StatusTLE // 4
|
||||
StatusOLE // 5
|
||||
StatusBan // 6
|
||||
StatusFatal // 7
|
||||
)
|
||||
|
||||
var (
|
||||
statusString = []string{
|
||||
"",
|
||||
"invalid",
|
||||
"runtime error",
|
||||
"memory limit exceeded",
|
||||
"time limit exceeded",
|
||||
"output limit exceeded",
|
||||
"syscall banned",
|
||||
"runner failed",
|
||||
}
|
||||
)
|
||||
|
||||
func (t Status) String() string {
|
||||
i := int(t)
|
||||
if i >= 0 && i < len(statusString) {
|
||||
return statusString[i]
|
||||
}
|
||||
return "invalid"
|
||||
}
|
||||
|
||||
func (t Status) Error() string {
|
||||
return t.String()
|
||||
}
|
||||
24
types/types.go
Normal file
24
types/types.go
Normal file
@ -0,0 +1,24 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
// Result is the result returned by strat trace
|
||||
type Result struct {
|
||||
Status // the final status for the process
|
||||
ExitStatus int // exit Status
|
||||
UserTime uint64 // used user CPU time (in ms)
|
||||
UserMem uint64 // used user memory (in kb)
|
||||
Stat // collects time usage for the runner
|
||||
}
|
||||
|
||||
// Stat is the time usages in ns
|
||||
type Stat struct {
|
||||
SetUpTime time.Duration
|
||||
RunningTime time.Duration
|
||||
}
|
||||
|
||||
// Limit represents the resource limit for traced process
|
||||
type Limit struct {
|
||||
TimeLimit uint64 // user CPU time limit (in ms)
|
||||
MemoryLimit uint64 // user memory limit (in kB)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user