Skip to content

Commit

Permalink
Add support to load a seccomp filter
Browse files Browse the repository at this point in the history
  • Loading branch information
criyle committed Dec 14, 2020
1 parent e3111ee commit 04cfb36
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 8 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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...
- `-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\])
- `-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

Expand Down
3 changes: 2 additions & 1 deletion cmd/executorserver/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ type Config struct {
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"`
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"`
CgroupPrefix string `flagUsage:"control cgroup prefix" default:"executor_server"`
ContainerCredStart int `flagUsage:"control the start uid&gid for container" default:"10000"`
Expand Down
1 change: 1 addition & 0 deletions cmd/executorserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func main() {
ContainerCredStart: conf.ContainerCredStart,
EnableCPURate: conf.EnableCPURate,
CPUCfsPeriod: conf.CPUCfsPeriod,
SeccompConf: conf.SeccompConf,
Logger: logger.Sugar(),
})
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions env/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Config struct {
TmpFsParam string
NetShare bool
MountConf string
SeccompConf string
CgroupPrefix string
Cpuset string
ContainerCredStart int
Expand Down
18 changes: 17 additions & 1 deletion env/env_linux.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package env

import (
"fmt"
"io/ioutil"
"os"
"sync/atomic"
Expand Down Expand Up @@ -45,6 +46,14 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) {
m := mb.FilterNotExist().Mounts
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)
if c.NetShare {
unshareFlags ^= syscall.CLONE_NEWNET
Expand Down Expand Up @@ -111,7 +120,14 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) {
if cgb != nil {
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 {
Expand Down
47 changes: 47 additions & 0 deletions env/seccomp_linux.go
Original file line number Diff line number Diff line change
@@ -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 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ require (
cloud.google.com/go v0.74.0 // indirect
github.com/creack/pty v1.1.11
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/structs v1.1.0 // indirect
github.com/gin-contrib/pprof v1.3.0
Expand All @@ -26,6 +28,7 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.16.0
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/sys v0.0.0-20201211090839-8ad439b19e0f
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
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-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/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=
Expand Down
25 changes: 19 additions & 6 deletions pkg/pool/envbuilder_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,34 @@ import (
"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 {
builder EnvironmentBuilder
cgPool CgroupPool
workDir string
seccomp []syscall.SockFilter
cpuset string
cpuRate bool
}

// 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{
builder: builder,
cgPool: cgPool,
workDir: workDir,
cpuset: cpuset,
cpuRate: cpuRate,
builder: c.Builder,
cgPool: c.CgroupPool,
workDir: c.WorkDir,
seccomp: c.Seccomp,
cpuset: c.Cpuset,
cpuRate: c.CPURate,
}
}

Expand All @@ -46,5 +58,6 @@ func (b *environmentBuilder) Build() (Environment, error) {
wd: wd[0],
cpuset: b.cpuset,
cpuRate: b.cpuRate,
seccomp: b.seccomp,
}, nil
}
2 changes: 2 additions & 0 deletions pkg/pool/environment_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type environ struct {
cgPool CgroupPool
wd *os.File // container work dir
cpuset string
seccomp []syscall.SockFilter
cpuRate bool
}

Expand Down Expand Up @@ -70,6 +71,7 @@ func (c *environ) Execve(ctx context.Context, param envexec.ExecveParam) (envexe
CTTY: param.TTY,
ExecFile: param.ExecFile,
RLimits: rLimits.PrepareRLimit(),
Seccomp: c.seccomp,
SyncFunc: syncFunc,
}
rt := c.Environment.Execve(ctx, p)
Expand Down
154 changes: 154 additions & 0 deletions seccomp_example.yaml
Original file line number Diff line number Diff line change
@@ -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


0 comments on commit 04cfb36

Please sign in to comment.