diff options
Diffstat (limited to 'bwrap')
| -rw-r--r-- | bwrap/config.bool.go | 64 | ||||
| -rw-r--r-- | bwrap/config.go | 265 | ||||
| -rw-r--r-- | bwrap/config.int.go | 22 | ||||
| -rw-r--r-- | bwrap/config.interface.go | 34 | ||||
| -rw-r--r-- | bwrap/config.pair.go | 54 | ||||
| -rw-r--r-- | bwrap/config.string.go | 35 | ||||
| -rw-r--r-- | bwrap/config_test.go | 88 |
7 files changed, 0 insertions, 562 deletions
diff --git a/bwrap/config.bool.go b/bwrap/config.bool.go deleted file mode 100644 index 81e6ab7b..00000000 --- a/bwrap/config.bool.go +++ /dev/null @@ -1,64 +0,0 @@ -package bwrap - -const ( - UnshareAll = iota - UnshareUser - UnshareIPC - UnsharePID - UnshareNet - UnshareUTS - UnshareCGroup - ShareNet - - UserNS - Clearenv - - NewSession - DieWithParent - AsInit - - boolC -) - -var boolArgs = func() (b [boolC][]string) { - b[UnshareAll] = []string{"--unshare-all"} - b[UnshareUser] = []string{"--unshare-user"} - b[UnshareIPC] = []string{"--unshare-ipc"} - b[UnsharePID] = []string{"--unshare-pid"} - b[UnshareNet] = []string{"--unshare-net"} - b[UnshareUTS] = []string{"--unshare-uts"} - b[UnshareCGroup] = []string{"--unshare-cgroup"} - b[ShareNet] = []string{"--share-net"} - - b[UserNS] = []string{"--disable-userns", "--assert-userns-disabled"} - b[Clearenv] = []string{"--clearenv"} - - b[NewSession] = []string{"--new-session"} - b[DieWithParent] = []string{"--die-with-parent"} - b[AsInit] = []string{"--as-pid-1"} - - return -}() - -func (c *Config) boolArgs() (b [boolC]bool) { - if c.Unshare == nil { - b[UnshareAll] = true - b[ShareNet] = c.Net - } else { - b[UnshareUser] = c.Unshare.User - b[UnshareIPC] = c.Unshare.IPC - b[UnsharePID] = c.Unshare.PID - b[UnshareNet] = c.Unshare.Net - b[UnshareUTS] = c.Unshare.UTS - b[UnshareCGroup] = c.Unshare.CGroup - } - - b[UserNS] = !c.UserNS - b[Clearenv] = c.Clearenv - - b[NewSession] = c.NewSession - b[DieWithParent] = c.DieWithParent - b[AsInit] = c.AsInit - - return -} diff --git a/bwrap/config.go b/bwrap/config.go deleted file mode 100644 index c20a33b0..00000000 --- a/bwrap/config.go +++ /dev/null @@ -1,265 +0,0 @@ -package bwrap - -import ( - "os" - "strconv" -) - -func (c *Config) Args() (args []string) { - b := c.boolArgs() - n := c.intArgs() - s := c.stringArgs() - p := c.pairArgs() - g := c.interfaceArgs() - - argc := 0 - for i, arg := range b { - if arg { - argc += len(boolArgs[i]) - } - } - for _, arg := range n { - if arg != nil { - argc += 2 - } - } - for _, arg := range s { - argc += len(arg) * 2 - } - for _, arg := range p { - argc += len(arg) * 3 - } - - args = make([]string, 0, argc) - for i, arg := range b { - if arg { - args = append(args, boolArgs[i]...) - } - } - for i, arg := range n { - if arg != nil { - args = append(args, intArgs[i], strconv.Itoa(*arg)) - } - } - for i, arg := range s { - for _, v := range arg { - args = append(args, stringArgs[i], v) - } - } - for i, arg := range p { - for _, v := range arg { - args = append(args, pairArgs[i], v[0], v[1]) - } - } - for i, arg := range g { - for _, v := range arg { - args = append(args, v.Value(interfaceArgs[i])...) - } - } - - return -} - -type Config struct { - // unshare every namespace we support by default if nil - // (--unshare-all) - Unshare *UnshareConfig `json:"unshare,omitempty"` - // retain the network namespace (can only combine with nil Unshare) - // (--share-net) - Net bool `json:"net"` - - // disable further use of user namespaces inside sandbox and fail unless - // further use of user namespace inside sandbox is disabled if false - // (--disable-userns) (--assert-userns-disabled) - UserNS bool `json:"userns"` - - // custom uid in the sandbox, requires new user namespace - // (--uid UID) - UID *int `json:"uid,omitempty"` - // custom gid in the sandbox, requires new user namespace - // (--gid GID) - GID *int `json:"gid,omitempty"` - // custom hostname in the sandbox, requires new uts namespace - // (--hostname NAME) - Hostname string `json:"hostname,omitempty"` - - // change directory - // (--chdir DIR) - Chdir string `json:"chdir,omitempty"` - // unset all environment variables - // (--clearenv) - Clearenv bool `json:"clearenv"` - // set environment variable - // (--setenv VAR VALUE) - SetEnv map[string]string `json:"setenv,omitempty"` - // unset environment variables - // (--unsetenv VAR) - UnsetEnv []string `json:"unsetenv,omitempty"` - - // take a lock on file while sandbox is running - // (--lock-file DEST) - LockFile []string `json:"lock_file,omitempty"` - - // bind mount host path on sandbox - // (--bind SRC DEST) - Bind [][2]string `json:"bind,omitempty"` - // equal to Bind but ignores non-existent host path - // (--bind-try SRC DEST) - BindTry [][2]string `json:"bind_try,omitempty"` - - // bind mount host path on sandbox, allowing device access - // (--dev-bind SRC DEST) - DevBind [][2]string `json:"dev_bind,omitempty"` - // equal to DevBind but ignores non-existent host path - // (--dev-bind-try SRC DEST) - DevBindTry [][2]string `json:"dev_bind_try,omitempty"` - - // bind mount host path readonly on sandbox - // (--ro-bind SRC DEST) - ROBind [][2]string `json:"ro_bind,omitempty"` - // equal to ROBind but ignores non-existent host path - // (--ro-bind-try SRC DEST) - ROBindTry [][2]string `json:"ro_bind_try,omitempty"` - - // remount path as readonly; does not recursively remount - // (--remount-ro DEST) - RemountRO []string `json:"remount_ro,omitempty"` - - // mount new procfs in sandbox - // (--proc DEST) - Procfs []PermConfig[string] `json:"proc,omitempty"` - // mount new dev in sandbox - // (--dev DEST) - DevTmpfs []PermConfig[string] `json:"dev,omitempty"` - // mount new tmpfs in sandbox - // (--tmpfs DEST) - Tmpfs []PermConfig[TmpfsConfig] `json:"tmpfs,omitempty"` - // mount new mqueue in sandbox - // (--mqueue DEST) - Mqueue []PermConfig[string] `json:"mqueue,omitempty"` - // create dir in sandbox - // (--dir DEST) - Dir []PermConfig[string] `json:"dir,omitempty"` - // create symlink within sandbox - // (--symlink SRC DEST) - Symlink []PermConfig[[2]string] `json:"symlink,omitempty"` - - // change permissions (must already exist) - // (--chmod OCTAL PATH) - Chmod map[string]os.FileMode `json:"chmod,omitempty"` - - // create a new terminal session - // (--new-session) - NewSession bool `json:"new_session"` - // kills with SIGKILL child process (COMMAND) when bwrap or bwrap's parent dies. - // (--die-with-parent) - DieWithParent bool `json:"die_with_parent"` - // do not install a reaper process with PID=1 - // (--as-pid-1) - AsInit bool `json:"as_init"` - - /* unmapped options include: - --unshare-user-try Create new user namespace if possible else continue by skipping it - --unshare-cgroup-try Create new cgroup namespace if possible else continue by skipping it - --userns FD Use this user namespace (cannot combine with --unshare-user) - --userns2 FD After setup switch to this user namespace, only useful with --userns - --pidns FD Use this pid namespace (as parent namespace if using --unshare-pid) - --sync-fd FD Keep this fd open while sandbox is running - --exec-label LABEL Exec label for the sandbox - --file-label LABEL File label for temporary sandbox content - --file FD DEST Copy from FD to destination DEST - --bind-data FD DEST Copy from FD to file which is bind-mounted on DEST - --ro-bind-data FD DEST Copy from FD to file which is readonly bind-mounted on DEST - --seccomp FD Load and use seccomp rules from FD (not repeatable) - --add-seccomp-fd FD Load and use seccomp rules from FD (repeatable) - --block-fd FD Block on FD until some data to read is available - --userns-block-fd FD Block on FD until the user namespace is ready - --info-fd FD Write information about the running container to FD - --json-status-fd FD Write container status to FD as multiple JSON documents - --cap-add CAP Add cap CAP when running as privileged user - --cap-drop CAP Drop cap CAP when running as privileged user - - among which --args is used internally for passing arguments */ -} - -type UnshareConfig struct { - // (--unshare-user) - // create new user namespace - User bool `json:"user"` - // (--unshare-ipc) - // create new ipc namespace - IPC bool `json:"ipc"` - // (--unshare-pid) - // create new pid namespace - PID bool `json:"pid"` - // (--unshare-net) - // create new network namespace - Net bool `json:"net"` - // (--unshare-uts) - // create new uts namespace - UTS bool `json:"uts"` - // (--unshare-cgroup) - // create new cgroup namespace - CGroup bool `json:"cgroup"` -} - -type TmpfsConfig struct { - // set size of tmpfs - // (--size BYTES) - Size int `json:"size,omitempty"` - // mount point of new tmpfs - // (--tmpfs DEST) - Dir string `json:"dir"` -} - -type argOf interface { - Value(arg string) (args []string) -} - -func copyToArgOfSlice[T [2]string | string | TmpfsConfig](src []PermConfig[T]) (dst []argOf) { - dst = make([]argOf, len(src)) - for i, arg := range src { - dst[i] = arg - } - return -} - -type PermConfig[T [2]string | string | TmpfsConfig] struct { - // set permissions of next argument - // (--perms OCTAL) - Mode *os.FileMode `json:"mode,omitempty"` - // path to get the new permission - // (--bind-data, --file, etc.) - Path T -} - -func (p PermConfig[T]) Value(arg string) (args []string) { - // max possible size - if p.Mode != nil { - args = make([]string, 0, 6) - args = append(args, "--perms", strconv.Itoa(int(*p.Mode))) - } else { - args = make([]string, 0, 4) - } - - switch v := any(p.Path).(type) { - case string: - args = append(args, arg, v) - return - case [2]string: - args = append(args, arg, v[0], v[1]) - return - case TmpfsConfig: - if arg != "--tmpfs" { - panic("unreachable") - } - - if v.Size > 0 { - args = append(args, "--size", strconv.Itoa(v.Size)) - } - args = append(args, arg, v.Dir) - return - default: - panic("unreachable") - } -} diff --git a/bwrap/config.int.go b/bwrap/config.int.go deleted file mode 100644 index 27c88c36..00000000 --- a/bwrap/config.int.go +++ /dev/null @@ -1,22 +0,0 @@ -package bwrap - -const ( - UID = iota - GID - - intC -) - -var intArgs = func() (n [intC]string) { - n[UID] = "--uid" - n[GID] = "--gid" - - return -}() - -func (c *Config) intArgs() (n [intC]*int) { - n[UID] = c.UID - n[GID] = c.GID - - return -} diff --git a/bwrap/config.interface.go b/bwrap/config.interface.go deleted file mode 100644 index eb559c1d..00000000 --- a/bwrap/config.interface.go +++ /dev/null @@ -1,34 +0,0 @@ -package bwrap - -const ( - Procfs = iota - DevTmpfs - Tmpfs - Mqueue - Dir - Symlink - - interfaceC -) - -var interfaceArgs = func() (g [interfaceC]string) { - g[Procfs] = "--proc" - g[DevTmpfs] = "--dev" - g[Tmpfs] = "--tmpfs" - g[Mqueue] = "--mqueue" - g[Dir] = "--dir" - g[Symlink] = "--symlink" - - return -}() - -func (c *Config) interfaceArgs() (g [interfaceC][]argOf) { - g[Procfs] = copyToArgOfSlice(c.Procfs) - g[DevTmpfs] = copyToArgOfSlice(c.DevTmpfs) - g[Tmpfs] = copyToArgOfSlice(c.Tmpfs) - g[Mqueue] = copyToArgOfSlice(c.Mqueue) - g[Dir] = copyToArgOfSlice(c.Dir) - g[Symlink] = copyToArgOfSlice(c.Symlink) - - return -} diff --git a/bwrap/config.pair.go b/bwrap/config.pair.go deleted file mode 100644 index b0b1001b..00000000 --- a/bwrap/config.pair.go +++ /dev/null @@ -1,54 +0,0 @@ -package bwrap - -import "strconv" - -const ( - SetEnv = iota - - Bind - BindTry - DevBind - DevBindTry - ROBind - ROBindTry - - Chmod - - pairC -) - -var pairArgs = func() (n [pairC]string) { - n[SetEnv] = "--setenv" - - n[Bind] = "--bind" - n[BindTry] = "--bind-try" - n[DevBind] = "--dev-bind" - n[DevBindTry] = "--dev-bind-try" - n[ROBind] = "--ro-bind" - n[ROBindTry] = "--ro-bind-try" - - n[Chmod] = "--chmod" - - return -}() - -func (c *Config) pairArgs() (n [pairC][][2]string) { - n[SetEnv] = make([][2]string, 0, len(c.SetEnv)) - for k, v := range c.SetEnv { - n[SetEnv] = append(n[SetEnv], [2]string{k, v}) - } - - n[Bind] = c.Bind - n[BindTry] = c.BindTry - n[DevBind] = c.DevBind - n[DevBindTry] = c.DevBindTry - n[ROBind] = c.ROBind - n[ROBindTry] = c.ROBindTry - - n[Chmod] = make([][2]string, 0, len(c.Chmod)) - for path, octal := range c.Chmod { - n[Chmod] = append(n[Chmod], [2]string{strconv.Itoa(int(octal)), path}) - } - - return -} diff --git a/bwrap/config.string.go b/bwrap/config.string.go deleted file mode 100644 index c5c7a41e..00000000 --- a/bwrap/config.string.go +++ /dev/null @@ -1,35 +0,0 @@ -package bwrap - -const ( - Hostname = iota - Chdir - UnsetEnv - LockFile - RemountRO - - stringC -) - -var stringArgs = func() (n [stringC]string) { - n[Hostname] = "--hostname" - n[Chdir] = "--chdir" - n[UnsetEnv] = "--unsetenv" - n[LockFile] = "--lock-file" - n[RemountRO] = "--remount-ro" - - return -}() - -func (c *Config) stringArgs() (n [stringC][]string) { - if c.Hostname != "" { - n[Hostname] = []string{c.Hostname} - } - if c.Chdir != "" { - n[Chdir] = []string{c.Chdir} - } - n[UnsetEnv] = c.UnsetEnv - n[LockFile] = c.LockFile - n[RemountRO] = c.RemountRO - - return -} diff --git a/bwrap/config_test.go b/bwrap/config_test.go deleted file mode 100644 index d43c671d..00000000 --- a/bwrap/config_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package bwrap - -import ( - "slices" - "testing" -) - -func TestConfig_Args(t *testing.T) { - testCases := []struct { - name string - conf *Config - want []string - }{ - { - name: "xdg-dbus-proxy constraint sample", - conf: &Config{ - Unshare: nil, - UserNS: false, - Clearenv: true, - Symlink: []PermConfig[[2]string]{ - {Path: [2]string{"usr/bin", "/bin"}}, - {Path: [2]string{"var/home", "/home"}}, - {Path: [2]string{"usr/lib", "/lib"}}, - {Path: [2]string{"usr/lib64", "/lib64"}}, - {Path: [2]string{"run/media", "/media"}}, - {Path: [2]string{"var/mnt", "/mnt"}}, - {Path: [2]string{"var/opt", "/opt"}}, - {Path: [2]string{"sysroot/ostree", "/ostree"}}, - {Path: [2]string{"var/roothome", "/root"}}, - {Path: [2]string{"usr/sbin", "/sbin"}}, - {Path: [2]string{"var/srv", "/srv"}}, - }, - Bind: [][2]string{ - {"/run", "/run"}, - {"/tmp", "/tmp"}, - {"/var", "/var"}, - {"/run/user/1971/.dbus-proxy/", "/run/user/1971/.dbus-proxy/"}, - }, - ROBind: [][2]string{ - {"/boot", "/boot"}, - {"/dev", "/dev"}, - {"/proc", "/proc"}, - {"/sys", "/sys"}, - {"/sysroot", "/sysroot"}, - {"/usr", "/usr"}, - {"/etc", "/etc"}, - }, - DieWithParent: true, - }, - want: []string{ - "--unshare-all", - "--disable-userns", - "--assert-userns-disabled", - "--clearenv", - "--die-with-parent", - "--bind", "/run", "/run", - "--bind", "/tmp", "/tmp", - "--bind", "/var", "/var", - "--bind", "/run/user/1971/.dbus-proxy/", "/run/user/1971/.dbus-proxy/", - "--ro-bind", "/boot", "/boot", - "--ro-bind", "/dev", "/dev", - "--ro-bind", "/proc", "/proc", - "--ro-bind", "/sys", "/sys", - "--ro-bind", "/sysroot", "/sysroot", - "--ro-bind", "/usr", "/usr", - "--ro-bind", "/etc", "/etc", - "--symlink", "usr/bin", "/bin", - "--symlink", "var/home", "/home", - "--symlink", "usr/lib", "/lib", - "--symlink", "usr/lib64", "/lib64", - "--symlink", "run/media", "/media", - "--symlink", "var/mnt", "/mnt", - "--symlink", "var/opt", "/opt", - "--symlink", "sysroot/ostree", "/ostree", - "--symlink", "var/roothome", "/root", - "--symlink", "usr/sbin", "/sbin", - "--symlink", "var/srv", "/srv"}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - if got := tc.conf.Args(); !slices.Equal(got, tc.want) { - t.Errorf("Args() = %#v, want %#v", got, tc.want) - } - }) - } -} |
