add support for arm32

This commit is contained in:
criyle 2019-04-29 18:12:06 -04:00
parent 79d33bd16d
commit 4828363e1d
8 changed files with 306 additions and 16 deletions

223
run_program/config_arm.go Normal file
View File

@ -0,0 +1,223 @@
package main
// This file includes configs for the run program settings
var (
// default read permission files
defaultReadableFiles = []string{
"/etc/ld.so.nohwcap",
"/etc/ld.so.preload",
"/etc/ld.so.cache",
"/lib/arm-linux-gnueabihf/", // 32-bit
"/usr/lib/arm-linux-gnueabihf/", // 32-bit
"/usr/lib/locale/locale-archive",
"/proc/self/exe",
"/etc/timezone",
"/usr/share/zoneinfo/",
"/dev/random",
"/dev/urandom",
"/proc/meminfo",
"/etc/localtime",
}
// default write permission files
defaultWritableFiles = []string{"/dev/null"}
// default allowed safe syscalls
defaultSyscallAllows = []string{
// file access through fd
"read",
"write",
"readv",
"writev",
"close",
"fstat",
"fstat64", // 32-bit
"lseek",
"_llseek", // 32-bit
"dup",
"dup2",
"dup3",
"ioctl",
"fcntl",
"fcntl64", // 32-bit
// memory action
"mmap",
"mmap2", // 32-bit
"mprotect",
"munmap",
"brk",
"mremap",
"msync",
"mincore",
"madvise",
// signal action
"rt_sigaction",
"rt_sigprocmask",
"rt_sigreturn",
"rt_sigpending",
"sigaltstack",
// get current work dir
"getcwd",
// process exit
"exit",
"exit_group",
// others
"arch_prctl",
"gettimeofday",
"getrlimit",
"getrusage",
"times",
"time",
"clock_gettime",
"restart_syscall",
// arch
"uname",
"set_tls",
}
// default syscalls to trace
defaultSyscallTraces = []string{
// should be traced
"execve",
// file open
"open",
"openat",
// file delete
"unlink",
"unlinkat",
// soft link
"readlink",
"readlinkat",
// permission check
"lstat",
"lstat64", // 32-bit
"stat",
"stat64", // 32-bit
"access",
}
// process related syscall if allowProc enabled
defaultProcSyscalls = []string{"clone", "fork", "vfork", "nanosleep", "execve"}
// config for different type of program
// workpath and arg0 have additional read / stat permission
runprogramConfig = map[string]ProgramConfig{
"python2.7": ProgramConfig{
Syscall: SyscallConfig{
ExtraAllow: []string{
"futex", "getdents", "getdents64", "prlimit64", "getpid", "sysinfo",
},
ExtraCount: map[string]int{
"set_tid_address": 1,
"set_robust_list": 1,
},
},
FileAccess: FileAccessConfig{
ExtraRead: []string{
"/usr/bin/python2.7",
"/usr/lib/python2.7/",
"/usr/bin/lib/python2.7/",
"/usr/local/lib/python2.7/",
"/usr/lib/pymodules/python2.7/",
"/usr/bin/Modules/",
"/usr/bin/pybuilddir.txt",
"/usr/lib/locale/",
"./answer.code",
},
ExtraStat: []string{
"/usr", "/usr/bin",
},
},
RunCommand: []string{"/usr/bin/python2.7", "-E", "-s", "-B"},
},
"python3": ProgramConfig{
Syscall: SyscallConfig{
ExtraAllow: []string{
"futex", "getdents", "getdents64", "prlimit64", "getpid", "sysinfo", "getrandom",
},
ExtraCount: map[string]int{
"set_tid_address": 1,
"set_robust_list": 1,
},
},
FileAccess: FileAccessConfig{
ExtraRead: []string{
"/usr/bin/python3",
"/usr/lib/python3/",
"/usr/bin/python3.6",
"/usr/lib/python3.6/",
"/usr/bin/lib/python3.6/",
"/usr/local/lib/python3.6/",
"/usr/bin/pyvenv.cfg",
"/usr/pyvenv.cfg",
"/usr/bin/Modules",
"/usr/bin/pybuilddir.txt",
"/usr/lib/dist-python",
"/usr/lib/locale/",
"./answer.code",
},
ExtraStat: []string{
"/usr", "/usr/bin", "/usr/lib", "/usr/lib/python36.zip",
},
},
RunCommand: []string{"/usr/bin/python3", "-I", "-B"},
},
"compiler": ProgramConfig{
Syscall: SyscallConfig{
ExtraAllow: []string{
"gettid", "set_tid_address", "set_robust_list", "futex",
"getpid", "vfork", "fork", "clone", "execve", "wait4",
"clock_gettime", "clock_getres",
"setrlimit", "pipe",
"getdents64", "getdents",
"umask", "rename", "chmod", "mkdir",
"chdir", "fchdir",
"ftruncate",
"sched_getaffinity", "sched_yield",
"uname", "sysinfo",
"prlimit64", "getrandom",
},
ExtraBan: []string{"socket", "connect", "geteuid", "getuid"},
},
FileAccess: FileAccessConfig{
ExtraWrite: []string{
"/tmp/", "./",
},
ExtraRead: []string{
"./",
"../runtime/",
"/etc/oracle/java/usagetracker.properties",
"/usr/",
"/lib/",
"/lib64/",
"/bin/",
"/sbin/",
"/sys/devices/system/cpu/",
"/proc/",
"/etc/timezone",
"/etc/fpc-2.6.2.cfg.d/",
"/etc/fpc.cfg",
"/*",
"/", // system_root
},
ExtraBan: []string{
"/etc/nsswitch.conf",
"/etc/passwd",
},
},
},
}
)

