diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-04-13 03:23:28 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-04-13 03:30:19 +0900 |
| commit | 31b7ddd122d54c36edb101d2c8bdf230651f27d4 (patch) | |
| tree | 2dd0623bfa0d410d83aabfc51d276df3a14ef3e8 /fst | |
| parent | c460892cbdfa66a2cf1f0ebcec59cf550e67962e (diff) | |
fst: improve config
The config struct more or less "grew" to what it is today. This change moves things around to make more sense and fixes nonsensical comments describing obsolete behaviour.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'fst')
| -rw-r--r-- | fst/config.go | 49 | ||||
| -rw-r--r-- | fst/container.go (renamed from fst/sandbox.go) | 14 | ||||
| -rw-r--r-- | fst/template.go | 130 | ||||
| -rw-r--r-- | fst/template_test.go | 206 |
4 files changed, 200 insertions, 199 deletions
diff --git a/fst/config.go b/fst/config.go index a56927f0..62c85701 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 index c4936a2e..1190caa3 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 0777c9d2..0ca928a1 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"}, - }, - 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}, - }, - 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, + + 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", }, - 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, + 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}, }, - 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 0ec2dae2..c7fd7804 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.*": "*" + }, + "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 }, - "extra_perms": [ + { + "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 - } - ], - "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.*": "*" + "src": "/run/current-system" }, - "broadcast": { - "org.freedesktop.portal.*": "@/org/freedesktop/portal/*" + { + "src": "/run/opengl-driver" }, - "filter": true - }, - "enablements": 13 + { + "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" + ] } }` |
