diff options
Diffstat (limited to 'helper')
| -rw-r--r-- | helper/bwrap/arg.go | 77 | ||||
| -rw-r--r-- | helper/bwrap/arg.static.awkward.go | 13 | ||||
| -rw-r--r-- | helper/bwrap/arg.static.bool.go | 81 | ||||
| -rw-r--r-- | helper/bwrap/arg.static.int.go | 47 | ||||
| -rw-r--r-- | helper/bwrap/arg.static.pair.go | 64 | ||||
| -rw-r--r-- | helper/bwrap/arg.static.string.go | 65 | ||||
| -rw-r--r-- | helper/bwrap/config.bool.go | 64 | ||||
| -rw-r--r-- | helper/bwrap/config.go | 219 | ||||
| -rw-r--r-- | helper/bwrap/config.int.go | 22 | ||||
| -rw-r--r-- | helper/bwrap/config.interface.go | 25 | ||||
| -rw-r--r-- | helper/bwrap/config.pair.go | 54 | ||||
| -rw-r--r-- | helper/bwrap/config.set.go | 138 | ||||
| -rw-r--r-- | helper/bwrap/config.string.go | 44 | ||||
| -rw-r--r-- | helper/bwrap/config_test.go | 60 |
14 files changed, 573 insertions, 400 deletions
diff --git a/helper/bwrap/arg.go b/helper/bwrap/arg.go new file mode 100644 index 00000000..efdab823 --- /dev/null +++ b/helper/bwrap/arg.go @@ -0,0 +1,77 @@ +package bwrap + +import "encoding/gob" + +type Builder interface { + Len() int + Append(args *[]string) +} + +type FSBuilder interface { + Path() string + Builder +} + +func init() { + gob.Register(new(pairF)) + gob.Register(new(stringF)) +} + +type pairF [3]string + +func (p *pairF) Path() string { + return p[2] +} + +func (p *pairF) Len() int { + return len(p) // compiler replaces this with 3 +} + +func (p *pairF) Append(args *[]string) { + *args = append(*args, p[0], p[1], p[2]) +} + +type stringF [2]string + +func (s stringF) Path() string { + return s[1] +} + +func (s stringF) Len() int { + return len(s) // compiler replaces this with 2 +} + +func (s stringF) Append(args *[]string) { + *args = append(*args, s[0], s[1]) +} + +// Args returns a slice of bwrap args corresponding to c. +func (c *Config) Args() (args []string) { + builders := []Builder{ + c.boolArgs(), + c.intArgs(), + c.stringArgs(), + c.pairArgs(), + } + + // copy FSBuilder slice to builder slice + fb := make([]Builder, len(c.Filesystem)+1) + for i, f := range c.Filesystem { + fb[i] = f + } + fb[len(fb)-1] = c.Chmod + builders = append(builders, fb...) + + // accumulate arg count + argc := 0 + for _, b := range builders { + argc += b.Len() + } + + args = make([]string, 0, argc) + for _, b := range builders { + b.Append(&args) + } + + return +} diff --git a/helper/bwrap/arg.static.awkward.go b/helper/bwrap/arg.static.awkward.go new file mode 100644 index 00000000..0848d1fb --- /dev/null +++ b/helper/bwrap/arg.static.awkward.go @@ -0,0 +1,13 @@ +package bwrap + +const ( + Tmpfs = iota + Dir + Symlink +) + +var awkwardArgs = [...]string{ + Tmpfs: "--tmpfs", + Dir: "--dir", + Symlink: "--symlink", +} diff --git a/helper/bwrap/arg.static.bool.go b/helper/bwrap/arg.static.bool.go new file mode 100644 index 00000000..6c3ca0c4 --- /dev/null +++ b/helper/bwrap/arg.static.bool.go @@ -0,0 +1,81 @@ +package bwrap + +const ( + UnshareAll = iota + UnshareUser + UnshareIPC + UnsharePID + UnshareNet + UnshareUTS + UnshareCGroup + ShareNet + + UserNS + Clearenv + + NewSession + DieWithParent + AsInit +) + +var boolArgs = [...][]string{ + UnshareAll: {"--unshare-all", "--unshare-user"}, + UnshareUser: {"--unshare-user"}, + UnshareIPC: {"--unshare-ipc"}, + UnsharePID: {"--unshare-pid"}, + UnshareNet: {"--unshare-net"}, + UnshareUTS: {"--unshare-uts"}, + UnshareCGroup: {"--unshare-cgroup"}, + ShareNet: {"--share-net"}, + + UserNS: {"--disable-userns", "--assert-userns-disabled"}, + Clearenv: {"--clearenv"}, + + NewSession: {"--new-session"}, + DieWithParent: {"--die-with-parent"}, + AsInit: {"--as-pid-1"}, +} + +func (c *Config) boolArgs() Builder { + b := boolArg{ + UserNS: !c.UserNS, + Clearenv: c.Clearenv, + + NewSession: c.NewSession, + DieWithParent: c.DieWithParent, + AsInit: c.AsInit, + } + + 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 + } + + return &b +} + +type boolArg [len(boolArgs)]bool + +func (b *boolArg) Len() (l int) { + for i, v := range b { + if v { + l += len(boolArgs[i]) + } + } + return +} + +func (b *boolArg) Append(args *[]string) { + for i, v := range b { + if v { + *args = append(*args, boolArgs[i]...) + } + } +} diff --git a/helper/bwrap/arg.static.int.go b/helper/bwrap/arg.static.int.go new file mode 100644 index 00000000..cba3b1f7 --- /dev/null +++ b/helper/bwrap/arg.static.int.go @@ -0,0 +1,47 @@ +package bwrap + +import "strconv" + +const ( + UID = iota + GID + Perms + Size +) + +var intArgs = [...]string{ + UID: "--uid", + GID: "--gid", + Perms: "--perms", + Size: "--size", +} + +func (c *Config) intArgs() Builder { + // Arg types: + // Perms + // are handled by the sequential builder + + return &intArg{ + UID: c.UID, + GID: c.GID, + } +} + +type intArg [len(intArgs)]*int + +func (n *intArg) Len() (l int) { + for _, v := range n { + if v != nil { + l += 2 + } + } + return +} + +func (n *intArg) Append(args *[]string) { + for i, v := range n { + if v != nil { + *args = append(*args, intArgs[i], strconv.Itoa(*v)) + } + } +} diff --git a/helper/bwrap/arg.static.pair.go b/helper/bwrap/arg.static.pair.go new file mode 100644 index 00000000..cc1765ae --- /dev/null +++ b/helper/bwrap/arg.static.pair.go @@ -0,0 +1,64 @@ +package bwrap + +const ( + SetEnv = iota + + Bind + BindTry + DevBind + DevBindTry + ROBind + ROBindTry + + Chmod +) + +var pairArgs = [...]string{ + SetEnv: "--setenv", + + Bind: "--bind", + BindTry: "--bind-try", + DevBind: "--dev-bind", + DevBindTry: "--dev-bind-try", + ROBind: "--ro-bind", + ROBindTry: "--ro-bind-try", + + Chmod: "--chmod", +} + +func (c *Config) pairArgs() Builder { + var n pairArg + n[SetEnv] = make([][2]string, 0, len(c.SetEnv)) + for k, v := range c.SetEnv { + n[SetEnv] = append(n[SetEnv], [2]string{k, v}) + } + + // Arg types: + // Bind + // BindTry + // DevBind + // DevBindTry + // ROBind + // ROBindTry + // Chmod + // are handled by the sequential builder + + return &n +} + +type pairArg [len(pairArgs)][][2]string + +func (p *pairArg) Len() (l int) { + for _, v := range p { + l += len(v) * 3 + } + return +} + +func (p *pairArg) Append(args *[]string) { + for i, arg := range p { + for _, v := range arg { + *args = append(*args, pairArgs[i], v[0], v[1]) + } + } +} diff --git a/helper/bwrap/arg.static.string.go b/helper/bwrap/arg.static.string.go new file mode 100644 index 00000000..e7f5c332 --- /dev/null +++ b/helper/bwrap/arg.static.string.go @@ -0,0 +1,65 @@ +package bwrap + +const ( + Hostname = iota + Chdir + UnsetEnv + LockFile + + RemountRO + Procfs + DevTmpfs + Mqueue +) + +var stringArgs = [...]string{ + Hostname: "--hostname", + Chdir: "--chdir", + UnsetEnv: "--unsetenv", + LockFile: "--lock-file", + + RemountRO: "--remount-ro", + Procfs: "--proc", + DevTmpfs: "--dev", + Mqueue: "--mqueue", +} + +func (c *Config) stringArgs() Builder { + n := stringArg{ + UnsetEnv: c.UnsetEnv, + LockFile: c.LockFile, + } + + if c.Hostname != "" { + n[Hostname] = []string{c.Hostname} + } + if c.Chdir != "" { + n[Chdir] = []string{c.Chdir} + } + + // Arg types: + // RemountRO + // Procfs + // DevTmpfs + // Mqueue + // are handled by the sequential builder + + return &n +} + +type stringArg [len(stringArgs)][]string + +func (s *stringArg) Len() (l int) { + for _, arg := range s { + l += len(arg) * 2 + } + return +} + +func (s *stringArg) Append(args *[]string) { + for i, arg := range s { + for _, v := range arg { + *args = append(*args, stringArgs[i], v) + } + } +} diff --git a/helper/bwrap/config.bool.go b/helper/bwrap/config.bool.go deleted file mode 100644 index c30f4df9..00000000 --- a/helper/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", "--unshare-user"} - 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/helper/bwrap/config.go b/helper/bwrap/config.go index 3ddb80b5..f62cc24e 100644 --- a/helper/bwrap/config.go +++ b/helper/bwrap/config.go @@ -5,75 +5,6 @@ import ( "strconv" ) -func (c *Config) Args() (args []string) { - b := c.boolArgs() - n := c.intArgs() - g := c.interfaceArgs() - s := c.stringArgs() - p := c.pairArgs() - - 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 g { - argc += len(arg) * 3 - } - 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 g { - for _, v := range arg { - if v.Later() { - continue - } - args = append(args, v.Value(interfaceArgs[i])...) - } - } - 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 { - if !v.Later() { - continue - } - args = append(args, v.Value(interfaceArgs[i])...) - } - } - - return -} - type Config struct { // unshare every namespace we support by default if nil // (--unshare-all) @@ -114,53 +45,12 @@ type Config struct { // (--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 []string `json:"proc,omitempty"` - // mount new dev in sandbox - // (--dev DEST) - DevTmpfs []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 []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"` + // ordered filesystem args + Filesystem []FSBuilder // change permissions (must already exist) // (--chmod OCTAL PATH) - Chmod map[string]os.FileMode `json:"chmod,omitempty"` + Chmod ChmodConfig `json:"chmod,omitempty"` // create a new terminal session // (--new-session) @@ -217,6 +107,34 @@ type UnshareConfig struct { CGroup bool `json:"cgroup"` } +type PermConfig[T FSBuilder] struct { + // set permissions of next argument + // (--perms OCTAL) + Mode *os.FileMode `json:"mode,omitempty"` + // path to get the new permission + // (--bind-data, --file, etc.) + Inner T `json:"path"` +} + +func (p *PermConfig[T]) Path() string { + return p.Inner.Path() +} + +func (p *PermConfig[T]) Len() int { + if p.Mode != nil { + return p.Inner.Len() + 2 + } else { + return p.Inner.Len() + } +} + +func (p *PermConfig[T]) Append(args *[]string) { + if p.Mode != nil { + *args = append(*args, intArgs[Perms], strconv.FormatInt(int64(*p.Mode), 8)) + } + p.Inner.Append(args) +} + type TmpfsConfig struct { // set size of tmpfs // (--size BYTES) @@ -226,62 +144,47 @@ type TmpfsConfig struct { Dir string `json:"dir"` } -type argOf interface { - Value(arg string) (args []string) - Later() bool +func (t *TmpfsConfig) Path() string { + return t.Dir } -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 +func (t *TmpfsConfig) Len() int { + if t.Size > 0 { + return 4 + } else { + return 2 } - return } -type PermConfig[T [2]string | string | TmpfsConfig] struct { - // append this at the end of the argument stream - Last bool +func (t *TmpfsConfig) Append(args *[]string) { + if t.Size > 0 { + *args = append(*args, intArgs[Size], strconv.Itoa(t.Size)) + } + *args = append(*args, awkwardArgs[Tmpfs], t.Dir) +} - // 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 +type SymlinkConfig [2]string + +func (s SymlinkConfig) Path() string { + return s[1] } -func (p PermConfig[T]) Later() bool { - return p.Last +func (s SymlinkConfig) Len() int { + return 3 } -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.FormatInt(int64(*p.Mode), 8)) - } else { - args = make([]string, 0, 4) - } +func (s SymlinkConfig) Append(args *[]string) { + *args = append(*args, awkwardArgs[Symlink], s[0], s[1]) +} + +type ChmodConfig map[string]os.FileMode - 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") - } +func (c ChmodConfig) Len() int { + return len(c) +} - if v.Size > 0 { - args = append(args, "--size", strconv.Itoa(v.Size)) - } - args = append(args, arg, v.Dir) - return - default: - panic("unreachable") +func (c ChmodConfig) Append(args *[]string) { + for path, mode := range c { + *args = append(*args, pairArgs[Chmod], strconv.FormatInt(int64(mode), 8), path) } } diff --git a/helper/bwrap/config.int.go b/helper/bwrap/config.int.go deleted file mode 100644 index 27c88c36..00000000 --- a/helper/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/helper/bwrap/config.interface.go b/helper/bwrap/config.interface.go deleted file mode 100644 index f68df83c..00000000 --- a/helper/bwrap/config.interface.go +++ /dev/null @@ -1,25 +0,0 @@ -package bwrap - -const ( - Tmpfs = iota - Dir - Symlink - - interfaceC -) - -var interfaceArgs = func() (g [interfaceC]string) { - g[Tmpfs] = "--tmpfs" - g[Dir] = "--dir" - g[Symlink] = "--symlink" - - return -}() - -func (c *Config) interfaceArgs() (g [interfaceC][]argOf) { - g[Tmpfs] = copyToArgOfSlice(c.Tmpfs) - g[Dir] = copyToArgOfSlice(c.Dir) - g[Symlink] = copyToArgOfSlice(c.Symlink) - - return -} diff --git a/helper/bwrap/config.pair.go b/helper/bwrap/config.pair.go deleted file mode 100644 index 049edafe..00000000 --- a/helper/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.FormatInt(int64(octal), 8), path}) - } - - return -} diff --git a/helper/bwrap/config.set.go b/helper/bwrap/config.set.go new file mode 100644 index 00000000..318ad7f2 --- /dev/null +++ b/helper/bwrap/config.set.go @@ -0,0 +1,138 @@ +package bwrap + +import "os" + +/* +Bind binds mount src on host to dest in sandbox. + +Bind(src, dest) bind mount host path readonly on sandbox +(--ro-bind SRC DEST). +Bind(src, dest, true) equal to ROBind but ignores non-existent host path +(--ro-bind-try SRC DEST). + +Bind(src, dest, false, true) bind mount host path on sandbox. +(--bind SRC DEST). +Bind(src, dest, true, true) equal to Bind but ignores non-existent host path +(--bind-try SRC DEST). + +Bind(src, dest, false, true, true) bind mount host path on sandbox, allowing device access +(--dev-bind SRC DEST). +Bind(src, dest, true, true, true) equal to DevBind but ignores non-existent host path +(--dev-bind-try SRC DEST). +*/ +func (c *Config) Bind(src, dest string, opts ...bool) *Config { + var ( + try bool + write bool + dev bool + ) + + if len(opts) > 0 { + try = opts[0] + } + if len(opts) > 1 { + write = opts[1] + } + if len(opts) > 2 { + dev = opts[2] + } + + if dev { + if try { + c.Filesystem = append(c.Filesystem, &pairF{pairArgs[DevBindTry], src, dest}) + } else { + c.Filesystem = append(c.Filesystem, &pairF{pairArgs[DevBind], src, dest}) + } + return c + } else if write { + if try { + c.Filesystem = append(c.Filesystem, &pairF{pairArgs[BindTry], src, dest}) + } else { + c.Filesystem = append(c.Filesystem, &pairF{pairArgs[Bind], src, dest}) + } + return c + } else { + if try { + c.Filesystem = append(c.Filesystem, &pairF{pairArgs[ROBindTry], src, dest}) + } else { + c.Filesystem = append(c.Filesystem, &pairF{pairArgs[ROBind], src, dest}) + } + return c + } +} + +// RemountRO remount path as readonly; does not recursively remount +// (--remount-ro DEST) +func (c *Config) RemountRO(dest string) *Config { + c.Filesystem = append(c.Filesystem, &stringF{stringArgs[RemountRO], dest}) + return c +} + +// Procfs mount new procfs in sandbox +// (--proc DEST) +func (c *Config) Procfs(dest string) *Config { + c.Filesystem = append(c.Filesystem, &stringF{stringArgs[Procfs], dest}) + return c +} + +// DevTmpfs mount new dev in sandbox +// (--dev DEST) +func (c *Config) DevTmpfs(dest string) *Config { + c.Filesystem = append(c.Filesystem, &stringF{stringArgs[DevTmpfs], dest}) + return c +} + +// Tmpfs mount new tmpfs in sandbox +// (--tmpfs DEST) +func (c *Config) Tmpfs(dest string, size int, perm ...os.FileMode) *Config { + tmpfs := &PermConfig[*TmpfsConfig]{Inner: &TmpfsConfig{Dir: dest}} + if size >= 0 { + tmpfs.Inner.Size = size + } + if len(perm) == 1 { + tmpfs.Mode = &perm[0] + } + c.Filesystem = append(c.Filesystem, tmpfs) + return c +} + +// Mqueue mount new mqueue in sandbox +// (--mqueue DEST) +func (c *Config) Mqueue(dest string) *Config { + c.Filesystem = append(c.Filesystem, &stringF{stringArgs[Mqueue], dest}) + return c +} + +// Dir create dir in sandbox +// (--dir DEST) +func (c *Config) Dir(dest string) *Config { + c.Filesystem = append(c.Filesystem, &stringF{stringArgs[Dir], dest}) + return c +} + +// Symlink create symlink within sandbox +// (--symlink SRC DEST) +func (c *Config) Symlink(src, dest string, perm ...os.FileMode) *Config { + symlink := &PermConfig[SymlinkConfig]{Inner: SymlinkConfig{src, dest}} + if len(perm) == 1 { + symlink.Mode = &perm[0] + } + c.Filesystem = append(c.Filesystem, symlink) + return c +} + +// SetUID sets custom uid in the sandbox, requires new user namespace (--uid UID). +func (c *Config) SetUID(uid int) *Config { + if uid >= 0 { + c.UID = &uid + } + return c +} + +// SetGID sets custom gid in the sandbox, requires new user namespace (--gid GID). +func (c *Config) SetGID(gid int) *Config { + if gid >= 0 { + c.GID = &gid + } + return c +} diff --git a/helper/bwrap/config.string.go b/helper/bwrap/config.string.go deleted file mode 100644 index 2aa05bee..00000000 --- a/helper/bwrap/config.string.go +++ /dev/null @@ -1,44 +0,0 @@ -package bwrap - -const ( - Hostname = iota - Chdir - UnsetEnv - LockFile - RemountRO - Procfs - DevTmpfs - Mqueue - - stringC -) - -var stringArgs = func() (n [stringC]string) { - n[Hostname] = "--hostname" - n[Chdir] = "--chdir" - n[UnsetEnv] = "--unsetenv" - n[LockFile] = "--lock-file" - n[RemountRO] = "--remount-ro" - n[Procfs] = "--proc" - n[DevTmpfs] = "--dev" - n[Mqueue] = "--mqueue" - - 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 - n[Procfs] = c.Procfs - n[DevTmpfs] = c.DevTmpfs - n[Mqueue] = c.Mqueue - - return -} diff --git a/helper/bwrap/config_test.go b/helper/bwrap/config_test.go index a14e310c..30b9ab06 100644 --- a/helper/bwrap/config_test.go +++ b/helper/bwrap/config_test.go @@ -13,40 +13,34 @@ func TestConfig_Args(t *testing.T) { }{ { 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"}, - }, + conf: (&Config{ + Unshare: nil, + UserNS: false, + Clearenv: true, DieWithParent: true, - }, + }). + 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"). + Bind("/run", "/run", false, true). + Bind("/tmp", "/tmp", false, true). + Bind("/var", "/var", false, true). + Bind("/run/user/1971/.dbus-proxy/", "/run/user/1971/.dbus-proxy/", false, true). + Bind("/boot", "/boot"). + Bind("/dev", "/dev"). + Bind("/proc", "/proc"). + Bind("/sys", "/sys"). + Bind("/sysroot", "/sysroot"). + Bind("/usr", "/usr"). + Bind("/etc", "/etc"), want: []string{ "--unshare-all", "--unshare-user", |
