diff --git a/cmd/runprog/main_linux.go b/cmd/runprog/main_linux.go index f408702..f010b3b 100644 --- a/cmd/runprog/main_linux.go +++ b/cmd/runprog/main_linux.go @@ -307,6 +307,9 @@ func start() (*runner.Result, error) { if err != nil { return nil, fmt.Errorf("failed to ping container: %v", err) } + if unsafe { + filter = nil + } r = &containerRunner{ Environment: m, ExecveParam: container.ExecveParam{ diff --git a/container/container_init_linux.go b/container/container_init_linux.go index e67d2b2..272aeff 100644 --- a/container/container_init_linux.go +++ b/container/container_init_linux.go @@ -3,6 +3,7 @@ package container import ( "fmt" "os" + "path/filepath" "runtime" "strconv" "sync" @@ -263,6 +264,17 @@ func initFileSystem(c containerConfig) error { if err := os.Remove(oldRoot); err != nil { return fmt.Errorf("init_fs: unlink(old_root) %v", err) } + // create symlinks + for _, l := range c.SymbolicLinks { + // ensure dir exists + dir := filepath.Dir(l.LinkPath) + if err := os.MkdirAll(dir, 0755); err != nil { + return fmt.Errorf("init_fs: mkdir_all(%s) %v", dir, err) + } + if err := os.Symlink(l.Target, l.LinkPath); err != nil { + return fmt.Errorf("init_fs: symlink %v", err) + } + } // readonly root const remountFlag = syscall.MS_BIND | syscall.MS_REMOUNT | syscall.MS_RDONLY | syscall.MS_NOATIME | syscall.MS_NOSUID if err := syscall.Mount(tmpfs, "/", tmpfs, remountFlag, ""); err != nil { diff --git a/container/environment_linux.go b/container/environment_linux.go index 6ff8b81..be038dc 100644 --- a/container/environment_linux.go +++ b/container/environment_linux.go @@ -27,6 +27,9 @@ type Builder struct { // Mounts defines container mount points, empty uses default mounts Mounts []mount.Mount + // SymbolicLinks defines symlinks to be created after mount file system + SymbolicLinks []SymbolicLink + // WorkDir defines container default work directory (default: /w) WorkDir string @@ -54,6 +57,12 @@ type Builder struct { ContainerGID int } +// SymbolicLink defines symlinks to be created after mount +type SymbolicLink struct { + LinkPath string + Target string +} + // CredGenerator generates uid / gid credential used by container // to isolate process and file system access type CredGenerator interface { @@ -94,6 +103,13 @@ type sendCmd struct { Msg unixsocket.Msg } +var defaultSymLinks = []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"}, +} + // Build creates new environment with underlying container func (b *Builder) Build() (Environment, error) { c, err := b.startContainer() @@ -116,6 +132,12 @@ func (b *Builder) Build() (Environment, error) { FilterNotExist().Mounts } + // container symbolic links + links := b.SymbolicLinks + if len(links) == 0 { + links = defaultSymLinks + } + // container root directory on the host root := b.Root if root == "" { @@ -143,6 +165,7 @@ func (b *Builder) Build() (Environment, error) { DomainName: domainName, ContainerRoot: root, Mounts: mounts, + SymbolicLinks: links, Cred: b.CredGenerator != nil, ContainerUID: b.ContainerUID, ContainerGID: b.ContainerGID, diff --git a/container/protocol_linux.go b/container/protocol_linux.go index 9c9b232..4859a8d 100644 --- a/container/protocol_linux.go +++ b/container/protocol_linux.go @@ -57,6 +57,7 @@ type containerConfig struct { ContainerRoot string Mounts []mount.Mount + SymbolicLinks []SymbolicLink ContainerUID int ContainerGID int diff --git a/go.mod b/go.mod index 8353dff..fa6987b 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.17 require ( github.com/elastic/go-seccomp-bpf v1.2.0 - golang.org/x/net v0.0.0-20211029224645-99673261e6eb - golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 + golang.org/x/net v0.0.0-20211111160137-58aab5ef257a + golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e ) require github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index f582c77..a77ddbb 100644 --- a/go.sum +++ b/go.sum @@ -13,14 +13,14 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=