From 049d26a17934710fc21ad3ec1baf482d057e16a6 Mon Sep 17 00:00:00 2001 From: criyle Date: Fri, 12 Nov 2021 01:35:47 -0800 Subject: [PATCH] linuxc: limit open file count & add stdio devices --- README.cn.md | 3 ++- README.md | 3 ++- cmd/executorserver/config/config.go | 1 + cmd/executorserver/main.go | 1 + env/env_linux.go | 14 +++++++++- env/linuxcontainer/environment_linux.go | 1 + env/mount_linux.go | 22 +++++++++++++++- envexec/cmd.go | 1 + envexec/interface.go | 1 + envexec/run_single.go | 2 ++ go.mod | 14 +++++----- go.sum | 34 +++++++++++++++---------- mount.yaml | 24 +++++++++++++++++ worker/model.go | 2 ++ worker/worker.go | 16 +++++++++++- 15 files changed, 113 insertions(+), 26 deletions(-) diff --git a/README.cn.md b/README.cn.md index b2b3de7..3c5a1a6 100644 --- a/README.cn.md +++ b/README.cn.md @@ -62,6 +62,7 @@ - 默认没有磁盘文件复制限制,使用 `-src-prefix` 限制 copyIn 操作文件目录前缀(需要绝对路径) - 默认时间和内存使用检查周期为 100 毫秒(`100ms`),使用 `-time-limit-checker-interval` 指定 - 默认最大输出限制为 `256MiB`,使用 `-output-limit` 指定 +- 默认最大打开文件描述符为 `256`,使用 `-open-file-limit` 指定 - 默认最大额外内存使用为 `16KiB` ,使用 `-extra-memory-limit` 指定 - 默认最大 `copyOut` 文件大小为 `64MiB` ,使用 `-copy-out-limit` 指定 - 使用 `-cpuset` 指定 `cpuset.cpus` (仅 Linux) @@ -128,7 +129,7 @@ docker run -it --rm --privileged --shm-size=256m -p 5050:5050 criyle/executorser ### 容器的文件系统 -在 Linux 平台,默认只读挂载点包括主机的 `/lib`, `/lib64`, `/usr`, `/bin`, `/etc/alternatives`, `/etc/fpc.cfg`, `/dev/null`, `/dev/urandom` 和临时文件系统 `/w`, `/tmp` 以及 `/proc`。 +在 Linux 平台,默认只读挂载点包括主机的 `/lib`, `/lib64`, `/usr`, `/bin`, `/etc/ld.so.cache`, `/etc/alternatives`, `/etc/fpc.cfg`, `/dev/null`, `/dev/urandom`, `/dev/random`, `/dev/zero`, `/dev/full` 和临时文件系统 `/w`, `/tmp` 以及 `/proc`。 使用 `mount.yaml` 定制容器文件系统。 diff --git a/README.md b/README.md index 421818e..d4078f2 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Sandbox: - `-output-limit` specifies size limit of POSIX rlimit of output (default 256MiB) - `-extra-memory-limit` specifies the additional memory limit to check memory limit exceeded (default 16KiB) - `-copy-out-limit` specifies the default file copy out max (default 64MiB) +- `-open-file-limit` specifies the max number of open files (default 256) - `-cpuset` specifies `cpuset.cpus` cgroup for each container (Linux only) - `-container-cred-start` specifies container `setuid` / `setgid` credential start point (default: 10000) (Linux only) - for example, by default container 0 will run with 10001 uid & gid and container 1 will run with 10002 uid & gid... @@ -147,7 +148,7 @@ Run `./executorshell`, connect to gRPC endpoint with interactive shell. ### Container Root Filesystem -For linux platform, the default mounts points are bind mounting host's `/lib`, `/lib64`, `/usr`, `/bin`, `/etc/alternatives`, `/etc/fpc.cfg`, `/dev/null`, `/dev/urandom` and mounts tmpfs at `/w`, `/tmp` and creates `/proc`. +For linux platform, the default mounts points are bind mounting host's `/lib`, `/lib64`, `/usr`, `/bin`, `/etc/ld.so.cache`, `/etc/alternatives`, `/etc/fpc.cfg`, `/dev/null`, `/dev/urandom`, `/dev/random`, `/dev/zero`, `/dev/full` and mounts tmpfs at `/w`, `/tmp` and creates `/proc`. To customize mount points, please look at example `mount.yaml` file. diff --git a/cmd/executorserver/config/config.go b/cmd/executorserver/config/config.go index f67e179..b49af00 100644 --- a/cmd/executorserver/config/config.go +++ b/cmd/executorserver/config/config.go @@ -31,6 +31,7 @@ type Config struct { ExtraMemoryLimit *envexec.Size `flagUsage:"specifies extra memory buffer for check memory limit" default:"16k"` OutputLimit *envexec.Size `flagUsage:"specifies POSIX rlimit for output for each command" default:"256m"` CopyOutLimit *envexec.Size `flagUsage:"specifies default file copy out max" default:"64m"` + OpenFileLimit int `flagUsage:"specifies max open file count" default:"256"` Cpuset string `flagUsage:"control the usage of cpuset for all containerd process"` EnableCPURate bool `flagUsage:"enable cpu cgroup rate control"` CPUCfsPeriod time.Duration `flagUsage:"set cpu.cfs_period" default:"100ms"` diff --git a/cmd/executorserver/main.go b/cmd/executorserver/main.go index 1bf2492..5dec31d 100644 --- a/cmd/executorserver/main.go +++ b/cmd/executorserver/main.go @@ -371,6 +371,7 @@ func newWorker(conf *config.Config, envPool worker.EnvironmentPool, fs filestore ExtraMemoryLimit: *conf.ExtraMemoryLimit, OutputLimit: *conf.OutputLimit, CopyOutLimit: *conf.CopyOutLimit, + OpenFileLimit: uint64(conf.OpenFileLimit), ExecObserver: execObserve, }) } diff --git a/env/env_linux.go b/env/env_linux.go index a31c415..eff74d7 100644 --- a/env/env_linux.go +++ b/env/env_linux.go @@ -30,7 +30,10 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) { } c.Info("Created tmp dir for container root at:", root) - var mb *mount.Builder + var ( + mb *mount.Builder + sym []container.SymbolicLink + ) mc, err := readMountConfig(c.MountConf) if err != nil { if !os.IsNotExist(err) { @@ -44,6 +47,14 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) { return nil, err } } + if mc != nil && len(mc.SymLinks) > 0 { + sym = make([]container.SymbolicLink, 0, len(mc.SymLinks)) + for _, l := range mc.SymLinks { + sym = append(sym, container.SymbolicLink{LinkPath: l.LinkPath, Target: l.Target}) + } + } else { + sym = defaultSymLinks + } m := mb.FilterNotExist().Mounts c.Info("Created container mount at:", mb) @@ -88,6 +99,7 @@ func NewBuilder(c Config) (pool.EnvBuilder, error) { b := &container.Builder{ Root: root, Mounts: m, + SymbolicLinks: sym, CredGenerator: credGen, Stderr: os.Stderr, CloneFlags: unshareFlags, diff --git a/env/linuxcontainer/environment_linux.go b/env/linuxcontainer/environment_linux.go index aa5fecc..4bb78af 100644 --- a/env/linuxcontainer/environment_linux.go +++ b/env/linuxcontainer/environment_linux.go @@ -59,6 +59,7 @@ func (c *environ) Execve(ctx context.Context, param envexec.ExecveParam) (envexe CPU: uint64(limit.Time.Truncate(time.Second)/time.Second) + 1, FileSize: limit.Output.Byte(), Stack: limit.Stack.Byte(), + OpenFile: limit.OpenFile, DisableCore: true, } diff --git a/env/mount_linux.go b/env/mount_linux.go index 9d57336..1dd31ff 100644 --- a/env/mount_linux.go +++ b/env/mount_linux.go @@ -5,6 +5,7 @@ import ( "os" "path" + "github.com/criyle/go-sandbox/container" "github.com/criyle/go-sandbox/pkg/mount" "gopkg.in/yaml.v2" ) @@ -19,9 +20,16 @@ type Mount struct { Data string `yaml:"data"` } +// Link defines symlinks to be created after mounts +type Link struct { + LinkPath string `yaml:"linkPath"` + Target string `yaml:"target"` +} + // Mounts defines mount points for the container. type Mounts struct { Mount []Mount `yaml:"mount"` + SymLinks []Link `yaml:"symLink"` WorkDir string `yaml:"workDir"` HostName string `yaml:"hostName"` DomainName string `yaml:"domainName"` @@ -63,7 +71,7 @@ func parseMountConfig(m *Mounts) (*mount.Builder, error) { case "tmpfs": b.WithTmpfs(target, mt.Data) default: - return nil, fmt.Errorf("Invalid mount type") + return nil, fmt.Errorf("invalid_mount_type: %v", mt.Type) } } if m.Proc { @@ -79,6 +87,7 @@ func getDefaultMount(tmpFsConf string) *mount.Builder { WithBind("/lib", "lib", true). WithBind("/lib64", "lib64", true). WithBind("/usr", "usr", true). + WithBind("/etc/ld.so.cache", "etc/ld.so.cache", true). // java wants /proc/self/exe as it need relative path for lib // however, /proc gives interface like /proc/1/fd/3 .. // it is fine since open that file will be a EPERM @@ -96,8 +105,19 @@ func getDefaultMount(tmpFsConf string) *mount.Builder { WithBind("/var/lib/ghc", "var/lib/ghc", true). // javaScript wants /dev/urandom WithBind("/dev/urandom", "dev/urandom", false). + // additional devices + WithBind("/dev/random", "dev/random", false). + WithBind("/dev/zero", "dev/zero", false). + WithBind("/dev/full", "dev/full", false). // work dir WithTmpfs("w", tmpFsConf). // tmp dir WithTmpfs("tmp", tmpFsConf) } + +var defaultSymLinks = []container.SymbolicLink{ + {LinkPath: "/dev/fd", Target: "/proc/self/fd"}, + {LinkPath: "/dev/stdin", Target: "/proc/self/fd/0"}, + {LinkPath: "/dev/stdout", Target: "/proc/self/fd/1"}, + {LinkPath: "/dev/stderr", Target: "/proc/self/fd/2"}, +} diff --git a/envexec/cmd.go b/envexec/cmd.go index 8dbf979..e04cff6 100644 --- a/envexec/cmd.go +++ b/envexec/cmd.go @@ -37,6 +37,7 @@ type Cmd struct { ExtraMemoryLimit Size OutputLimit Size ProcLimit uint64 + OpenFileLimit uint64 CPURateLimit uint64 StrictMemoryLimit bool CPUSetLimit string diff --git a/envexec/interface.go b/envexec/interface.go index 6192e12..b288e3a 100644 --- a/envexec/interface.go +++ b/envexec/interface.go @@ -35,6 +35,7 @@ type Limit struct { Stack Size // Stack limit Output Size // Output limit Rate uint64 // CPU Rate limit + OpenFile uint64 // Number of open files CPUSet string // CPU set limit StrictMemory bool // Use stricter memory limit (e.g. rlimit) } diff --git a/envexec/run_single.go b/envexec/run_single.go index 833bfd9..5247f66 100644 --- a/envexec/run_single.go +++ b/envexec/run_single.go @@ -113,7 +113,9 @@ func runSingleExecve(ctx context.Context, m Environment, c *Cmd, fds []*os.File) Memory: memoryLimit, Proc: c.ProcLimit, Stack: stackLimit, + Output: c.OutputLimit, Rate: c.CPURateLimit, + OpenFile: c.OpenFileLimit, CPUSet: c.CPUSetLimit, StrictMemory: c.StrictMemoryLimit, }, diff --git a/go.mod b/go.mod index ad6e312..d857a7f 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.17 require ( github.com/creack/pty v1.1.17 - github.com/criyle/go-sandbox v0.8.7 + github.com/criyle/go-sandbox v0.8.9 github.com/elastic/go-seccomp-bpf v1.2.0 - github.com/elastic/go-ucfg v0.8.3 + github.com/elastic/go-ucfg v0.8.4 github.com/gin-contrib/pprof v1.3.0 github.com/gin-contrib/zap v0.0.1 github.com/gin-gonic/gin v1.7.4 @@ -18,11 +18,11 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/zsais/go-gin-prometheus v0.1.0 go.uber.org/zap v1.19.1 - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 - golang.org/x/net v0.0.0-20211029224645-99673261e6eb + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa + golang.org/x/net v0.0.0-20211111160137-58aab5ef257a golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 - google.golang.org/grpc v1.41.0 + golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e + google.golang.org/grpc v1.42.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -53,7 +53,7 @@ require ( go.uber.org/multierr v1.7.0 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/genproto v0.0.0-20211029142109-e255c875f7c7 // indirect + google.golang.org/genproto v0.0.0-20211111162719-482062a4217b // indirect ) retract ( diff --git a/go.sum b/go.sum index c0d6ac1..6eda341 100644 --- a/go.sum +++ b/go.sum @@ -61,21 +61,24 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/criyle/go-sandbox v0.8.7 h1:mwRNoKz/DTvl8F37Ik0E8+BiJB//OMczeeOrMOEHPC8= -github.com/criyle/go-sandbox v0.8.7/go.mod h1:jPzRziXvdL3ZdK47bAUJP7F3s4udupx9M5lz/uPyeXg= +github.com/criyle/go-sandbox v0.8.9 h1:xZZBTnY/jgZzgfQeA7+vu9PrY+EEdF7U1ypSfUWN6cQ= +github.com/criyle/go-sandbox v0.8.9/go.mod h1:lOJ9IuA26DCglL8BakkM/xMmQ455mZvEapGZ4c02jkc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elastic/go-seccomp-bpf v1.2.0 h1:K5fToUAMzm0pmdlYORmw0FP0DloRa1SfqRYkum647Yk= github.com/elastic/go-seccomp-bpf v1.2.0/go.mod h1:l+89Vy5BzjVcaX8USZRMOwmwwDScE+vxCFzzvQwN7T8= github.com/elastic/go-ucfg v0.7.0/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo= -github.com/elastic/go-ucfg v0.8.3 h1:leywnFjzr2QneZZWhE6uWd+QN/UpP0sdJRHYyuFvkeo= -github.com/elastic/go-ucfg v0.8.3/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo= +github.com/elastic/go-ucfg v0.8.4 h1:OAHTnubzXKsYYYWVzl8psLcS5mCbNKjXxtMY41itthk= +github.com/elastic/go-ucfg v0.8.4/go.mod h1:4E8mPOLSUV9hQ7sgLEJ4bvt0KhMuDJa8joDT2QGAEKA= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -235,6 +238,7 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -324,8 +328,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -389,8 +393,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211111160137-58aab5ef257a h1:c83jeVQW0KGKNaKBRfelNYNHaev+qawl9yaA825s8XE= +golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -455,8 +459,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 h1:giLT+HuUP/gXYrG2Plg9WTjj4qhfgaW424ZIFog3rlk= -golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e h1:zeJt6jBtVDK23XK9QXcmG0FvO0elikp0dYZQZOeL1y0= +golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -574,8 +578,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211029142109-e255c875f7c7 h1:aaSaYY/DIDJy3f/JLXWv6xJ1mBQSRnQ1s5JhAFTnzO4= -google.golang.org/genproto v0.0.0-20211029142109-e255c875f7c7/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211111162719-482062a4217b h1:qvEQEwKjZRAg6rjY/jqfJ7T8/w/D7jTIFJGcaSka96k= +google.golang.org/genproto v0.0.0-20211111162719-482062a4217b/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -591,8 +595,8 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -611,11 +615,13 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/hjson/hjson-go.v3 v3.0.1/go.mod h1:X6zrTSVeImfwfZLfgQdInl9mWjqPqgH90jom9nym/lw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/mount.yaml b/mount.yaml index b387f99..2230a79 100644 --- a/mount.yaml +++ b/mount.yaml @@ -16,6 +16,10 @@ mount: source: /usr target: /usr readonly: true + - type: bind + source: /etc/ld.so.cache + target: /etc/ld.so.cache + readonly: true # Some compiler have multiple versions - type: bind source: /etc/alternatives @@ -44,6 +48,16 @@ mount: - type: bind source: /dev/urandom target: /dev/urandom + # additional devices + - type: bind + source: /dev/random + target: /dev/random + - type: bind + source: /dev/zero + target: /dev/zero + - type: bind + source: /dev/full + target: /dev/full # work dir - type: tmpfs target: /w @@ -58,6 +72,16 @@ mount: target: /etc/passwd # java & ghc wants /proc/self/exe proc: true +# create /dev standard io +symLink: + - linkPath: /dev/fd + target: /proc/self/fd + - linkPath: /dev/stdin + target: /proc/self/fd/0 + - linkPath: /dev/stdout + target: /proc/self/fd/1 + - linkPath: /dev/stderr + target: /proc/self/fd/2 # container work directory workDir: /w # container host name diff --git a/worker/model.go b/worker/model.go index 89fe806..dd76774 100644 --- a/worker/model.go +++ b/worker/model.go @@ -24,7 +24,9 @@ type Cmd struct { ClockLimit time.Duration MemoryLimit Size StackLimit Size + OutputLimit Size ProcLimit uint64 + OpenFileLimit uint64 CPURateLimit uint64 CPUSetLimit string StrictMemoryLimit bool diff --git a/worker/worker.go b/worker/worker.go index a73ecda..8492db9 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -30,6 +30,7 @@ type Config struct { ExtraMemoryLimit envexec.Size OutputLimit envexec.Size CopyOutLimit envexec.Size + OpenFileLimit uint64 ExecObserver func(Response) } @@ -52,6 +53,7 @@ type worker struct { extraMemoryLimit envexec.Size outputLimit envexec.Size copyOutLimit envexec.Size + openFileLimit uint64 execObserver func(Response) @@ -79,6 +81,7 @@ func New(conf Config) Worker { extraMemoryLimit: conf.ExtraMemoryLimit, outputLimit: conf.OutputLimit, copyOutLimit: conf.CopyOutLimit, + openFileLimit: conf.OpenFileLimit, execObserver: conf.ExecObserver, } } @@ -311,6 +314,16 @@ func (w *worker) prepareCmd(rc Cmd) (*envexec.Cmd, error) { copyOutMax = envexec.Size(rc.CopyOutMax) } + outputLimit := rc.OutputLimit + if outputLimit == 0 { + outputLimit = w.outputLimit + } + + openFileLimit := rc.OpenFileLimit + if openFileLimit == 0 { + openFileLimit = w.openFileLimit + } + return &envexec.Cmd{ Args: rc.Args, Env: rc.Env, @@ -320,8 +333,9 @@ func (w *worker) prepareCmd(rc Cmd) (*envexec.Cmd, error) { MemoryLimit: envexec.Size(rc.MemoryLimit), StackLimit: envexec.Size(rc.StackLimit), ExtraMemoryLimit: w.extraMemoryLimit, - OutputLimit: w.outputLimit, + OutputLimit: outputLimit, ProcLimit: rc.ProcLimit, + OpenFileLimit: openFileLimit, CPURateLimit: rc.CPURateLimit, CPUSetLimit: rc.CPUSetLimit, StrictMemoryLimit: rc.StrictMemoryLimit,