mirror of
https://github.com/criyle/go-judge.git
synced 2025-11-04 14:50:02 +08:00
Add support to load a seccomp filter
This commit is contained in:
parent
e3111eef82
commit
04cfb36722
@ -68,6 +68,10 @@ The `executorserver` need root privilege to create `cgroup`. Either creates sub-
|
|||||||
- for example, by default container 0 will run with 10001 uid & gid and container 1 will run with 10002 uid & gid...
|
- for example, by default container 0 will run with 10001 uid & gid and container 1 will run with 10002 uid & gid...
|
||||||
- `-enable-cpu-rate` enabled `cpu` cgroup to control cpu rate using cfs_quota & cfs_period control
|
- `-enable-cpu-rate` enabled `cpu` cgroup to control cpu rate using cfs_quota & cfs_period control
|
||||||
- `-cpu-cfs-period` specifies cfs_period if cpu rate is enabled (default 100ms) (valid value: \[1ms, 1s\])
|
- `-cpu-cfs-period` specifies cfs_period if cpu rate is enabled (default 100ms) (valid value: \[1ms, 1s\])
|
||||||
|
- `-seccomp-conf` specifies `seecomp` filter setting to load when running program
|
||||||
|
- for example, by `strace -c prog` to get all `syscall` needed and restrict to that sub set
|
||||||
|
- however, the `syscall` count in one platform(e.g. x86_64) is not suitable for all platform, so this option is not recommended
|
||||||
|
- the program killed by seccomp filter will have status `Dangerous Syscall`
|
||||||
|
|
||||||
#### Environment Variables
|
#### Environment Variables
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,8 @@ type Config struct {
|
|||||||
PreFork int `flagUsage:"control # of the prefork workers"`
|
PreFork int `flagUsage:"control # of the prefork workers"`
|
||||||
TmpFsParam string `flagUsage:"tmpfs mount data (only for default mount with no mount.yaml)" default:"size=16m,nr_inodes=4k"`
|
TmpFsParam string `flagUsage:"tmpfs mount data (only for default mount with no mount.yaml)" default:"size=16m,nr_inodes=4k"`
|
||||||
NetShare bool `flagUsage:"share net namespace with host"`
|
NetShare bool `flagUsage:"share net namespace with host"`
|
||||||
MountConf string `flagUsage:"specifics mount configuration file" default:"mount.yaml"`
|
MountConf string `flagUsage:"specifies mount configuration file" default:"mount.yaml"`
|
||||||
|
SeccompConf string `flagUsage:"specifies seccomp filter" default:"seccomp.yaml"`
|
||||||
Parallelism int `flagUsage:"control the # of concurrency execution" default:"4"`
|
Parallelism int `flagUsage:"control the # of concurrency execution" default:"4"`
|
||||||
CgroupPrefix string `flagUsage:"control cgroup prefix" default:"executor_server"`
|
CgroupPrefix string `flagUsage:"control cgroup prefix" default:"executor_server"`
|
||||||
ContainerCredStart int `flagUsage:"control the start uid&gid for container" default:"10000"`
|
ContainerCredStart int `flagUsage:"control the start uid&gid for container" default:"10000"`
|
||||||
|
|||||||
@ -79,6 +79,7 @@ func main() {
|
|||||||
ContainerCredStart: conf.ContainerCredStart,
|
ContainerCredStart: conf.ContainerCredStart,
|
||||||
EnableCPURate: conf.EnableCPURate,
|
EnableCPURate: conf.EnableCPURate,
|
||||||
CPUCfsPeriod: conf.CPUCfsPeriod,
|
CPUCfsPeriod: conf.CPUCfsPeriod,
|
||||||
|
SeccompConf: conf.SeccompConf,
|
||||||
Logger: logger.Sugar(),
|
Logger: logger.Sugar(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
1
env/config.go
vendored
1
env/config.go
vendored
@ -16,6 +16,7 @@ type Config struct {
|
|||||||
TmpFsParam string
|
TmpFsParam string
|
||||||
NetShare bool
|
NetShare bool
|
||||||
MountConf string
|
MountConf string
|
||||||
|
SeccompConf string
|
||||||
CgroupPrefix string
|
CgroupPrefix string
|
||||||
Cpuset string
|
Cpuset string
|
||||||
ContainerCredStart int
|
ContainerCredStart int
|
||||||
|
|||||||
18
env/env_linux.go
vendored
18
env/env_linux.go
vendored
@ -1,6 +1,7 @@
|
|||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -45,6 +46,14 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) {
|
|||||||
m := mb.FilterNotExist().Mounts
|
m := mb.FilterNotExist().Mounts
|
||||||
c.Info("Created container mount at:", mb)
|
c.Info("Created container mount at:", mb)
|
||||||
|
|
||||||
|
seccomp, err := readSeccompConf(c.SeccompConf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load seccomp config: %v", err)
|
||||||
|
}
|
||||||
|
if seccomp != nil {
|
||||||
|
c.Info("Load seccomp filter: ", c.SeccompConf)
|
||||||
|
}
|
||||||
|
|
||||||
unshareFlags := uintptr(forkexec.UnshareFlags)
|
unshareFlags := uintptr(forkexec.UnshareFlags)
|
||||||
if c.NetShare {
|
if c.NetShare {
|
||||||
unshareFlags ^= syscall.CLONE_NEWNET
|
unshareFlags ^= syscall.CLONE_NEWNET
|
||||||
@ -111,7 +120,14 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) {
|
|||||||
if cgb != nil {
|
if cgb != nil {
|
||||||
cgroupPool = pool.NewFakeCgroupPool(cgb, c.CPUCfsPeriod)
|
cgroupPool = pool.NewFakeCgroupPool(cgb, c.CPUCfsPeriod)
|
||||||
}
|
}
|
||||||
return pool.NewEnvBuilder(b, cgroupPool, workDir, c.Cpuset, c.EnableCPURate), nil
|
return pool.NewEnvBuilder(pool.Config{
|
||||||
|
Builder: b,
|
||||||
|
CgroupPool: cgroupPool,
|
||||||
|
WorkDir: workDir,
|
||||||
|
Cpuset: c.Cpuset,
|
||||||
|
CPURate: c.EnableCPURate,
|
||||||
|
Seccomp: seccomp,
|
||||||
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type credGen struct {
|
type credGen struct {
|
||||||
|
|||||||
47
env/seccomp_linux.go
vendored
Normal file
47
env/seccomp_linux.go
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package env
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/elastic/go-seccomp-bpf"
|
||||||
|
"github.com/elastic/go-ucfg/yaml"
|
||||||
|
"golang.org/x/net/bpf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readSeccompConf(name string) ([]syscall.SockFilter, error) {
|
||||||
|
conf, err := yaml.NewConfigWithFile(name)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var policy seccomp.Policy
|
||||||
|
if err := conf.Unpack(&policy); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inst, err := policy.Assemble()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rawInst, err := bpf.Assemble(inst)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return toSockFilter(rawInst), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toSockFilter(raw []bpf.RawInstruction) []syscall.SockFilter {
|
||||||
|
filter := make([]syscall.SockFilter, 0, len(raw))
|
||||||
|
for _, instruction := range raw {
|
||||||
|
filter = append(filter, syscall.SockFilter{
|
||||||
|
Code: instruction.Op,
|
||||||
|
Jt: instruction.Jt,
|
||||||
|
Jf: instruction.Jf,
|
||||||
|
K: instruction.K,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return filter
|
||||||
|
}
|
||||||
3
go.mod
3
go.mod
@ -6,6 +6,8 @@ require (
|
|||||||
cloud.google.com/go v0.74.0 // indirect
|
cloud.google.com/go v0.74.0 // indirect
|
||||||
github.com/creack/pty v1.1.11
|
github.com/creack/pty v1.1.11
|
||||||
github.com/criyle/go-sandbox v0.5.8
|
github.com/criyle/go-sandbox v0.5.8
|
||||||
|
github.com/elastic/go-seccomp-bpf v1.1.0
|
||||||
|
github.com/elastic/go-ucfg v0.7.0
|
||||||
github.com/fatih/camelcase v1.0.0 // indirect
|
github.com/fatih/camelcase v1.0.0 // indirect
|
||||||
github.com/fatih/structs v1.1.0 // indirect
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
github.com/gin-contrib/pprof v1.3.0
|
github.com/gin-contrib/pprof v1.3.0
|
||||||
@ -26,6 +28,7 @@ require (
|
|||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
go.uber.org/zap v1.16.0
|
go.uber.org/zap v1.16.0
|
||||||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9
|
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||||
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f
|
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
|
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -96,7 +96,9 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
|||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
|
github.com/elastic/go-seccomp-bpf v1.1.0 h1:jUzzDc6LyCtdolZdvL/26dad6rZ9vsc7xZ2eadKECAU=
|
||||||
github.com/elastic/go-seccomp-bpf v1.1.0/go.mod h1:l+89Vy5BzjVcaX8USZRMOwmwwDScE+vxCFzzvQwN7T8=
|
github.com/elastic/go-seccomp-bpf v1.1.0/go.mod h1:l+89Vy5BzjVcaX8USZRMOwmwwDScE+vxCFzzvQwN7T8=
|
||||||
|
github.com/elastic/go-ucfg v0.7.0 h1:1+C/sZdJKww8hKl7XtLPTjs4cFslhQF2fazKTF+ZE+4=
|
||||||
github.com/elastic/go-ucfg v0.7.0/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo=
|
github.com/elastic/go-ucfg v0.7.0/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo=
|
||||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
|||||||
@ -7,22 +7,34 @@ import (
|
|||||||
"github.com/criyle/go-sandbox/container"
|
"github.com/criyle/go-sandbox/container"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Config specifies configuration to build environment builder
|
||||||
|
type Config struct {
|
||||||
|
Builder EnvironmentBuilder
|
||||||
|
CgroupPool CgroupPool
|
||||||
|
WorkDir string
|
||||||
|
Seccomp []syscall.SockFilter
|
||||||
|
Cpuset string
|
||||||
|
CPURate bool
|
||||||
|
}
|
||||||
|
|
||||||
type environmentBuilder struct {
|
type environmentBuilder struct {
|
||||||
builder EnvironmentBuilder
|
builder EnvironmentBuilder
|
||||||
cgPool CgroupPool
|
cgPool CgroupPool
|
||||||
workDir string
|
workDir string
|
||||||
|
seccomp []syscall.SockFilter
|
||||||
cpuset string
|
cpuset string
|
||||||
cpuRate bool
|
cpuRate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEnvBuilder creates builder for linux container pools
|
// NewEnvBuilder creates builder for linux container pools
|
||||||
func NewEnvBuilder(builder EnvironmentBuilder, cgPool CgroupPool, workDir, cpuset string, cpuRate bool) EnvBuilder {
|
func NewEnvBuilder(c Config) EnvBuilder {
|
||||||
return &environmentBuilder{
|
return &environmentBuilder{
|
||||||
builder: builder,
|
builder: c.Builder,
|
||||||
cgPool: cgPool,
|
cgPool: c.CgroupPool,
|
||||||
workDir: workDir,
|
workDir: c.WorkDir,
|
||||||
cpuset: cpuset,
|
seccomp: c.Seccomp,
|
||||||
cpuRate: cpuRate,
|
cpuset: c.Cpuset,
|
||||||
|
cpuRate: c.CPURate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,5 +58,6 @@ func (b *environmentBuilder) Build() (Environment, error) {
|
|||||||
wd: wd[0],
|
wd: wd[0],
|
||||||
cpuset: b.cpuset,
|
cpuset: b.cpuset,
|
||||||
cpuRate: b.cpuRate,
|
cpuRate: b.cpuRate,
|
||||||
|
seccomp: b.seccomp,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ type environ struct {
|
|||||||
cgPool CgroupPool
|
cgPool CgroupPool
|
||||||
wd *os.File // container work dir
|
wd *os.File // container work dir
|
||||||
cpuset string
|
cpuset string
|
||||||
|
seccomp []syscall.SockFilter
|
||||||
cpuRate bool
|
cpuRate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ func (c *environ) Execve(ctx context.Context, param envexec.ExecveParam) (envexe
|
|||||||
CTTY: param.TTY,
|
CTTY: param.TTY,
|
||||||
ExecFile: param.ExecFile,
|
ExecFile: param.ExecFile,
|
||||||
RLimits: rLimits.PrepareRLimit(),
|
RLimits: rLimits.PrepareRLimit(),
|
||||||
|
Seccomp: c.seccomp,
|
||||||
SyncFunc: syncFunc,
|
SyncFunc: syncFunc,
|
||||||
}
|
}
|
||||||
rt := c.Environment.Execve(ctx, p)
|
rt := c.Environment.Execve(ctx, p)
|
||||||
|
|||||||
154
seccomp_example.yaml
Normal file
154
seccomp_example.yaml
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# This is an example seccomp policy for x86_64 that whitelist regular syscalls and prevents network syscalls.
|
||||||
|
# The example is not ready for production use now, should be tuned for specific usages
|
||||||
|
|
||||||
|
# The default action is applied if none of the syscalls match.
|
||||||
|
#
|
||||||
|
# Possible actions:
|
||||||
|
# - kill_process (since Linux 4.14)
|
||||||
|
# - kill_thread
|
||||||
|
# - trap
|
||||||
|
# - errno (returns EPERM)
|
||||||
|
# - trace
|
||||||
|
# - log (since Linux 4.14)
|
||||||
|
# - allow
|
||||||
|
default_action: kill_process
|
||||||
|
|
||||||
|
syscalls:
|
||||||
|
- action: allow
|
||||||
|
names:
|
||||||
|
# file actions
|
||||||
|
- read
|
||||||
|
- write
|
||||||
|
- readv
|
||||||
|
- writev
|
||||||
|
- close
|
||||||
|
- fstat
|
||||||
|
- lseek
|
||||||
|
- dup
|
||||||
|
- dup2
|
||||||
|
- dup3
|
||||||
|
- ioctl
|
||||||
|
- fcntl
|
||||||
|
- fadvise64
|
||||||
|
- pipe
|
||||||
|
- pread64
|
||||||
|
- pwrite64
|
||||||
|
|
||||||
|
# memory action
|
||||||
|
- mmap
|
||||||
|
- mprotect
|
||||||
|
- munmap
|
||||||
|
- brk
|
||||||
|
- mremap
|
||||||
|
- msync
|
||||||
|
- mincore
|
||||||
|
- madvise
|
||||||
|
|
||||||
|
# signal
|
||||||
|
- rt_sigaction
|
||||||
|
- rt_sigprocmask
|
||||||
|
- rt_sigreturn
|
||||||
|
- rt_sigpending
|
||||||
|
- sigaltstack
|
||||||
|
|
||||||
|
# work dir
|
||||||
|
- getcwd
|
||||||
|
|
||||||
|
# exit
|
||||||
|
- exit
|
||||||
|
- exit_group
|
||||||
|
|
||||||
|
# others
|
||||||
|
- arch_prctl
|
||||||
|
- restart_syscall
|
||||||
|
|
||||||
|
# time
|
||||||
|
- gettimeofday
|
||||||
|
- times
|
||||||
|
- time
|
||||||
|
- clock_gettime
|
||||||
|
- clock_getres
|
||||||
|
|
||||||
|
# rlimit
|
||||||
|
- getrlimit
|
||||||
|
- getrusage
|
||||||
|
- setrlimit
|
||||||
|
|
||||||
|
# execve
|
||||||
|
- execve
|
||||||
|
- execveat
|
||||||
|
|
||||||
|
# open
|
||||||
|
- open
|
||||||
|
- openat
|
||||||
|
|
||||||
|
# delete
|
||||||
|
- unlink
|
||||||
|
- unlinkat
|
||||||
|
|
||||||
|
# link
|
||||||
|
- readlink
|
||||||
|
- readlinkat
|
||||||
|
|
||||||
|
# permission check
|
||||||
|
- lstat
|
||||||
|
- stat
|
||||||
|
- access
|
||||||
|
- faccessat
|
||||||
|
|
||||||
|
# process
|
||||||
|
- clone
|
||||||
|
- fork
|
||||||
|
- vfork
|
||||||
|
- nanosleep
|
||||||
|
- wait4
|
||||||
|
|
||||||
|
- getpid
|
||||||
|
- gettid
|
||||||
|
|
||||||
|
# lock
|
||||||
|
- futex
|
||||||
|
|
||||||
|
# other
|
||||||
|
- getdents
|
||||||
|
- getdents64
|
||||||
|
- sysinfo
|
||||||
|
- set_tid_address
|
||||||
|
- set_robust_list
|
||||||
|
- getrandom
|
||||||
|
|
||||||
|
- umask
|
||||||
|
- rename
|
||||||
|
- chmod
|
||||||
|
- mkdir
|
||||||
|
- chdir
|
||||||
|
- fchdir
|
||||||
|
- ftruncate
|
||||||
|
- sched_getaffinity
|
||||||
|
- sched_yield
|
||||||
|
- uname
|
||||||
|
- prlimit64
|
||||||
|
- fchmodat
|
||||||
|
- poll
|
||||||
|
|
||||||
|
# user
|
||||||
|
- getuid
|
||||||
|
- geteuid
|
||||||
|
- getgid
|
||||||
|
- getegid
|
||||||
|
|
||||||
|
- action: errno
|
||||||
|
names:
|
||||||
|
- connect
|
||||||
|
- accept
|
||||||
|
- sendto
|
||||||
|
- recvfrom
|
||||||
|
- sendmsg
|
||||||
|
- recvmsg
|
||||||
|
- bind
|
||||||
|
- listen
|
||||||
|
- setsockopt
|
||||||
|
- socketpair
|
||||||
|
- getsockopt
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user