diff --git a/.gitignore b/.gitignore index 6d66f3d..f9b3f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ # Test Env test*/ -env.sh +env*.sh diff --git a/README.md b/README.md index 02a3360..3e01e99 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,26 @@ Under developing. Goal is to reimplement [uoj-judger/run_program](https://github.com/vfleaking/uoj) in GO language using [libseccomp](https://github.com/seccomp/libseccomp-golang). Install: + + install go compiler: `apt install golang-go` + install libseccomp-dev: `apt install libseccomp-dev` + install: `go install github.com/criyle/go-judger/...` Features (same as uoj-judger/run_program): + 1. Restricted computing resource: Time & Memory (Stack) & Output -2. Restricted syscall access (by libseccomp & ptrace) -3. Restricted file access (read & write & access & exec) +1. Restricted syscall access (by libseccomp & ptrace) +1. Restricted file access (read & write & access & exec) + +New Features: + +1. Percise resource limits (s -> ms, mb -> kb) +1. More architectures (arm32, arm64, x86) +1. Allow multiple traced programs in different threads +1. Allow pipes as input / output files Default file access action: + + check file read / write: `open`, `openat` + check file read: `readlink`, `readlinkat` + check file write: `unlink`, `unlinkat`, `chmod`, `rename` @@ -22,22 +32,21 @@ Default file access action: + check file exec: `execve` Packages: -+ Secutil: provides common utility function that wrappers libseccomp -+ Tracee: ptraced fork-exec with seccomp loaded -+ Tracer: ptrace tracee and provides syscall trap context + ++ secutil: provides common utility function that wrappers libseccomp ++ tracee: ptraced fork-exec with seccomp loaded ++ tracer: ptrace tracee and provides syscall trap context ++ runprogram: wrapper to call trecee and trecer ++ runconfig: defines arch & language specified trace condition Executable: + + run_program: under construction Configuations: + + run_program/config.go: all configs toward running specs -Features: -+ Percise resource limits (s -> ms, mb -> kb) -+ More architectures (arm32, arm64, x86) - TODO: - -+ allow multiple traced programs -+ allow pipes -+ ... +1. Use Linux Namespace to isolate file access (elimilate ptrace) +1. Use Linux Control Groups to limit & acct CPU & memory (elimilate wait4 rusage) diff --git a/tracer/proc.go b/tracer/proc.go new file mode 100644 index 0000000..13da50c --- /dev/null +++ b/tracer/proc.go @@ -0,0 +1,11 @@ +package tracer + +import ( + "fmt" + "io/ioutil" +) + +// clearRefs clears the ru_maxrss counter (/proc/[pid]/clear_refs 5 to clear maxrss) +func clearRefs(pid int) error { + return ioutil.WriteFile(fmt.Sprintf("/proc/%d/clear_refs", pid), []byte("5"), 0755) +} diff --git a/tracer/tracer_track.go b/tracer/tracer_track.go index 340d0b8..a82e4f1 100644 --- a/tracer/tracer_track.go +++ b/tracer/tracer_track.go @@ -24,6 +24,7 @@ func Trace(handler Handler, runner Runner, limits ResLimit) (result TraceResult, tle bool // whether the timmer triggered due to timeout traced = make(map[int]bool) // store all process that have set ptrace options execved = false // store whether the runner process have successfully execvd + pid int // store pid of wait4 result ) // ptrace is thread based (kernel proc) @@ -62,7 +63,9 @@ func Trace(handler Handler, runner Runner, limits ResLimit) (result TraceResult, // trace unixs for { - var pid int + if err = clearRefs(pgid); err != nil { + return result, err + } if execved { // Wait for all child in the process group pid, err = unix.Wait4(-pgid, &wstatus, unix.WALL, &rusage)