diff --git a/cmd/fpkg/app.go b/cmd/fpkg/app.go index facf2dc..7246870 100644 --- a/cmd/fpkg/app.go +++ b/cmd/fpkg/app.go @@ -19,7 +19,7 @@ type appInfo struct { // passed through to [fst.Config] ID string `json:"id"` // passed through to [fst.Config] - AppID int `json:"app_id"` + Identity int `json:"identity"` // passed through to [fst.Config] Groups []string `json:"groups,omitempty"` // passed through to [fst.Config] @@ -64,57 +64,61 @@ type appInfo struct { func (app *appInfo) toFst(pathSet *appPathSet, argv []string, flagDropShell bool) *fst.Config { config := &fst.Config{ - ID: app.ID, + ID: app.ID, + Path: argv[0], Args: argv, - Confinement: fst.ConfinementConfig{ - AppID: app.AppID, - Groups: app.Groups, - Username: "fortify", - Inner: path.Join("/data/data", app.ID), - Outer: pathSet.homeDir, - Shell: shellPath, - Sandbox: &fst.SandboxConfig{ - Hostname: formatHostname(app.Name), - Devel: app.Devel, - Userns: app.Userns, - Net: app.Net, - Device: app.Device, - Tty: app.Tty || flagDropShell, - MapRealUID: app.MapRealUID, - DirectWayland: app.DirectWayland, - Filesystem: []*fst.FilesystemConfig{ - {Src: path.Join(pathSet.nixPath, "store"), Dst: "/nix/store", Must: true}, - {Src: pathSet.metaPath, Dst: path.Join(fst.Tmp, "app"), Must: true}, - {Src: "/etc/resolv.conf"}, - {Src: "/sys/block"}, - {Src: "/sys/bus"}, - {Src: "/sys/class"}, - {Src: "/sys/dev"}, - {Src: "/sys/devices"}, - }, - Link: [][2]string{ - {app.CurrentSystem, "/run/current-system"}, - {"/run/current-system/sw/bin", "/bin"}, - {"/run/current-system/sw/bin", "/usr/bin"}, - }, - Etc: path.Join(pathSet.cacheDir, "etc"), - AutoEtc: true, + + Enablements: app.Enablements, + + SystemBus: app.SystemBus, + SessionBus: app.SessionBus, + DirectWayland: app.DirectWayland, + + Username: "fortify", + Shell: shellPath, + Data: pathSet.homeDir, + Dir: path.Join("/data/data", app.ID), + + Identity: app.Identity, + Groups: app.Groups, + + Container: &fst.ContainerConfig{ + Hostname: formatHostname(app.Name), + Devel: app.Devel, + Userns: app.Userns, + Net: app.Net, + Device: app.Device, + Tty: app.Tty || flagDropShell, + MapRealUID: app.MapRealUID, + Filesystem: []*fst.FilesystemConfig{ + {Src: path.Join(pathSet.nixPath, "store"), Dst: "/nix/store", Must: true}, + {Src: pathSet.metaPath, Dst: path.Join(fst.Tmp, "app"), Must: true}, + {Src: "/etc/resolv.conf"}, + {Src: "/sys/block"}, + {Src: "/sys/bus"}, + {Src: "/sys/class"}, + {Src: "/sys/dev"}, + {Src: "/sys/devices"}, }, - ExtraPerms: []*fst.ExtraPermConfig{ - {Path: dataHome, Execute: true}, - {Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true}, + Link: [][2]string{ + {app.CurrentSystem, "/run/current-system"}, + {"/run/current-system/sw/bin", "/bin"}, + {"/run/current-system/sw/bin", "/usr/bin"}, }, - SystemBus: app.SystemBus, - SessionBus: app.SessionBus, - Enablements: app.Enablements, + Etc: path.Join(pathSet.cacheDir, "etc"), + AutoEtc: true, + }, + ExtraPerms: []*fst.ExtraPermConfig{ + {Path: dataHome, Execute: true}, + {Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true}, }, } if app.Multiarch { - config.Confinement.Sandbox.Seccomp |= seccomp.FilterMultiarch + config.Container.Seccomp |= seccomp.FilterMultiarch } if app.Bluetooth { - config.Confinement.Sandbox.Seccomp |= seccomp.FilterBluetooth + config.Container.Seccomp |= seccomp.FilterBluetooth } return config } diff --git a/cmd/fpkg/build.nix b/cmd/fpkg/build.nix index 17dfa93..0a0a558 100644 --- a/cmd/fpkg/build.nix +++ b/cmd/fpkg/build.nix @@ -31,7 +31,7 @@ '', id ? name, - app_id ? throw "app_id is required", + identity ? throw "identity is required", groups ? [ ], userns ? false, net ? true, @@ -147,7 +147,7 @@ let name version id - app_id + identity launcher groups userns diff --git a/cmd/fpkg/main.go b/cmd/fpkg/main.go index e48cfb5..ac95bc1 100644 --- a/cmd/fpkg/main.go +++ b/cmd/fpkg/main.go @@ -157,11 +157,11 @@ func main() { return errSuccess } - // AppID determines uid - if a.AppID != bundle.AppID { + // identity determines uid + if a.Identity != bundle.Identity { cleanup() - log.Printf("package %q app id %d differs from installed %d", - pkgPath, bundle.AppID, a.AppID) + log.Printf("package %q identity %d differs from installed %d", + pkgPath, bundle.Identity, a.Identity) return syscall.EBADE } @@ -292,7 +292,7 @@ func main() { "--override-input nixpkgs path:/etc/nixpkgs " + "path:" + a.NixGL + "#nixVulkanNvidia", }, true, func(config *fst.Config) *fst.Config { - config.Confinement.Sandbox.Filesystem = append(config.Confinement.Sandbox.Filesystem, []*fst.FilesystemConfig{ + config.Container.Filesystem = append(config.Container.Filesystem, []*fst.FilesystemConfig{ {Src: "/etc/resolv.conf"}, {Src: "/sys/block"}, {Src: "/sys/bus"}, @@ -324,7 +324,7 @@ func main() { */ if a.GPU { - config.Confinement.Sandbox.Filesystem = append(config.Confinement.Sandbox.Filesystem, + config.Container.Filesystem = append(config.Container.Filesystem, &fst.FilesystemConfig{Src: path.Join(pathSet.nixPath, ".nixGL"), Dst: path.Join(fst.Tmp, "nixGL")}) appendGPUFilesystem(config) } diff --git a/cmd/fpkg/paths.go b/cmd/fpkg/paths.go index 3d832d6..2eaeb42 100644 --- a/cmd/fpkg/paths.go +++ b/cmd/fpkg/paths.go @@ -72,7 +72,7 @@ func pathSetByApp(id string) *appPathSet { } func appendGPUFilesystem(config *fst.Config) { - config.Confinement.Sandbox.Filesystem = append(config.Confinement.Sandbox.Filesystem, []*fst.FilesystemConfig{ + config.Container.Filesystem = append(config.Container.Filesystem, []*fst.FilesystemConfig{ // flatpak commit 763a686d874dd668f0236f911de00b80766ffe79 {Src: "/dev/dri", Device: true}, // mali diff --git a/cmd/fpkg/test/foot.nix b/cmd/fpkg/test/foot.nix index 34469da..76b677a 100644 --- a/cmd/fpkg/test/foot.nix +++ b/cmd/fpkg/test/foot.nix @@ -10,7 +10,7 @@ buildPackage { name = "foot"; inherit (foot) version; - app_id = 2; + identity = 2; id = "org.codeberg.dnkl.foot"; modules = [ diff --git a/cmd/fpkg/test/test.py b/cmd/fpkg/test/test.py index 7d4e0d5..641062f 100644 --- a/cmd/fpkg/test/test.py +++ b/cmd/fpkg/test/test.py @@ -65,8 +65,8 @@ def check_state(name, enablements): if len(config['args']) != 1 or not (config['args'][0].startswith("/nix/store/")) or f"fortify-{name}-" not in (config['args'][0]): raise Exception(f"unexpected args {instance['config']['args']}") - if config['confinement']['enablements'] != enablements: - raise Exception(f"unexpected enablements {instance['config']['confinement']['enablements']}") + if config['enablements'] != enablements: + raise Exception(f"unexpected enablements {instance['config']['enablements']}") start_all() diff --git a/cmd/fpkg/with.go b/cmd/fpkg/with.go index 92c5ba9..9de1a39 100644 --- a/cmd/fpkg/with.go +++ b/cmd/fpkg/with.go @@ -16,7 +16,8 @@ func withNixDaemon( app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(), ) { mustRunAppDropShell(ctx, updateConfig(&fst.Config{ - ID: app.ID, + ID: app.ID, + Path: shellPath, Args: []string{shellPath, "-lc", "rm -f /nix/var/nix/daemon-socket/socket && " + // start nix-daemon @@ -29,33 +30,34 @@ func withNixDaemon( // terminate nix-daemon " && pkill nix-daemon", }, - Confinement: fst.ConfinementConfig{ - AppID: app.AppID, - Username: "fortify", - Inner: path.Join("/data/data", app.ID), - Outer: pathSet.homeDir, - Shell: shellPath, - Sandbox: &fst.SandboxConfig{ - Hostname: formatHostname(app.Name) + "-" + action, - Userns: true, // nix sandbox requires userns - Net: net, - Seccomp: seccomp.FilterMultiarch, - Tty: dropShell, - Filesystem: []*fst.FilesystemConfig{ - {Src: pathSet.nixPath, Dst: "/nix", Write: true, Must: true}, - }, - Link: [][2]string{ - {app.CurrentSystem, "/run/current-system"}, - {"/run/current-system/sw/bin", "/bin"}, - {"/run/current-system/sw/bin", "/usr/bin"}, - }, - Etc: path.Join(pathSet.cacheDir, "etc"), - AutoEtc: true, + + Username: "fortify", + Shell: shellPath, + Data: pathSet.homeDir, + Dir: path.Join("/data/data", app.ID), + ExtraPerms: []*fst.ExtraPermConfig{ + {Path: dataHome, Execute: true}, + {Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true}, + }, + + Identity: app.Identity, + + Container: &fst.ContainerConfig{ + Hostname: formatHostname(app.Name) + "-" + action, + Userns: true, // nix sandbox requires userns + Net: net, + Seccomp: seccomp.FilterMultiarch, + Tty: dropShell, + Filesystem: []*fst.FilesystemConfig{ + {Src: pathSet.nixPath, Dst: "/nix", Write: true, Must: true}, }, - ExtraPerms: []*fst.ExtraPermConfig{ - {Path: dataHome, Execute: true}, - {Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true}, + Link: [][2]string{ + {app.CurrentSystem, "/run/current-system"}, + {"/run/current-system/sw/bin", "/bin"}, + {"/run/current-system/sw/bin", "/usr/bin"}, }, + Etc: path.Join(pathSet.cacheDir, "etc"), + AutoEtc: true, }, }), dropShell, beforeFail) } @@ -65,36 +67,38 @@ func withCacheDir( action string, command []string, workDir string, app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func()) { mustRunAppDropShell(ctx, &fst.Config{ - ID: app.ID, + ID: app.ID, + Path: shellPath, Args: []string{shellPath, "-lc", strings.Join(command, " && ")}, - Confinement: fst.ConfinementConfig{ - AppID: app.AppID, - Username: "nixos", - Inner: path.Join("/data/data", app.ID, "cache"), - Outer: pathSet.cacheDir, // this also ensures cacheDir via shim - Shell: shellPath, - Sandbox: &fst.SandboxConfig{ - Hostname: formatHostname(app.Name) + "-" + action, - Seccomp: seccomp.FilterMultiarch, - Tty: dropShell, - Filesystem: []*fst.FilesystemConfig{ - {Src: path.Join(workDir, "nix"), Dst: "/nix", Must: true}, - {Src: workDir, Dst: path.Join(fst.Tmp, "bundle"), Must: true}, - }, - Link: [][2]string{ - {app.CurrentSystem, "/run/current-system"}, - {"/run/current-system/sw/bin", "/bin"}, - {"/run/current-system/sw/bin", "/usr/bin"}, - }, - Etc: path.Join(workDir, "etc"), - AutoEtc: true, + + Username: "nixos", + Shell: shellPath, + Data: pathSet.cacheDir, // this also ensures cacheDir via shim + Dir: path.Join("/data/data", app.ID, "cache"), + ExtraPerms: []*fst.ExtraPermConfig{ + {Path: dataHome, Execute: true}, + {Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true}, + {Path: workDir, Execute: true}, + }, + + Identity: app.Identity, + + Container: &fst.ContainerConfig{ + Hostname: formatHostname(app.Name) + "-" + action, + Seccomp: seccomp.FilterMultiarch, + Tty: dropShell, + Filesystem: []*fst.FilesystemConfig{ + {Src: path.Join(workDir, "nix"), Dst: "/nix", Must: true}, + {Src: workDir, Dst: path.Join(fst.Tmp, "bundle"), Must: true}, }, - ExtraPerms: []*fst.ExtraPermConfig{ - {Path: dataHome, Execute: true}, - {Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true}, - {Path: workDir, Execute: true}, + Link: [][2]string{ + {app.CurrentSystem, "/run/current-system"}, + {"/run/current-system/sw/bin", "/bin"}, + {"/run/current-system/sw/bin", "/usr/bin"}, }, + Etc: path.Join(workDir, "etc"), + AutoEtc: true, }, }, dropShell, beforeFail) } diff --git a/fst/config.go b/fst/config.go index a56927f..62c8570 100644 --- a/fst/config.go +++ b/fst/config.go @@ -8,7 +8,7 @@ import ( const Tmp = "/.fortify" -// Config is used to seal an app +// Config is used to seal an app implementation. type Config struct { // reverse-DNS style arbitrary identifier string from config; // passed to wayland security-context-v1 as application ID @@ -20,39 +20,40 @@ type Config struct { // final args passed to container init Args []string `json:"args"` - Confinement ConfinementConfig `json:"confinement"` -} + // system services to make available in the container + Enablements system.Enablement `json:"enablements"` + + // session D-Bus proxy configuration; + // nil makes session bus proxy assume built-in defaults + SessionBus *dbus.Config `json:"session_bus,omitempty"` + // system D-Bus proxy configuration; + // nil disables system bus proxy + SystemBus *dbus.Config `json:"system_bus,omitempty"` + // direct access to wayland socket; when this gets set no attempt is made to attach security-context-v1 + // and the bare socket is mounted to the sandbox + DirectWayland bool `json:"direct_wayland,omitempty"` -// ConfinementConfig defines fortified child's confinement -type ConfinementConfig struct { - // numerical application id, determines uid in the init namespace - AppID int `json:"app_id"` - // list of supplementary groups to inherit - Groups []string `json:"groups"` // passwd username in container, defaults to passwd name of target uid or chronos Username string `json:"username,omitempty"` - // home directory in container, empty for outer - Inner string `json:"home_inner"` - // home directory in init namespace - Outer string `json:"home"` // absolute path to shell, empty for host shell Shell string `json:"shell,omitempty"` - // abstract sandbox configuration - Sandbox *SandboxConfig `json:"sandbox"` - // extra acl ops, runs after everything else + // absolute path to home directory in the init mount namespace + Data string `json:"data"` + // directory to enter and use as home in the container mount namespace, empty for Data + Dir string `json:"dir"` + // extra acl ops, dispatches before container init ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"` - // 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"` + // numerical application id, used for init user namespace credentials + Identity int `json:"identity"` + // list of supplementary groups inherited by container processes + Groups []string `json:"groups"` - // system resources to expose to the container - Enablements system.Enablement `json:"enablements"` + // abstract container configuration baseline + Container *ContainerConfig `json:"container"` } +// ExtraPermConfig describes an acl update op. type ExtraPermConfig struct { Ensure bool `json:"ensure,omitempty"` Path string `json:"path"` diff --git a/fst/sandbox.go b/fst/container.go similarity index 79% rename from fst/sandbox.go rename to fst/container.go index c4936a2..1190caa 100644 --- a/fst/sandbox.go +++ b/fst/container.go @@ -4,9 +4,9 @@ import ( "git.gensokyo.uk/security/fortify/sandbox/seccomp" ) -// SandboxConfig describes resources made available to the sandbox. type ( - SandboxConfig struct { + // ContainerConfig describes the container configuration baseline to which the app implementation adds upon. + ContainerConfig struct { // container hostname Hostname string `json:"hostname,omitempty"` @@ -18,7 +18,7 @@ type ( Userns bool `json:"userns,omitempty"` // share host net namespace Net bool `json:"net,omitempty"` - // expose main process tty + // allow dangerous terminal I/O Tty bool `json:"tty,omitempty"` // allow multiarch Multiarch bool `json:"multiarch,omitempty"` @@ -28,17 +28,13 @@ type ( // map target user uid to privileged user uid in the user namespace MapRealUID bool `json:"map_real_uid"` - // expose all devices + // pass through all devices Device bool `json:"device,omitempty"` // container host filesystem bind mounts Filesystem []*FilesystemConfig `json:"filesystem"` // create symlinks inside container filesystem Link [][2]string `json:"symlink"` - // direct access to wayland socket; when this gets set no attempt is made to attach security-context-v1 - // and the bare socket is mounted to the sandbox - DirectWayland bool `json:"direct_wayland,omitempty"` - // read-only /etc directory Etc string `json:"etc,omitempty"` // automatically set up /etc symlinks @@ -47,7 +43,7 @@ type ( Cover []string `json:"cover"` } - // FilesystemConfig is a representation of [sandbox.BindMount]. + // FilesystemConfig is an abstract representation of a bind mount. FilesystemConfig struct { // mount point in container, same as src if empty Dst string `json:"dst,omitempty"` diff --git a/fst/template.go b/fst/template.go index 0777c9d..0ca928a 100644 --- a/fst/template.go +++ b/fst/template.go @@ -9,7 +9,8 @@ import ( // Template returns a fully populated instance of Config. func Template() *Config { return &Config{ - ID: "org.chromium.Chromium", + ID: "org.chromium.Chromium", + Path: "/run/current-system/sw/bin/chromium", Args: []string{ "chromium", @@ -18,70 +19,73 @@ func Template() *Config { "--enable-features=UseOzonePlatform", "--ozone-platform=wayland", }, - Confinement: ConfinementConfig{ - AppID: 9, - Groups: []string{"video"}, - Username: "chronos", - Outer: "/var/lib/persist/home/org.chromium.Chromium", - Inner: "/var/lib/fortify", - Shell: "/run/current-system/sw/bin/zsh", - Sandbox: &SandboxConfig{ - Hostname: "localhost", - Devel: true, - Userns: true, - Net: true, - Device: true, - Seccomp: seccomp.FilterMultiarch, - Tty: true, - Multiarch: true, - MapRealUID: true, - DirectWayland: 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/store"}, - {Src: "/run/current-system"}, - {Src: "/run/opengl-driver"}, - {Src: "/var/db/nix-channels"}, - {Src: "/var/lib/fortify/u0/org.chromium.Chromium", - Dst: "/data/data/org.chromium.Chromium", Write: true, Must: true}, - {Src: "/dev/dri", Device: true}, - }, - Link: [][2]string{{"/run/user/65534", "/run/user/150"}}, - Etc: "/etc", - AutoEtc: true, - Cover: []string{"/var/run/nscd"}, + + Enablements: system.EWayland | system.EDBus | system.EPulse, + + 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, + }, + 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, + }, + DirectWayland: false, + + Username: "chronos", + Shell: "/run/current-system/sw/bin/zsh", + Data: "/var/lib/fortify/u0/org.chromium.Chromium", + Dir: "/data/data/org.chromium.Chromium", + ExtraPerms: []*ExtraPermConfig{ + {Path: "/var/lib/fortify/u0", Ensure: true, Execute: true}, + {Path: "/var/lib/fortify/u0/org.chromium.Chromium", Read: true, Write: true, Execute: true}, + }, + + Identity: 9, + Groups: []string{"video", "dialout", "plugdev"}, + + Container: &ContainerConfig{ + Hostname: "localhost", + Devel: true, + Userns: true, + Net: true, + Device: true, + Seccomp: seccomp.FilterMultiarch, + Tty: true, + Multiarch: true, + MapRealUID: true, + // 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", }, - ExtraPerms: []*ExtraPermConfig{ - {Path: "/var/lib/fortify/u0", Ensure: true, Execute: true}, - {Path: "/var/lib/fortify/u0/org.chromium.Chromium", Read: true, Write: true, Execute: true}, + Filesystem: []*FilesystemConfig{ + {Src: "/nix/store"}, + {Src: "/run/current-system"}, + {Src: "/run/opengl-driver"}, + {Src: "/var/db/nix-channels"}, + {Src: "/var/lib/fortify/u0/org.chromium.Chromium", + Dst: "/data/data/org.chromium.Chromium", Write: true, Must: true}, + {Src: "/dev/dri", Device: true}, }, - 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: system.EWayland | system.EDBus | system.EPulse, + Link: [][2]string{{"/run/user/65534", "/run/user/150"}}, + Etc: "/etc", + AutoEtc: true, + Cover: []string{"/var/run/nscd"}, }, } } diff --git a/fst/template_test.go b/fst/template_test.go index 0ec2dae..c7fd780 100644 --- a/fst/template_test.go +++ b/fst/template_test.go @@ -18,116 +18,116 @@ func TestTemplate(t *testing.T) { "--enable-features=UseOzonePlatform", "--ozone-platform=wayland" ], - "confinement": { - "app_id": 9, - "groups": [ - "video" + "enablements": 13, + "session_bus": { + "see": null, + "talk": [ + "org.freedesktop.Notifications", + "org.freedesktop.FileManager1", + "org.freedesktop.ScreenSaver", + "org.freedesktop.secrets", + "org.kde.kwalletd5", + "org.kde.kwalletd6", + "org.gnome.SessionManager" ], - "username": "chronos", - "home_inner": "/var/lib/fortify", - "home": "/var/lib/persist/home/org.chromium.Chromium", - "shell": "/run/current-system/sw/bin/zsh", - "sandbox": { - "hostname": "localhost", - "seccomp": 32, - "devel": true, - "userns": true, - "net": true, - "tty": true, - "multiarch": true, - "env": { - "GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY", - "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", - "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT" - }, - "map_real_uid": true, - "device": true, - "filesystem": [ - { - "src": "/nix/store" - }, - { - "src": "/run/current-system" - }, - { - "src": "/run/opengl-driver" - }, - { - "src": "/var/db/nix-channels" - }, - { - "dst": "/data/data/org.chromium.Chromium", - "src": "/var/lib/fortify/u0/org.chromium.Chromium", - "write": true, - "require": true - }, - { - "src": "/dev/dri", - "dev": true - } - ], - "symlink": [ - [ - "/run/user/65534", - "/run/user/150" - ] - ], - "etc": "/etc", - "auto_etc": true, - "cover": [ - "/var/run/nscd" - ] + "own": [ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*" + ], + "call": { + "org.freedesktop.portal.*": "*" }, - "extra_perms": [ + "broadcast": { + "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" + }, + "filter": true + }, + "system_bus": { + "see": null, + "talk": [ + "org.bluez", + "org.freedesktop.Avahi", + "org.freedesktop.UPower" + ], + "own": null, + "call": null, + "broadcast": null, + "filter": true + }, + "username": "chronos", + "shell": "/run/current-system/sw/bin/zsh", + "data": "/var/lib/fortify/u0/org.chromium.Chromium", + "dir": "/data/data/org.chromium.Chromium", + "extra_perms": [ + { + "ensure": true, + "path": "/var/lib/fortify/u0", + "x": true + }, + { + "path": "/var/lib/fortify/u0/org.chromium.Chromium", + "r": true, + "w": true, + "x": true + } + ], + "identity": 9, + "groups": [ + "video", + "dialout", + "plugdev" + ], + "container": { + "hostname": "localhost", + "seccomp": 32, + "devel": true, + "userns": true, + "net": true, + "tty": true, + "multiarch": true, + "env": { + "GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY", + "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", + "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT" + }, + "map_real_uid": true, + "device": true, + "filesystem": [ { - "ensure": true, - "path": "/var/lib/fortify/u0", - "x": true + "src": "/nix/store" }, { - "path": "/var/lib/fortify/u0/org.chromium.Chromium", - "r": true, - "w": true, - "x": true + "src": "/run/current-system" + }, + { + "src": "/run/opengl-driver" + }, + { + "src": "/var/db/nix-channels" + }, + { + "dst": "/data/data/org.chromium.Chromium", + "src": "/var/lib/fortify/u0/org.chromium.Chromium", + "write": true, + "require": true + }, + { + "src": "/dev/dri", + "dev": true } ], - "system_bus": { - "see": null, - "talk": [ - "org.bluez", - "org.freedesktop.Avahi", - "org.freedesktop.UPower" - ], - "own": null, - "call": null, - "broadcast": null, - "filter": true - }, - "session_bus": { - "see": null, - "talk": [ - "org.freedesktop.Notifications", - "org.freedesktop.FileManager1", - "org.freedesktop.ScreenSaver", - "org.freedesktop.secrets", - "org.kde.kwalletd5", - "org.kde.kwalletd6", - "org.gnome.SessionManager" - ], - "own": [ - "org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.chromium.*" - ], - "call": { - "org.freedesktop.portal.*": "*" - }, - "broadcast": { - "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" - }, - "filter": true - }, - "enablements": 13 + "symlink": [ + [ + "/run/user/65534", + "/run/user/150" + ] + ], + "etc": "/etc", + "auto_etc": true, + "cover": [ + "/var/run/nscd" + ] } }` diff --git a/internal/app/instance/common/container.go b/internal/app/instance/common/container.go index cc26c80..370997a 100644 --- a/internal/app/instance/common/container.go +++ b/internal/app/instance/common/container.go @@ -16,9 +16,9 @@ import ( "git.gensokyo.uk/security/fortify/sandbox/seccomp" ) -// NewContainer initialises [sandbox.Params] via [fst.SandboxConfig]. +// NewContainer initialises [sandbox.Params] via [fst.ContainerConfig]. // Note that remaining container setup must be queued by the caller. -func NewContainer(s *fst.SandboxConfig, os sys.State, uid, gid *int) (*sandbox.Params, map[string]string, error) { +func NewContainer(s *fst.ContainerConfig, os sys.State, uid, gid *int) (*sandbox.Params, map[string]string, error) { if s == nil { return nil, nil, syscall.EBADE } diff --git a/internal/app/internal/setuid/app_nixos_test.go b/internal/app/internal/setuid/app_nixos_test.go index 0daaf69..0e649ad 100644 --- a/internal/app/internal/setuid/app_nixos_test.go +++ b/internal/app/internal/setuid/app_nixos_test.go @@ -13,41 +13,43 @@ var testCasesNixos = []sealTestCase{ { "nixos chromium direct wayland", new(stubNixOS), &fst.Config{ - ID: "org.chromium.Chromium", - Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start", - Confinement: fst.ConfinementConfig{ - AppID: 1, Groups: []string{}, Username: "u0_a1", - Outer: "/var/lib/persist/module/fortify/0/1", - Sandbox: &fst.SandboxConfig{ - Userns: true, Net: true, MapRealUID: true, DirectWayland: true, Env: nil, AutoEtc: true, - Filesystem: []*fst.FilesystemConfig{ - {Src: "/bin", Must: true}, {Src: "/usr/bin", Must: true}, - {Src: "/nix/store", Must: true}, {Src: "/run/current-system", Must: true}, - {Src: "/sys/block"}, {Src: "/sys/bus"}, {Src: "/sys/class"}, {Src: "/sys/dev"}, {Src: "/sys/devices"}, - {Src: "/run/opengl-driver", Must: true}, {Src: "/dev/dri", Device: true}, - }, - Cover: []string{"/var/run/nscd"}, + ID: "org.chromium.Chromium", + Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start", + Enablements: system.EWayland | system.EDBus | system.EPulse, + + Container: &fst.ContainerConfig{ + Userns: true, Net: true, MapRealUID: true, Env: nil, AutoEtc: true, + Filesystem: []*fst.FilesystemConfig{ + {Src: "/bin", Must: true}, {Src: "/usr/bin", Must: true}, + {Src: "/nix/store", Must: true}, {Src: "/run/current-system", Must: true}, + {Src: "/sys/block"}, {Src: "/sys/bus"}, {Src: "/sys/class"}, {Src: "/sys/dev"}, {Src: "/sys/devices"}, + {Src: "/run/opengl-driver", Must: true}, {Src: "/dev/dri", Device: true}, }, - SystemBus: &dbus.Config{ - Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"}, - Filter: true, - }, - SessionBus: &dbus.Config{ - Talk: []string{ - "org.freedesktop.FileManager1", "org.freedesktop.Notifications", - "org.freedesktop.ScreenSaver", "org.freedesktop.secrets", - "org.kde.kwalletd5", "org.kde.kwalletd6", - }, - Own: []string{ - "org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.chromium.*", - }, - Call: map[string]string{}, Broadcast: map[string]string{}, - Filter: true, - }, - Enablements: system.EWayland | system.EDBus | system.EPulse, + Cover: []string{"/var/run/nscd"}, }, + SystemBus: &dbus.Config{ + Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"}, + Filter: true, + }, + SessionBus: &dbus.Config{ + Talk: []string{ + "org.freedesktop.FileManager1", "org.freedesktop.Notifications", + "org.freedesktop.ScreenSaver", "org.freedesktop.secrets", + "org.kde.kwalletd5", "org.kde.kwalletd6", + }, + Own: []string{ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*", + }, + Call: map[string]string{}, Broadcast: map[string]string{}, + Filter: true, + }, + DirectWayland: true, + + Username: "u0_a1", + Data: "/var/lib/persist/module/fortify/0/1", + Identity: 1, Groups: []string{}, }, app.ID{ 0x8e, 0x2c, 0x76, 0xb0, diff --git a/internal/app/internal/setuid/app_pd_test.go b/internal/app/internal/setuid/app_pd_test.go index 2dc0625..b331684 100644 --- a/internal/app/internal/setuid/app_pd_test.go +++ b/internal/app/internal/setuid/app_pd_test.go @@ -14,13 +14,7 @@ import ( var testCasesPd = []sealTestCase{ { "nixos permissive defaults no enablements", new(stubNixOS), - &fst.Config{ - Confinement: fst.ConfinementConfig{ - AppID: 0, - Username: "chronos", - Outer: "/home/chronos", - }, - }, + &fst.Config{Username: "chronos", Data: "/home/chronos"}, app.ID{ 0x4a, 0x45, 0x0b, 0x65, 0x96, 0xd7, 0xbc, 0x15, @@ -77,46 +71,44 @@ var testCasesPd = []sealTestCase{ { "nixos permissive defaults chromium", new(stubNixOS), &fst.Config{ - ID: "org.chromium.Chromium", - Args: []string{"zsh", "-c", "exec chromium "}, - Confinement: fst.ConfinementConfig{ - AppID: 9, - Groups: []string{"video"}, - Username: "chronos", - Outer: "/home/chronos", - SessionBus: &dbus.Config{ - 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/*", - }, - Filter: true, + ID: "org.chromium.Chromium", + Args: []string{"zsh", "-c", "exec chromium "}, + Identity: 9, + Groups: []string{"video"}, + Username: "chronos", + Data: "/home/chronos", + SessionBus: &dbus.Config{ + Talk: []string{ + "org.freedesktop.Notifications", + "org.freedesktop.FileManager1", + "org.freedesktop.ScreenSaver", + "org.freedesktop.secrets", + "org.kde.kwalletd5", + "org.kde.kwalletd6", + "org.gnome.SessionManager", }, - SystemBus: &dbus.Config{ - Talk: []string{ - "org.bluez", - "org.freedesktop.Avahi", - "org.freedesktop.UPower", - }, - Filter: true, + Own: []string{ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*", }, - Enablements: system.EWayland | system.EDBus | system.EPulse, + Call: map[string]string{ + "org.freedesktop.portal.*": "*", + }, + Broadcast: map[string]string{ + "org.freedesktop.portal.*": "@/org/freedesktop/portal/*", + }, + Filter: true, }, + SystemBus: &dbus.Config{ + Talk: []string{ + "org.bluez", + "org.freedesktop.Avahi", + "org.freedesktop.UPower", + }, + Filter: true, + }, + Enablements: system.EWayland | system.EDBus | system.EPulse, }, app.ID{ 0xeb, 0xf0, 0x83, 0xd1, diff --git a/internal/app/internal/setuid/process.go b/internal/app/internal/setuid/process.go index 271e64e..d3114c7 100644 --- a/internal/app/internal/setuid/process.go +++ b/internal/app/internal/setuid/process.go @@ -65,7 +65,7 @@ func (seal *outcome) Run(rs *RunState) error { // accumulate enablements of remaining launchers for i, s := range states { if s.Config != nil { - rt |= s.Config.Confinement.Enablements + rt |= s.Config.Enablements } else { log.Printf("state entry %d does not contain config", i) } diff --git a/internal/app/internal/setuid/seal.go b/internal/app/internal/setuid/seal.go index 44a73b1..edf7c87 100644 --- a/internal/app/internal/setuid/seal.go +++ b/internal/app/internal/setuid/seal.go @@ -169,16 +169,16 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } // allowed aid range 0 to 9999, this is checked again in fsu - if config.Confinement.AppID < 0 || config.Confinement.AppID > 9999 { + if config.Identity < 0 || config.Identity > 9999 { return fmsg.WrapError(ErrUser, - fmt.Sprintf("aid %d out of range", config.Confinement.AppID)) + fmt.Sprintf("identity %d out of range", config.Identity)) } seal.user = fsuUser{ - aid: newInt(config.Confinement.AppID), - data: config.Confinement.Outer, - home: config.Confinement.Inner, - username: config.Confinement.Username, + aid: newInt(config.Identity), + data: config.Data, + home: config.Dir, + username: config.Username, } if seal.user.username == "" { seal.user.username = "chronos" @@ -199,8 +199,8 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } else { seal.user.uid = newInt(u) } - seal.user.supp = make([]string, len(config.Confinement.Groups)) - for i, name := range config.Confinement.Groups { + seal.user.supp = make([]string, len(config.Groups)) + for i, name := range config.Groups { if g, err := sys.LookupGroup(name); err != nil { return fmsg.WrapError(err, fmt.Sprintf("unknown group %q", name)) @@ -210,17 +210,17 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } // this also falls back to host path if encountering an invalid path - if !path.IsAbs(config.Confinement.Shell) { - config.Confinement.Shell = "/bin/sh" + if !path.IsAbs(config.Shell) { + config.Shell = "/bin/sh" if s, ok := sys.LookupEnv(shell); ok && path.IsAbs(s) { - config.Confinement.Shell = s + config.Shell = s } } // do not use the value of shell before this point // permissive defaults - if config.Confinement.Sandbox == nil { - fmsg.Verbose("sandbox configuration not supplied, PROCEED WITH CAUTION") + if config.Container == nil { + fmsg.Verbose("container configuration not supplied, PROCEED WITH CAUTION") // fsu clears the environment so resolve paths early if !path.IsAbs(config.Path) { @@ -231,11 +231,11 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co config.Path = p } } else { - config.Path = config.Confinement.Shell + config.Path = config.Shell } } - conf := &fst.SandboxConfig{ + conf := &fst.ContainerConfig{ Userns: true, Net: true, Tty: true, @@ -268,20 +268,20 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co conf.Cover = append(conf.Cover, nscd) } // bind GPU stuff - if config.Confinement.Enablements&(system.EX11|system.EWayland) != 0 { + if config.Enablements&(system.EX11|system.EWayland) != 0 { conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/dri", Device: true}) } // opportunistically bind kvm conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/kvm", Device: true}) - config.Confinement.Sandbox = conf + config.Container = conf } var mapuid, mapgid *stringPair[int] { var uid, gid int var err error - seal.container, seal.env, err = common.NewContainer(config.Confinement.Sandbox, sys, &uid, &gid) + seal.container, seal.env, err = common.NewContainer(config.Container, sys, &uid, &gid) if err != nil { return fmsg.WrapErrorSuffix(err, "cannot initialise container configuration:") @@ -303,12 +303,12 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if !config.Confinement.Sandbox.AutoEtc { - if config.Confinement.Sandbox.Etc != "" { - seal.container.Bind(config.Confinement.Sandbox.Etc, "/etc", 0) + if !config.Container.AutoEtc { + if config.Container.Etc != "" { + seal.container.Bind(config.Container.Etc, "/etc", 0) } } else { - etcPath := config.Confinement.Sandbox.Etc + etcPath := config.Container.Etc if etcPath == "" { etcPath = "/etc" } @@ -352,10 +352,10 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co seal.container.Dir = homeDir seal.env["HOME"] = homeDir seal.env["USER"] = username - seal.env[shell] = config.Confinement.Shell + seal.env[shell] = config.Shell seal.container.Place("/etc/passwd", - []byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Confinement.Shell+"\n")) + []byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Shell+"\n")) seal.container.Place("/etc/group", []byte("fortify:x:"+mapgid.String()+":\n")) } @@ -365,7 +365,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co seal.env[term] = t } - if config.Confinement.Enablements&system.EWayland != 0 { + if config.Enablements&system.EWayland != 0 { // outer wayland socket (usually `/run/user/%d/wayland-%d`) var socketPath string if name, ok := sys.LookupEnv(wl.WaylandDisplay); !ok { @@ -380,7 +380,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co innerPath := path.Join(innerRuntimeDir, wl.FallbackName) seal.env[wl.WaylandDisplay] = wl.FallbackName - if !config.Confinement.Sandbox.DirectWayland { // set up security-context-v1 + if !config.DirectWayland { // set up security-context-v1 appID := config.ID if appID == "" { // use instance ID in case app id is not set @@ -398,7 +398,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if config.Confinement.Enablements&system.EX11 != 0 { + if config.Enablements&system.EX11 != 0 { if d, ok := sys.LookupEnv(display); !ok { return fmsg.WrapError(ErrXDisplay, "DISPLAY is not set") @@ -409,7 +409,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if config.Confinement.Enablements&system.EPulse != 0 { + if config.Enablements&system.EPulse != 0 { // PulseAudio runtime directory (usually `/run/user/%d/pulse`) pulseRuntimeDir := path.Join(share.sc.RuntimePath, "pulse") // PulseAudio socket (usually `/run/user/%d/pulse/native`) @@ -458,10 +458,10 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if config.Confinement.Enablements&system.EDBus != 0 { + if config.Enablements&system.EDBus != 0 { // ensure dbus session bus defaults - if config.Confinement.SessionBus == nil { - config.Confinement.SessionBus = dbus.NewConfig(config.ID, true, true) + if config.SessionBus == nil { + config.SessionBus = dbus.NewConfig(config.ID, true, true) } // downstream socket paths @@ -470,7 +470,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co // configure dbus proxy if f, err := seal.sys.ProxyDBus( - config.Confinement.SessionBus, config.Confinement.SystemBus, + config.SessionBus, config.SystemBus, sessionPath, systemPath, ); err != nil { return err @@ -483,7 +483,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co seal.env[dbusSessionBusAddress] = "unix:path=" + sessionInner seal.container.Bind(sessionPath, sessionInner, 0) seal.sys.UpdatePerm(sessionPath, acl.Read, acl.Write) - if config.Confinement.SystemBus != nil { + if config.SystemBus != nil { systemInner := "/run/dbus/system_bus_socket" seal.env[dbusSystemBusAddress] = "unix:path=" + systemInner seal.container.Bind(systemPath, systemInner, 0) @@ -491,12 +491,12 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - for _, dest := range config.Confinement.Sandbox.Cover { + for _, dest := range config.Container.Cover { seal.container.Tmpfs(dest, 1<<13, 0755) } // append ExtraPerms last - for _, p := range config.Confinement.ExtraPerms { + for _, p := range config.ExtraPerms { if p == nil { continue } @@ -530,7 +530,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co slices.Sort(seal.container.Env) fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, argv: %s", - seal.user.uid, seal.user.username, config.Confinement.Groups, seal.container.Args) + seal.user.uid, seal.user.username, config.Groups, seal.container.Args) return nil } diff --git a/main.go b/main.go index 1fe2f7a..4c13edc 100644 --- a/main.go +++ b/main.go @@ -154,33 +154,33 @@ func buildCommand(out io.Writer) command.Command { userName = passwd.Username } - config.Confinement.AppID = aid - config.Confinement.Groups = groups - config.Confinement.Outer = homeDir - config.Confinement.Username = userName + config.Identity = aid + config.Groups = groups + config.Data = homeDir + config.Username = userName if wayland { - config.Confinement.Enablements |= system.EWayland + config.Enablements |= system.EWayland } if x11 { - config.Confinement.Enablements |= system.EX11 + config.Enablements |= system.EX11 } if dBus { - config.Confinement.Enablements |= system.EDBus + config.Enablements |= system.EDBus } if pulse { - config.Confinement.Enablements |= system.EPulse + config.Enablements |= system.EPulse } // parse D-Bus config file from flags if applicable if dBus { if dbusConfigSession == "builtin" { - config.Confinement.SessionBus = dbus.NewConfig(fid, true, mpris) + config.SessionBus = dbus.NewConfig(fid, true, mpris) } else { if conf, err := dbus.NewConfigFromFile(dbusConfigSession); err != nil { log.Fatalf("cannot load session bus proxy config from %q: %s", dbusConfigSession, err) } else { - config.Confinement.SessionBus = conf + config.SessionBus = conf } } @@ -189,14 +189,14 @@ func buildCommand(out io.Writer) command.Command { if conf, err := dbus.NewConfigFromFile(dbusConfigSystem); err != nil { log.Fatalf("cannot load system bus proxy config from %q: %s", dbusConfigSystem, err) } else { - config.Confinement.SystemBus = conf + config.SystemBus = conf } } // override log from configuration if dbusVerbose { - config.Confinement.SessionBus.Log = true - config.Confinement.SystemBus.Log = true + config.SessionBus.Log = true + config.SystemBus.Log = true } } diff --git a/nixos.nix b/nixos.nix index 030cb3a..49d41f3 100644 --- a/nixos.nix +++ b/nixos.nix @@ -88,6 +88,7 @@ in conf = { inherit (app) id; + path = if app.path == null then pkgs.writeScript "${app.name}-start" '' @@ -98,88 +99,90 @@ in app.path; args = if app.args == null then [ "${app.name}-start" ] else app.args; - confinement = { - app_id = aid; - inherit (app) groups; - username = getsubname fid aid; - home = getsubhome fid aid; - sandbox = { - inherit (app) - devel - userns - net - device - tty - multiarch - env - ; - map_real_uid = app.mapRealUid; - direct_wayland = app.insecureWayland; + inherit enablements; - filesystem = - let - bind = src: { inherit src; }; - mustBind = src: { - inherit src; - require = true; - }; - devBind = src: { - inherit src; - dev = true; - }; - in + inherit (dbusConfig) session_bus system_bus; + direct_wayland = app.insecureWayland; + + username = getsubname fid aid; + data = getsubhome fid aid; + + identity = aid; + inherit (app) groups; + + container = { + inherit (app) + devel + userns + net + device + tty + multiarch + env + ; + map_real_uid = app.mapRealUid; + + filesystem = + let + bind = src: { inherit src; }; + mustBind = src: { + inherit src; + require = true; + }; + devBind = src: { + inherit src; + dev = true; + }; + in + [ + (mustBind "/bin") + (mustBind "/usr/bin") + (mustBind "/nix/store") + (bind "/sys/block") + (bind "/sys/bus") + (bind "/sys/class") + (bind "/sys/dev") + (bind "/sys/devices") + ] + ++ optionals app.nix [ + (mustBind "/nix/var") + (bind "/var/db/nix-channels") + ] + ++ optionals isGraphical [ + (devBind "/dev/dri") + (devBind "/dev/nvidiactl") + (devBind "/dev/nvidia-modeset") + (devBind "/dev/nvidia-uvm") + (devBind "/dev/nvidia-uvm-tools") + (devBind "/dev/nvidia0") + ] + ++ app.extraPaths; + auto_etc = true; + cover = [ "/var/run/nscd" ]; + + symlink = + [ [ - (mustBind "/bin") - (mustBind "/usr/bin") - (mustBind "/nix/store") - (bind "/sys/block") - (bind "/sys/bus") - (bind "/sys/class") - (bind "/sys/dev") - (bind "/sys/devices") + "*/run/current-system" + "/run/current-system" ] - ++ optionals app.nix [ - (mustBind "/nix/var") - (bind "/var/db/nix-channels") - ] - ++ optionals isGraphical [ - (devBind "/dev/dri") - (devBind "/dev/nvidiactl") - (devBind "/dev/nvidia-modeset") - (devBind "/dev/nvidia-uvm") - (devBind "/dev/nvidia-uvm-tools") - (devBind "/dev/nvidia0") - ] - ++ app.extraPaths; - auto_etc = true; - cover = [ "/var/run/nscd" ]; - - symlink = + ] + ++ optionals (isGraphical && config.hardware.graphics.enable) ( [ [ - "*/run/current-system" - "/run/current-system" + config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver"."L+".argument + "/run/opengl-driver" ] ] - ++ optionals (isGraphical && config.hardware.graphics.enable) ( + ++ optionals (app.multiarch && config.hardware.graphics.enable32Bit) [ [ - [ - config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver"."L+".argument - "/run/opengl-driver" - ] + config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver-32"."L+".argument + /run/opengl-driver-32 ] - ++ optionals (app.multiarch && config.hardware.graphics.enable32Bit) [ - [ - config.systemd.tmpfiles.settings.graphics-driver."/run/opengl-driver-32"."L+".argument - /run/opengl-driver-32 - ] - ] - ); - }; - - inherit enablements; - inherit (dbusConfig) session_bus system_bus; + ] + ); }; + }; in pkgs.writeShellScriptBin app.name '' diff --git a/print.go b/print.go index e77f60b..2f679eb 100644 --- a/print.go +++ b/print.go @@ -56,7 +56,7 @@ func printShowInstance( t := newPrinter(output) defer t.MustFlush() - if config.Confinement.Sandbox == nil { + if config.Container == nil { mustPrint(output, "Warning: this configuration uses permissive defaults!\n\n") } @@ -69,21 +69,21 @@ func printShowInstance( t.Printf("App\n") if config.ID != "" { - t.Printf(" ID:\t%d (%s)\n", config.Confinement.AppID, config.ID) + t.Printf(" ID:\t%d (%s)\n", config.Identity, config.ID) } else { - t.Printf(" ID:\t%d\n", config.Confinement.AppID) + t.Printf(" ID:\t%d\n", config.Identity) } - t.Printf(" Enablements:\t%s\n", config.Confinement.Enablements.String()) - if len(config.Confinement.Groups) > 0 { - t.Printf(" Groups:\t%q\n", config.Confinement.Groups) + t.Printf(" Enablements:\t%s\n", config.Enablements.String()) + if len(config.Groups) > 0 { + t.Printf(" Groups:\t%s\n", strings.Join(config.Groups, ", ")) } - if config.Confinement.Outer != "" { - t.Printf(" Directory:\t%s\n", config.Confinement.Outer) + if config.Data != "" { + t.Printf(" Data:\t%s\n", config.Data) } - if config.Confinement.Sandbox != nil { - sandbox := config.Confinement.Sandbox - if sandbox.Hostname != "" { - t.Printf(" Hostname:\t%q\n", sandbox.Hostname) + if config.Container != nil { + container := config.Container + if container.Hostname != "" { + t.Printf(" Hostname:\t%s\n", container.Hostname) } flags := make([]string, 0, 7) writeFlag := func(name string, value bool) { @@ -91,33 +91,29 @@ func printShowInstance( flags = append(flags, name) } } - writeFlag("userns", sandbox.Userns) - writeFlag("devel", sandbox.Devel) - writeFlag("net", sandbox.Net) - writeFlag("device", sandbox.Device) - writeFlag("tty", sandbox.Tty) - writeFlag("mapuid", sandbox.MapRealUID) - writeFlag("directwl", sandbox.DirectWayland) - writeFlag("autoetc", sandbox.AutoEtc) + writeFlag("userns", container.Userns) + writeFlag("devel", container.Devel) + writeFlag("net", container.Net) + writeFlag("device", container.Device) + writeFlag("tty", container.Tty) + writeFlag("mapuid", container.MapRealUID) + writeFlag("directwl", config.DirectWayland) + writeFlag("autoetc", container.AutoEtc) if len(flags) == 0 { flags = append(flags, "none") } t.Printf(" Flags:\t%s\n", strings.Join(flags, " ")) - etc := sandbox.Etc + etc := container.Etc if etc == "" { etc = "/etc" } t.Printf(" Etc:\t%s\n", etc) - if len(sandbox.Cover) > 0 { - t.Printf(" Cover:\t%s\n", strings.Join(sandbox.Cover, " ")) + if len(container.Cover) > 0 { + t.Printf(" Cover:\t%s\n", strings.Join(container.Cover, " ")) } - // Env map[string]string `json:"env"` - // Link [][2]string `json:"symlink"` - } - if config.Confinement.Sandbox != nil { t.Printf(" Path:\t%s\n", config.Path) } if len(config.Args) > 0 { @@ -126,9 +122,9 @@ func printShowInstance( t.Printf("\n") if !short { - if config.Confinement.Sandbox != nil && len(config.Confinement.Sandbox.Filesystem) > 0 { + if config.Container != nil && len(config.Container.Filesystem) > 0 { t.Printf("Filesystem\n") - for _, f := range config.Confinement.Sandbox.Filesystem { + for _, f := range config.Container.Filesystem { if f == nil { continue } @@ -156,9 +152,9 @@ func printShowInstance( } t.Printf("\n") } - if len(config.Confinement.ExtraPerms) > 0 { + if len(config.ExtraPerms) > 0 { t.Printf("Extra ACL\n") - for _, p := range config.Confinement.ExtraPerms { + for _, p := range config.ExtraPerms { if p == nil { continue } @@ -186,14 +182,14 @@ func printShowInstance( t.Printf(" Broadcast:\t%q\n", c.Broadcast) } } - if config.Confinement.SessionBus != nil { + if config.SessionBus != nil { t.Printf("Session bus\n") - printDBus(config.Confinement.SessionBus) + printDBus(config.SessionBus) t.Printf("\n") } - if config.Confinement.SystemBus != nil { + if config.SystemBus != nil { t.Printf("System bus\n") - printDBus(config.Confinement.SystemBus) + printDBus(config.SystemBus) t.Printf("\n") } } @@ -265,7 +261,7 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo as := "(No configuration information)" if e.Config != nil { - as = strconv.Itoa(e.Config.Confinement.AppID) + as = strconv.Itoa(e.Config.Identity) id := e.Config.ID if id == "" { id = "uk.gensokyo.fortify." + e.s[:8] diff --git a/print_test.go b/print_test.go index 1073a07..4e50dfd 100644 --- a/print_test.go +++ b/print_test.go @@ -39,9 +39,9 @@ func Test_printShowInstance(t *testing.T) { {"config", nil, fst.Template(), false, false, `App ID: 9 (org.chromium.Chromium) Enablements: wayland, dbus, pulseaudio - Groups: ["video"] - Directory: /var/lib/persist/home/org.chromium.Chromium - Hostname: "localhost" + Groups: video, dialout, plugdev + Data: /var/lib/fortify/u0/org.chromium.Chromium + Hostname: localhost Flags: userns devel net device tty mapuid autoetc Etc: /etc Cover: /var/run/nscd @@ -79,7 +79,7 @@ App Enablements: (no enablements) `}, - {"config flag none", nil, &fst.Config{Confinement: fst.ConfinementConfig{Sandbox: new(fst.SandboxConfig)}}, false, false, `App + {"config flag none", nil, &fst.Config{Container: new(fst.ContainerConfig)}, false, false, `App ID: 0 Enablements: (no enablements) Flags: none @@ -87,7 +87,7 @@ App Path: `}, - {"config nil entries", nil, &fst.Config{Confinement: fst.ConfinementConfig{Sandbox: &fst.SandboxConfig{Filesystem: make([]*fst.FilesystemConfig, 1)}, ExtraPerms: make([]*fst.ExtraPermConfig, 1)}}, false, false, `App + {"config nil entries", nil, &fst.Config{Container: &fst.ContainerConfig{Filesystem: make([]*fst.FilesystemConfig, 1)}, ExtraPerms: make([]*fst.ExtraPermConfig, 1)}, false, false, `App ID: 0 Enablements: (no enablements) Flags: none @@ -99,7 +99,7 @@ Filesystem Extra ACL `}, - {"config pd dbus see", nil, &fst.Config{Confinement: fst.ConfinementConfig{SessionBus: &dbus.Config{See: []string{"org.example.test"}}}}, false, false, `Warning: this configuration uses permissive defaults! + {"config pd dbus see", nil, &fst.Config{SessionBus: &dbus.Config{See: []string{"org.example.test"}}}, false, false, `Warning: this configuration uses permissive defaults! App ID: 0 @@ -118,9 +118,9 @@ Session bus App ID: 9 (org.chromium.Chromium) Enablements: wayland, dbus, pulseaudio - Groups: ["video"] - Directory: /var/lib/persist/home/org.chromium.Chromium - Hostname: "localhost" + Groups: video, dialout, plugdev + Data: /var/lib/fortify/u0/org.chromium.Chromium + Hostname: localhost Flags: userns devel net device tty mapuid autoetc Etc: /etc Cover: /var/run/nscd @@ -195,141 +195,67 @@ App "--enable-features=UseOzonePlatform", "--ozone-platform=wayland" ], - "confinement": { - "app_id": 9, - "groups": [ - "video" + "enablements": 13, + "session_bus": { + "see": null, + "talk": [ + "org.freedesktop.Notifications", + "org.freedesktop.FileManager1", + "org.freedesktop.ScreenSaver", + "org.freedesktop.secrets", + "org.kde.kwalletd5", + "org.kde.kwalletd6", + "org.gnome.SessionManager" ], - "username": "chronos", - "home_inner": "/var/lib/fortify", - "home": "/var/lib/persist/home/org.chromium.Chromium", - "shell": "/run/current-system/sw/bin/zsh", - "sandbox": { - "hostname": "localhost", - "seccomp": 32, - "devel": true, - "userns": true, - "net": true, - "tty": true, - "multiarch": true, - "env": { - "GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY", - "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", - "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT" - }, - "map_real_uid": true, - "device": true, - "filesystem": [ - { - "src": "/nix/store" - }, - { - "src": "/run/current-system" - }, - { - "src": "/run/opengl-driver" - }, - { - "src": "/var/db/nix-channels" - }, - { - "dst": "/data/data/org.chromium.Chromium", - "src": "/var/lib/fortify/u0/org.chromium.Chromium", - "write": true, - "require": true - }, - { - "src": "/dev/dri", - "dev": true - } - ], - "symlink": [ - [ - "/run/user/65534", - "/run/user/150" - ] - ], - "etc": "/etc", - "auto_etc": true, - "cover": [ - "/var/run/nscd" - ] - }, - "extra_perms": [ - { - "ensure": true, - "path": "/var/lib/fortify/u0", - "x": true - }, - { - "path": "/var/lib/fortify/u0/org.chromium.Chromium", - "r": true, - "w": true, - "x": true - } + "own": [ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*" ], - "system_bus": { - "see": null, - "talk": [ - "org.bluez", - "org.freedesktop.Avahi", - "org.freedesktop.UPower" - ], - "own": null, - "call": null, - "broadcast": null, - "filter": true + "call": { + "org.freedesktop.portal.*": "*" }, - "session_bus": { - "see": null, - "talk": [ - "org.freedesktop.Notifications", - "org.freedesktop.FileManager1", - "org.freedesktop.ScreenSaver", - "org.freedesktop.secrets", - "org.kde.kwalletd5", - "org.kde.kwalletd6", - "org.gnome.SessionManager" - ], - "own": [ - "org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.chromium.*" - ], - "call": { - "org.freedesktop.portal.*": "*" - }, - "broadcast": { - "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" - }, - "filter": true + "broadcast": { + "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" }, - "enablements": 13 - } - }, - "time": "1970-01-01T00:00:00.000000009Z" -} -`}, - {"json config", nil, fst.Template(), false, true, `{ - "id": "org.chromium.Chromium", - "path": "/run/current-system/sw/bin/chromium", - "args": [ - "chromium", - "--ignore-gpu-blocklist", - "--disable-smooth-scrolling", - "--enable-features=UseOzonePlatform", - "--ozone-platform=wayland" - ], - "confinement": { - "app_id": 9, - "groups": [ - "video" - ], + "filter": true + }, + "system_bus": { + "see": null, + "talk": [ + "org.bluez", + "org.freedesktop.Avahi", + "org.freedesktop.UPower" + ], + "own": null, + "call": null, + "broadcast": null, + "filter": true + }, "username": "chronos", - "home_inner": "/var/lib/fortify", - "home": "/var/lib/persist/home/org.chromium.Chromium", "shell": "/run/current-system/sw/bin/zsh", - "sandbox": { + "data": "/var/lib/fortify/u0/org.chromium.Chromium", + "dir": "/data/data/org.chromium.Chromium", + "extra_perms": [ + { + "ensure": true, + "path": "/var/lib/fortify/u0", + "x": true + }, + { + "path": "/var/lib/fortify/u0/org.chromium.Chromium", + "r": true, + "w": true, + "x": true + } + ], + "identity": 9, + "groups": [ + "video", + "dialout", + "plugdev" + ], + "container": { "hostname": "localhost", "seccomp": 32, "devel": true, @@ -379,57 +305,131 @@ App "cover": [ "/var/run/nscd" ] + } + }, + "time": "1970-01-01T00:00:00.000000009Z" +} +`}, + {"json config", nil, fst.Template(), false, true, `{ + "id": "org.chromium.Chromium", + "path": "/run/current-system/sw/bin/chromium", + "args": [ + "chromium", + "--ignore-gpu-blocklist", + "--disable-smooth-scrolling", + "--enable-features=UseOzonePlatform", + "--ozone-platform=wayland" + ], + "enablements": 13, + "session_bus": { + "see": null, + "talk": [ + "org.freedesktop.Notifications", + "org.freedesktop.FileManager1", + "org.freedesktop.ScreenSaver", + "org.freedesktop.secrets", + "org.kde.kwalletd5", + "org.kde.kwalletd6", + "org.gnome.SessionManager" + ], + "own": [ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*" + ], + "call": { + "org.freedesktop.portal.*": "*" }, - "extra_perms": [ + "broadcast": { + "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" + }, + "filter": true + }, + "system_bus": { + "see": null, + "talk": [ + "org.bluez", + "org.freedesktop.Avahi", + "org.freedesktop.UPower" + ], + "own": null, + "call": null, + "broadcast": null, + "filter": true + }, + "username": "chronos", + "shell": "/run/current-system/sw/bin/zsh", + "data": "/var/lib/fortify/u0/org.chromium.Chromium", + "dir": "/data/data/org.chromium.Chromium", + "extra_perms": [ + { + "ensure": true, + "path": "/var/lib/fortify/u0", + "x": true + }, + { + "path": "/var/lib/fortify/u0/org.chromium.Chromium", + "r": true, + "w": true, + "x": true + } + ], + "identity": 9, + "groups": [ + "video", + "dialout", + "plugdev" + ], + "container": { + "hostname": "localhost", + "seccomp": 32, + "devel": true, + "userns": true, + "net": true, + "tty": true, + "multiarch": true, + "env": { + "GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY", + "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", + "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT" + }, + "map_real_uid": true, + "device": true, + "filesystem": [ { - "ensure": true, - "path": "/var/lib/fortify/u0", - "x": true + "src": "/nix/store" }, { - "path": "/var/lib/fortify/u0/org.chromium.Chromium", - "r": true, - "w": true, - "x": true + "src": "/run/current-system" + }, + { + "src": "/run/opengl-driver" + }, + { + "src": "/var/db/nix-channels" + }, + { + "dst": "/data/data/org.chromium.Chromium", + "src": "/var/lib/fortify/u0/org.chromium.Chromium", + "write": true, + "require": true + }, + { + "src": "/dev/dri", + "dev": true } ], - "system_bus": { - "see": null, - "talk": [ - "org.bluez", - "org.freedesktop.Avahi", - "org.freedesktop.UPower" - ], - "own": null, - "call": null, - "broadcast": null, - "filter": true - }, - "session_bus": { - "see": null, - "talk": [ - "org.freedesktop.Notifications", - "org.freedesktop.FileManager1", - "org.freedesktop.ScreenSaver", - "org.freedesktop.secrets", - "org.kde.kwalletd5", - "org.kde.kwalletd6", - "org.gnome.SessionManager" - ], - "own": [ - "org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.chromium.*" - ], - "call": { - "org.freedesktop.portal.*": "*" - }, - "broadcast": { - "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" - }, - "filter": true - }, - "enablements": 13 + "symlink": [ + [ + "/run/user/65534", + "/run/user/150" + ] + ], + "etc": "/etc", + "auto_etc": true, + "cover": [ + "/var/run/nscd" + ] } } `}, @@ -499,116 +499,116 @@ func Test_printPs(t *testing.T) { "--enable-features=UseOzonePlatform", "--ozone-platform=wayland" ], - "confinement": { - "app_id": 9, - "groups": [ - "video" + "enablements": 13, + "session_bus": { + "see": null, + "talk": [ + "org.freedesktop.Notifications", + "org.freedesktop.FileManager1", + "org.freedesktop.ScreenSaver", + "org.freedesktop.secrets", + "org.kde.kwalletd5", + "org.kde.kwalletd6", + "org.gnome.SessionManager" ], - "username": "chronos", - "home_inner": "/var/lib/fortify", - "home": "/var/lib/persist/home/org.chromium.Chromium", - "shell": "/run/current-system/sw/bin/zsh", - "sandbox": { - "hostname": "localhost", - "seccomp": 32, - "devel": true, - "userns": true, - "net": true, - "tty": true, - "multiarch": true, - "env": { - "GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY", - "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", - "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT" - }, - "map_real_uid": true, - "device": true, - "filesystem": [ - { - "src": "/nix/store" - }, - { - "src": "/run/current-system" - }, - { - "src": "/run/opengl-driver" - }, - { - "src": "/var/db/nix-channels" - }, - { - "dst": "/data/data/org.chromium.Chromium", - "src": "/var/lib/fortify/u0/org.chromium.Chromium", - "write": true, - "require": true - }, - { - "src": "/dev/dri", - "dev": true - } - ], - "symlink": [ - [ - "/run/user/65534", - "/run/user/150" - ] - ], - "etc": "/etc", - "auto_etc": true, - "cover": [ - "/var/run/nscd" - ] + "own": [ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*" + ], + "call": { + "org.freedesktop.portal.*": "*" }, - "extra_perms": [ + "broadcast": { + "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" + }, + "filter": true + }, + "system_bus": { + "see": null, + "talk": [ + "org.bluez", + "org.freedesktop.Avahi", + "org.freedesktop.UPower" + ], + "own": null, + "call": null, + "broadcast": null, + "filter": true + }, + "username": "chronos", + "shell": "/run/current-system/sw/bin/zsh", + "data": "/var/lib/fortify/u0/org.chromium.Chromium", + "dir": "/data/data/org.chromium.Chromium", + "extra_perms": [ + { + "ensure": true, + "path": "/var/lib/fortify/u0", + "x": true + }, + { + "path": "/var/lib/fortify/u0/org.chromium.Chromium", + "r": true, + "w": true, + "x": true + } + ], + "identity": 9, + "groups": [ + "video", + "dialout", + "plugdev" + ], + "container": { + "hostname": "localhost", + "seccomp": 32, + "devel": true, + "userns": true, + "net": true, + "tty": true, + "multiarch": true, + "env": { + "GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY", + "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", + "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT" + }, + "map_real_uid": true, + "device": true, + "filesystem": [ { - "ensure": true, - "path": "/var/lib/fortify/u0", - "x": true + "src": "/nix/store" }, { - "path": "/var/lib/fortify/u0/org.chromium.Chromium", - "r": true, - "w": true, - "x": true + "src": "/run/current-system" + }, + { + "src": "/run/opengl-driver" + }, + { + "src": "/var/db/nix-channels" + }, + { + "dst": "/data/data/org.chromium.Chromium", + "src": "/var/lib/fortify/u0/org.chromium.Chromium", + "write": true, + "require": true + }, + { + "src": "/dev/dri", + "dev": true } ], - "system_bus": { - "see": null, - "talk": [ - "org.bluez", - "org.freedesktop.Avahi", - "org.freedesktop.UPower" - ], - "own": null, - "call": null, - "broadcast": null, - "filter": true - }, - "session_bus": { - "see": null, - "talk": [ - "org.freedesktop.Notifications", - "org.freedesktop.FileManager1", - "org.freedesktop.ScreenSaver", - "org.freedesktop.secrets", - "org.kde.kwalletd5", - "org.kde.kwalletd6", - "org.gnome.SessionManager" - ], - "own": [ - "org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.chromium.*" - ], - "call": { - "org.freedesktop.portal.*": "*" - }, - "broadcast": { - "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" - }, - "filter": true - }, - "enablements": 13 + "symlink": [ + [ + "/run/user/65534", + "/run/user/150" + ] + ], + "etc": "/etc", + "auto_etc": true, + "cover": [ + "/var/run/nscd" + ] } }, "time": "1970-01-01T00:00:00.000000009Z" diff --git a/test/test.py b/test/test.py index b7e85c1..d72dafb 100644 --- a/test/test.py +++ b/test/test.py @@ -69,8 +69,8 @@ def check_state(name, enablements): if len(config['args']) != 1 or config['args'][0] != command: raise Exception(f"unexpected args {config['args']}") - if config['confinement']['enablements'] != enablements: - raise Exception(f"unexpected enablements {instance['config']['confinement']['enablements']}") + if config['enablements'] != enablements: + raise Exception(f"unexpected enablements {instance['config']['enablements']}") def fortify(command):