diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/app/instance/common/container.go | 4 | ||||
| -rw-r--r-- | internal/app/internal/setuid/app_nixos_test.go | 64 | ||||
| -rw-r--r-- | internal/app/internal/setuid/app_pd_test.go | 80 | ||||
| -rw-r--r-- | internal/app/internal/setuid/process.go | 2 | ||||
| -rw-r--r-- | internal/app/internal/setuid/seal.go | 72 |
5 files changed, 108 insertions, 114 deletions
diff --git a/internal/app/instance/common/container.go b/internal/app/instance/common/container.go index cc26c803..370997aa 100644 --- a/internal/app/instance/common/container.go +++ b/internal/app/instance/common/container.go @@ -16,9 +16,9 @@ import ( "git.gensokyo.uk/security/fortify/sandbox/seccomp" ) -// NewContainer initialises [sandbox.Params] via [fst.SandboxConfig]. +// NewContainer initialises [sandbox.Params] via [fst.ContainerConfig]. // Note that remaining container setup must be queued by the caller. -func NewContainer(s *fst.SandboxConfig, os sys.State, uid, gid *int) (*sandbox.Params, map[string]string, error) { +func NewContainer(s *fst.ContainerConfig, os sys.State, uid, gid *int) (*sandbox.Params, map[string]string, error) { if s == nil { return nil, nil, syscall.EBADE } diff --git a/internal/app/internal/setuid/app_nixos_test.go b/internal/app/internal/setuid/app_nixos_test.go index 0daaf690..0e649ad4 100644 --- a/internal/app/internal/setuid/app_nixos_test.go +++ b/internal/app/internal/setuid/app_nixos_test.go @@ -13,41 +13,43 @@ var testCasesNixos = []sealTestCase{ { "nixos chromium direct wayland", new(stubNixOS), &fst.Config{ - ID: "org.chromium.Chromium", - Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start", - Confinement: fst.ConfinementConfig{ - AppID: 1, Groups: []string{}, Username: "u0_a1", - Outer: "/var/lib/persist/module/fortify/0/1", - Sandbox: &fst.SandboxConfig{ - Userns: true, Net: true, MapRealUID: true, DirectWayland: true, Env: nil, AutoEtc: true, - Filesystem: []*fst.FilesystemConfig{ - {Src: "/bin", Must: true}, {Src: "/usr/bin", Must: true}, - {Src: "/nix/store", Must: true}, {Src: "/run/current-system", Must: true}, - {Src: "/sys/block"}, {Src: "/sys/bus"}, {Src: "/sys/class"}, {Src: "/sys/dev"}, {Src: "/sys/devices"}, - {Src: "/run/opengl-driver", Must: true}, {Src: "/dev/dri", Device: true}, - }, - Cover: []string{"/var/run/nscd"}, + ID: "org.chromium.Chromium", + Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start", + Enablements: system.EWayland | system.EDBus | system.EPulse, + + Container: &fst.ContainerConfig{ + Userns: true, Net: true, MapRealUID: true, Env: nil, AutoEtc: true, + Filesystem: []*fst.FilesystemConfig{ + {Src: "/bin", Must: true}, {Src: "/usr/bin", Must: true}, + {Src: "/nix/store", Must: true}, {Src: "/run/current-system", Must: true}, + {Src: "/sys/block"}, {Src: "/sys/bus"}, {Src: "/sys/class"}, {Src: "/sys/dev"}, {Src: "/sys/devices"}, + {Src: "/run/opengl-driver", Must: true}, {Src: "/dev/dri", Device: true}, }, - SystemBus: &dbus.Config{ - Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"}, - Filter: true, + Cover: []string{"/var/run/nscd"}, + }, + SystemBus: &dbus.Config{ + Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"}, + Filter: true, + }, + SessionBus: &dbus.Config{ + Talk: []string{ + "org.freedesktop.FileManager1", "org.freedesktop.Notifications", + "org.freedesktop.ScreenSaver", "org.freedesktop.secrets", + "org.kde.kwalletd5", "org.kde.kwalletd6", }, - 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, + Own: []string{ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*", }, - Enablements: system.EWayland | system.EDBus | system.EPulse, + Call: map[string]string{}, Broadcast: map[string]string{}, + Filter: true, }, + DirectWayland: true, + + Username: "u0_a1", + Data: "/var/lib/persist/module/fortify/0/1", + Identity: 1, Groups: []string{}, }, app.ID{ 0x8e, 0x2c, 0x76, 0xb0, diff --git a/internal/app/internal/setuid/app_pd_test.go b/internal/app/internal/setuid/app_pd_test.go index 2dc06253..b331684b 100644 --- a/internal/app/internal/setuid/app_pd_test.go +++ b/internal/app/internal/setuid/app_pd_test.go @@ -14,13 +14,7 @@ import ( var testCasesPd = []sealTestCase{ { "nixos permissive defaults no enablements", new(stubNixOS), - &fst.Config{ - Confinement: fst.ConfinementConfig{ - AppID: 0, - Username: "chronos", - Outer: "/home/chronos", - }, - }, + &fst.Config{Username: "chronos", Data: "/home/chronos"}, app.ID{ 0x4a, 0x45, 0x0b, 0x65, 0x96, 0xd7, 0xbc, 0x15, @@ -77,46 +71,44 @@ var testCasesPd = []sealTestCase{ { "nixos permissive defaults chromium", new(stubNixOS), &fst.Config{ - ID: "org.chromium.Chromium", - Args: []string{"zsh", "-c", "exec chromium "}, - Confinement: fst.ConfinementConfig{ - AppID: 9, - Groups: []string{"video"}, - Username: "chronos", - Outer: "/home/chronos", - SessionBus: &dbus.Config{ - Talk: []string{ - "org.freedesktop.Notifications", - "org.freedesktop.FileManager1", - "org.freedesktop.ScreenSaver", - "org.freedesktop.secrets", - "org.kde.kwalletd5", - "org.kde.kwalletd6", - "org.gnome.SessionManager", - }, - Own: []string{ - "org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.org.chromium.Chromium.*", - "org.mpris.MediaPlayer2.chromium.*", - }, - Call: map[string]string{ - "org.freedesktop.portal.*": "*", - }, - Broadcast: map[string]string{ - "org.freedesktop.portal.*": "@/org/freedesktop/portal/*", - }, - Filter: true, + ID: "org.chromium.Chromium", + Args: []string{"zsh", "-c", "exec chromium "}, + Identity: 9, + Groups: []string{"video"}, + Username: "chronos", + Data: "/home/chronos", + SessionBus: &dbus.Config{ + Talk: []string{ + "org.freedesktop.Notifications", + "org.freedesktop.FileManager1", + "org.freedesktop.ScreenSaver", + "org.freedesktop.secrets", + "org.kde.kwalletd5", + "org.kde.kwalletd6", + "org.gnome.SessionManager", }, - SystemBus: &dbus.Config{ - Talk: []string{ - "org.bluez", - "org.freedesktop.Avahi", - "org.freedesktop.UPower", - }, - Filter: true, + Own: []string{ + "org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.org.chromium.Chromium.*", + "org.mpris.MediaPlayer2.chromium.*", }, - Enablements: system.EWayland | system.EDBus | system.EPulse, + Call: map[string]string{ + "org.freedesktop.portal.*": "*", + }, + Broadcast: map[string]string{ + "org.freedesktop.portal.*": "@/org/freedesktop/portal/*", + }, + Filter: true, + }, + SystemBus: &dbus.Config{ + Talk: []string{ + "org.bluez", + "org.freedesktop.Avahi", + "org.freedesktop.UPower", + }, + Filter: true, }, + Enablements: system.EWayland | system.EDBus | system.EPulse, }, app.ID{ 0xeb, 0xf0, 0x83, 0xd1, diff --git a/internal/app/internal/setuid/process.go b/internal/app/internal/setuid/process.go index 271e64e7..d3114c7a 100644 --- a/internal/app/internal/setuid/process.go +++ b/internal/app/internal/setuid/process.go @@ -65,7 +65,7 @@ func (seal *outcome) Run(rs *RunState) error { // accumulate enablements of remaining launchers for i, s := range states { if s.Config != nil { - rt |= s.Config.Confinement.Enablements + rt |= s.Config.Enablements } else { log.Printf("state entry %d does not contain config", i) } diff --git a/internal/app/internal/setuid/seal.go b/internal/app/internal/setuid/seal.go index 44a73b1a..edf7c87b 100644 --- a/internal/app/internal/setuid/seal.go +++ b/internal/app/internal/setuid/seal.go @@ -169,16 +169,16 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } // allowed aid range 0 to 9999, this is checked again in fsu - if config.Confinement.AppID < 0 || config.Confinement.AppID > 9999 { + if config.Identity < 0 || config.Identity > 9999 { return fmsg.WrapError(ErrUser, - fmt.Sprintf("aid %d out of range", config.Confinement.AppID)) + fmt.Sprintf("identity %d out of range", config.Identity)) } seal.user = fsuUser{ - aid: newInt(config.Confinement.AppID), - data: config.Confinement.Outer, - home: config.Confinement.Inner, - username: config.Confinement.Username, + aid: newInt(config.Identity), + data: config.Data, + home: config.Dir, + username: config.Username, } if seal.user.username == "" { seal.user.username = "chronos" @@ -199,8 +199,8 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } else { seal.user.uid = newInt(u) } - seal.user.supp = make([]string, len(config.Confinement.Groups)) - for i, name := range config.Confinement.Groups { + seal.user.supp = make([]string, len(config.Groups)) + for i, name := range config.Groups { if g, err := sys.LookupGroup(name); err != nil { return fmsg.WrapError(err, fmt.Sprintf("unknown group %q", name)) @@ -210,17 +210,17 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } // this also falls back to host path if encountering an invalid path - if !path.IsAbs(config.Confinement.Shell) { - config.Confinement.Shell = "/bin/sh" + if !path.IsAbs(config.Shell) { + config.Shell = "/bin/sh" if s, ok := sys.LookupEnv(shell); ok && path.IsAbs(s) { - config.Confinement.Shell = s + config.Shell = s } } // do not use the value of shell before this point // permissive defaults - if config.Confinement.Sandbox == nil { - fmsg.Verbose("sandbox configuration not supplied, PROCEED WITH CAUTION") + if config.Container == nil { + fmsg.Verbose("container configuration not supplied, PROCEED WITH CAUTION") // fsu clears the environment so resolve paths early if !path.IsAbs(config.Path) { @@ -231,11 +231,11 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co config.Path = p } } else { - config.Path = config.Confinement.Shell + config.Path = config.Shell } } - conf := &fst.SandboxConfig{ + conf := &fst.ContainerConfig{ Userns: true, Net: true, Tty: true, @@ -268,20 +268,20 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co conf.Cover = append(conf.Cover, nscd) } // bind GPU stuff - if config.Confinement.Enablements&(system.EX11|system.EWayland) != 0 { + if config.Enablements&(system.EX11|system.EWayland) != 0 { conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/dri", Device: true}) } // opportunistically bind kvm conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/kvm", Device: true}) - config.Confinement.Sandbox = conf + config.Container = conf } var mapuid, mapgid *stringPair[int] { var uid, gid int var err error - seal.container, seal.env, err = common.NewContainer(config.Confinement.Sandbox, sys, &uid, &gid) + seal.container, seal.env, err = common.NewContainer(config.Container, sys, &uid, &gid) if err != nil { return fmsg.WrapErrorSuffix(err, "cannot initialise container configuration:") @@ -303,12 +303,12 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if !config.Confinement.Sandbox.AutoEtc { - if config.Confinement.Sandbox.Etc != "" { - seal.container.Bind(config.Confinement.Sandbox.Etc, "/etc", 0) + if !config.Container.AutoEtc { + if config.Container.Etc != "" { + seal.container.Bind(config.Container.Etc, "/etc", 0) } } else { - etcPath := config.Confinement.Sandbox.Etc + etcPath := config.Container.Etc if etcPath == "" { etcPath = "/etc" } @@ -352,10 +352,10 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co seal.container.Dir = homeDir seal.env["HOME"] = homeDir seal.env["USER"] = username - seal.env[shell] = config.Confinement.Shell + seal.env[shell] = config.Shell seal.container.Place("/etc/passwd", - []byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Confinement.Shell+"\n")) + []byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Shell+"\n")) seal.container.Place("/etc/group", []byte("fortify:x:"+mapgid.String()+":\n")) } @@ -365,7 +365,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co seal.env[term] = t } - if config.Confinement.Enablements&system.EWayland != 0 { + if config.Enablements&system.EWayland != 0 { // outer wayland socket (usually `/run/user/%d/wayland-%d`) var socketPath string if name, ok := sys.LookupEnv(wl.WaylandDisplay); !ok { @@ -380,7 +380,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co innerPath := path.Join(innerRuntimeDir, wl.FallbackName) seal.env[wl.WaylandDisplay] = wl.FallbackName - if !config.Confinement.Sandbox.DirectWayland { // set up security-context-v1 + if !config.DirectWayland { // set up security-context-v1 appID := config.ID if appID == "" { // use instance ID in case app id is not set @@ -398,7 +398,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if config.Confinement.Enablements&system.EX11 != 0 { + if config.Enablements&system.EX11 != 0 { if d, ok := sys.LookupEnv(display); !ok { return fmsg.WrapError(ErrXDisplay, "DISPLAY is not set") @@ -409,7 +409,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if config.Confinement.Enablements&system.EPulse != 0 { + if config.Enablements&system.EPulse != 0 { // PulseAudio runtime directory (usually `/run/user/%d/pulse`) pulseRuntimeDir := path.Join(share.sc.RuntimePath, "pulse") // PulseAudio socket (usually `/run/user/%d/pulse/native`) @@ -458,10 +458,10 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - if config.Confinement.Enablements&system.EDBus != 0 { + if config.Enablements&system.EDBus != 0 { // ensure dbus session bus defaults - if config.Confinement.SessionBus == nil { - config.Confinement.SessionBus = dbus.NewConfig(config.ID, true, true) + if config.SessionBus == nil { + config.SessionBus = dbus.NewConfig(config.ID, true, true) } // downstream socket paths @@ -470,7 +470,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co // configure dbus proxy if f, err := seal.sys.ProxyDBus( - config.Confinement.SessionBus, config.Confinement.SystemBus, + config.SessionBus, config.SystemBus, sessionPath, systemPath, ); err != nil { return err @@ -483,7 +483,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co seal.env[dbusSessionBusAddress] = "unix:path=" + sessionInner seal.container.Bind(sessionPath, sessionInner, 0) seal.sys.UpdatePerm(sessionPath, acl.Read, acl.Write) - if config.Confinement.SystemBus != nil { + if config.SystemBus != nil { systemInner := "/run/dbus/system_bus_socket" seal.env[dbusSystemBusAddress] = "unix:path=" + systemInner seal.container.Bind(systemPath, systemInner, 0) @@ -491,12 +491,12 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co } } - for _, dest := range config.Confinement.Sandbox.Cover { + for _, dest := range config.Container.Cover { seal.container.Tmpfs(dest, 1<<13, 0755) } // append ExtraPerms last - for _, p := range config.Confinement.ExtraPerms { + for _, p := range config.ExtraPerms { if p == nil { continue } @@ -530,7 +530,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co slices.Sort(seal.container.Env) fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, argv: %s", - seal.user.uid, seal.user.username, config.Confinement.Groups, seal.container.Args) + seal.user.uid, seal.user.username, config.Groups, seal.container.Args) return nil } |