View File

@ -118,9 +118,9 @@ func (h *handler) Handle(ctx *tracer.Context) tracer.TraceAction {
case "access":
return h.checkStat(ctx, ctx.Arg0())
case "stat":
case "stat", "stat64":
return h.checkStat(ctx, ctx.Arg0())
case "lstat":
case "lstat", "lstat64":
return h.checkStat(ctx, ctx.Arg0())
case "execve":

View File

@ -5,7 +5,6 @@ import (
"fmt"
"os"
"runtime"
"runtime/debug"
secutil "github.com/criyle/go-judger/secutil"
tracee "github.com/criyle/go-judger/tracee"
@ -21,7 +20,6 @@ func main() {
timeLimit, realTimeLimit, memoryLimit, outputLimit, stackLimit uint
inputFileName, outputFileName, errorFileName, workPath string
)
debug.SetGCPercent(-1)
flag.UintVar(&timeLimit, "tl", 1, "Set time limit (in second)")
flag.UintVar(&realTimeLimit, "rtl", 0, "Set real time limit (in second)")
@ -101,11 +99,15 @@ func main() {
fds[i] = uintptr(i)
}
}
// Rlimit
rlimit := prepareRLimit(timeLimit, realTimeLimit, outputLimit<<20, stackLimit<<20)
// get tracee
ch := &tracee.Runner{
Args: args,
Env: []string{"PATH=/"},
RLimits: prepareRLimit(timeLimit, realTimeLimit, outputLimit<<20, stackLimit<<20),
RLimits: rlimit,
Files: fds,
WorkDir: workPath,
BPF: bpf,

View File

@ -91,7 +91,8 @@ func (r *Runner) Start() (int, error) {
// Set limit
for _, rlim := range r.RLimits {
_, _, err1 = syscall.RawSyscall(syscall.SYS_SETRLIMIT, uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0)
// Prlimit instead of setrlimit to avoid 32-bit limitation (linux > 3.2)
_, _, err1 = syscall.RawSyscall6(syscall.SYS_PRLIMIT64, 0, uintptr(rlim.Res), uintptr(unsafe.Pointer(&rlim.Rlim)), 0, 0, 0)
if err1 != 0 {
goto childerror
}

1
tracee/tracee_fork.s Normal file
View File

@ -0,0 +1 @@
// to use go:linkname

61
tracer/context_arm.go Normal file
View File

@ -0,0 +1,61 @@
package tracer
import (
"syscall"
unix "golang.org/x/sys/unix"
)
// SyscallNo get current syscall no
func (c *Context) SyscallNo() uint {
return uint(c.regs.Uregs[7]) // R7
}
// Arg0 gets the arg0 for the current syscall
func (c *Context) Arg0() uint {
return uint(c.regs.Uregs[17]) //Orig_R0
}
// Arg1 gets the arg1 for the current syscall
func (c *Context) Arg1() uint {
return uint(c.regs.Uregs[1]) // R1
}
// Arg2 gets the arg2 for the current syscall
func (c *Context) Arg2() uint {
return uint(c.regs.Uregs[2]) // R2
}
// Arg3 gets the arg3 for the current syscall
func (c *Context) Arg3() uint {
return uint(c.regs.Uregs[3]) // R3
}
// Arg4 gets the arg4 for the current syscall
func (c *Context) Arg4() uint {
return uint(c.regs.Uregs[4]) // R4
}
// Arg5 gets the arg5 for the current syscall
func (c *Context) Arg5() uint {
return uint(c.regs.Uregs[5]) //R5
}
// SetReturnValue set the return value if skip the syscall
func (c *Context) SetReturnValue(retval int) {
c.regs.Uregs[0] = uint32(retval) // R0
}
func (c *Context) skipSyscall() error {
c.regs.Uregs[7] = ^uint32(0) //-1
return syscall.PtraceSetRegs(c.Pid, &c.regs)
}
func getIovecs(base *byte, l int) []unix.Iovec {
return []unix.Iovec{
unix.Iovec{
Base: base,
Len: uint32(l),
},
}
}

View File

@ -83,16 +83,6 @@ func Trace(handler Handler, runners []Runner, limits ResLimit, timeout int64) (r
return results, TraceCodeFatal
}
println("------ ", pid, " ------")
// Set option if the process is newly forked
if !traced[pid] {
println("set ptrace option")
traced[pid] = true
// Ptrace set option valid if the tracee is stopped
err = setPtraceOption(pid)
if err != nil {
return results, err
}
}
// update resource usage and check against limits
userTime := uint(rusage.Utime.Sec*1e3 + rusage.Utime.Usec/1e3) // ms
@ -155,6 +145,18 @@ func Trace(handler Handler, runners []Runner, limits ResLimit, timeout int64) (r
delete(traced, pid)
case wstatus.Stopped():
// Set option if the process is newly forked
if !traced[pid] {
println("set ptrace option")
traced[pid] = true
// Ptrace set option valid if the tracee is stopped
err = setPtraceOption(pid)
if err != nil {
return results, err
}
}
// Check stop signal, if trap then check seccomp
if stopSig := wstatus.StopSignal(); stopSig == unix.SIGTRAP {
switch trapCause := wstatus.TrapCause(); trapCause {
case unix.PTRACE_EVENT_SECCOMP: