go-sandbox/run_program/run_util.go

88 lines
2.2 KiB
Go

package main
import (
"os"
"syscall"
secutil "github.com/criyle/go-judger/secutil"
tracee "github.com/criyle/go-judger/tracee"
tracer "github.com/criyle/go-judger/tracer"
libseccomp "github.com/seccomp/libseccomp-golang"
)
// build filter builds the libseccomp filter according to the allow, trace and show details
func buildFilter(showDetails bool, allow, trace []string) (*libseccomp.ScmpFilter, error) {
// make filter
var defaultAction libseccomp.ScmpAction
// if debug, allow all syscalls and output what was blocked
if showDetails {
defaultAction = libseccomp.ActTrace.SetReturnCode(tracer.MsgDisallow)
} else {
defaultAction = libseccomp.ActKill
}
return secutil.BuildFilter(defaultAction, libseccomp.ActTrace.SetReturnCode(tracer.MsgHandle), allow, trace)
}
// prepareFile opens file for new process
func prepareFiles(inputFile, outputFile, errorFile string) ([]*os.File, error) {
var err error
files := make([]*os.File, 3)
if inputFile != "" {
files[0], err = os.OpenFile(inputFile, os.O_RDONLY, 0755)
if err != nil {
goto openerror
}
}
if outputFile != "" {
files[1], err = os.OpenFile(outputFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0755)
if err != nil {
goto openerror
}
}
if errorFile != "" {
files[2], err = os.OpenFile(errorFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0755)
if err != nil {
goto openerror
}
}
return files, nil
openerror:
closeFiles(files)
return nil, err
}
// closeFiles close all file in the list
func closeFiles(files []*os.File) {
for _, f := range files {
if f != nil {
f.Close()
}
}
}
func getRlimit(cur, max uint) syscall.Rlimit {
return syscall.Rlimit{Cur: uint64(cur), Max: uint64(max)}
}
// prepareRLimit creates rlimit structures for tracee
// TimeLimit in s, SizeLimit in byte
func prepareRLimit(TimeLimit, RealTimeLimit, OutputLimit, StackLimit uint) []tracee.RLimit {
return []tracee.RLimit{
// CPU limit
{
Res: syscall.RLIMIT_CPU,
Rlim: getRlimit(TimeLimit, RealTimeLimit),
},
// File limit
{
Res: syscall.RLIMIT_FSIZE,
Rlim: getRlimit(OutputLimit, OutputLimit),
},
// Stack limit
{
Res: syscall.RLIMIT_STACK,
Rlim: getRlimit(StackLimit, StackLimit),
},
}
}