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