aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dbus/run.go8
-rw-r--r--helper/bwrap/arg.go77
-rw-r--r--helper/bwrap/arg.static.awkward.go13
-rw-r--r--helper/bwrap/arg.static.bool.go81
-rw-r--r--helper/bwrap/arg.static.int.go47
-rw-r--r--helper/bwrap/arg.static.pair.go64
-rw-r--r--helper/bwrap/arg.static.string.go65
-rw-r--r--helper/bwrap/config.bool.go64
-rw-r--r--helper/bwrap/config.go219
-rw-r--r--helper/bwrap/config.int.go22
-rw-r--r--helper/bwrap/config.interface.go25
-rw-r--r--helper/bwrap/config.pair.go54
-rw-r--r--helper/bwrap/config.set.go138
-rw-r--r--helper/bwrap/config.string.go44
-rw-r--r--helper/bwrap/config_test.go60
-rw-r--r--internal/app/config.go61
-rw-r--r--internal/app/seal.go4
-rw-r--r--internal/app/share.dbus.go4
-rw-r--r--internal/app/share.display.go4
-rw-r--r--internal/app/share.pulse.go2
-rw-r--r--internal/app/share.runtime.go41
-rw-r--r--internal/app/share.system.go25
-rw-r--r--internal/app/start.go2
-rw-r--r--internal/app/system.go24
-rw-r--r--internal/shim/parent.go6
25 files changed, 650 insertions, 504 deletions
diff --git a/dbus/run.go b/dbus/run.go
index 2aad777a..a9b31e50 100644
--- a/dbus/run.go
+++ b/dbus/run.go
@@ -79,11 +79,9 @@ func (p *Proxy) Start(ready chan error, output io.Writer, sandbox bool) error {
}
}
}
- bindTargetDedup := make([][2]string, 0, len(bindTarget))
for k := range bindTarget {
- bindTargetDedup = append(bindTargetDedup, [2]string{k, k})
+ bc.Bind(k, k, false, true)
}
- bc.Bind = append(bc.Bind, bindTargetDedup...)
roBindTarget := make(map[string]struct{}, 2+1+len(proxyDeps))
@@ -103,11 +101,9 @@ func (p *Proxy) Start(ready chan error, output io.Writer, sandbox bool) error {
}
}
- roBindTargetDedup := make([][2]string, 0, len(roBindTarget))
for k := range roBindTarget {
- roBindTargetDedup = append(roBindTargetDedup, [2]string{k, k})
+ bc.Bind(k, k)
}
- bc.ROBind = append(bc.ROBind, roBindTargetDedup...)
h = helper.MustNewBwrap(bc, p.seal, toolPath, argF)
cmd = h.Unwrap()
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",
diff --git a/internal/app/config.go b/internal/app/config.go
index 7950c59d..3f6d1c0f 100644
--- a/internal/app/config.go
+++ b/internal/app/config.go
@@ -1,11 +1,18 @@
package app
import (
+ "encoding/gob"
+ "os"
+
"git.ophivana.moe/cat/fortify/dbus"
"git.ophivana.moe/cat/fortify/helper/bwrap"
"git.ophivana.moe/cat/fortify/internal/state"
)
+func init() {
+ gob.Register(new(bwrap.PermConfig[*bwrap.TmpfsConfig]))
+}
+
// Config is used to seal an *App
type Config struct {
// D-Bus application ID
@@ -55,7 +62,7 @@ type SandboxConfig struct {
// sandbox host filesystem access
Filesystem []*FilesystemConfig `json:"filesystem"`
// tmpfs mount points to mount last
- Tmpfs []bwrap.TmpfsConfig `json:"tmpfs"`
+ Tmpfs []string `json:"tmpfs"`
}
type FilesystemConfig struct {
@@ -71,61 +78,39 @@ type FilesystemConfig struct {
Must bool `json:"require,omitempty"`
}
+// Bwrap returns the address of the corresponding bwrap.Config to s.
+// Note that remaining tmpfs entries must be queued by the caller prior to launch.
func (s *SandboxConfig) Bwrap() *bwrap.Config {
if s == nil {
return nil
}
- nobody := 65534
- conf := &bwrap.Config{
+ conf := (&bwrap.Config{
Net: s.Net,
UserNS: s.UserNS,
- UID: &nobody,
- GID: &nobody,
Hostname: s.Hostname,
Clearenv: true,
SetEnv: s.Env,
- Procfs: []string{"/proc"},
- DevTmpfs: []string{"/dev"},
- Mqueue: []string{"/dev/mqueue"},
NewSession: !s.NoNewSession,
DieWithParent: true,
AsInit: true,
- }
+
+ // initialise map
+ Chmod: make(map[string]os.FileMode),
+ }).
+ SetUID(65534).SetGID(65534).
+ Procfs("/proc").DevTmpfs("/dev").Mqueue("/dev/mqueue")
for _, c := range s.Filesystem {
if c == nil {
continue
}
- p := [2]string{c.Src, c.Dst}
+ src := c.Src
+ dest := c.Dst
if c.Dst == "" {
- p[1] = c.Src
- }
-
- switch {
- case c.Device:
- if c.Must {
- conf.DevBind = append(conf.DevBind, p)
- } else {
- conf.DevBindTry = append(conf.DevBindTry, p)
- }
- case c.Write:
- if c.Must {
- conf.Bind = append(conf.Bind, p)
- } else {
- conf.BindTry = append(conf.BindTry, p)
- }
- default:
- if c.Must {
- conf.ROBind = append(conf.ROBind, p)
- } else {
- conf.ROBindTry = append(conf.ROBindTry, p)
- }
+ dest = c.Src
}
- }
-
- for _, tmpfs := range s.Tmpfs {
- conf.Tmpfs = append(conf.Tmpfs, bwrap.PermConfig[bwrap.TmpfsConfig]{Path: tmpfs, Last: true})
+ conf.Bind(src, dest, !c.Must, c.Write, c.Device)
}
return conf
@@ -164,9 +149,7 @@ func Template() *Config {
{Src: "/data/user/0", Dst: "/data/data", Write: true, Must: true},
{Src: "/var/tmp", Write: true},
},
- Tmpfs: []bwrap.TmpfsConfig{
- {Size: 8 * 1024, Dir: "/var/run/nscd"},
- },
+ Tmpfs: []string{"/var/run/nscd"},
},
SystemBus: &dbus.Config{
See: nil,
diff --git a/internal/app/seal.go b/internal/app/seal.go
index 9199f5b0..146bcc52 100644
--- a/internal/app/seal.go
+++ b/internal/app/seal.go
@@ -9,7 +9,6 @@ import (
"strconv"
"git.ophivana.moe/cat/fortify/dbus"
- "git.ophivana.moe/cat/fortify/helper/bwrap"
"git.ophivana.moe/cat/fortify/internal"
"git.ophivana.moe/cat/fortify/internal/state"
"git.ophivana.moe/cat/fortify/internal/verbose"
@@ -163,7 +162,7 @@ func (a *app) Seal(config *Config) error {
// hide nscd from sandbox if present
nscd := "/var/run/nscd"
if _, err := os.Stat(nscd); !errors.Is(err, os.ErrNotExist) {
- conf.Tmpfs = append(conf.Tmpfs, bwrap.TmpfsConfig{Size: 8 * 1024, Dir: nscd})
+ conf.Tmpfs = append(conf.Tmpfs, nscd)
}
// bind GPU stuff
if config.Confinement.Enablements.Has(state.EnableX) || config.Confinement.Enablements.Has(state.EnableWayland) {
@@ -172,6 +171,7 @@ func (a *app) Seal(config *Config) error {
config.Confinement.Sandbox = conf
}
seal.sys.bwrap = config.Confinement.Sandbox.Bwrap()
+ seal.sys.tmpfs = config.Confinement.Sandbox.Tmpfs
if seal.sys.bwrap.SetEnv == nil {
seal.sys.bwrap.SetEnv = make(map[string]string)
}
diff --git a/internal/app/share.dbus.go b/internal/app/share.dbus.go
index 804dbd3f..912cd97b 100644
--- a/internal/app/share.dbus.go
+++ b/internal/app/share.dbus.go
@@ -65,12 +65,12 @@ func (seal *appSeal) shareDBus(config [2]*dbus.Config) error {
// share proxy sockets
sessionInner := path.Join(seal.sys.runtime, "bus")
seal.sys.setEnv(dbusSessionBusAddress, "unix:path="+sessionInner)
- seal.sys.bind(sessionBus[1], sessionInner, true)
+ seal.sys.bwrap.Bind(sessionBus[1], sessionInner)
seal.sys.updatePerm(sessionBus[1], acl.Read, acl.Write)
if seal.sys.dbusSystem {
systemInner := "/run/dbus/system_bus_socket"
seal.sys.setEnv(dbusSystemBusAddress, "unix:path="+systemInner)
- seal.sys.bind(systemBus[1], systemInner, true)
+ seal.sys.bwrap.Bind(systemBus[1], systemInner)
seal.sys.updatePerm(systemBus[1], acl.Read, acl.Write)
}
diff --git a/internal/app/share.display.go b/internal/app/share.display.go
index da9f6eff..86343d8b 100644
--- a/internal/app/share.display.go
+++ b/internal/app/share.display.go
@@ -41,7 +41,7 @@ func (seal *appSeal) shareDisplay() error {
w := path.Join(seal.sys.runtime, "wayland-0")
seal.sys.link(wp, wpi)
seal.sys.setEnv(waylandDisplay, w)
- seal.sys.bind(wpi, w, true)
+ seal.sys.bwrap.Bind(wpi, w)
// ensure Wayland socket ACL (e.g. `/run/user/%d/wayland-%d`)
seal.sys.updatePermTag(state.EnableWayland, wp, acl.Read, acl.Write, acl.Execute)
@@ -59,7 +59,7 @@ func (seal *appSeal) shareDisplay() error {
} else {
seal.sys.changeHosts(seal.sys.Username)
seal.sys.setEnv(display, d)
- seal.sys.bind("/tmp/.X11-unix", "/tmp/.X11-unix", true)
+ seal.sys.bwrap.Bind("/tmp/.X11-unix", "/tmp/.X11-unix")
}
}
diff --git a/internal/app/share.pulse.go b/internal/app/share.pulse.go
index 39e6fc82..df26b16c 100644
--- a/internal/app/share.pulse.go
+++ b/internal/app/share.pulse.go
@@ -65,7 +65,7 @@ func (seal *appSeal) sharePulse() error {
psi := path.Join(seal.shareLocal, "pulse")
p := path.Join(seal.sys.runtime, "pulse", "native")
seal.sys.link(ps, psi)
- seal.sys.bind(psi, p, true)
+ seal.sys.bwrap.Bind(psi, p)
seal.sys.setEnv(pulseServer, "unix:"+p)
// publish current user's pulse cookie for target user
diff --git a/internal/app/share.runtime.go b/internal/app/share.runtime.go
index ac4135f4..ebb13aa6 100644
--- a/internal/app/share.runtime.go
+++ b/internal/app/share.runtime.go
@@ -4,7 +4,6 @@ import (
"path"
"git.ophivana.moe/cat/fortify/acl"
- "git.ophivana.moe/cat/fortify/helper/bwrap"
"git.ophivana.moe/cat/fortify/internal/state"
)
@@ -17,20 +16,13 @@ const (
// shareRuntime queues actions for sharing/ensuring the runtime and share directories
func (seal *appSeal) shareRuntime() {
// mount tmpfs on inner runtime (e.g. `/run/user/%d`)
- seal.sys.bwrap.Tmpfs = append(seal.sys.bwrap.Tmpfs,
- bwrap.PermConfig[bwrap.TmpfsConfig]{
- Path: bwrap.TmpfsConfig{
- Size: 1 * 1024 * 1024,
- Dir: "/run/user",
- },
- },
- bwrap.PermConfig[bwrap.TmpfsConfig]{
- Path: bwrap.TmpfsConfig{
- Size: 8 * 1024 * 1024,
- Dir: seal.sys.runtime,
- },
- },
- )
+ seal.sys.bwrap.Tmpfs("/run/user", 1*1024*1024)
+ seal.sys.bwrap.Tmpfs(seal.sys.runtime, 8*1024*1024)
+
+ // point to inner runtime path `/run/user/%d`
+ seal.sys.setEnv(xdgRuntimeDir, seal.sys.runtime)
+ seal.sys.setEnv(xdgSessionClass, "user")
+ seal.sys.setEnv(xdgSessionType, "tty")
// ensure RunDir (e.g. `/run/user/%d/fortify`)
seal.sys.ensure(seal.RunDirPath, 0700)
@@ -53,22 +45,3 @@ func (seal *appSeal) shareRuntime() {
seal.sys.ensureEphemeral(seal.shareLocal, 0700)
seal.sys.updatePerm(seal.shareLocal, acl.Execute)
}
-
-func (seal *appSeal) shareRuntimeChild() string {
- // ensure child runtime parent directory (e.g. `/tmp/fortify.%d/runtime`)
- targetRuntimeParent := path.Join(seal.SharePath, "runtime")
- seal.sys.ensure(targetRuntimeParent, 0700)
- seal.sys.updatePermTag(state.EnableLength, targetRuntimeParent, acl.Execute)
-
- // ensure child runtime directory (e.g. `/tmp/fortify.%d/runtime/%d`)
- targetRuntime := path.Join(targetRuntimeParent, seal.sys.Uid)
- seal.sys.ensure(targetRuntime, 0700)
- seal.sys.updatePermTag(state.EnableLength, targetRuntime, acl.Read, acl.Write, acl.Execute)
-
- // point to ensured runtime path
- seal.sys.setEnv(xdgRuntimeDir, targetRuntime)
- seal.sys.setEnv(xdgSessionClass, "user")
- seal.sys.setEnv(xdgSessionType, "tty")
-
- return targetRuntime
-}
diff --git a/internal/app/share.system.go b/internal/app/share.system.go
index 1b17ca49..e1a3e1de 100644
--- a/internal/app/share.system.go
+++ b/internal/app/share.system.go
@@ -3,6 +3,9 @@ package app
import (
"os"
"path"
+
+ "git.ophivana.moe/cat/fortify/acl"
+ "git.ophivana.moe/cat/fortify/internal/state"
)
const (
@@ -38,6 +41,24 @@ func (seal *appSeal) shareSystem() {
seal.sys.writeFile(groupPath, []byte("fortify:x:65534:\n"))
// bind /etc/passwd and /etc/group
- seal.sys.bind(passwdPath, "/etc/passwd", true)
- seal.sys.bind(groupPath, "/etc/group", true)
+ seal.sys.bwrap.Bind(passwdPath, "/etc/passwd")
+ seal.sys.bwrap.Bind(groupPath, "/etc/group")
+}
+
+func (seal *appSeal) shareTmpdirChild() string {
+ // ensure child tmpdir parent directory (e.g. `/tmp/fortify.%d/tmpdir`)
+ targetTmpdirParent := path.Join(seal.SharePath, "tmpdir")
+ seal.sys.ensure(targetTmpdirParent, 0700)
+ seal.sys.updatePermTag(state.EnableLength, targetTmpdirParent, acl.Execute)
+
+ // ensure child tmpdir (e.g. `/tmp/fortify.%d/tmpdir/%d`)
+ targetTmpdir := path.Join(targetTmpdirParent, seal.sys.Uid)
+ seal.sys.ensure(targetTmpdir, 01700)
+ seal.sys.updatePermTag(state.EnableLength, targetTmpdir, acl.Read, acl.Write, acl.Execute)
+ seal.sys.bwrap.Bind(targetTmpdir, "/tmp", false, true)
+
+ // mount tmpfs on inner shared directory (e.g. `/tmp/fortify.%d`)
+ seal.sys.bwrap.Tmpfs(seal.SharePath, 1*1024*1024)
+
+ return targetTmpdir
}
diff --git a/internal/app/start.go b/internal/app/start.go
index 725d69dd..c496561c 100644
--- a/internal/app/start.go
+++ b/internal/app/start.go
@@ -70,7 +70,7 @@ func (a *app) Start() error {
a.cmd.Stderr = os.Stderr
a.cmd.Dir = a.seal.RunDirPath
- if wls, err := shim.ServeConfig(confSockPath, &shim.Payload{
+ if wls, err := shim.ServeConfig(confSockPath, a.seal.sys.uid, &shim.Payload{
Argv: a.seal.command,
Exec: shimExec,
Bwrap: a.seal.sys.bwrap,
diff --git a/internal/app/system.go b/internal/app/system.go
index 4f3b6730..a0162939 100644
--- a/internal/app/system.go
+++ b/internal/app/system.go
@@ -59,6 +59,7 @@ type appSeal struct {
// appSealTx contains the system-level component of the app seal
type appSealTx struct {
bwrap *bwrap.Config
+ tmpfs []string
// reference to D-Bus proxy instance, nil if disabled
dbus *dbus.Proxy
@@ -110,15 +111,6 @@ func (tx *appSealTx) setEnv(k, v string) {
tx.bwrap.SetEnv[k] = v
}
-// bind mounts a directory within the sandbox
-func (tx *appSealTx) bind(src, dest string, ro bool) {
- if !ro {
- tx.bwrap.Bind = append(tx.bwrap.Bind, [2]string{src, dest})
- } else {
- tx.bwrap.ROBind = append(tx.bwrap.ROBind, [2]string{src, dest})
- }
-}
-
// ensure appends a directory ensure action
func (tx *appSealTx) ensure(path string, perm os.FileMode) {
tx.mkdir = append(tx.mkdir, appEnsureEntry{path, perm, false})
@@ -183,14 +175,14 @@ func (tx *appSealTx) changeHosts(username string) {
func (tx *appSealTx) writeFile(dst string, data []byte) {
tx.files = append(tx.files, [2]string{dst, string(data)})
tx.updatePerm(dst, acl.Read)
- tx.bind(dst, dst, true)
+ tx.bwrap.Bind(dst, dst)
}
// copyFile appends a tmpfiles action
func (tx *appSealTx) copyFile(dst, src string) {
tx.tmpfiles = append(tx.tmpfiles, [2]string{dst, src})
tx.updatePerm(dst, acl.Read)
- tx.bind(dst, dst, true)
+ tx.bwrap.Bind(dst, dst)
}
// link appends a hardlink action
@@ -324,6 +316,12 @@ func (tx *appSealTx) commit() error {
// disarm partial commit rollback
txp = nil
+
+ // queue tmpfs at the end of tx.bwrap.Filesystem
+ for _, dest := range tx.tmpfs {
+ tx.bwrap.Tmpfs(dest, 8*1024)
+ }
+
return nil
}
@@ -416,10 +414,10 @@ func (seal *appSeal) shareAll(bus [2]*dbus.Config) error {
}
seal.shared = true
+ targetTmpdir := seal.shareTmpdirChild()
+ verbose.Printf("child tmpdir %q configured\n", targetTmpdir)
seal.shareRuntime()
seal.shareSystem()
- targetRuntime := seal.shareRuntimeChild()
- verbose.Printf("child runtime data dir '%s' configured\n", targetRuntime)
if err := seal.shareDisplay(); err != nil {
return err
}
diff --git a/internal/shim/parent.go b/internal/shim/parent.go
index 98856555..59be5885 100644
--- a/internal/shim/parent.go
+++ b/internal/shim/parent.go
@@ -8,12 +8,13 @@ import (
"os"
"syscall"
+ "git.ophivana.moe/cat/fortify/acl"
"git.ophivana.moe/cat/fortify/internal/verbose"
)
// called in the parent process
-func ServeConfig(socket string, payload *Payload, wl string, done chan struct{}) (*net.UnixConn, error) {
+func ServeConfig(socket string, uid int, payload *Payload, wl string, done chan struct{}) (*net.UnixConn, error) {
var ws *net.UnixConn
if payload.WL {
if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl, Net: "unix"}); err != nil {
@@ -28,7 +29,7 @@ func ServeConfig(socket string, payload *Payload, wl string, done chan struct{})
return nil, err
} else {
verbose.Println("configuring shim on socket", socket)
- if err = os.Chmod(socket, 0777); err != nil {
+ if err = acl.UpdatePerm(socket, uid, acl.Read, acl.Write, acl.Execute); err != nil {
fmt.Println("fortify: cannot change permissions of shim setup socket:", err)
}
@@ -39,6 +40,7 @@ func ServeConfig(socket string, payload *Payload, wl string, done chan struct{})
} else {
if err = gob.NewEncoder(conn).Encode(*payload); err != nil {
fmt.Println("fortify: cannot stream shim payload:", err)
+ _ = os.Remove(socket)
return
}