diff --git a/internal/app/config.go b/internal/app/config.go index ca3133c..d633a24 100644 --- a/internal/app/config.go +++ b/internal/app/config.go @@ -55,10 +55,21 @@ type SandboxConfig struct { // final environment variables Env map[string]string `json:"env"` - // paths made available within the sandbox - Bind [][2]string `json:"bind"` - // paths made available read-only within the sandbox - ROBind [][2]string `json:"ro-bind"` + // sandbox host filesystem access + Filesystem []*FilesystemConfig `json:"filesystem"` +} + +type FilesystemConfig struct { + // mount point in sandbox, same as src if empty + Dst string `json:"dst,omitempty"` + // host filesystem path to make available to sandbox + Src string `json:"src"` + // write access + Write bool `json:"write,omitempty"` + // device access + Device bool `json:"dev,omitempty"` + // exit if unable to share + Must bool `json:"require,omitempty"` } func (s *SandboxConfig) Bwrap() *bwrap.Config { @@ -72,8 +83,6 @@ func (s *SandboxConfig) Bwrap() *bwrap.Config { Hostname: s.Hostname, Clearenv: true, SetEnv: s.Env, - Bind: s.Bind, - ROBind: s.ROBind, Procfs: []string{"/proc"}, DevTmpfs: []string{"/dev"}, Mqueue: []string{"/dev/mqueue"}, @@ -87,6 +96,37 @@ func (s *SandboxConfig) Bwrap() *bwrap.Config { conf.GID = &s.GID } + for _, c := range s.Filesystem { + if c == nil { + continue + } + p := [2]string{c.Src, 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) + } + } + } + return conf } @@ -119,8 +159,12 @@ func Template() *Config { "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT", }, - Bind: [][2]string{{"/sdcard", "/sdcard"}, {"/var/tmp", "/var/tmp"}}, - ROBind: [][2]string{{"/nix", "/nix"}}, + Filesystem: []*FilesystemConfig{ + {Src: "/nix"}, + {Src: "/storage/emulated/0", Write: true, Must: true}, + {Src: "/data/user/0", Dst: "/data/data", Write: true, Must: true}, + {Src: "/var/tmp", Write: true}, + }, }, SystemBus: &dbus.Config{ See: nil, diff --git a/internal/app/seal.go b/internal/app/seal.go index 0d5ee7a..ad16663 100644 --- a/internal/app/seal.go +++ b/internal/app/seal.go @@ -127,7 +127,7 @@ func (a *app) Seal(config *Config) error { if d, err := os.ReadDir("/"); err != nil { return err } else { - b := make([][2]string, 0, len(d)) + b := make([]*FilesystemConfig, 0, len(d)) for _, ent := range d { name := ent.Name() switch name { @@ -136,16 +136,16 @@ func (a *app) Seal(config *Config) error { case "run": default: p := "/" + name - b = append(b, [2]string{p, p}) + b = append(b, &FilesystemConfig{Src: p, Write: true, Must: true}) } } - conf.Bind = append(conf.Bind, b...) + conf.Filesystem = append(conf.Filesystem, b...) } // bind entries in /run if d, err := os.ReadDir("/run"); err != nil { return err } else { - b := make([][2]string, 0, len(d)) + b := make([]*FilesystemConfig, 0, len(d)) for _, ent := range d { name := ent.Name() switch name { @@ -153,10 +153,10 @@ func (a *app) Seal(config *Config) error { case "dbus": default: p := "/run/" + name - b = append(b, [2]string{p, p}) + b = append(b, &FilesystemConfig{Src: p, Write: true, Must: true}) } } - conf.Bind = append(conf.Bind, b...) + conf.Filesystem = append(conf.Filesystem, b...) } config.Confinement.Sandbox = conf } diff --git a/internal/app/start.go b/internal/app/start.go index 7325ee8..d5912ba 100644 --- a/internal/app/start.go +++ b/internal/app/start.go @@ -41,7 +41,7 @@ func (a *app) Start() error { if s, err := exec.LookPath(n); err == nil { e[i] = s } else { - return (*ProcessError)(wrapError(err, fmt.Sprintf("cannot find %q in PATH: %v", n, err))) + return (*ProcessError)(wrapError(err, fmt.Sprintf("cannot find %q: %v", n, err))) } } }