mirror of
https://github.com/criyle/go-judge.git
synced 2025-09-26 22:39:12 +08:00
143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package env
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
|
|
"github.com/criyle/go-sandbox/container"
|
|
"github.com/criyle/go-sandbox/pkg/mount"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
// Mount defines single mount point configuration.
|
|
// type could be bind / tmpfs
|
|
type Mount struct {
|
|
Type string `yaml:"type"`
|
|
Source string `yaml:"source"`
|
|
Target string `yaml:"target"`
|
|
Readonly bool `yaml:"readonly"`
|
|
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"`
|
|
MaskPaths []string `yaml:"maskPath"`
|
|
InitCmd string `yaml:"initCmd"`
|
|
WorkDir string `yaml:"workDir"`
|
|
HostName string `yaml:"hostName"`
|
|
DomainName string `yaml:"domainName"`
|
|
UID int `yaml:"uid"`
|
|
GID int `yaml:"gid"`
|
|
Proc bool `yaml:"proc"`
|
|
ProcRW bool `yaml:"procrw"`
|
|
}
|
|
|
|
func readMountConfig(p string) (*Mounts, error) {
|
|
var m Mounts
|
|
d, err := os.ReadFile(p)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := yaml.Unmarshal(d, &m); err != nil {
|
|
return nil, err
|
|
}
|
|
return &m, nil
|
|
}
|
|
|
|
func parseMountConfig(m *Mounts) (*mount.Builder, error) {
|
|
b := mount.NewBuilder()
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, mt := range m.Mount {
|
|
target := mt.Target
|
|
if path.IsAbs(target) {
|
|
target = path.Clean(target[1:])
|
|
}
|
|
source := mt.Source
|
|
if !path.IsAbs(source) {
|
|
source = path.Join(wd, source)
|
|
}
|
|
switch mt.Type {
|
|
case "bind":
|
|
b.WithBind(source, target, mt.Readonly)
|
|
case "tmpfs":
|
|
b.WithTmpfs(target, mt.Data)
|
|
default:
|
|
return nil, fmt.Errorf("invalid_mount_type: %v", mt.Type)
|
|
}
|
|
}
|
|
if m.Proc {
|
|
b.WithProcRW(m.ProcRW)
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
func getDefaultMount(tmpFsConf string) *mount.Builder {
|
|
return mount.NewBuilder().
|
|
// basic exec and lib
|
|
WithBind("/bin", "bin", true).
|
|
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
|
|
// changing the fs uid and gid would be a good idea
|
|
WithProc().
|
|
// some compiler have multiple version
|
|
WithBind("/etc/alternatives", "etc/alternatives", true).
|
|
// fpc wants /etc/fpc.cfg
|
|
WithBind("/etc/fpc.cfg", "etc/fpc.cfg", true).
|
|
// mono wants /etc/mono
|
|
WithBind("/etc/mono", "etc/mono", true).
|
|
// go wants /dev/null
|
|
WithBind("/dev/null", "dev/null", false).
|
|
// ghc wants /var/lib/ghc
|
|
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"},
|
|
}
|
|
|
|
var defaultMaskPaths = []string{
|
|
"/sys/firmware",
|
|
"/sys/devices/virtual/powercap",
|
|
"/proc/acpi",
|
|
"/proc/asound",
|
|
"/proc/kcore",
|
|
"/proc/keys",
|
|
"/proc/latency_stats",
|
|
"/proc/timer_list",
|
|
"/proc/timer_stats",
|
|
"/proc/sched_debug",
|
|
"/proc/scsi",
|
|
"/usr/lib/wsl/drivers",
|
|
"/usr/lib/wsl/lib",
|
|
}
|