Ophestra Umiker
2faf510146
The argument builder was written based on the incorrect assumption that bwrap arguments are unordered. The argument builder is replaced in this commit to correct that mistake. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
178 lines
5.2 KiB
Go
178 lines
5.2 KiB
Go
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
|
|
ID string `json:"id"`
|
|
// username of the target user to switch to
|
|
User string `json:"user"`
|
|
// value passed through to the child process as its argv
|
|
Command []string `json:"command"`
|
|
// string representation of the child's launch method
|
|
Method string `json:"method"`
|
|
|
|
// child confinement configuration
|
|
Confinement ConfinementConfig `json:"confinement"`
|
|
}
|
|
|
|
// ConfinementConfig defines fortified child's confinement
|
|
type ConfinementConfig struct {
|
|
// bwrap sandbox confinement configuration
|
|
Sandbox *SandboxConfig `json:"sandbox"`
|
|
|
|
// reference to a system D-Bus proxy configuration,
|
|
// nil value disables system bus proxy
|
|
SystemBus *dbus.Config `json:"system_bus,omitempty"`
|
|
// reference to a session D-Bus proxy configuration,
|
|
// nil value makes session bus proxy assume built-in defaults
|
|
SessionBus *dbus.Config `json:"session_bus,omitempty"`
|
|
|
|
// child capability enablements
|
|
Enablements state.Enablements `json:"enablements"`
|
|
}
|
|
|
|
// SandboxConfig describes resources made available to the sandbox.
|
|
type SandboxConfig struct {
|
|
// unix hostname within sandbox
|
|
Hostname string `json:"hostname,omitempty"`
|
|
// userns availability within sandbox
|
|
UserNS bool `json:"userns,omitempty"`
|
|
// share net namespace
|
|
Net bool `json:"net,omitempty"`
|
|
// do not run in new session
|
|
NoNewSession bool `json:"no_new_session,omitempty"`
|
|
// mediated access to wayland socket
|
|
Wayland bool `json:"wayland,omitempty"`
|
|
|
|
// final environment variables
|
|
Env map[string]string `json:"env"`
|
|
// sandbox host filesystem access
|
|
Filesystem []*FilesystemConfig `json:"filesystem"`
|
|
// tmpfs mount points to mount last
|
|
Tmpfs []string `json:"tmpfs"`
|
|
}
|
|
|
|
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"`
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
conf := (&bwrap.Config{
|
|
Net: s.Net,
|
|
UserNS: s.UserNS,
|
|
Hostname: s.Hostname,
|
|
Clearenv: true,
|
|
SetEnv: s.Env,
|
|
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
|
|
}
|
|
src := c.Src
|
|
dest := c.Dst
|
|
if c.Dst == "" {
|
|
dest = c.Src
|
|
}
|
|
conf.Bind(src, dest, !c.Must, c.Write, c.Device)
|
|
}
|
|
|
|
return conf
|
|
}
|
|
|
|
// Template returns a fully populated instance of Config.
|
|
func Template() *Config {
|
|
return &Config{
|
|
ID: "org.chromium.Chromium",
|
|
User: "chronos",
|
|
Command: []string{
|
|
"chromium",
|
|
"--ignore-gpu-blocklist",
|
|
"--disable-smooth-scrolling",
|
|
"--enable-features=UseOzonePlatform",
|
|
"--ozone-platform=wayland",
|
|
},
|
|
Method: "sudo",
|
|
Confinement: ConfinementConfig{
|
|
Sandbox: &SandboxConfig{
|
|
Hostname: "localhost",
|
|
UserNS: true,
|
|
Net: true,
|
|
NoNewSession: true,
|
|
Wayland: false,
|
|
// example API credentials pulled from Google Chrome
|
|
// DO NOT USE THESE IN A REAL BROWSER
|
|
Env: map[string]string{
|
|
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
|
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
|
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT",
|
|
},
|
|
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},
|
|
},
|
|
Tmpfs: []string{"/var/run/nscd"},
|
|
},
|
|
SystemBus: &dbus.Config{
|
|
See: nil,
|
|
Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"},
|
|
Own: nil,
|
|
Call: nil,
|
|
Broadcast: nil,
|
|
Log: false,
|
|
Filter: true,
|
|
},
|
|
SessionBus: &dbus.Config{
|
|
See: nil,
|
|
Talk: []string{"org.freedesktop.Notifications", "org.freedesktop.FileManager1", "org.freedesktop.ScreenSaver",
|
|
"org.freedesktop.secrets", "org.kde.kwalletd5", "org.kde.kwalletd6", "org.gnome.SessionManager"},
|
|
Own: []string{"org.chromium.Chromium.*", "org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
"org.mpris.MediaPlayer2.chromium.*"},
|
|
Call: map[string]string{"org.freedesktop.portal.*": "*"},
|
|
Broadcast: map[string]string{"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"},
|
|
Log: false,
|
|
Filter: true,
|
|
},
|
|
Enablements: state.EnableWayland.Mask() | state.EnableDBus.Mask() | state.EnablePulse.Mask(),
|
|
},
|
|
}
|
|
}
|