app: run in native sandbox
Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
e732dca762
commit
4e8f72022d
@ -4,12 +4,15 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
|
"git.gensokyo.uk/security/fortify/sandbox/seccomp"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bundleInfo struct {
|
type appInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
|
||||||
@ -20,13 +23,15 @@ type bundleInfo struct {
|
|||||||
// 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]
|
||||||
UserNS bool `json:"userns,omitempty"`
|
Devel bool `json:"devel,omitempty"`
|
||||||
|
// passed through to [fst.Config]
|
||||||
|
Userns bool `json:"userns,omitempty"`
|
||||||
// passed through to [fst.Config]
|
// passed through to [fst.Config]
|
||||||
Net bool `json:"net,omitempty"`
|
Net bool `json:"net,omitempty"`
|
||||||
// passed through to [fst.Config]
|
// passed through to [fst.Config]
|
||||||
Dev bool `json:"dev,omitempty"`
|
Dev bool `json:"dev,omitempty"`
|
||||||
// passed through to [fst.Config]
|
// passed through to [fst.Config]
|
||||||
NoNewSession bool `json:"no_new_session,omitempty"`
|
Tty bool `json:"tty,omitempty"`
|
||||||
// passed through to [fst.Config]
|
// passed through to [fst.Config]
|
||||||
MapRealUID bool `json:"map_real_uid,omitempty"`
|
MapRealUID bool `json:"map_real_uid,omitempty"`
|
||||||
// passed through to [fst.Config]
|
// passed through to [fst.Config]
|
||||||
@ -38,11 +43,9 @@ type bundleInfo struct {
|
|||||||
// passed through to [fst.Config]
|
// passed through to [fst.Config]
|
||||||
Enablements system.Enablements `json:"enablements"`
|
Enablements system.Enablements `json:"enablements"`
|
||||||
|
|
||||||
// passed through inverted to [bwrap.SyscallPolicy]
|
// passed through to [fst.Config]
|
||||||
Devel bool `json:"devel,omitempty"`
|
|
||||||
// passed through to [bwrap.SyscallPolicy]
|
|
||||||
Multiarch bool `json:"multiarch,omitempty"`
|
Multiarch bool `json:"multiarch,omitempty"`
|
||||||
// passed through to [bwrap.SyscallPolicy]
|
// passed through to [fst.Config]
|
||||||
Bluetooth bool `json:"bluetooth,omitempty"`
|
Bluetooth bool `json:"bluetooth,omitempty"`
|
||||||
|
|
||||||
// allow gpu access within sandbox
|
// allow gpu access within sandbox
|
||||||
@ -59,8 +62,63 @@ type bundleInfo struct {
|
|||||||
ActivationPackage string `json:"activation_package"`
|
ActivationPackage string `json:"activation_package"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadBundleInfo(name string, beforeFail func()) *bundleInfo {
|
func (app *appInfo) toFst(pathSet *appPathSet, argv []string, flagDropShell bool) *fst.Config {
|
||||||
bundle := new(bundleInfo)
|
config := &fst.Config{
|
||||||
|
ID: app.ID,
|
||||||
|
Args: argv,
|
||||||
|
Confinement: fst.ConfinementConfig{
|
||||||
|
AppID: app.AppID,
|
||||||
|
Groups: app.Groups,
|
||||||
|
Username: "fortify",
|
||||||
|
Inner: path.Join("/data/data", app.ID),
|
||||||
|
Outer: pathSet.homeDir,
|
||||||
|
Sandbox: &fst.SandboxConfig{
|
||||||
|
Hostname: formatHostname(app.Name),
|
||||||
|
Devel: app.Devel,
|
||||||
|
Userns: app.Userns,
|
||||||
|
Net: app.Net,
|
||||||
|
Dev: app.Dev,
|
||||||
|
Tty: app.Tty || flagDropShell,
|
||||||
|
MapRealUID: app.MapRealUID,
|
||||||
|
DirectWayland: app.DirectWayland,
|
||||||
|
Filesystem: []*fst.FilesystemConfig{
|
||||||
|
{Src: path.Join(pathSet.nixPath, "store"), Dst: "/nix/store", Must: true},
|
||||||
|
{Src: pathSet.metaPath, Dst: path.Join(fst.Tmp, "app"), Must: true},
|
||||||
|
{Src: "/etc/resolv.conf"},
|
||||||
|
{Src: "/sys/block"},
|
||||||
|
{Src: "/sys/bus"},
|
||||||
|
{Src: "/sys/class"},
|
||||||
|
{Src: "/sys/dev"},
|
||||||
|
{Src: "/sys/devices"},
|
||||||
|
},
|
||||||
|
Link: [][2]string{
|
||||||
|
{app.CurrentSystem, "/run/current-system"},
|
||||||
|
{"/run/current-system/sw/bin", "/bin"},
|
||||||
|
{"/run/current-system/sw/bin", "/usr/bin"},
|
||||||
|
},
|
||||||
|
Etc: path.Join(pathSet.cacheDir, "etc"),
|
||||||
|
AutoEtc: true,
|
||||||
|
},
|
||||||
|
ExtraPerms: []*fst.ExtraPermConfig{
|
||||||
|
{Path: dataHome, Execute: true},
|
||||||
|
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
|
||||||
|
},
|
||||||
|
SystemBus: app.SystemBus,
|
||||||
|
SessionBus: app.SessionBus,
|
||||||
|
Enablements: app.Enablements,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if app.Multiarch {
|
||||||
|
config.Confinement.Sandbox.Seccomp |= seccomp.FlagMultiarch
|
||||||
|
}
|
||||||
|
if app.Bluetooth {
|
||||||
|
config.Confinement.Sandbox.Seccomp |= seccomp.FlagBluetooth
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadAppInfo(name string, beforeFail func()) *appInfo {
|
||||||
|
bundle := new(appInfo)
|
||||||
if f, err := os.Open(name); err != nil {
|
if f, err := os.Open(name); err != nil {
|
||||||
beforeFail()
|
beforeFail()
|
||||||
log.Fatalf("cannot open bundle: %v", err)
|
log.Fatalf("cannot open bundle: %v", err)
|
@ -12,9 +12,7 @@ import (
|
|||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/command"
|
"git.gensokyo.uk/security/fortify/command"
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/app/init0"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal/app/shim"
|
"git.gensokyo.uk/security/fortify/internal/app/shim"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||||
@ -39,7 +37,6 @@ func init() {
|
|||||||
func main() {
|
func main() {
|
||||||
// early init path, skips root check and duplicate PR_SET_DUMPABLE
|
// early init path, skips root check and duplicate PR_SET_DUMPABLE
|
||||||
sandbox.TryArgv0(fmsg.Output{}, fmsg.Prepare, internal.InstallFmsg)
|
sandbox.TryArgv0(fmsg.Output{}, fmsg.Prepare, internal.InstallFmsg)
|
||||||
init0.TryArgv0()
|
|
||||||
|
|
||||||
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
||||||
log.Printf("cannot set SUID_DUMP_DISABLE: %s", err)
|
log.Printf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||||
@ -65,9 +62,7 @@ func main() {
|
|||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console").
|
Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console").
|
||||||
Flag(&flagDropShell, "s", command.BoolFlag(false), "Drop to a shell in place of next fortify action")
|
Flag(&flagDropShell, "s", command.BoolFlag(false), "Drop to a shell in place of next fortify action")
|
||||||
|
|
||||||
// internal commands
|
|
||||||
c.Command("shim", command.UsageInternal, func([]string) error { shim.Main(); return errSuccess })
|
c.Command("shim", command.UsageInternal, func([]string) error { shim.Main(); return errSuccess })
|
||||||
c.Command("init", command.UsageInternal, func([]string) error { init0.Main(); return errSuccess })
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var (
|
var (
|
||||||
@ -124,7 +119,7 @@ func main() {
|
|||||||
Parse bundle and app metadata, do pre-install checks.
|
Parse bundle and app metadata, do pre-install checks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bundle := loadBundleInfo(path.Join(workDir, "bundle.json"), cleanup)
|
bundle := loadAppInfo(path.Join(workDir, "bundle.json"), cleanup)
|
||||||
pathSet := pathSetByApp(bundle.ID)
|
pathSet := pathSetByApp(bundle.ID)
|
||||||
|
|
||||||
app := bundle
|
app := bundle
|
||||||
@ -140,7 +135,7 @@ func main() {
|
|||||||
log.Printf("metadata path %q is not a file", pathSet.metaPath)
|
log.Printf("metadata path %q is not a file", pathSet.metaPath)
|
||||||
return syscall.EBADMSG
|
return syscall.EBADMSG
|
||||||
} else {
|
} else {
|
||||||
app = loadBundleInfo(pathSet.metaPath, cleanup)
|
app = loadAppInfo(pathSet.metaPath, cleanup)
|
||||||
if app.ID != bundle.ID {
|
if app.ID != bundle.ID {
|
||||||
cleanup()
|
cleanup()
|
||||||
log.Printf("app %q claims to have identifier %q",
|
log.Printf("app %q claims to have identifier %q",
|
||||||
@ -273,7 +268,7 @@ func main() {
|
|||||||
|
|
||||||
id := args[0]
|
id := args[0]
|
||||||
pathSet := pathSetByApp(id)
|
pathSet := pathSetByApp(id)
|
||||||
app := loadBundleInfo(pathSet.metaPath, func() {})
|
app := loadAppInfo(pathSet.metaPath, func() {})
|
||||||
if app.ID != id {
|
if app.ID != id {
|
||||||
log.Printf("app %q claims to have identifier %q", id, app.ID)
|
log.Printf("app %q claims to have identifier %q", id, app.ID)
|
||||||
return syscall.EBADE
|
return syscall.EBADE
|
||||||
@ -322,51 +317,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
argv = append(argv, args[1:]...)
|
argv = append(argv, args[1:]...)
|
||||||
|
|
||||||
config := &fst.Config{
|
config := app.toFst(pathSet, argv, flagDropShell)
|
||||||
ID: app.ID,
|
|
||||||
Command: argv,
|
|
||||||
Confinement: fst.ConfinementConfig{
|
|
||||||
AppID: app.AppID,
|
|
||||||
Groups: app.Groups,
|
|
||||||
Username: "fortify",
|
|
||||||
Inner: path.Join("/data/data", app.ID),
|
|
||||||
Outer: pathSet.homeDir,
|
|
||||||
Sandbox: &fst.SandboxConfig{
|
|
||||||
Hostname: formatHostname(app.Name),
|
|
||||||
UserNS: app.UserNS,
|
|
||||||
Net: app.Net,
|
|
||||||
Dev: app.Dev,
|
|
||||||
Syscall: &bwrap.SyscallPolicy{DenyDevel: !app.Devel, Multiarch: app.Multiarch, Bluetooth: app.Bluetooth},
|
|
||||||
NoNewSession: app.NoNewSession || flagDropShell,
|
|
||||||
MapRealUID: app.MapRealUID,
|
|
||||||
DirectWayland: app.DirectWayland,
|
|
||||||
Filesystem: []*fst.FilesystemConfig{
|
|
||||||
{Src: path.Join(pathSet.nixPath, "store"), Dst: "/nix/store", Must: true},
|
|
||||||
{Src: pathSet.metaPath, Dst: path.Join(fst.Tmp, "app"), Must: true},
|
|
||||||
{Src: "/etc/resolv.conf"},
|
|
||||||
{Src: "/sys/block"},
|
|
||||||
{Src: "/sys/bus"},
|
|
||||||
{Src: "/sys/class"},
|
|
||||||
{Src: "/sys/dev"},
|
|
||||||
{Src: "/sys/devices"},
|
|
||||||
},
|
|
||||||
Link: [][2]string{
|
|
||||||
{app.CurrentSystem, "/run/current-system"},
|
|
||||||
{"/run/current-system/sw/bin", "/bin"},
|
|
||||||
{"/run/current-system/sw/bin", "/usr/bin"},
|
|
||||||
},
|
|
||||||
Etc: path.Join(pathSet.cacheDir, "etc"),
|
|
||||||
AutoEtc: true,
|
|
||||||
},
|
|
||||||
ExtraPerms: []*fst.ExtraPermConfig{
|
|
||||||
{Path: dataHome, Execute: true},
|
|
||||||
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
|
|
||||||
},
|
|
||||||
SystemBus: app.SystemBus,
|
|
||||||
SessionBus: app.SessionBus,
|
|
||||||
Enablements: app.Enablements,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Expose GPU devices.
|
Expose GPU devices.
|
||||||
|
@ -11,14 +11,14 @@ import (
|
|||||||
|
|
||||||
func mustRunApp(ctx context.Context, config *fst.Config, beforeFail func()) {
|
func mustRunApp(ctx context.Context, config *fst.Config, beforeFail func()) {
|
||||||
rs := new(fst.RunState)
|
rs := new(fst.RunState)
|
||||||
a := app.MustNew(std)
|
a := app.MustNew(ctx, std)
|
||||||
|
|
||||||
if sa, err := a.Seal(config); err != nil {
|
if sa, err := a.Seal(config); err != nil {
|
||||||
fmsg.PrintBaseError(err, "cannot seal app:")
|
fmsg.PrintBaseError(err, "cannot seal app:")
|
||||||
rs.ExitCode = 1
|
rs.ExitCode = 1
|
||||||
} else {
|
} else {
|
||||||
// this updates ExitCode
|
// this updates ExitCode
|
||||||
app.PrintRunStateErr(rs, sa.Run(ctx, rs))
|
app.PrintRunStateErr(rs, sa.Run(rs))
|
||||||
}
|
}
|
||||||
|
|
||||||
if rs.ExitCode != 0 {
|
if rs.ExitCode != 0 {
|
||||||
|
@ -6,18 +6,18 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
|
"git.gensokyo.uk/security/fortify/sandbox/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func withNixDaemon(
|
func withNixDaemon(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
action string, command []string, net bool, updateConfig func(config *fst.Config) *fst.Config,
|
action string, command []string, net bool, updateConfig func(config *fst.Config) *fst.Config,
|
||||||
app *bundleInfo, 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,
|
||||||
Command: []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
|
||||||
"nix-daemon --store / & " +
|
"nix-daemon --store / & " +
|
||||||
// wait for socket to appear
|
// wait for socket to appear
|
||||||
@ -34,11 +34,11 @@ func withNixDaemon(
|
|||||||
Inner: path.Join("/data/data", app.ID),
|
Inner: path.Join("/data/data", app.ID),
|
||||||
Outer: pathSet.homeDir,
|
Outer: pathSet.homeDir,
|
||||||
Sandbox: &fst.SandboxConfig{
|
Sandbox: &fst.SandboxConfig{
|
||||||
Hostname: formatHostname(app.Name) + "-" + action,
|
Hostname: formatHostname(app.Name) + "-" + action,
|
||||||
UserNS: true, // nix sandbox requires userns
|
Userns: true, // nix sandbox requires userns
|
||||||
Net: net,
|
Net: net,
|
||||||
Syscall: &bwrap.SyscallPolicy{Multiarch: true},
|
Seccomp: seccomp.FlagMultiarch,
|
||||||
NoNewSession: dropShell,
|
Tty: dropShell,
|
||||||
Filesystem: []*fst.FilesystemConfig{
|
Filesystem: []*fst.FilesystemConfig{
|
||||||
{Src: pathSet.nixPath, Dst: "/nix", Write: true, Must: true},
|
{Src: pathSet.nixPath, Dst: "/nix", Write: true, Must: true},
|
||||||
},
|
},
|
||||||
@ -61,19 +61,19 @@ func withNixDaemon(
|
|||||||
func withCacheDir(
|
func withCacheDir(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
action string, command []string, workDir string,
|
action string, command []string, workDir string,
|
||||||
app *bundleInfo, 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,
|
||||||
Command: []string{shellPath, "-lc", strings.Join(command, " && ")},
|
Args: []string{shellPath, "-lc", strings.Join(command, " && ")},
|
||||||
Confinement: fst.ConfinementConfig{
|
Confinement: fst.ConfinementConfig{
|
||||||
AppID: app.AppID,
|
AppID: app.AppID,
|
||||||
Username: "nixos",
|
Username: "nixos",
|
||||||
Inner: path.Join("/data/data", app.ID, "cache"),
|
Inner: path.Join("/data/data", app.ID, "cache"),
|
||||||
Outer: pathSet.cacheDir, // this also ensures cacheDir via shim
|
Outer: pathSet.cacheDir, // this also ensures cacheDir via shim
|
||||||
Sandbox: &fst.SandboxConfig{
|
Sandbox: &fst.SandboxConfig{
|
||||||
Hostname: formatHostname(app.Name) + "-" + action,
|
Hostname: formatHostname(app.Name) + "-" + action,
|
||||||
Syscall: &bwrap.SyscallPolicy{Multiarch: true},
|
Seccomp: seccomp.FlagMultiarch,
|
||||||
NoNewSession: dropShell,
|
Tty: dropShell,
|
||||||
Filesystem: []*fst.FilesystemConfig{
|
Filesystem: []*fst.FilesystemConfig{
|
||||||
{Src: path.Join(workDir, "nix"), Dst: "/nix", Must: true},
|
{Src: path.Join(workDir, "nix"), Dst: "/nix", Must: true},
|
||||||
{Src: workDir, Dst: path.Join(fst.Tmp, "bundle"), Must: true},
|
{Src: workDir, Dst: path.Join(fst.Tmp, "bundle"), Must: true},
|
||||||
@ -97,7 +97,7 @@ func withCacheDir(
|
|||||||
|
|
||||||
func mustRunAppDropShell(ctx context.Context, config *fst.Config, dropShell bool, beforeFail func()) {
|
func mustRunAppDropShell(ctx context.Context, config *fst.Config, dropShell bool, beforeFail func()) {
|
||||||
if dropShell {
|
if dropShell {
|
||||||
config.Command = []string{shellPath, "-l"}
|
config.Args = []string{shellPath, "-l"}
|
||||||
mustRunApp(ctx, config, beforeFail)
|
mustRunApp(ctx, config, beforeFail)
|
||||||
beforeFail()
|
beforeFail()
|
||||||
internal.Exit(0)
|
internal.Exit(0)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
package fst
|
package fst
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ type App interface {
|
|||||||
|
|
||||||
type SealedApp interface {
|
type SealedApp interface {
|
||||||
// Run commits sealed system setup and starts the app process.
|
// Run commits sealed system setup and starts the app process.
|
||||||
Run(ctx context.Context, rs *RunState) error
|
Run(rs *RunState) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunState stores the outcome of a call to [SealedApp.Run].
|
// RunState stores the outcome of a call to [SealedApp.Run].
|
||||||
|
@ -2,7 +2,7 @@ package fst
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
"git.gensokyo.uk/security/fortify/sandbox/seccomp"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,8 +14,11 @@ type Config struct {
|
|||||||
// passed to wayland security-context-v1 as application ID
|
// passed to wayland security-context-v1 as application ID
|
||||||
// and used as part of defaults in dbus session proxy
|
// and used as part of defaults in dbus session proxy
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
// final argv, passed to init
|
|
||||||
Command []string `json:"command"`
|
// absolute path to executable file
|
||||||
|
Path string `json:"path,omitempty"`
|
||||||
|
// final args passed to container init
|
||||||
|
Args []string `json:"args"`
|
||||||
|
|
||||||
Confinement ConfinementConfig `json:"confinement"`
|
Confinement ConfinementConfig `json:"confinement"`
|
||||||
}
|
}
|
||||||
@ -26,13 +29,13 @@ type ConfinementConfig struct {
|
|||||||
AppID int `json:"app_id"`
|
AppID int `json:"app_id"`
|
||||||
// list of supplementary groups to inherit
|
// list of supplementary groups to inherit
|
||||||
Groups []string `json:"groups"`
|
Groups []string `json:"groups"`
|
||||||
// passwd username in the sandbox, 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 sandbox, empty for outer
|
// home directory in container, empty for outer
|
||||||
Inner string `json:"home_inner"`
|
Inner string `json:"home_inner"`
|
||||||
// home directory in init namespace
|
// home directory in init namespace
|
||||||
Outer string `json:"home"`
|
Outer string `json:"home"`
|
||||||
// bwrap sandbox confinement configuration
|
// abstract sandbox configuration
|
||||||
Sandbox *SandboxConfig `json:"sandbox"`
|
Sandbox *SandboxConfig `json:"sandbox"`
|
||||||
// extra acl ops, runs after everything else
|
// extra acl ops, runs after everything else
|
||||||
ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"`
|
ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"`
|
||||||
@ -44,7 +47,7 @@ type ConfinementConfig struct {
|
|||||||
// nil value makes session bus proxy assume built-in defaults
|
// nil value makes session bus proxy assume built-in defaults
|
||||||
SessionBus *dbus.Config `json:"session_bus,omitempty"`
|
SessionBus *dbus.Config `json:"session_bus,omitempty"`
|
||||||
|
|
||||||
// system resources to expose to the sandbox
|
// system resources to expose to the container
|
||||||
Enablements system.Enablements `json:"enablements"`
|
Enablements system.Enablements `json:"enablements"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,24 +79,12 @@ func (e *ExtraPermConfig) String() string {
|
|||||||
return string(buf)
|
return string(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
type FilesystemConfig struct {
|
|
||||||
// mount point in sandbox, same as src if empty
|
|
||||||
Dst string `json:"dst,omitempty"`
|
|
||||||
// host filesystem path to make available to sandbox
|
|
||||||
Src string `json:"src"`
|
|
||||||
// write access
|
|
||||||
Write bool `json:"write,omitempty"`
|
|
||||||
// device access
|
|
||||||
Device bool `json:"dev,omitempty"`
|
|
||||||
// fail if mount fails
|
|
||||||
Must bool `json:"require,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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",
|
||||||
Command: []string{
|
Path: "/run/current-system/sw/bin/chromium",
|
||||||
|
Args: []string{
|
||||||
"chromium",
|
"chromium",
|
||||||
"--ignore-gpu-blocklist",
|
"--ignore-gpu-blocklist",
|
||||||
"--disable-smooth-scrolling",
|
"--disable-smooth-scrolling",
|
||||||
@ -108,11 +99,13 @@ func Template() *Config {
|
|||||||
Inner: "/var/lib/fortify",
|
Inner: "/var/lib/fortify",
|
||||||
Sandbox: &SandboxConfig{
|
Sandbox: &SandboxConfig{
|
||||||
Hostname: "localhost",
|
Hostname: "localhost",
|
||||||
UserNS: true,
|
Devel: true,
|
||||||
|
Userns: true,
|
||||||
Net: true,
|
Net: true,
|
||||||
Dev: true,
|
Dev: true,
|
||||||
Syscall: &bwrap.SyscallPolicy{DenyDevel: true, Multiarch: true},
|
Seccomp: seccomp.FlagMultiarch,
|
||||||
NoNewSession: true,
|
Tty: true,
|
||||||
|
Multiarch: true,
|
||||||
MapRealUID: true,
|
MapRealUID: true,
|
||||||
DirectWayland: false,
|
DirectWayland: false,
|
||||||
// example API credentials pulled from Google Chrome
|
// example API credentials pulled from Google Chrome
|
||||||
@ -131,10 +124,10 @@ func Template() *Config {
|
|||||||
Dst: "/data/data/org.chromium.Chromium", Write: true, Must: true},
|
Dst: "/data/data/org.chromium.Chromium", Write: true, Must: true},
|
||||||
{Src: "/dev/dri", Device: true},
|
{Src: "/dev/dri", Device: true},
|
||||||
},
|
},
|
||||||
Link: [][2]string{{"/run/user/65534", "/run/user/150"}},
|
Link: [][2]string{{"/run/user/65534", "/run/user/150"}},
|
||||||
Etc: "/etc",
|
Etc: "/etc",
|
||||||
AutoEtc: true,
|
AutoEtc: true,
|
||||||
Override: []string{"/var/run/nscd"},
|
Cover: []string{"/var/run/nscd"},
|
||||||
},
|
},
|
||||||
ExtraPerms: []*ExtraPermConfig{
|
ExtraPerms: []*ExtraPermConfig{
|
||||||
{Path: "/var/lib/fortify/u0", Ensure: true, Execute: true},
|
{Path: "/var/lib/fortify/u0", Ensure: true, Execute: true},
|
||||||
|
269
fst/sandbox.go
269
fst/sandbox.go
@ -4,125 +4,149 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"maps"
|
||||||
"path"
|
"path"
|
||||||
|
"slices"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
|
"git.gensokyo.uk/security/fortify/sandbox/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SandboxConfig describes resources made available to the sandbox.
|
// SandboxConfig describes resources made available to the sandbox.
|
||||||
type SandboxConfig struct {
|
type (
|
||||||
// unix hostname within sandbox
|
SandboxConfig struct {
|
||||||
Hostname string `json:"hostname,omitempty"`
|
// container hostname
|
||||||
// allow userns within sandbox
|
Hostname string `json:"hostname,omitempty"`
|
||||||
UserNS bool `json:"userns,omitempty"`
|
|
||||||
// share net namespace
|
|
||||||
Net bool `json:"net,omitempty"`
|
|
||||||
// share all devices
|
|
||||||
Dev bool `json:"dev,omitempty"`
|
|
||||||
// seccomp syscall filter policy
|
|
||||||
Syscall *bwrap.SyscallPolicy `json:"syscall"`
|
|
||||||
// do not run in new session
|
|
||||||
NoNewSession bool `json:"no_new_session,omitempty"`
|
|
||||||
// map target user uid to privileged user uid in the user namespace
|
|
||||||
MapRealUID bool `json:"map_real_uid"`
|
|
||||||
// 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"`
|
|
||||||
|
|
||||||
// final environment variables
|
// extra seccomp flags
|
||||||
Env map[string]string `json:"env"`
|
Seccomp seccomp.SyscallOpts `json:"seccomp"`
|
||||||
// sandbox host filesystem access
|
// allow ptrace and friends
|
||||||
Filesystem []*FilesystemConfig `json:"filesystem"`
|
Devel bool `json:"devel,omitempty"`
|
||||||
// symlinks created inside the sandbox
|
// allow userns creation in container
|
||||||
Link [][2]string `json:"symlink"`
|
Userns bool `json:"userns,omitempty"`
|
||||||
// read-only /etc directory
|
// share host net namespace
|
||||||
Etc string `json:"etc,omitempty"`
|
Net bool `json:"net,omitempty"`
|
||||||
// automatically set up /etc symlinks
|
// expose main process tty
|
||||||
AutoEtc bool `json:"auto_etc"`
|
Tty bool `json:"tty,omitempty"`
|
||||||
// mount tmpfs over these paths,
|
// allow multiarch
|
||||||
// runs right before [ConfinementConfig.ExtraPerms]
|
Multiarch bool `json:"multiarch,omitempty"`
|
||||||
Override []string `json:"override"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SandboxSys encapsulates system functions used during the creation of [bwrap.Config].
|
// initial process environment variables
|
||||||
type SandboxSys interface {
|
Env map[string]string `json:"env"`
|
||||||
Getuid() int
|
// map target user uid to privileged user uid in the user namespace
|
||||||
Paths() Paths
|
MapRealUID bool `json:"map_real_uid"`
|
||||||
ReadDir(name string) ([]fs.DirEntry, error)
|
|
||||||
EvalSymlinks(path string) (string, error)
|
|
||||||
|
|
||||||
Println(v ...any)
|
// expose all devices
|
||||||
Printf(format string, v ...any)
|
Dev bool `json:"dev,omitempty"`
|
||||||
}
|
// container host filesystem bind mounts
|
||||||
|
Filesystem []*FilesystemConfig `json:"filesystem"`
|
||||||
|
// create symlinks inside container filesystem
|
||||||
|
Link [][2]string `json:"symlink"`
|
||||||
|
|
||||||
// Bwrap returns the address of the corresponding bwrap.Config to s.
|
// direct access to wayland socket; when this gets set no attempt is made to attach security-context-v1
|
||||||
// Note that remaining tmpfs entries must be queued by the caller prior to launch.
|
// and the bare socket is mounted to the sandbox
|
||||||
func (s *SandboxConfig) Bwrap(sys SandboxSys, uid *int) (*bwrap.Config, error) {
|
DirectWayland bool `json:"direct_wayland,omitempty"`
|
||||||
|
|
||||||
|
// read-only /etc directory
|
||||||
|
Etc string `json:"etc,omitempty"`
|
||||||
|
// automatically set up /etc symlinks
|
||||||
|
AutoEtc bool `json:"auto_etc"`
|
||||||
|
// cover these paths or create them if they do not already exist
|
||||||
|
Cover []string `json:"cover"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SandboxSys encapsulates system functions used during [sandbox.Container] initialisation.
|
||||||
|
SandboxSys interface {
|
||||||
|
Getuid() int
|
||||||
|
Getgid() int
|
||||||
|
Paths() Paths
|
||||||
|
ReadDir(name string) ([]fs.DirEntry, error)
|
||||||
|
EvalSymlinks(path string) (string, error)
|
||||||
|
|
||||||
|
Println(v ...any)
|
||||||
|
Printf(format string, v ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilesystemConfig is a representation of [sandbox.BindMount].
|
||||||
|
FilesystemConfig struct {
|
||||||
|
// mount point in container, same as src if empty
|
||||||
|
Dst string `json:"dst,omitempty"`
|
||||||
|
// host filesystem path to make available to the container
|
||||||
|
Src string `json:"src"`
|
||||||
|
// do not mount filesystem read-only
|
||||||
|
Write bool `json:"write,omitempty"`
|
||||||
|
// do not disable device files
|
||||||
|
Device bool `json:"dev,omitempty"`
|
||||||
|
// fail if the bind mount cannot be established for any reason
|
||||||
|
Must bool `json:"require,omitempty"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToContainer initialises [sandbox.Params] via [SandboxConfig].
|
||||||
|
// Note that remaining container setup must be queued by the [App] implementation.
|
||||||
|
func (s *SandboxConfig) ToContainer(sys SandboxSys, uid, gid *int) (*sandbox.Params, map[string]string, error) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil, errors.New("nil sandbox config")
|
return nil, nil, syscall.EBADE
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Syscall == nil {
|
container := &sandbox.Params{
|
||||||
sys.Println("syscall filter not configured, PROCEED WITH CAUTION")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.MapRealUID {
|
|
||||||
// mapped uid defaults to 65534 to work around file ownership checks due to a bwrap limitation
|
|
||||||
*uid = 65534
|
|
||||||
} else {
|
|
||||||
// some programs fail to connect to dbus session running as a different uid, so a separate workaround
|
|
||||||
// is introduced to map priv-side caller uid in namespace
|
|
||||||
*uid = sys.Getuid()
|
|
||||||
}
|
|
||||||
|
|
||||||
conf := (&bwrap.Config{
|
|
||||||
Net: s.Net,
|
|
||||||
UserNS: s.UserNS,
|
|
||||||
UID: uid,
|
|
||||||
GID: uid,
|
|
||||||
Hostname: s.Hostname,
|
Hostname: s.Hostname,
|
||||||
Clearenv: true,
|
Ops: new(sandbox.Ops),
|
||||||
SetEnv: s.Env,
|
Seccomp: s.Seccomp,
|
||||||
|
}
|
||||||
|
|
||||||
/* this is only 4 KiB of memory on a 64-bit system,
|
/* this is only 4 KiB of memory on a 64-bit system,
|
||||||
permissive defaults on NixOS results in around 100 entries
|
permissive defaults on NixOS results in around 100 entries
|
||||||
so this capacity should eliminate copies for most setups */
|
so this capacity should eliminate copies for most setups */
|
||||||
Filesystem: make([]bwrap.FSBuilder, 0, 256),
|
*container.Ops = slices.Grow(*container.Ops, 1<<8)
|
||||||
|
|
||||||
Syscall: s.Syscall,
|
if s.Devel {
|
||||||
NewSession: !s.NoNewSession,
|
container.Flags |= sandbox.FAllowDevel
|
||||||
DieWithParent: true,
|
}
|
||||||
AsInit: true,
|
if s.Userns {
|
||||||
|
container.Flags |= sandbox.FAllowUserns
|
||||||
|
}
|
||||||
|
if s.Net {
|
||||||
|
container.Flags |= sandbox.FAllowNet
|
||||||
|
}
|
||||||
|
if s.Tty {
|
||||||
|
container.Flags |= sandbox.FAllowTTY
|
||||||
|
}
|
||||||
|
|
||||||
// initialise unconditionally as Once cannot be justified
|
if s.MapRealUID {
|
||||||
// for saving such a miniscule amount of memory
|
/* some programs fail to connect to dbus session running as a different uid
|
||||||
Chmod: make(bwrap.ChmodConfig),
|
so this workaround is introduced to map priv-side caller uid in container */
|
||||||
}).
|
container.Uid = sys.Getuid()
|
||||||
Procfs("/proc").
|
*uid = container.Uid
|
||||||
Tmpfs(Tmp, 4*1024)
|
container.Gid = sys.Getgid()
|
||||||
|
*gid = container.Gid
|
||||||
|
} else {
|
||||||
|
*uid = sandbox.OverflowUid()
|
||||||
|
*gid = sandbox.OverflowGid()
|
||||||
|
}
|
||||||
|
|
||||||
|
container.
|
||||||
|
Proc("/proc").
|
||||||
|
Tmpfs(Tmp, 1<<12, 0755)
|
||||||
|
|
||||||
if !s.Dev {
|
if !s.Dev {
|
||||||
conf.DevTmpfs("/dev").Mqueue("/dev/mqueue")
|
container.Dev("/dev").Mqueue("/dev/mqueue")
|
||||||
} else {
|
} else {
|
||||||
conf.Bind("/dev", "/dev", false, true, true)
|
container.Bind("/dev", "/dev", sandbox.BindDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.AutoEtc {
|
/* retrieve paths and hide them if they're made available in the sandbox;
|
||||||
if s.Etc == "" {
|
this feature tries to improve user experience of permissive defaults, and
|
||||||
conf.Dir("/etc")
|
to warn about issues in custom configuration; it is NOT a security feature
|
||||||
} else {
|
and should not be treated as such, ALWAYS be careful with what you bind */
|
||||||
conf.Bind(s.Etc, "/etc")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve paths and hide them if they're made available in the sandbox
|
|
||||||
var hidePaths []string
|
var hidePaths []string
|
||||||
sc := sys.Paths()
|
sc := sys.Paths()
|
||||||
hidePaths = append(hidePaths, sc.RuntimePath, sc.SharePath)
|
hidePaths = append(hidePaths, sc.RuntimePath, sc.SharePath)
|
||||||
_, systemBusAddr := dbus.Address()
|
_, systemBusAddr := dbus.Address()
|
||||||
if entries, err := dbus.Parse([]byte(systemBusAddr)); err != nil {
|
if entries, err := dbus.Parse([]byte(systemBusAddr)); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
} else {
|
} else {
|
||||||
// there is usually only one, do not preallocate
|
// there is usually only one, do not preallocate
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
@ -148,7 +172,7 @@ func (s *SandboxConfig) Bwrap(sys SandboxSys, uid *int) (*bwrap.Config, error) {
|
|||||||
hidePathMatch := make([]bool, len(hidePaths))
|
hidePathMatch := make([]bool, len(hidePaths))
|
||||||
for i := range hidePaths {
|
for i := range hidePaths {
|
||||||
if err := evalSymlinks(sys, &hidePaths[i]); err != nil {
|
if err := evalSymlinks(sys, &hidePaths[i]); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,19 +182,19 @@ func (s *SandboxConfig) Bwrap(sys SandboxSys, uid *int) (*bwrap.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !path.IsAbs(c.Src) {
|
if !path.IsAbs(c.Src) {
|
||||||
return nil, fmt.Errorf("src path %q is not absolute", c.Src)
|
return nil, nil, fmt.Errorf("src path %q is not absolute", c.Src)
|
||||||
}
|
}
|
||||||
|
|
||||||
dest := c.Dst
|
dest := c.Dst
|
||||||
if c.Dst == "" {
|
if c.Dst == "" {
|
||||||
dest = c.Src
|
dest = c.Src
|
||||||
} else if !path.IsAbs(dest) {
|
} else if !path.IsAbs(dest) {
|
||||||
return nil, fmt.Errorf("dst path %q is not absolute", dest)
|
return nil, nil, fmt.Errorf("dst path %q is not absolute", dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
srcH := c.Src
|
srcH := c.Src
|
||||||
if err := evalSymlinks(sys, &srcH); err != nil {
|
if err := evalSymlinks(sys, &srcH); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range hidePaths {
|
for i := range hidePaths {
|
||||||
@ -180,54 +204,71 @@ func (s *SandboxConfig) Bwrap(sys SandboxSys, uid *int) (*bwrap.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok, err := deepContainsH(srcH, hidePaths[i]); err != nil {
|
if ok, err := deepContainsH(srcH, hidePaths[i]); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
} else if ok {
|
} else if ok {
|
||||||
hidePathMatch[i] = true
|
hidePathMatch[i] = true
|
||||||
sys.Printf("hiding paths from %q", c.Src)
|
sys.Printf("hiding paths from %q", c.Src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Bind(c.Src, dest, !c.Must, c.Write, c.Device)
|
var flags int
|
||||||
|
if c.Write {
|
||||||
|
flags |= sandbox.BindWritable
|
||||||
|
}
|
||||||
|
if c.Device {
|
||||||
|
flags |= sandbox.BindDevice | sandbox.BindWritable
|
||||||
|
}
|
||||||
|
if !c.Must {
|
||||||
|
flags |= sandbox.BindOptional
|
||||||
|
}
|
||||||
|
container.Bind(c.Src, dest, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide marked paths before setting up shares
|
// cover matched paths
|
||||||
for i, ok := range hidePathMatch {
|
for i, ok := range hidePathMatch {
|
||||||
if ok {
|
if ok {
|
||||||
conf.Tmpfs(hidePaths[i], 8192)
|
container.Tmpfs(hidePaths[i], 1<<13, 0755)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range s.Link {
|
for _, l := range s.Link {
|
||||||
conf.Symlink(l[0], l[1])
|
container.Link(l[0], l[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.AutoEtc {
|
// perf: this might work better if implemented as a setup op in container init
|
||||||
etc := s.Etc
|
if !s.AutoEtc {
|
||||||
if etc == "" {
|
if s.Etc != "" {
|
||||||
etc = "/etc"
|
container.Bind(s.Etc, "/etc", 0)
|
||||||
}
|
}
|
||||||
conf.Bind(etc, Tmp+"/etc")
|
} else {
|
||||||
|
etcPath := s.Etc
|
||||||
|
if etcPath == "" {
|
||||||
|
etcPath = "/etc"
|
||||||
|
}
|
||||||
|
container.
|
||||||
|
Bind(etcPath, Tmp+"/etc", 0).
|
||||||
|
Mkdir("/etc", 0700)
|
||||||
|
|
||||||
// link host /etc contents to prevent passwd/group from being overwritten
|
// link host /etc contents to prevent dropping passwd/group bind mounts
|
||||||
if d, err := sys.ReadDir(etc); err != nil {
|
if d, err := sys.ReadDir(etcPath); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
} else {
|
} else {
|
||||||
for _, ent := range d {
|
for _, ent := range d {
|
||||||
name := ent.Name()
|
n := ent.Name()
|
||||||
switch name {
|
switch n {
|
||||||
case "passwd":
|
case "passwd":
|
||||||
case "group":
|
case "group":
|
||||||
|
|
||||||
case "mtab":
|
case "mtab":
|
||||||
conf.Symlink("/proc/mounts", "/etc/"+name)
|
container.Link("/proc/mounts", "/etc/"+n)
|
||||||
default:
|
default:
|
||||||
conf.Symlink(Tmp+"/etc/"+name, "/etc/"+name)
|
container.Link(Tmp+"/etc/"+n, "/etc/"+n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf, nil
|
return container, maps.Clone(s.Env), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalSymlinks(sys SandboxSys, v *string) error {
|
func evalSymlinks(sys SandboxSys, v *string) error {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
@ -10,9 +11,10 @@ import (
|
|||||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(os sys.State) (fst.App, error) {
|
func New(ctx context.Context, os sys.State) (fst.App, error) {
|
||||||
a := new(app)
|
a := new(app)
|
||||||
a.sys = os
|
a.sys = os
|
||||||
|
a.ctx = ctx
|
||||||
|
|
||||||
id := new(fst.ID)
|
id := new(fst.ID)
|
||||||
err := fst.NewAppID(id)
|
err := fst.NewAppID(id)
|
||||||
@ -21,8 +23,8 @@ func New(os sys.State) (fst.App, error) {
|
|||||||
return a, err
|
return a, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustNew(os sys.State) fst.App {
|
func MustNew(ctx context.Context, os sys.State) fst.App {
|
||||||
a, err := New(os)
|
a, err := New(ctx, os)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("cannot create app: %v", err)
|
log.Fatalf("cannot create app: %v", err)
|
||||||
}
|
}
|
||||||
@ -32,6 +34,7 @@ func MustNew(os sys.State) fst.App {
|
|||||||
type app struct {
|
type app struct {
|
||||||
id *stringPair[fst.ID]
|
id *stringPair[fst.ID]
|
||||||
sys sys.State
|
sys sys.State
|
||||||
|
ctx context.Context
|
||||||
|
|
||||||
*outcome
|
*outcome
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
@ -71,7 +74,7 @@ func (a *app) Seal(config *fst.Config) (fst.SealedApp, error) {
|
|||||||
|
|
||||||
seal := new(outcome)
|
seal := new(outcome)
|
||||||
seal.id = a.id
|
seal.id = a.id
|
||||||
err := seal.finalise(a.sys, config)
|
err := seal.finalise(a.ctx, a.sys, config)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
a.outcome = seal
|
a.outcome = seal
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"git.gensokyo.uk/security/fortify/acl"
|
"git.gensokyo.uk/security/fortify/acl"
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,20 +12,20 @@ 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",
|
||||||
Command: []string{"/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"},
|
Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start",
|
||||||
Confinement: fst.ConfinementConfig{
|
Confinement: fst.ConfinementConfig{
|
||||||
AppID: 1, Groups: []string{}, Username: "u0_a1",
|
AppID: 1, Groups: []string{}, Username: "u0_a1",
|
||||||
Outer: "/var/lib/persist/module/fortify/0/1",
|
Outer: "/var/lib/persist/module/fortify/0/1",
|
||||||
Sandbox: &fst.SandboxConfig{
|
Sandbox: &fst.SandboxConfig{
|
||||||
UserNS: true, Net: true, MapRealUID: true, DirectWayland: 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},
|
||||||
},
|
},
|
||||||
Override: []string{"/var/run/nscd"},
|
Cover: []string{"/var/run/nscd"},
|
||||||
},
|
},
|
||||||
SystemBus: &dbus.Config{
|
SystemBus: &dbus.Config{
|
||||||
Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"},
|
Talk: []string{"org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"},
|
||||||
@ -88,136 +88,133 @@ var testCasesNixos = []sealTestCase{
|
|||||||
}).
|
}).
|
||||||
UpdatePerm("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", acl.Read, acl.Write).
|
UpdatePerm("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", acl.Read, acl.Write).
|
||||||
UpdatePerm("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", acl.Read, acl.Write),
|
UpdatePerm("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", acl.Read, acl.Write),
|
||||||
(&bwrap.Config{
|
&sandbox.Params{
|
||||||
Net: true,
|
Uid: 1971,
|
||||||
UserNS: true,
|
Gid: 100,
|
||||||
Chdir: "/var/lib/persist/module/fortify/0/1",
|
Flags: sandbox.FAllowNet | sandbox.FAllowUserns,
|
||||||
Clearenv: true,
|
Dir: "/var/lib/persist/module/fortify/0/1",
|
||||||
SetEnv: map[string]string{
|
Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start",
|
||||||
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1971/bus",
|
Args: []string{"/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"},
|
||||||
"DBUS_SYSTEM_BUS_ADDRESS": "unix:path=/run/dbus/system_bus_socket",
|
Env: []string{
|
||||||
"HOME": "/var/lib/persist/module/fortify/0/1",
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1971/bus",
|
||||||
"PULSE_COOKIE": fst.Tmp + "/pulse-cookie",
|
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket",
|
||||||
"PULSE_SERVER": "unix:/run/user/1971/pulse/native",
|
"HOME=/var/lib/persist/module/fortify/0/1",
|
||||||
"SHELL": "/run/current-system/sw/bin/zsh",
|
"PULSE_COOKIE=" + fst.Tmp + "/pulse-cookie",
|
||||||
"TERM": "xterm-256color",
|
"PULSE_SERVER=unix:/run/user/1971/pulse/native",
|
||||||
"USER": "u0_a1",
|
"TERM=xterm-256color",
|
||||||
"WAYLAND_DISPLAY": "wayland-0",
|
"USER=u0_a1",
|
||||||
"XDG_RUNTIME_DIR": "/run/user/1971",
|
"WAYLAND_DISPLAY=wayland-0",
|
||||||
"XDG_SESSION_CLASS": "user",
|
"XDG_RUNTIME_DIR=/run/user/1971",
|
||||||
"XDG_SESSION_TYPE": "tty",
|
"XDG_SESSION_CLASS=user",
|
||||||
|
"XDG_SESSION_TYPE=tty",
|
||||||
},
|
},
|
||||||
Chmod: make(bwrap.ChmodConfig),
|
Ops: new(sandbox.Ops).
|
||||||
NewSession: true,
|
Proc("/proc").
|
||||||
DieWithParent: true,
|
Tmpfs(fst.Tmp, 4096, 0755).
|
||||||
AsInit: true,
|
Dev("/dev").Mqueue("/dev/mqueue").
|
||||||
}).SetUID(1971).SetGID(1971).
|
Bind("/bin", "/bin", 0).
|
||||||
Procfs("/proc").
|
Bind("/usr/bin", "/usr/bin", 0).
|
||||||
Tmpfs(fst.Tmp, 4096).
|
Bind("/nix/store", "/nix/store", 0).
|
||||||
DevTmpfs("/dev").Mqueue("/dev/mqueue").
|
Bind("/run/current-system", "/run/current-system", 0).
|
||||||
Bind("/bin", "/bin").
|
Bind("/sys/block", "/sys/block", sandbox.BindOptional).
|
||||||
Bind("/usr/bin", "/usr/bin").
|
Bind("/sys/bus", "/sys/bus", sandbox.BindOptional).
|
||||||
Bind("/nix/store", "/nix/store").
|
Bind("/sys/class", "/sys/class", sandbox.BindOptional).
|
||||||
Bind("/run/current-system", "/run/current-system").
|
Bind("/sys/dev", "/sys/dev", sandbox.BindOptional).
|
||||||
Bind("/sys/block", "/sys/block", true).
|
Bind("/sys/devices", "/sys/devices", sandbox.BindOptional).
|
||||||
Bind("/sys/bus", "/sys/bus", true).
|
Bind("/run/opengl-driver", "/run/opengl-driver", 0).
|
||||||
Bind("/sys/class", "/sys/class", true).
|
Bind("/dev/dri", "/dev/dri", sandbox.BindDevice|sandbox.BindWritable|sandbox.BindOptional).
|
||||||
Bind("/sys/dev", "/sys/dev", true).
|
Bind("/etc", fst.Tmp+"/etc", 0).
|
||||||
Bind("/sys/devices", "/sys/devices", true).
|
Mkdir("/etc", 0700).
|
||||||
Bind("/run/opengl-driver", "/run/opengl-driver").
|
Link(fst.Tmp+"/etc/alsa", "/etc/alsa").
|
||||||
Bind("/dev/dri", "/dev/dri", true, true, true).
|
Link(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
|
||||||
Bind("/etc", fst.Tmp+"/etc").
|
Link(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
|
||||||
Symlink(fst.Tmp+"/etc/alsa", "/etc/alsa").
|
Link(fst.Tmp+"/etc/dbus-1", "/etc/dbus-1").
|
||||||
Symlink(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
|
Link(fst.Tmp+"/etc/default", "/etc/default").
|
||||||
Symlink(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
|
Link(fst.Tmp+"/etc/ethertypes", "/etc/ethertypes").
|
||||||
Symlink(fst.Tmp+"/etc/dbus-1", "/etc/dbus-1").
|
Link(fst.Tmp+"/etc/fonts", "/etc/fonts").
|
||||||
Symlink(fst.Tmp+"/etc/default", "/etc/default").
|
Link(fst.Tmp+"/etc/fstab", "/etc/fstab").
|
||||||
Symlink(fst.Tmp+"/etc/ethertypes", "/etc/ethertypes").
|
Link(fst.Tmp+"/etc/fuse.conf", "/etc/fuse.conf").
|
||||||
Symlink(fst.Tmp+"/etc/fonts", "/etc/fonts").
|
Link(fst.Tmp+"/etc/host.conf", "/etc/host.conf").
|
||||||
Symlink(fst.Tmp+"/etc/fstab", "/etc/fstab").
|
Link(fst.Tmp+"/etc/hostid", "/etc/hostid").
|
||||||
Symlink(fst.Tmp+"/etc/fuse.conf", "/etc/fuse.conf").
|
Link(fst.Tmp+"/etc/hostname", "/etc/hostname").
|
||||||
Symlink(fst.Tmp+"/etc/host.conf", "/etc/host.conf").
|
Link(fst.Tmp+"/etc/hostname.CHECKSUM", "/etc/hostname.CHECKSUM").
|
||||||
Symlink(fst.Tmp+"/etc/hostid", "/etc/hostid").
|
Link(fst.Tmp+"/etc/hosts", "/etc/hosts").
|
||||||
Symlink(fst.Tmp+"/etc/hostname", "/etc/hostname").
|
Link(fst.Tmp+"/etc/inputrc", "/etc/inputrc").
|
||||||
Symlink(fst.Tmp+"/etc/hostname.CHECKSUM", "/etc/hostname.CHECKSUM").
|
Link(fst.Tmp+"/etc/ipsec.d", "/etc/ipsec.d").
|
||||||
Symlink(fst.Tmp+"/etc/hosts", "/etc/hosts").
|
Link(fst.Tmp+"/etc/issue", "/etc/issue").
|
||||||
Symlink(fst.Tmp+"/etc/inputrc", "/etc/inputrc").
|
Link(fst.Tmp+"/etc/kbd", "/etc/kbd").
|
||||||
Symlink(fst.Tmp+"/etc/ipsec.d", "/etc/ipsec.d").
|
Link(fst.Tmp+"/etc/libblockdev", "/etc/libblockdev").
|
||||||
Symlink(fst.Tmp+"/etc/issue", "/etc/issue").
|
Link(fst.Tmp+"/etc/locale.conf", "/etc/locale.conf").
|
||||||
Symlink(fst.Tmp+"/etc/kbd", "/etc/kbd").
|
Link(fst.Tmp+"/etc/localtime", "/etc/localtime").
|
||||||
Symlink(fst.Tmp+"/etc/libblockdev", "/etc/libblockdev").
|
Link(fst.Tmp+"/etc/login.defs", "/etc/login.defs").
|
||||||
Symlink(fst.Tmp+"/etc/locale.conf", "/etc/locale.conf").
|
Link(fst.Tmp+"/etc/lsb-release", "/etc/lsb-release").
|
||||||
Symlink(fst.Tmp+"/etc/localtime", "/etc/localtime").
|
Link(fst.Tmp+"/etc/lvm", "/etc/lvm").
|
||||||
Symlink(fst.Tmp+"/etc/login.defs", "/etc/login.defs").
|
Link(fst.Tmp+"/etc/machine-id", "/etc/machine-id").
|
||||||
Symlink(fst.Tmp+"/etc/lsb-release", "/etc/lsb-release").
|
Link(fst.Tmp+"/etc/man_db.conf", "/etc/man_db.conf").
|
||||||
Symlink(fst.Tmp+"/etc/lvm", "/etc/lvm").
|
Link(fst.Tmp+"/etc/modprobe.d", "/etc/modprobe.d").
|
||||||
Symlink(fst.Tmp+"/etc/machine-id", "/etc/machine-id").
|
Link(fst.Tmp+"/etc/modules-load.d", "/etc/modules-load.d").
|
||||||
Symlink(fst.Tmp+"/etc/man_db.conf", "/etc/man_db.conf").
|
Link("/proc/mounts", "/etc/mtab").
|
||||||
Symlink(fst.Tmp+"/etc/modprobe.d", "/etc/modprobe.d").
|
Link(fst.Tmp+"/etc/nanorc", "/etc/nanorc").
|
||||||
Symlink(fst.Tmp+"/etc/modules-load.d", "/etc/modules-load.d").
|
Link(fst.Tmp+"/etc/netgroup", "/etc/netgroup").
|
||||||
Symlink("/proc/mounts", "/etc/mtab").
|
Link(fst.Tmp+"/etc/NetworkManager", "/etc/NetworkManager").
|
||||||
Symlink(fst.Tmp+"/etc/nanorc", "/etc/nanorc").
|
Link(fst.Tmp+"/etc/nix", "/etc/nix").
|
||||||
Symlink(fst.Tmp+"/etc/netgroup", "/etc/netgroup").
|
Link(fst.Tmp+"/etc/nixos", "/etc/nixos").
|
||||||
Symlink(fst.Tmp+"/etc/NetworkManager", "/etc/NetworkManager").
|
Link(fst.Tmp+"/etc/NIXOS", "/etc/NIXOS").
|
||||||
Symlink(fst.Tmp+"/etc/nix", "/etc/nix").
|
Link(fst.Tmp+"/etc/nscd.conf", "/etc/nscd.conf").
|
||||||
Symlink(fst.Tmp+"/etc/nixos", "/etc/nixos").
|
Link(fst.Tmp+"/etc/nsswitch.conf", "/etc/nsswitch.conf").
|
||||||
Symlink(fst.Tmp+"/etc/NIXOS", "/etc/NIXOS").
|
Link(fst.Tmp+"/etc/opensnitchd", "/etc/opensnitchd").
|
||||||
Symlink(fst.Tmp+"/etc/nscd.conf", "/etc/nscd.conf").
|
Link(fst.Tmp+"/etc/os-release", "/etc/os-release").
|
||||||
Symlink(fst.Tmp+"/etc/nsswitch.conf", "/etc/nsswitch.conf").
|
Link(fst.Tmp+"/etc/pam", "/etc/pam").
|
||||||
Symlink(fst.Tmp+"/etc/opensnitchd", "/etc/opensnitchd").
|
Link(fst.Tmp+"/etc/pam.d", "/etc/pam.d").
|
||||||
Symlink(fst.Tmp+"/etc/os-release", "/etc/os-release").
|
Link(fst.Tmp+"/etc/pipewire", "/etc/pipewire").
|
||||||
Symlink(fst.Tmp+"/etc/pam", "/etc/pam").
|
Link(fst.Tmp+"/etc/pki", "/etc/pki").
|
||||||
Symlink(fst.Tmp+"/etc/pam.d", "/etc/pam.d").
|
Link(fst.Tmp+"/etc/polkit-1", "/etc/polkit-1").
|
||||||
Symlink(fst.Tmp+"/etc/pipewire", "/etc/pipewire").
|
Link(fst.Tmp+"/etc/profile", "/etc/profile").
|
||||||
Symlink(fst.Tmp+"/etc/pki", "/etc/pki").
|
Link(fst.Tmp+"/etc/protocols", "/etc/protocols").
|
||||||
Symlink(fst.Tmp+"/etc/polkit-1", "/etc/polkit-1").
|
Link(fst.Tmp+"/etc/qemu", "/etc/qemu").
|
||||||
Symlink(fst.Tmp+"/etc/profile", "/etc/profile").
|
Link(fst.Tmp+"/etc/resolv.conf", "/etc/resolv.conf").
|
||||||
Symlink(fst.Tmp+"/etc/protocols", "/etc/protocols").
|
Link(fst.Tmp+"/etc/resolvconf.conf", "/etc/resolvconf.conf").
|
||||||
Symlink(fst.Tmp+"/etc/qemu", "/etc/qemu").
|
Link(fst.Tmp+"/etc/rpc", "/etc/rpc").
|
||||||
Symlink(fst.Tmp+"/etc/resolv.conf", "/etc/resolv.conf").
|
Link(fst.Tmp+"/etc/samba", "/etc/samba").
|
||||||
Symlink(fst.Tmp+"/etc/resolvconf.conf", "/etc/resolvconf.conf").
|
Link(fst.Tmp+"/etc/sddm.conf", "/etc/sddm.conf").
|
||||||
Symlink(fst.Tmp+"/etc/rpc", "/etc/rpc").
|
Link(fst.Tmp+"/etc/secureboot", "/etc/secureboot").
|
||||||
Symlink(fst.Tmp+"/etc/samba", "/etc/samba").
|
Link(fst.Tmp+"/etc/services", "/etc/services").
|
||||||
Symlink(fst.Tmp+"/etc/sddm.conf", "/etc/sddm.conf").
|
Link(fst.Tmp+"/etc/set-environment", "/etc/set-environment").
|
||||||
Symlink(fst.Tmp+"/etc/secureboot", "/etc/secureboot").
|
Link(fst.Tmp+"/etc/shadow", "/etc/shadow").
|
||||||
Symlink(fst.Tmp+"/etc/services", "/etc/services").
|
Link(fst.Tmp+"/etc/shells", "/etc/shells").
|
||||||
Symlink(fst.Tmp+"/etc/set-environment", "/etc/set-environment").
|
Link(fst.Tmp+"/etc/ssh", "/etc/ssh").
|
||||||
Symlink(fst.Tmp+"/etc/shadow", "/etc/shadow").
|
Link(fst.Tmp+"/etc/ssl", "/etc/ssl").
|
||||||
Symlink(fst.Tmp+"/etc/shells", "/etc/shells").
|
Link(fst.Tmp+"/etc/static", "/etc/static").
|
||||||
Symlink(fst.Tmp+"/etc/ssh", "/etc/ssh").
|
Link(fst.Tmp+"/etc/subgid", "/etc/subgid").
|
||||||
Symlink(fst.Tmp+"/etc/ssl", "/etc/ssl").
|
Link(fst.Tmp+"/etc/subuid", "/etc/subuid").
|
||||||
Symlink(fst.Tmp+"/etc/static", "/etc/static").
|
Link(fst.Tmp+"/etc/sudoers", "/etc/sudoers").
|
||||||
Symlink(fst.Tmp+"/etc/subgid", "/etc/subgid").
|
Link(fst.Tmp+"/etc/sysctl.d", "/etc/sysctl.d").
|
||||||
Symlink(fst.Tmp+"/etc/subuid", "/etc/subuid").
|
Link(fst.Tmp+"/etc/systemd", "/etc/systemd").
|
||||||
Symlink(fst.Tmp+"/etc/sudoers", "/etc/sudoers").
|
Link(fst.Tmp+"/etc/terminfo", "/etc/terminfo").
|
||||||
Symlink(fst.Tmp+"/etc/sysctl.d", "/etc/sysctl.d").
|
Link(fst.Tmp+"/etc/tmpfiles.d", "/etc/tmpfiles.d").
|
||||||
Symlink(fst.Tmp+"/etc/systemd", "/etc/systemd").
|
Link(fst.Tmp+"/etc/udev", "/etc/udev").
|
||||||
Symlink(fst.Tmp+"/etc/terminfo", "/etc/terminfo").
|
Link(fst.Tmp+"/etc/udisks2", "/etc/udisks2").
|
||||||
Symlink(fst.Tmp+"/etc/tmpfiles.d", "/etc/tmpfiles.d").
|
Link(fst.Tmp+"/etc/UPower", "/etc/UPower").
|
||||||
Symlink(fst.Tmp+"/etc/udev", "/etc/udev").
|
Link(fst.Tmp+"/etc/vconsole.conf", "/etc/vconsole.conf").
|
||||||
Symlink(fst.Tmp+"/etc/udisks2", "/etc/udisks2").
|
Link(fst.Tmp+"/etc/X11", "/etc/X11").
|
||||||
Symlink(fst.Tmp+"/etc/UPower", "/etc/UPower").
|
Link(fst.Tmp+"/etc/zfs", "/etc/zfs").
|
||||||
Symlink(fst.Tmp+"/etc/vconsole.conf", "/etc/vconsole.conf").
|
Link(fst.Tmp+"/etc/zinputrc", "/etc/zinputrc").
|
||||||
Symlink(fst.Tmp+"/etc/X11", "/etc/X11").
|
Link(fst.Tmp+"/etc/zoneinfo", "/etc/zoneinfo").
|
||||||
Symlink(fst.Tmp+"/etc/zfs", "/etc/zfs").
|
Link(fst.Tmp+"/etc/zprofile", "/etc/zprofile").
|
||||||
Symlink(fst.Tmp+"/etc/zinputrc", "/etc/zinputrc").
|
Link(fst.Tmp+"/etc/zshenv", "/etc/zshenv").
|
||||||
Symlink(fst.Tmp+"/etc/zoneinfo", "/etc/zoneinfo").
|
Link(fst.Tmp+"/etc/zshrc", "/etc/zshrc").
|
||||||
Symlink(fst.Tmp+"/etc/zprofile", "/etc/zprofile").
|
Tmpfs("/run/user", 4096, 0755).
|
||||||
Symlink(fst.Tmp+"/etc/zshenv", "/etc/zshenv").
|
Tmpfs("/run/user/1971", 8388608, 0755).
|
||||||
Symlink(fst.Tmp+"/etc/zshrc", "/etc/zshrc").
|
Bind("/tmp/fortify.1971/tmpdir/1", "/tmp", sandbox.BindWritable).
|
||||||
Tmpfs("/run/user", 1048576).
|
Bind("/var/lib/persist/module/fortify/0/1", "/var/lib/persist/module/fortify/0/1", sandbox.BindWritable).
|
||||||
Tmpfs("/run/user/1971", 8388608).
|
Place("/etc/passwd", []byte("u0_a1:x:1971:100:Fortify:/var/lib/persist/module/fortify/0/1:/run/current-system/sw/bin/zsh\n")).
|
||||||
Bind("/tmp/fortify.1971/tmpdir/1", "/tmp", false, true).
|
Place("/etc/group", []byte("fortify:x:100:\n")).
|
||||||
Bind("/var/lib/persist/module/fortify/0/1", "/var/lib/persist/module/fortify/0/1", false, true).
|
Bind("/run/user/1971/wayland-0", "/run/user/1971/wayland-0", 0).
|
||||||
CopyBind("/etc/passwd", []byte("u0_a1:x:1971:1971:Fortify:/var/lib/persist/module/fortify/0/1:/run/current-system/sw/bin/zsh\n")).
|
Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse", "/run/user/1971/pulse/native", 0).
|
||||||
CopyBind("/etc/group", []byte("fortify:x:1971:\n")).
|
Place(fst.Tmp+"/pulse-cookie", nil).
|
||||||
Bind("/run/user/1971/wayland-0", "/run/user/1971/wayland-0").
|
Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", "/run/user/1971/bus", 0).
|
||||||
Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse", "/run/user/1971/pulse/native").
|
Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", "/run/dbus/system_bus_socket", 0).
|
||||||
CopyBind(fst.Tmp+"/pulse-cookie", nil).
|
Tmpfs("/var/run/nscd", 8192, 0755),
|
||||||
Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", "/run/user/1971/bus").
|
},
|
||||||
Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", "/run/dbus/system_bus_socket").
|
|
||||||
Tmpfs("/var/run/nscd", 8192).
|
|
||||||
Bind("/run/wrappers/bin/fortify", "/.fortify/sbin/fortify").
|
|
||||||
Symlink("fortify", "/.fortify/sbin/init0"),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"git.gensokyo.uk/security/fortify/acl"
|
"git.gensokyo.uk/security/fortify/acl"
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,7 +14,6 @@ var testCasesPd = []sealTestCase{
|
|||||||
{
|
{
|
||||||
"nixos permissive defaults no enablements", new(stubNixOS),
|
"nixos permissive defaults no enablements", new(stubNixOS),
|
||||||
&fst.Config{
|
&fst.Config{
|
||||||
Command: make([]string, 0),
|
|
||||||
Confinement: fst.ConfinementConfig{
|
Confinement: fst.ConfinementConfig{
|
||||||
AppID: 0,
|
AppID: 0,
|
||||||
Username: "chronos",
|
Username: "chronos",
|
||||||
@ -35,136 +34,132 @@ var testCasesPd = []sealTestCase{
|
|||||||
Ephemeral(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", acl.Execute).
|
Ephemeral(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", acl.Execute).
|
||||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||||
Ensure("/tmp/fortify.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute),
|
Ensure("/tmp/fortify.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute),
|
||||||
(&bwrap.Config{
|
&sandbox.Params{
|
||||||
Net: true,
|
Flags: sandbox.FAllowNet | sandbox.FAllowUserns | sandbox.FAllowTTY,
|
||||||
UserNS: true,
|
Dir: "/home/chronos",
|
||||||
Clearenv: true,
|
Path: "/run/current-system/sw/bin/zsh",
|
||||||
Syscall: new(bwrap.SyscallPolicy),
|
Args: []string{"/run/current-system/sw/bin/zsh"},
|
||||||
Chdir: "/home/chronos",
|
Env: []string{
|
||||||
SetEnv: map[string]string{
|
"HOME=/home/chronos",
|
||||||
"HOME": "/home/chronos",
|
"TERM=xterm-256color",
|
||||||
"SHELL": "/run/current-system/sw/bin/zsh",
|
"USER=chronos",
|
||||||
"TERM": "xterm-256color",
|
"XDG_RUNTIME_DIR=/run/user/65534",
|
||||||
"USER": "chronos",
|
"XDG_SESSION_CLASS=user",
|
||||||
"XDG_RUNTIME_DIR": "/run/user/65534",
|
"XDG_SESSION_TYPE=tty",
|
||||||
"XDG_SESSION_CLASS": "user",
|
},
|
||||||
"XDG_SESSION_TYPE": "tty"},
|
Ops: new(sandbox.Ops).
|
||||||
Chmod: make(bwrap.ChmodConfig),
|
Proc("/proc").
|
||||||
DieWithParent: true,
|
Tmpfs(fst.Tmp, 4096, 0755).
|
||||||
AsInit: true,
|
Dev("/dev").Mqueue("/dev/mqueue").
|
||||||
}).SetUID(65534).SetGID(65534).
|
Bind("/bin", "/bin", sandbox.BindWritable).
|
||||||
Procfs("/proc").
|
Bind("/boot", "/boot", sandbox.BindWritable).
|
||||||
Tmpfs(fst.Tmp, 4096).
|
Bind("/home", "/home", sandbox.BindWritable).
|
||||||
DevTmpfs("/dev").Mqueue("/dev/mqueue").
|
Bind("/lib", "/lib", sandbox.BindWritable).
|
||||||
Bind("/bin", "/bin", false, true).
|
Bind("/lib64", "/lib64", sandbox.BindWritable).
|
||||||
Bind("/boot", "/boot", false, true).
|
Bind("/nix", "/nix", sandbox.BindWritable).
|
||||||
Bind("/home", "/home", false, true).
|
Bind("/root", "/root", sandbox.BindWritable).
|
||||||
Bind("/lib", "/lib", false, true).
|
Bind("/run", "/run", sandbox.BindWritable).
|
||||||
Bind("/lib64", "/lib64", false, true).
|
Bind("/srv", "/srv", sandbox.BindWritable).
|
||||||
Bind("/nix", "/nix", false, true).
|
Bind("/sys", "/sys", sandbox.BindWritable).
|
||||||
Bind("/root", "/root", false, true).
|
Bind("/usr", "/usr", sandbox.BindWritable).
|
||||||
Bind("/run", "/run", false, true).
|
Bind("/var", "/var", sandbox.BindWritable).
|
||||||
Bind("/srv", "/srv", false, true).
|
Bind("/dev/kvm", "/dev/kvm", sandbox.BindWritable|sandbox.BindDevice|sandbox.BindOptional).
|
||||||
Bind("/sys", "/sys", false, true).
|
Tmpfs("/run/user/1971", 8192, 0755).
|
||||||
Bind("/usr", "/usr", false, true).
|
Tmpfs("/run/dbus", 8192, 0755).
|
||||||
Bind("/var", "/var", false, true).
|
Bind("/etc", fst.Tmp+"/etc", 0).
|
||||||
Bind("/dev/kvm", "/dev/kvm", true, true, true).
|
Mkdir("/etc", 0700).
|
||||||
Tmpfs("/run/user/1971", 8192).
|
Link(fst.Tmp+"/etc/alsa", "/etc/alsa").
|
||||||
Tmpfs("/run/dbus", 8192).
|
Link(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
|
||||||
Bind("/etc", fst.Tmp+"/etc").
|
Link(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
|
||||||
Symlink(fst.Tmp+"/etc/alsa", "/etc/alsa").
|
Link(fst.Tmp+"/etc/dbus-1", "/etc/dbus-1").
|
||||||
Symlink(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
|
Link(fst.Tmp+"/etc/default", "/etc/default").
|
||||||
Symlink(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
|
Link(fst.Tmp+"/etc/ethertypes", "/etc/ethertypes").
|
||||||
Symlink(fst.Tmp+"/etc/dbus-1", "/etc/dbus-1").
|
Link(fst.Tmp+"/etc/fonts", "/etc/fonts").
|
||||||
Symlink(fst.Tmp+"/etc/default", "/etc/default").
|
Link(fst.Tmp+"/etc/fstab", "/etc/fstab").
|
||||||
Symlink(fst.Tmp+"/etc/ethertypes", "/etc/ethertypes").
|
Link(fst.Tmp+"/etc/fuse.conf", "/etc/fuse.conf").
|
||||||
Symlink(fst.Tmp+"/etc/fonts", "/etc/fonts").
|
Link(fst.Tmp+"/etc/host.conf", "/etc/host.conf").
|
||||||
Symlink(fst.Tmp+"/etc/fstab", "/etc/fstab").
|
Link(fst.Tmp+"/etc/hostid", "/etc/hostid").
|
||||||
Symlink(fst.Tmp+"/etc/fuse.conf", "/etc/fuse.conf").
|
Link(fst.Tmp+"/etc/hostname", "/etc/hostname").
|
||||||
Symlink(fst.Tmp+"/etc/host.conf", "/etc/host.conf").
|
Link(fst.Tmp+"/etc/hostname.CHECKSUM", "/etc/hostname.CHECKSUM").
|
||||||
Symlink(fst.Tmp+"/etc/hostid", "/etc/hostid").
|
Link(fst.Tmp+"/etc/hosts", "/etc/hosts").
|
||||||
Symlink(fst.Tmp+"/etc/hostname", "/etc/hostname").
|
Link(fst.Tmp+"/etc/inputrc", "/etc/inputrc").
|
||||||
Symlink(fst.Tmp+"/etc/hostname.CHECKSUM", "/etc/hostname.CHECKSUM").
|
Link(fst.Tmp+"/etc/ipsec.d", "/etc/ipsec.d").
|
||||||
Symlink(fst.Tmp+"/etc/hosts", "/etc/hosts").
|
Link(fst.Tmp+"/etc/issue", "/etc/issue").
|
||||||
Symlink(fst.Tmp+"/etc/inputrc", "/etc/inputrc").
|
Link(fst.Tmp+"/etc/kbd", "/etc/kbd").
|
||||||
Symlink(fst.Tmp+"/etc/ipsec.d", "/etc/ipsec.d").
|
Link(fst.Tmp+"/etc/libblockdev", "/etc/libblockdev").
|
||||||
Symlink(fst.Tmp+"/etc/issue", "/etc/issue").
|
Link(fst.Tmp+"/etc/locale.conf", "/etc/locale.conf").
|
||||||
Symlink(fst.Tmp+"/etc/kbd", "/etc/kbd").
|
Link(fst.Tmp+"/etc/localtime", "/etc/localtime").
|
||||||
Symlink(fst.Tmp+"/etc/libblockdev", "/etc/libblockdev").
|
Link(fst.Tmp+"/etc/login.defs", "/etc/login.defs").
|
||||||
Symlink(fst.Tmp+"/etc/locale.conf", "/etc/locale.conf").
|
Link(fst.Tmp+"/etc/lsb-release", "/etc/lsb-release").
|
||||||
Symlink(fst.Tmp+"/etc/localtime", "/etc/localtime").
|
Link(fst.Tmp+"/etc/lvm", "/etc/lvm").
|
||||||
Symlink(fst.Tmp+"/etc/login.defs", "/etc/login.defs").
|
Link(fst.Tmp+"/etc/machine-id", "/etc/machine-id").
|
||||||
Symlink(fst.Tmp+"/etc/lsb-release", "/etc/lsb-release").
|
Link(fst.Tmp+"/etc/man_db.conf", "/etc/man_db.conf").
|
||||||
Symlink(fst.Tmp+"/etc/lvm", "/etc/lvm").
|
Link(fst.Tmp+"/etc/modprobe.d", "/etc/modprobe.d").
|
||||||
Symlink(fst.Tmp+"/etc/machine-id", "/etc/machine-id").
|
Link(fst.Tmp+"/etc/modules-load.d", "/etc/modules-load.d").
|
||||||
Symlink(fst.Tmp+"/etc/man_db.conf", "/etc/man_db.conf").
|
Link("/proc/mounts", "/etc/mtab").
|
||||||
Symlink(fst.Tmp+"/etc/modprobe.d", "/etc/modprobe.d").
|
Link(fst.Tmp+"/etc/nanorc", "/etc/nanorc").
|
||||||
Symlink(fst.Tmp+"/etc/modules-load.d", "/etc/modules-load.d").
|
Link(fst.Tmp+"/etc/netgroup", "/etc/netgroup").
|
||||||
Symlink("/proc/mounts", "/etc/mtab").
|
Link(fst.Tmp+"/etc/NetworkManager", "/etc/NetworkManager").
|
||||||
Symlink(fst.Tmp+"/etc/nanorc", "/etc/nanorc").
|
Link(fst.Tmp+"/etc/nix", "/etc/nix").
|
||||||
Symlink(fst.Tmp+"/etc/netgroup", "/etc/netgroup").
|
Link(fst.Tmp+"/etc/nixos", "/etc/nixos").
|
||||||
Symlink(fst.Tmp+"/etc/NetworkManager", "/etc/NetworkManager").
|
Link(fst.Tmp+"/etc/NIXOS", "/etc/NIXOS").
|
||||||
Symlink(fst.Tmp+"/etc/nix", "/etc/nix").
|
Link(fst.Tmp+"/etc/nscd.conf", "/etc/nscd.conf").
|
||||||
Symlink(fst.Tmp+"/etc/nixos", "/etc/nixos").
|
Link(fst.Tmp+"/etc/nsswitch.conf", "/etc/nsswitch.conf").
|
||||||
Symlink(fst.Tmp+"/etc/NIXOS", "/etc/NIXOS").
|
Link(fst.Tmp+"/etc/opensnitchd", "/etc/opensnitchd").
|
||||||
Symlink(fst.Tmp+"/etc/nscd.conf", "/etc/nscd.conf").
|
Link(fst.Tmp+"/etc/os-release", "/etc/os-release").
|
||||||
Symlink(fst.Tmp+"/etc/nsswitch.conf", "/etc/nsswitch.conf").
|
Link(fst.Tmp+"/etc/pam", "/etc/pam").
|
||||||
Symlink(fst.Tmp+"/etc/opensnitchd", "/etc/opensnitchd").
|
Link(fst.Tmp+"/etc/pam.d", "/etc/pam.d").
|
||||||
Symlink(fst.Tmp+"/etc/os-release", "/etc/os-release").
|
Link(fst.Tmp+"/etc/pipewire", "/etc/pipewire").
|
||||||
Symlink(fst.Tmp+"/etc/pam", "/etc/pam").
|
Link(fst.Tmp+"/etc/pki", "/etc/pki").
|
||||||
Symlink(fst.Tmp+"/etc/pam.d", "/etc/pam.d").
|
Link(fst.Tmp+"/etc/polkit-1", "/etc/polkit-1").
|
||||||
Symlink(fst.Tmp+"/etc/pipewire", "/etc/pipewire").
|
Link(fst.Tmp+"/etc/profile", "/etc/profile").
|
||||||
Symlink(fst.Tmp+"/etc/pki", "/etc/pki").
|
Link(fst.Tmp+"/etc/protocols", "/etc/protocols").
|
||||||
Symlink(fst.Tmp+"/etc/polkit-1", "/etc/polkit-1").
|
Link(fst.Tmp+"/etc/qemu", "/etc/qemu").
|
||||||
Symlink(fst.Tmp+"/etc/profile", "/etc/profile").
|
Link(fst.Tmp+"/etc/resolv.conf", "/etc/resolv.conf").
|
||||||
Symlink(fst.Tmp+"/etc/protocols", "/etc/protocols").
|
Link(fst.Tmp+"/etc/resolvconf.conf", "/etc/resolvconf.conf").
|
||||||
Symlink(fst.Tmp+"/etc/qemu", "/etc/qemu").
|
Link(fst.Tmp+"/etc/rpc", "/etc/rpc").
|
||||||
Symlink(fst.Tmp+"/etc/resolv.conf", "/etc/resolv.conf").
|
Link(fst.Tmp+"/etc/samba", "/etc/samba").
|
||||||
Symlink(fst.Tmp+"/etc/resolvconf.conf", "/etc/resolvconf.conf").
|
Link(fst.Tmp+"/etc/sddm.conf", "/etc/sddm.conf").
|
||||||
Symlink(fst.Tmp+"/etc/rpc", "/etc/rpc").
|
Link(fst.Tmp+"/etc/secureboot", "/etc/secureboot").
|
||||||
Symlink(fst.Tmp+"/etc/samba", "/etc/samba").
|
Link(fst.Tmp+"/etc/services", "/etc/services").
|
||||||
Symlink(fst.Tmp+"/etc/sddm.conf", "/etc/sddm.conf").
|
Link(fst.Tmp+"/etc/set-environment", "/etc/set-environment").
|
||||||
Symlink(fst.Tmp+"/etc/secureboot", "/etc/secureboot").
|
Link(fst.Tmp+"/etc/shadow", "/etc/shadow").
|
||||||
Symlink(fst.Tmp+"/etc/services", "/etc/services").
|
Link(fst.Tmp+"/etc/shells", "/etc/shells").
|
||||||
Symlink(fst.Tmp+"/etc/set-environment", "/etc/set-environment").
|
Link(fst.Tmp+"/etc/ssh", "/etc/ssh").
|
||||||
Symlink(fst.Tmp+"/etc/shadow", "/etc/shadow").
|
Link(fst.Tmp+"/etc/ssl", "/etc/ssl").
|
||||||
Symlink(fst.Tmp+"/etc/shells", "/etc/shells").
|
Link(fst.Tmp+"/etc/static", "/etc/static").
|
||||||
Symlink(fst.Tmp+"/etc/ssh", "/etc/ssh").
|
Link(fst.Tmp+"/etc/subgid", "/etc/subgid").
|
||||||
Symlink(fst.Tmp+"/etc/ssl", "/etc/ssl").
|
Link(fst.Tmp+"/etc/subuid", "/etc/subuid").
|
||||||
Symlink(fst.Tmp+"/etc/static", "/etc/static").
|
Link(fst.Tmp+"/etc/sudoers", "/etc/sudoers").
|
||||||
Symlink(fst.Tmp+"/etc/subgid", "/etc/subgid").
|
Link(fst.Tmp+"/etc/sysctl.d", "/etc/sysctl.d").
|
||||||
Symlink(fst.Tmp+"/etc/subuid", "/etc/subuid").
|
Link(fst.Tmp+"/etc/systemd", "/etc/systemd").
|
||||||
Symlink(fst.Tmp+"/etc/sudoers", "/etc/sudoers").
|
Link(fst.Tmp+"/etc/terminfo", "/etc/terminfo").
|
||||||
Symlink(fst.Tmp+"/etc/sysctl.d", "/etc/sysctl.d").
|
Link(fst.Tmp+"/etc/tmpfiles.d", "/etc/tmpfiles.d").
|
||||||
Symlink(fst.Tmp+"/etc/systemd", "/etc/systemd").
|
Link(fst.Tmp+"/etc/udev", "/etc/udev").
|
||||||
Symlink(fst.Tmp+"/etc/terminfo", "/etc/terminfo").
|
Link(fst.Tmp+"/etc/udisks2", "/etc/udisks2").
|
||||||
Symlink(fst.Tmp+"/etc/tmpfiles.d", "/etc/tmpfiles.d").
|
Link(fst.Tmp+"/etc/UPower", "/etc/UPower").
|
||||||
Symlink(fst.Tmp+"/etc/udev", "/etc/udev").
|
Link(fst.Tmp+"/etc/vconsole.conf", "/etc/vconsole.conf").
|
||||||
Symlink(fst.Tmp+"/etc/udisks2", "/etc/udisks2").
|
Link(fst.Tmp+"/etc/X11", "/etc/X11").
|
||||||
Symlink(fst.Tmp+"/etc/UPower", "/etc/UPower").
|
Link(fst.Tmp+"/etc/zfs", "/etc/zfs").
|
||||||
Symlink(fst.Tmp+"/etc/vconsole.conf", "/etc/vconsole.conf").
|
Link(fst.Tmp+"/etc/zinputrc", "/etc/zinputrc").
|
||||||
Symlink(fst.Tmp+"/etc/X11", "/etc/X11").
|
Link(fst.Tmp+"/etc/zoneinfo", "/etc/zoneinfo").
|
||||||
Symlink(fst.Tmp+"/etc/zfs", "/etc/zfs").
|
Link(fst.Tmp+"/etc/zprofile", "/etc/zprofile").
|
||||||
Symlink(fst.Tmp+"/etc/zinputrc", "/etc/zinputrc").
|
Link(fst.Tmp+"/etc/zshenv", "/etc/zshenv").
|
||||||
Symlink(fst.Tmp+"/etc/zoneinfo", "/etc/zoneinfo").
|
Link(fst.Tmp+"/etc/zshrc", "/etc/zshrc").
|
||||||
Symlink(fst.Tmp+"/etc/zprofile", "/etc/zprofile").
|
Tmpfs("/run/user", 4096, 0755).
|
||||||
Symlink(fst.Tmp+"/etc/zshenv", "/etc/zshenv").
|
Tmpfs("/run/user/65534", 8388608, 0755).
|
||||||
Symlink(fst.Tmp+"/etc/zshrc", "/etc/zshrc").
|
Bind("/tmp/fortify.1971/tmpdir/0", "/tmp", sandbox.BindWritable).
|
||||||
Tmpfs("/run/user", 1048576).
|
Bind("/home/chronos", "/home/chronos", sandbox.BindWritable).
|
||||||
Tmpfs("/run/user/65534", 8388608).
|
Place("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||||
Bind("/tmp/fortify.1971/tmpdir/0", "/tmp", false, true).
|
Place("/etc/group", []byte("fortify:x:65534:\n")).
|
||||||
Bind("/home/chronos", "/home/chronos", false, true).
|
Tmpfs("/var/run/nscd", 8192, 0755),
|
||||||
CopyBind("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
},
|
||||||
CopyBind("/etc/group", []byte("fortify:x:65534:\n")).
|
|
||||||
Tmpfs("/var/run/nscd", 8192).
|
|
||||||
Bind("/run/wrappers/bin/fortify", "/.fortify/sbin/fortify").
|
|
||||||
Symlink("fortify", "/.fortify/sbin/init0"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"nixos permissive defaults chromium", new(stubNixOS),
|
"nixos permissive defaults chromium", new(stubNixOS),
|
||||||
&fst.Config{
|
&fst.Config{
|
||||||
ID: "org.chromium.Chromium",
|
ID: "org.chromium.Chromium",
|
||||||
Command: []string{"/run/current-system/sw/bin/zsh", "-c", "exec chromium "},
|
Args: []string{"zsh", "-c", "exec chromium "},
|
||||||
Confinement: fst.ConfinementConfig{
|
Confinement: fst.ConfinementConfig{
|
||||||
AppID: 9,
|
AppID: 9,
|
||||||
Groups: []string{"video"},
|
Groups: []string{"video"},
|
||||||
@ -254,141 +249,136 @@ var testCasesPd = []sealTestCase{
|
|||||||
}).
|
}).
|
||||||
UpdatePerm("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", acl.Read, acl.Write).
|
UpdatePerm("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", acl.Read, acl.Write).
|
||||||
UpdatePerm("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", acl.Read, acl.Write),
|
UpdatePerm("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", acl.Read, acl.Write),
|
||||||
(&bwrap.Config{
|
&sandbox.Params{
|
||||||
Net: true,
|
Flags: sandbox.FAllowNet | sandbox.FAllowUserns | sandbox.FAllowTTY,
|
||||||
UserNS: true,
|
Dir: "/home/chronos",
|
||||||
Chdir: "/home/chronos",
|
Path: "/run/current-system/sw/bin/zsh",
|
||||||
Clearenv: true,
|
Args: []string{"zsh", "-c", "exec chromium "},
|
||||||
Syscall: new(bwrap.SyscallPolicy),
|
Env: []string{
|
||||||
SetEnv: map[string]string{
|
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/65534/bus",
|
||||||
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/65534/bus",
|
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket",
|
||||||
"DBUS_SYSTEM_BUS_ADDRESS": "unix:path=/run/dbus/system_bus_socket",
|
"HOME=/home/chronos",
|
||||||
"HOME": "/home/chronos",
|
"PULSE_COOKIE=" + fst.Tmp + "/pulse-cookie",
|
||||||
"PULSE_COOKIE": fst.Tmp + "/pulse-cookie",
|
"PULSE_SERVER=unix:/run/user/65534/pulse/native",
|
||||||
"PULSE_SERVER": "unix:/run/user/65534/pulse/native",
|
"TERM=xterm-256color",
|
||||||
"SHELL": "/run/current-system/sw/bin/zsh",
|
"USER=chronos",
|
||||||
"TERM": "xterm-256color",
|
"WAYLAND_DISPLAY=wayland-0",
|
||||||
"USER": "chronos",
|
"XDG_RUNTIME_DIR=/run/user/65534",
|
||||||
"WAYLAND_DISPLAY": "wayland-0",
|
"XDG_SESSION_CLASS=user",
|
||||||
"XDG_RUNTIME_DIR": "/run/user/65534",
|
"XDG_SESSION_TYPE=tty",
|
||||||
"XDG_SESSION_CLASS": "user",
|
|
||||||
"XDG_SESSION_TYPE": "tty",
|
|
||||||
},
|
},
|
||||||
Chmod: make(bwrap.ChmodConfig),
|
Ops: new(sandbox.Ops).
|
||||||
DieWithParent: true,
|
Proc("/proc").
|
||||||
AsInit: true,
|
Tmpfs(fst.Tmp, 4096, 0755).
|
||||||
}).SetUID(65534).SetGID(65534).
|
Dev("/dev").Mqueue("/dev/mqueue").
|
||||||
Procfs("/proc").
|
Bind("/bin", "/bin", sandbox.BindWritable).
|
||||||
Tmpfs(fst.Tmp, 4096).
|
Bind("/boot", "/boot", sandbox.BindWritable).
|
||||||
DevTmpfs("/dev").Mqueue("/dev/mqueue").
|
Bind("/home", "/home", sandbox.BindWritable).
|
||||||
Bind("/bin", "/bin", false, true).
|
Bind("/lib", "/lib", sandbox.BindWritable).
|
||||||
Bind("/boot", "/boot", false, true).
|
Bind("/lib64", "/lib64", sandbox.BindWritable).
|
||||||
Bind("/home", "/home", false, true).
|
Bind("/nix", "/nix", sandbox.BindWritable).
|
||||||
Bind("/lib", "/lib", false, true).
|
Bind("/root", "/root", sandbox.BindWritable).
|
||||||
Bind("/lib64", "/lib64", false, true).
|
Bind("/run", "/run", sandbox.BindWritable).
|
||||||
Bind("/nix", "/nix", false, true).
|
Bind("/srv", "/srv", sandbox.BindWritable).
|
||||||
Bind("/root", "/root", false, true).
|
Bind("/sys", "/sys", sandbox.BindWritable).
|
||||||
Bind("/run", "/run", false, true).
|
Bind("/usr", "/usr", sandbox.BindWritable).
|
||||||
Bind("/srv", "/srv", false, true).
|
Bind("/var", "/var", sandbox.BindWritable).
|
||||||
Bind("/sys", "/sys", false, true).
|
Bind("/dev/dri", "/dev/dri", sandbox.BindWritable|sandbox.BindDevice|sandbox.BindOptional).
|
||||||
Bind("/usr", "/usr", false, true).
|
Bind("/dev/kvm", "/dev/kvm", sandbox.BindWritable|sandbox.BindDevice|sandbox.BindOptional).
|
||||||
Bind("/var", "/var", false, true).
|
Tmpfs("/run/user/1971", 8192, 0755).
|
||||||
Bind("/dev/dri", "/dev/dri", true, true, true).
|
Tmpfs("/run/dbus", 8192, 0755).
|
||||||
Bind("/dev/kvm", "/dev/kvm", true, true, true).
|
Bind("/etc", fst.Tmp+"/etc", 0).
|
||||||
Tmpfs("/run/user/1971", 8192).
|
Mkdir("/etc", 0700).
|
||||||
Tmpfs("/run/dbus", 8192).
|
Link(fst.Tmp+"/etc/alsa", "/etc/alsa").
|
||||||
Bind("/etc", fst.Tmp+"/etc").
|
Link(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
|
||||||
Symlink(fst.Tmp+"/etc/alsa", "/etc/alsa").
|
Link(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
|
||||||
Symlink(fst.Tmp+"/etc/bashrc", "/etc/bashrc").
|
Link(fst.Tmp+"/etc/dbus-1", "/etc/dbus-1").
|
||||||
Symlink(fst.Tmp+"/etc/binfmt.d", "/etc/binfmt.d").
|
Link(fst.Tmp+"/etc/default", "/etc/default").
|
||||||
Symlink(fst.Tmp+"/etc/dbus-1", "/etc/dbus-1").
|
Link(fst.Tmp+"/etc/ethertypes", "/etc/ethertypes").
|
||||||
Symlink(fst.Tmp+"/etc/default", "/etc/default").
|
Link(fst.Tmp+"/etc/fonts", "/etc/fonts").
|
||||||
Symlink(fst.Tmp+"/etc/ethertypes", "/etc/ethertypes").
|
Link(fst.Tmp+"/etc/fstab", "/etc/fstab").
|
||||||
Symlink(fst.Tmp+"/etc/fonts", "/etc/fonts").
|
Link(fst.Tmp+"/etc/fuse.conf", "/etc/fuse.conf").
|
||||||
Symlink(fst.Tmp+"/etc/fstab", "/etc/fstab").
|
Link(fst.Tmp+"/etc/host.conf", "/etc/host.conf").
|
||||||
Symlink(fst.Tmp+"/etc/fuse.conf", "/etc/fuse.conf").
|
Link(fst.Tmp+"/etc/hostid", "/etc/hostid").
|
||||||
Symlink(fst.Tmp+"/etc/host.conf", "/etc/host.conf").
|
Link(fst.Tmp+"/etc/hostname", "/etc/hostname").
|
||||||
Symlink(fst.Tmp+"/etc/hostid", "/etc/hostid").
|
Link(fst.Tmp+"/etc/hostname.CHECKSUM", "/etc/hostname.CHECKSUM").
|
||||||
Symlink(fst.Tmp+"/etc/hostname", "/etc/hostname").
|
Link(fst.Tmp+"/etc/hosts", "/etc/hosts").
|
||||||
Symlink(fst.Tmp+"/etc/hostname.CHECKSUM", "/etc/hostname.CHECKSUM").
|
Link(fst.Tmp+"/etc/inputrc", "/etc/inputrc").
|
||||||
Symlink(fst.Tmp+"/etc/hosts", "/etc/hosts").
|
Link(fst.Tmp+"/etc/ipsec.d", "/etc/ipsec.d").
|
||||||
Symlink(fst.Tmp+"/etc/inputrc", "/etc/inputrc").
|
Link(fst.Tmp+"/etc/issue", "/etc/issue").
|
||||||
Symlink(fst.Tmp+"/etc/ipsec.d", "/etc/ipsec.d").
|
Link(fst.Tmp+"/etc/kbd", "/etc/kbd").
|
||||||
Symlink(fst.Tmp+"/etc/issue", "/etc/issue").
|
Link(fst.Tmp+"/etc/libblockdev", "/etc/libblockdev").
|
||||||
Symlink(fst.Tmp+"/etc/kbd", "/etc/kbd").
|
Link(fst.Tmp+"/etc/locale.conf", "/etc/locale.conf").
|
||||||
Symlink(fst.Tmp+"/etc/libblockdev", "/etc/libblockdev").
|
Link(fst.Tmp+"/etc/localtime", "/etc/localtime").
|
||||||
Symlink(fst.Tmp+"/etc/locale.conf", "/etc/locale.conf").
|
Link(fst.Tmp+"/etc/login.defs", "/etc/login.defs").
|
||||||
Symlink(fst.Tmp+"/etc/localtime", "/etc/localtime").
|
Link(fst.Tmp+"/etc/lsb-release", "/etc/lsb-release").
|
||||||
Symlink(fst.Tmp+"/etc/login.defs", "/etc/login.defs").
|
Link(fst.Tmp+"/etc/lvm", "/etc/lvm").
|
||||||
Symlink(fst.Tmp+"/etc/lsb-release", "/etc/lsb-release").
|
Link(fst.Tmp+"/etc/machine-id", "/etc/machine-id").
|
||||||
Symlink(fst.Tmp+"/etc/lvm", "/etc/lvm").
|
Link(fst.Tmp+"/etc/man_db.conf", "/etc/man_db.conf").
|
||||||
Symlink(fst.Tmp+"/etc/machine-id", "/etc/machine-id").
|
Link(fst.Tmp+"/etc/modprobe.d", "/etc/modprobe.d").
|
||||||
Symlink(fst.Tmp+"/etc/man_db.conf", "/etc/man_db.conf").
|
Link(fst.Tmp+"/etc/modules-load.d", "/etc/modules-load.d").
|
||||||
Symlink(fst.Tmp+"/etc/modprobe.d", "/etc/modprobe.d").
|
Link("/proc/mounts", "/etc/mtab").
|
||||||
Symlink(fst.Tmp+"/etc/modules-load.d", "/etc/modules-load.d").
|
Link(fst.Tmp+"/etc/nanorc", "/etc/nanorc").
|
||||||
Symlink("/proc/mounts", "/etc/mtab").
|
Link(fst.Tmp+"/etc/netgroup", "/etc/netgroup").
|
||||||
Symlink(fst.Tmp+"/etc/nanorc", "/etc/nanorc").
|
Link(fst.Tmp+"/etc/NetworkManager", "/etc/NetworkManager").
|
||||||
Symlink(fst.Tmp+"/etc/netgroup", "/etc/netgroup").
|
Link(fst.Tmp+"/etc/nix", "/etc/nix").
|
||||||
Symlink(fst.Tmp+"/etc/NetworkManager", "/etc/NetworkManager").
|
Link(fst.Tmp+"/etc/nixos", "/etc/nixos").
|
||||||
Symlink(fst.Tmp+"/etc/nix", "/etc/nix").
|
Link(fst.Tmp+"/etc/NIXOS", "/etc/NIXOS").
|
||||||
Symlink(fst.Tmp+"/etc/nixos", "/etc/nixos").
|
Link(fst.Tmp+"/etc/nscd.conf", "/etc/nscd.conf").
|
||||||
Symlink(fst.Tmp+"/etc/NIXOS", "/etc/NIXOS").
|
Link(fst.Tmp+"/etc/nsswitch.conf", "/etc/nsswitch.conf").
|
||||||
Symlink(fst.Tmp+"/etc/nscd.conf", "/etc/nscd.conf").
|
Link(fst.Tmp+"/etc/opensnitchd", "/etc/opensnitchd").
|
||||||
Symlink(fst.Tmp+"/etc/nsswitch.conf", "/etc/nsswitch.conf").
|
Link(fst.Tmp+"/etc/os-release", "/etc/os-release").
|
||||||
Symlink(fst.Tmp+"/etc/opensnitchd", "/etc/opensnitchd").
|
Link(fst.Tmp+"/etc/pam", "/etc/pam").
|
||||||
Symlink(fst.Tmp+"/etc/os-release", "/etc/os-release").
|
Link(fst.Tmp+"/etc/pam.d", "/etc/pam.d").
|
||||||
Symlink(fst.Tmp+"/etc/pam", "/etc/pam").
|
Link(fst.Tmp+"/etc/pipewire", "/etc/pipewire").
|
||||||
Symlink(fst.Tmp+"/etc/pam.d", "/etc/pam.d").
|
Link(fst.Tmp+"/etc/pki", "/etc/pki").
|
||||||
Symlink(fst.Tmp+"/etc/pipewire", "/etc/pipewire").
|
Link(fst.Tmp+"/etc/polkit-1", "/etc/polkit-1").
|
||||||
Symlink(fst.Tmp+"/etc/pki", "/etc/pki").
|
Link(fst.Tmp+"/etc/profile", "/etc/profile").
|
||||||
Symlink(fst.Tmp+"/etc/polkit-1", "/etc/polkit-1").
|
Link(fst.Tmp+"/etc/protocols", "/etc/protocols").
|
||||||
Symlink(fst.Tmp+"/etc/profile", "/etc/profile").
|
Link(fst.Tmp+"/etc/qemu", "/etc/qemu").
|
||||||
Symlink(fst.Tmp+"/etc/protocols", "/etc/protocols").
|
Link(fst.Tmp+"/etc/resolv.conf", "/etc/resolv.conf").
|
||||||
Symlink(fst.Tmp+"/etc/qemu", "/etc/qemu").
|
Link(fst.Tmp+"/etc/resolvconf.conf", "/etc/resolvconf.conf").
|
||||||
Symlink(fst.Tmp+"/etc/resolv.conf", "/etc/resolv.conf").
|
Link(fst.Tmp+"/etc/rpc", "/etc/rpc").
|
||||||
Symlink(fst.Tmp+"/etc/resolvconf.conf", "/etc/resolvconf.conf").
|
Link(fst.Tmp+"/etc/samba", "/etc/samba").
|
||||||
Symlink(fst.Tmp+"/etc/rpc", "/etc/rpc").
|
Link(fst.Tmp+"/etc/sddm.conf", "/etc/sddm.conf").
|
||||||
Symlink(fst.Tmp+"/etc/samba", "/etc/samba").
|
Link(fst.Tmp+"/etc/secureboot", "/etc/secureboot").
|
||||||
Symlink(fst.Tmp+"/etc/sddm.conf", "/etc/sddm.conf").
|
Link(fst.Tmp+"/etc/services", "/etc/services").
|
||||||
Symlink(fst.Tmp+"/etc/secureboot", "/etc/secureboot").
|
Link(fst.Tmp+"/etc/set-environment", "/etc/set-environment").
|
||||||
Symlink(fst.Tmp+"/etc/services", "/etc/services").
|
Link(fst.Tmp+"/etc/shadow", "/etc/shadow").
|
||||||
Symlink(fst.Tmp+"/etc/set-environment", "/etc/set-environment").
|
Link(fst.Tmp+"/etc/shells", "/etc/shells").
|
||||||
Symlink(fst.Tmp+"/etc/shadow", "/etc/shadow").
|
Link(fst.Tmp+"/etc/ssh", "/etc/ssh").
|
||||||
Symlink(fst.Tmp+"/etc/shells", "/etc/shells").
|
Link(fst.Tmp+"/etc/ssl", "/etc/ssl").
|
||||||
Symlink(fst.Tmp+"/etc/ssh", "/etc/ssh").
|
Link(fst.Tmp+"/etc/static", "/etc/static").
|
||||||
Symlink(fst.Tmp+"/etc/ssl", "/etc/ssl").
|
Link(fst.Tmp+"/etc/subgid", "/etc/subgid").
|
||||||
Symlink(fst.Tmp+"/etc/static", "/etc/static").
|
Link(fst.Tmp+"/etc/subuid", "/etc/subuid").
|
||||||
Symlink(fst.Tmp+"/etc/subgid", "/etc/subgid").
|
Link(fst.Tmp+"/etc/sudoers", "/etc/sudoers").
|
||||||
Symlink(fst.Tmp+"/etc/subuid", "/etc/subuid").
|
Link(fst.Tmp+"/etc/sysctl.d", "/etc/sysctl.d").
|
||||||
Symlink(fst.Tmp+"/etc/sudoers", "/etc/sudoers").
|
Link(fst.Tmp+"/etc/systemd", "/etc/systemd").
|
||||||
Symlink(fst.Tmp+"/etc/sysctl.d", "/etc/sysctl.d").
|
Link(fst.Tmp+"/etc/terminfo", "/etc/terminfo").
|
||||||
Symlink(fst.Tmp+"/etc/systemd", "/etc/systemd").
|
Link(fst.Tmp+"/etc/tmpfiles.d", "/etc/tmpfiles.d").
|
||||||
Symlink(fst.Tmp+"/etc/terminfo", "/etc/terminfo").
|
Link(fst.Tmp+"/etc/udev", "/etc/udev").
|
||||||
Symlink(fst.Tmp+"/etc/tmpfiles.d", "/etc/tmpfiles.d").
|
Link(fst.Tmp+"/etc/udisks2", "/etc/udisks2").
|
||||||
Symlink(fst.Tmp+"/etc/udev", "/etc/udev").
|
Link(fst.Tmp+"/etc/UPower", "/etc/UPower").
|
||||||
Symlink(fst.Tmp+"/etc/udisks2", "/etc/udisks2").
|
Link(fst.Tmp+"/etc/vconsole.conf", "/etc/vconsole.conf").
|
||||||
Symlink(fst.Tmp+"/etc/UPower", "/etc/UPower").
|
Link(fst.Tmp+"/etc/X11", "/etc/X11").
|
||||||
Symlink(fst.Tmp+"/etc/vconsole.conf", "/etc/vconsole.conf").
|
Link(fst.Tmp+"/etc/zfs", "/etc/zfs").
|
||||||
Symlink(fst.Tmp+"/etc/X11", "/etc/X11").
|
Link(fst.Tmp+"/etc/zinputrc", "/etc/zinputrc").
|
||||||
Symlink(fst.Tmp+"/etc/zfs", "/etc/zfs").
|
Link(fst.Tmp+"/etc/zoneinfo", "/etc/zoneinfo").
|
||||||
Symlink(fst.Tmp+"/etc/zinputrc", "/etc/zinputrc").
|
Link(fst.Tmp+"/etc/zprofile", "/etc/zprofile").
|
||||||
Symlink(fst.Tmp+"/etc/zoneinfo", "/etc/zoneinfo").
|
Link(fst.Tmp+"/etc/zshenv", "/etc/zshenv").
|
||||||
Symlink(fst.Tmp+"/etc/zprofile", "/etc/zprofile").
|
Link(fst.Tmp+"/etc/zshrc", "/etc/zshrc").
|
||||||
Symlink(fst.Tmp+"/etc/zshenv", "/etc/zshenv").
|
Tmpfs("/run/user", 4096, 0755).
|
||||||
Symlink(fst.Tmp+"/etc/zshrc", "/etc/zshrc").
|
Tmpfs("/run/user/65534", 8388608, 0755).
|
||||||
Tmpfs("/run/user", 1048576).
|
Bind("/tmp/fortify.1971/tmpdir/9", "/tmp", sandbox.BindWritable).
|
||||||
Tmpfs("/run/user/65534", 8388608).
|
Bind("/home/chronos", "/home/chronos", sandbox.BindWritable).
|
||||||
Bind("/tmp/fortify.1971/tmpdir/9", "/tmp", false, true).
|
Place("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||||
Bind("/home/chronos", "/home/chronos", false, true).
|
Place("/etc/group", []byte("fortify:x:65534:\n")).
|
||||||
CopyBind("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
Bind("/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/65534/wayland-0", 0).
|
||||||
CopyBind("/etc/group", []byte("fortify:x:65534:\n")).
|
Bind("/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse", "/run/user/65534/pulse/native", 0).
|
||||||
Bind("/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/65534/wayland-0").
|
Place(fst.Tmp+"/pulse-cookie", nil).
|
||||||
Bind("/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse", "/run/user/65534/pulse/native").
|
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", "/run/user/65534/bus", 0).
|
||||||
CopyBind(fst.Tmp+"/pulse-cookie", nil).
|
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", "/run/dbus/system_bus_socket", 0).
|
||||||
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", "/run/user/65534/bus").
|
Tmpfs("/var/run/nscd", 8192, 0755),
|
||||||
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", "/run/dbus/system_bus_socket").
|
},
|
||||||
Tmpfs("/var/run/nscd", 8192).
|
|
||||||
Bind("/run/wrappers/bin/fortify", "/.fortify/sbin/fortify").
|
|
||||||
Symlink("fortify", "/.fortify/sbin/init0"),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -55,10 +55,8 @@ func (s *stubNixOS) LookPath(file string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch file {
|
switch file {
|
||||||
case "sudo":
|
case "zsh":
|
||||||
return "/run/wrappers/bin/sudo", nil
|
return "/run/current-system/sw/bin/zsh", nil
|
||||||
case "machinectl":
|
|
||||||
return "/home/ophestra/.nix-profile/bin/machinectl", nil
|
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("attempted to look up unexpected executable %q", file))
|
panic(fmt.Sprintf("attempted to look up unexpected executable %q", file))
|
||||||
}
|
}
|
||||||
|
@ -8,19 +8,19 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal/app"
|
"git.gensokyo.uk/security/fortify/internal/app"
|
||||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||||
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sealTestCase struct {
|
type sealTestCase struct {
|
||||||
name string
|
name string
|
||||||
os sys.State
|
os sys.State
|
||||||
config *fst.Config
|
config *fst.Config
|
||||||
id fst.ID
|
id fst.ID
|
||||||
wantSys *system.I
|
wantSys *system.I
|
||||||
wantBwrap *bwrap.Config
|
wantContainer *sandbox.Params
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApp(t *testing.T) {
|
func TestApp(t *testing.T) {
|
||||||
@ -30,15 +30,15 @@ func TestApp(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
a := app.NewWithID(tc.id, tc.os)
|
a := app.NewWithID(tc.id, tc.os)
|
||||||
var (
|
var (
|
||||||
gotSys *system.I
|
gotSys *system.I
|
||||||
gotBwrap *bwrap.Config
|
gotContainer *sandbox.Params
|
||||||
)
|
)
|
||||||
if !t.Run("seal", func(t *testing.T) {
|
if !t.Run("seal", func(t *testing.T) {
|
||||||
if sa, err := a.Seal(tc.config); err != nil {
|
if sa, err := a.Seal(tc.config); err != nil {
|
||||||
t.Errorf("Seal: error = %v", err)
|
t.Errorf("Seal: error = %v", err)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
gotSys, gotBwrap = app.AppSystemBwrap(a, sa)
|
gotSys, gotContainer = app.AppIParams(a, sa)
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
return
|
return
|
||||||
@ -51,10 +51,10 @@ func TestApp(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("compare bwrap", func(t *testing.T) {
|
t.Run("compare params", func(t *testing.T) {
|
||||||
if !reflect.DeepEqual(gotBwrap, tc.wantBwrap) {
|
if !reflect.DeepEqual(gotContainer, tc.wantContainer) {
|
||||||
t.Errorf("seal: bwrap =\n%s\n, want\n%s",
|
t.Errorf("seal: params =\n%s\n, want\n%s",
|
||||||
mustMarshal(gotBwrap), mustMarshal(tc.wantBwrap))
|
mustMarshal(gotContainer), mustMarshal(tc.wantContainer))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -2,8 +2,8 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||||
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ func NewWithID(id fst.ID, os sys.State) fst.App {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func AppSystemBwrap(a fst.App, sa fst.SealedApp) (*system.I, *bwrap.Config) {
|
func AppIParams(a fst.App, sa fst.SealedApp) (*system.I, *sandbox.Params) {
|
||||||
v := a.(*app)
|
v := a.(*app)
|
||||||
seal := sa.(*outcome)
|
seal := sa.(*outcome)
|
||||||
if v.outcome != seal || v.id != seal.id {
|
if v.outcome != seal || v.id != seal.id {
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package init0
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// used by the parent process
|
|
||||||
|
|
||||||
// TryArgv0 calls [Main] if the last element of argv0 is "init0".
|
|
||||||
func TryArgv0() {
|
|
||||||
if len(os.Args) > 0 && path.Base(os.Args[0]) == "init0" {
|
|
||||||
Main()
|
|
||||||
internal.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,165 +0,0 @@
|
|||||||
package init0
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
|
||||||
"git.gensokyo.uk/security/fortify/sandbox"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// time to wait for linger processes after death of initial process
|
|
||||||
residualProcessTimeout = 5 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
// everything beyond this point runs within pid namespace
|
|
||||||
// proceed with caution!
|
|
||||||
|
|
||||||
func Main() {
|
|
||||||
// sharing stdout with shim
|
|
||||||
// USE WITH CAUTION
|
|
||||||
fmsg.Prepare("init0")
|
|
||||||
|
|
||||||
// setting this prevents ptrace
|
|
||||||
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
|
||||||
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if os.Getpid() != 1 {
|
|
||||||
log.Fatal("this process must run as pid 1")
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive setup payload
|
|
||||||
var (
|
|
||||||
payload Payload
|
|
||||||
closeSetup func() error
|
|
||||||
)
|
|
||||||
if f, err := sandbox.Receive(Env, &payload, nil); err != nil {
|
|
||||||
if errors.Is(err, sandbox.ErrInvalid) {
|
|
||||||
log.Fatal("invalid config descriptor")
|
|
||||||
}
|
|
||||||
if errors.Is(err, sandbox.ErrNotSet) {
|
|
||||||
log.Fatal("FORTIFY_INIT not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Fatalf("cannot decode init setup payload: %v", err)
|
|
||||||
} else {
|
|
||||||
fmsg.Store(payload.Verbose)
|
|
||||||
closeSetup = f
|
|
||||||
|
|
||||||
// child does not need to see this
|
|
||||||
if err = os.Unsetenv(Env); err != nil {
|
|
||||||
log.Printf("cannot unset %s: %v", Env, err)
|
|
||||||
// not fatal
|
|
||||||
} else {
|
|
||||||
fmsg.Verbose("received configuration")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// die with parent
|
|
||||||
if err := sandbox.SetPdeathsig(syscall.SIGKILL); err != nil {
|
|
||||||
log.Fatalf("prctl(PR_SET_PDEATHSIG, SIGKILL): %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command(payload.Argv0)
|
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
|
||||||
cmd.Args = payload.Argv
|
|
||||||
cmd.Env = os.Environ()
|
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
log.Fatalf("cannot start %q: %v", payload.Argv0, err)
|
|
||||||
}
|
|
||||||
fmsg.Suspend()
|
|
||||||
|
|
||||||
// close setup pipe as setup is now complete
|
|
||||||
if err := closeSetup(); err != nil {
|
|
||||||
log.Println("cannot close setup pipe:", err)
|
|
||||||
// not fatal
|
|
||||||
}
|
|
||||||
|
|
||||||
sig := make(chan os.Signal, 2)
|
|
||||||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
|
|
||||||
type winfo struct {
|
|
||||||
wpid int
|
|
||||||
wstatus syscall.WaitStatus
|
|
||||||
}
|
|
||||||
info := make(chan winfo, 1)
|
|
||||||
done := make(chan struct{})
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
wpid = -2
|
|
||||||
wstatus syscall.WaitStatus
|
|
||||||
)
|
|
||||||
|
|
||||||
// keep going until no child process is left
|
|
||||||
for wpid != -1 {
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if wpid != -2 {
|
|
||||||
info <- winfo{wpid, wstatus}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = syscall.EINTR
|
|
||||||
for errors.Is(err, syscall.EINTR) {
|
|
||||||
wpid, err = syscall.Wait4(-1, &wstatus, 0, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !errors.Is(err, syscall.ECHILD) {
|
|
||||||
log.Println("unexpected wait4 response:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// closed after residualProcessTimeout has elapsed after initial process death
|
|
||||||
timeout := make(chan struct{})
|
|
||||||
|
|
||||||
r := 2
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case s := <-sig:
|
|
||||||
if fmsg.Resume() {
|
|
||||||
fmsg.Verbosef("terminating on %s after process start", s.String())
|
|
||||||
} else {
|
|
||||||
fmsg.Verbosef("terminating on %s", s.String())
|
|
||||||
}
|
|
||||||
internal.Exit(0)
|
|
||||||
case w := <-info:
|
|
||||||
if w.wpid == cmd.Process.Pid {
|
|
||||||
// initial process exited, output is most likely available again
|
|
||||||
fmsg.Resume()
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case w.wstatus.Exited():
|
|
||||||
r = w.wstatus.ExitStatus()
|
|
||||||
case w.wstatus.Signaled():
|
|
||||||
r = 128 + int(w.wstatus.Signal())
|
|
||||||
default:
|
|
||||||
r = 255
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
time.Sleep(residualProcessTimeout)
|
|
||||||
close(timeout)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
case <-done:
|
|
||||||
internal.Exit(r)
|
|
||||||
case <-timeout:
|
|
||||||
log.Println("timeout exceeded waiting for lingering processes")
|
|
||||||
internal.Exit(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package init0
|
|
||||||
|
|
||||||
const Env = "FORTIFY_INIT"
|
|
||||||
|
|
||||||
type Payload struct {
|
|
||||||
// target full exec path
|
|
||||||
Argv0 string
|
|
||||||
// child full argv
|
|
||||||
Argv []string
|
|
||||||
|
|
||||||
// verbosity pass through
|
|
||||||
Verbose bool
|
|
||||||
}
|
|
@ -3,15 +3,12 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/app/shim"
|
"git.gensokyo.uk/security/fortify/internal/app/shim"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
@ -21,7 +18,7 @@ import (
|
|||||||
|
|
||||||
const shimSetupTimeout = 5 * time.Second
|
const shimSetupTimeout = 5 * time.Second
|
||||||
|
|
||||||
func (seal *outcome) Run(ctx context.Context, rs *fst.RunState) error {
|
func (seal *outcome) Run(rs *fst.RunState) error {
|
||||||
if !seal.f.CompareAndSwap(false, true) {
|
if !seal.f.CompareAndSwap(false, true) {
|
||||||
// run does much more than just starting a process; calling it twice, even if the first call fails, will result
|
// run does much more than just starting a process; calling it twice, even if the first call fails, will result
|
||||||
// in inconsistent state that is impossible to clean up; return here to limit damage and hopefully give the
|
// in inconsistent state that is impossible to clean up; return here to limit damage and hopefully give the
|
||||||
@ -37,33 +34,11 @@ func (seal *outcome) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
fmsg.Verbosef("version %s", internal.Version())
|
fmsg.Verbosef("version %s", internal.Version())
|
||||||
fmsg.Verbosef("setuid helper at %s", internal.MustFsuPath())
|
fmsg.Verbosef("setuid helper at %s", internal.MustFsuPath())
|
||||||
|
|
||||||
/*
|
|
||||||
resolve exec paths
|
|
||||||
*/
|
|
||||||
|
|
||||||
shimExec := [2]string{helper.BubblewrapName}
|
|
||||||
if len(seal.command) > 0 {
|
|
||||||
shimExec[1] = seal.command[0]
|
|
||||||
}
|
|
||||||
for i, n := range shimExec {
|
|
||||||
if len(n) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if filepath.Base(n) == n {
|
|
||||||
if s, err := exec.LookPath(n); err == nil {
|
|
||||||
shimExec[i] = s
|
|
||||||
} else {
|
|
||||||
return fmsg.WrapError(err,
|
|
||||||
fmt.Sprintf("executable file %q not found in $PATH", n))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
prepare/revert os state
|
prepare/revert os state
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if err := seal.sys.Commit(ctx); err != nil {
|
if err := seal.sys.Commit(seal.ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
store := state.NewMulti(seal.runDirPath)
|
store := state.NewMulti(seal.runDirPath)
|
||||||
@ -137,7 +112,6 @@ func (seal *outcome) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
if startTime, err := cmd.Start(
|
if startTime, err := cmd.Start(
|
||||||
seal.user.aid.String(),
|
seal.user.aid.String(),
|
||||||
seal.user.supp,
|
seal.user.supp,
|
||||||
seal.bwrapSync,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -145,7 +119,7 @@ func (seal *outcome) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
rs.Time = startTime
|
rs.Time = startTime
|
||||||
}
|
}
|
||||||
|
|
||||||
c, cancel := context.WithTimeout(ctx, shimSetupTimeout)
|
ctx, cancel := context.WithTimeout(seal.ctx, shimSetupTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -154,11 +128,9 @@ func (seal *outcome) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := cmd.Serve(c, &shim.Payload{
|
if err := cmd.Serve(ctx, &shim.Params{
|
||||||
Argv: seal.command,
|
Container: seal.container,
|
||||||
Exec: shimExec,
|
Home: seal.user.data,
|
||||||
Bwrap: seal.container,
|
|
||||||
Home: seal.user.data,
|
|
||||||
|
|
||||||
Verbose: fmsg.Load(),
|
Verbose: fmsg.Load(),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -199,18 +171,22 @@ func (seal *outcome) Run(ctx context.Context, rs *fst.RunState) error {
|
|||||||
// this is reached when a fault makes an already running shim impossible to continue execution
|
// this is reached when a fault makes an already running shim impossible to continue execution
|
||||||
// however a kill signal could not be delivered (should actually always happen like that since fsu)
|
// however a kill signal could not be delivered (should actually always happen like that since fsu)
|
||||||
// the effects of this is similar to the alternative exit path and ensures shim death
|
// the effects of this is similar to the alternative exit path and ensures shim death
|
||||||
case err := <-cmd.WaitFallback():
|
case err := <-cmd.Fallback():
|
||||||
rs.ExitCode = 255
|
rs.ExitCode = 255
|
||||||
log.Printf("cannot terminate shim on faulted setup: %v", err)
|
log.Printf("cannot terminate shim on faulted setup: %v", err)
|
||||||
|
|
||||||
// alternative exit path relying on shim behaviour on monitor process exit
|
// alternative exit path relying on shim behaviour on monitor process exit
|
||||||
case <-ctx.Done():
|
case <-seal.ctx.Done():
|
||||||
fmsg.Verbose("alternative exit path selected")
|
fmsg.Verbose("alternative exit path selected")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmsg.Resume()
|
fmsg.Resume()
|
||||||
|
if seal.sync != nil {
|
||||||
|
if err := seal.sync.Close(); err != nil {
|
||||||
|
log.Printf("cannot close wayland security context: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if seal.dbusMsg != nil {
|
if seal.dbusMsg != nil {
|
||||||
// dump dbus message buffer
|
|
||||||
seal.dbusMsg()
|
seal.dbusMsg()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,24 +2,28 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"maps"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/acl"
|
"git.gensokyo.uk/security/fortify/acl"
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||||
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
"git.gensokyo.uk/security/fortify/system"
|
"git.gensokyo.uk/security/fortify/system"
|
||||||
"git.gensokyo.uk/security/fortify/wl"
|
"git.gensokyo.uk/security/fortify/wl"
|
||||||
)
|
)
|
||||||
@ -65,19 +69,19 @@ type outcome struct {
|
|||||||
// copied from [sys.State] response
|
// copied from [sys.State] response
|
||||||
runDirPath string
|
runDirPath string
|
||||||
|
|
||||||
// passed through from [fst.Config]
|
|
||||||
command []string
|
|
||||||
|
|
||||||
// initial [fst.Config] gob stream for state data;
|
// initial [fst.Config] gob stream for state data;
|
||||||
// this is prepared ahead of time as config is mutated during seal creation
|
// this is prepared ahead of time as config is clobbered during seal creation
|
||||||
ct io.WriterTo
|
ct io.WriterTo
|
||||||
// dump dbus proxy message buffer
|
// dump dbus proxy message buffer
|
||||||
dbusMsg func()
|
dbusMsg func()
|
||||||
|
|
||||||
user fsuUser
|
user fsuUser
|
||||||
sys *system.I
|
sys *system.I
|
||||||
container *bwrap.Config
|
ctx context.Context
|
||||||
bwrapSync *os.File
|
|
||||||
|
container *sandbox.Params
|
||||||
|
env map[string]string
|
||||||
|
sync *os.File
|
||||||
|
|
||||||
f atomic.Bool
|
f atomic.Bool
|
||||||
}
|
}
|
||||||
@ -100,7 +104,17 @@ type fsuUser struct {
|
|||||||
username string
|
username string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Config) error {
|
||||||
|
if seal.ctx != nil {
|
||||||
|
panic("finalise called twice")
|
||||||
|
}
|
||||||
|
seal.ctx = ctx
|
||||||
|
|
||||||
|
shellPath := "/bin/sh"
|
||||||
|
if s, ok := sys.LookupEnv(shell); ok && path.IsAbs(s) {
|
||||||
|
shellPath = s
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// encode initial configuration for state tracking
|
// encode initial configuration for state tracking
|
||||||
ct := new(bytes.Buffer)
|
ct := new(bytes.Buffer)
|
||||||
@ -111,9 +125,6 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
seal.ct = ct
|
seal.ct = ct
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass through command slice; this value is never touched in the main process
|
|
||||||
seal.command = config.Command
|
|
||||||
|
|
||||||
// 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.Confinement.AppID < 0 || config.Confinement.AppID > 9999 {
|
||||||
return fmsg.WrapError(ErrUser,
|
return fmsg.WrapError(ErrUser,
|
||||||
@ -167,12 +178,24 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
if config.Confinement.Sandbox == nil {
|
if config.Confinement.Sandbox == nil {
|
||||||
fmsg.Verbose("sandbox configuration not supplied, PROCEED WITH CAUTION")
|
fmsg.Verbose("sandbox configuration not supplied, PROCEED WITH CAUTION")
|
||||||
|
|
||||||
|
// fsu clears the environment so resolve paths early
|
||||||
|
if !path.IsAbs(config.Path) {
|
||||||
|
if len(config.Args) > 0 {
|
||||||
|
if p, err := sys.LookPath(config.Args[0]); err != nil {
|
||||||
|
return fmsg.WrapError(err, err.Error())
|
||||||
|
} else {
|
||||||
|
config.Path = p
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.Path = shellPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
conf := &fst.SandboxConfig{
|
conf := &fst.SandboxConfig{
|
||||||
UserNS: true,
|
Userns: true,
|
||||||
Net: true,
|
Net: true,
|
||||||
Syscall: new(bwrap.SyscallPolicy),
|
Tty: true,
|
||||||
NoNewSession: true,
|
AutoEtc: true,
|
||||||
AutoEtc: true,
|
|
||||||
}
|
}
|
||||||
// bind entries in /
|
// bind entries in /
|
||||||
if d, err := sys.ReadDir("/"); err != nil {
|
if d, err := sys.ReadDir("/"); err != nil {
|
||||||
@ -198,7 +221,7 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
// hide nscd from sandbox if present
|
// hide nscd from sandbox if present
|
||||||
nscd := "/var/run/nscd"
|
nscd := "/var/run/nscd"
|
||||||
if _, err := sys.Stat(nscd); !errors.Is(err, fs.ErrNotExist) {
|
if _, err := sys.Stat(nscd); !errors.Is(err, fs.ErrNotExist) {
|
||||||
conf.Override = append(conf.Override, nscd)
|
conf.Cover = append(conf.Cover, nscd)
|
||||||
}
|
}
|
||||||
// bind GPU stuff
|
// bind GPU stuff
|
||||||
if config.Confinement.Enablements.Has(system.EX11) || config.Confinement.Enablements.Has(system.EWayland) {
|
if config.Confinement.Enablements.Has(system.EX11) || config.Confinement.Enablements.Has(system.EWayland) {
|
||||||
@ -210,17 +233,29 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
config.Confinement.Sandbox = conf
|
config.Confinement.Sandbox = conf
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapuid *stringPair[int]
|
var mapuid, mapgid *stringPair[int]
|
||||||
{
|
{
|
||||||
var uid int
|
var uid, gid int
|
||||||
var err error
|
var err error
|
||||||
seal.container, err = config.Confinement.Sandbox.Bwrap(sys, &uid)
|
seal.container, seal.env, err = config.Confinement.Sandbox.ToContainer(sys, &uid, &gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmsg.WrapErrorSuffix(err,
|
||||||
|
"cannot initialise container configuration:")
|
||||||
}
|
}
|
||||||
|
if !path.IsAbs(config.Path) {
|
||||||
|
return fmsg.WrapError(syscall.EINVAL,
|
||||||
|
"invalid program path")
|
||||||
|
}
|
||||||
|
if len(config.Args) == 0 {
|
||||||
|
config.Args = []string{config.Path}
|
||||||
|
}
|
||||||
|
seal.container.Path = config.Path
|
||||||
|
seal.container.Args = config.Args
|
||||||
|
|
||||||
mapuid = newInt(uid)
|
mapuid = newInt(uid)
|
||||||
if seal.container.SetEnv == nil {
|
mapgid = newInt(gid)
|
||||||
seal.container.SetEnv = make(map[string]string)
|
if seal.env == nil {
|
||||||
|
seal.env = make(map[string]string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,35 +290,27 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
|
|
||||||
// inner XDG_RUNTIME_DIR default formatting of `/run/user/%d` as post-fsu user
|
// inner XDG_RUNTIME_DIR default formatting of `/run/user/%d` as post-fsu user
|
||||||
innerRuntimeDir := path.Join("/run/user", mapuid.String())
|
innerRuntimeDir := path.Join("/run/user", mapuid.String())
|
||||||
seal.container.Tmpfs("/run/user", 1*1024*1024)
|
seal.container.Tmpfs("/run/user", 1<<12, 0755)
|
||||||
seal.container.Tmpfs(innerRuntimeDir, 8*1024*1024)
|
seal.container.Tmpfs(innerRuntimeDir, 1<<23, 0755)
|
||||||
seal.container.SetEnv[xdgRuntimeDir] = innerRuntimeDir
|
seal.env[xdgRuntimeDir] = innerRuntimeDir
|
||||||
seal.container.SetEnv[xdgSessionClass] = "user"
|
seal.env[xdgSessionClass] = "user"
|
||||||
seal.container.SetEnv[xdgSessionType] = "tty"
|
seal.env[xdgSessionType] = "tty"
|
||||||
|
|
||||||
// outer path for inner /tmp
|
// outer path for inner /tmp
|
||||||
{
|
{
|
||||||
tmpdir := path.Join(sc.SharePath, "tmpdir")
|
tmpdir := path.Join(sc.SharePath, "tmpdir")
|
||||||
seal.sys.Ensure(tmpdir, 0700)
|
seal.sys.Ensure(tmpdir, 0700)
|
||||||
seal.sys.UpdatePermType(system.User, tmpdir, acl.Execute)
|
seal.sys.UpdatePermType(system.User, tmpdir, acl.Execute)
|
||||||
tmpdirProc := path.Join(tmpdir, seal.user.aid.String())
|
tmpdirInst := path.Join(tmpdir, seal.user.aid.String())
|
||||||
seal.sys.Ensure(tmpdirProc, 01700)
|
seal.sys.Ensure(tmpdirInst, 01700)
|
||||||
seal.sys.UpdatePermType(system.User, tmpdirProc, acl.Read, acl.Write, acl.Execute)
|
seal.sys.UpdatePermType(system.User, tmpdirInst, acl.Read, acl.Write, acl.Execute)
|
||||||
seal.container.Bind(tmpdirProc, "/tmp", false, true)
|
seal.container.Bind(tmpdirInst, "/tmp", sandbox.BindWritable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Passwd database
|
Passwd database
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// look up shell
|
|
||||||
sh := "/bin/sh"
|
|
||||||
if s, ok := sys.LookupEnv(shell); ok {
|
|
||||||
seal.container.SetEnv[shell] = s
|
|
||||||
sh = s
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind home directory
|
|
||||||
homeDir := "/var/empty"
|
homeDir := "/var/empty"
|
||||||
if seal.user.home != "" {
|
if seal.user.home != "" {
|
||||||
homeDir = seal.user.home
|
homeDir = seal.user.home
|
||||||
@ -292,27 +319,25 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
if seal.user.username != "" {
|
if seal.user.username != "" {
|
||||||
username = seal.user.username
|
username = seal.user.username
|
||||||
}
|
}
|
||||||
seal.container.Bind(seal.user.data, homeDir, false, true)
|
seal.container.Bind(seal.user.data, homeDir, sandbox.BindWritable)
|
||||||
seal.container.Chdir = homeDir
|
seal.container.Dir = homeDir
|
||||||
seal.container.SetEnv["HOME"] = homeDir
|
seal.env["HOME"] = homeDir
|
||||||
seal.container.SetEnv["USER"] = username
|
seal.env["USER"] = username
|
||||||
|
|
||||||
// generate /etc/passwd and /etc/group
|
seal.container.Place("/etc/passwd",
|
||||||
seal.container.CopyBind("/etc/passwd",
|
[]byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+shellPath+"\n"))
|
||||||
[]byte(username+":x:"+mapuid.String()+":"+mapuid.String()+":Fortify:"+homeDir+":"+sh+"\n"))
|
seal.container.Place("/etc/group",
|
||||||
seal.container.CopyBind("/etc/group",
|
[]byte("fortify:x:"+mapgid.String()+":\n"))
|
||||||
[]byte("fortify:x:"+mapuid.String()+":\n"))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Display servers
|
Display servers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// pass $TERM to launcher
|
// pass $TERM for proper terminal I/O in shell
|
||||||
if t, ok := sys.LookupEnv(term); ok {
|
if t, ok := sys.LookupEnv(term); ok {
|
||||||
seal.container.SetEnv[term] = t
|
seal.env[term] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up wayland
|
|
||||||
if config.Confinement.Enablements.Has(system.EWayland) {
|
if config.Confinement.Enablements.Has(system.EWayland) {
|
||||||
// outer wayland socket (usually `/run/user/%d/wayland-%d`)
|
// outer wayland socket (usually `/run/user/%d/wayland-%d`)
|
||||||
var socketPath string
|
var socketPath string
|
||||||
@ -326,7 +351,7 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
innerPath := path.Join(innerRuntimeDir, wl.FallbackName)
|
innerPath := path.Join(innerRuntimeDir, wl.FallbackName)
|
||||||
seal.container.SetEnv[wl.WaylandDisplay] = wl.FallbackName
|
seal.env[wl.WaylandDisplay] = wl.FallbackName
|
||||||
|
|
||||||
if !config.Confinement.Sandbox.DirectWayland { // set up security-context-v1
|
if !config.Confinement.Sandbox.DirectWayland { // set up security-context-v1
|
||||||
socketDir := path.Join(sc.SharePath, "wayland")
|
socketDir := path.Join(sc.SharePath, "wayland")
|
||||||
@ -337,25 +362,23 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
// use instance ID in case app id is not set
|
// use instance ID in case app id is not set
|
||||||
appID = "uk.gensokyo.fortify." + seal.id.String()
|
appID = "uk.gensokyo.fortify." + seal.id.String()
|
||||||
}
|
}
|
||||||
seal.sys.Wayland(&seal.bwrapSync, outerPath, socketPath, appID, seal.id.String())
|
seal.sys.Wayland(&seal.sync, outerPath, socketPath, appID, seal.id.String())
|
||||||
seal.container.Bind(outerPath, innerPath)
|
seal.container.Bind(outerPath, innerPath, 0)
|
||||||
} else { // bind mount wayland socket (insecure)
|
} else { // bind mount wayland socket (insecure)
|
||||||
fmsg.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
fmsg.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
||||||
seal.container.Bind(socketPath, innerPath)
|
seal.container.Bind(socketPath, innerPath, 0)
|
||||||
seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
|
seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up X11
|
|
||||||
if config.Confinement.Enablements.Has(system.EX11) {
|
if config.Confinement.Enablements.Has(system.EX11) {
|
||||||
// discover X11 and grant user permission via the `ChangeHosts` command
|
|
||||||
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")
|
||||||
} else {
|
} else {
|
||||||
seal.sys.ChangeHosts("#" + seal.user.uid.String())
|
seal.sys.ChangeHosts("#" + seal.user.uid.String())
|
||||||
seal.container.SetEnv[display] = d
|
seal.env[display] = d
|
||||||
seal.container.Bind("/tmp/.X11-unix", "/tmp/.X11-unix")
|
seal.container.Bind("/tmp/.X11-unix", "/tmp/.X11-unix", 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,8 +419,8 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
innerPulseRuntimeDir := path.Join(sharePathLocal, "pulse")
|
innerPulseRuntimeDir := path.Join(sharePathLocal, "pulse")
|
||||||
innerPulseSocket := path.Join(innerRuntimeDir, "pulse", "native")
|
innerPulseSocket := path.Join(innerRuntimeDir, "pulse", "native")
|
||||||
seal.sys.Link(pulseSocket, innerPulseRuntimeDir)
|
seal.sys.Link(pulseSocket, innerPulseRuntimeDir)
|
||||||
seal.container.Bind(innerPulseRuntimeDir, innerPulseSocket)
|
seal.container.Bind(innerPulseRuntimeDir, innerPulseSocket, 0)
|
||||||
seal.container.SetEnv[pulseServer] = "unix:" + innerPulseSocket
|
seal.env[pulseServer] = "unix:" + innerPulseSocket
|
||||||
|
|
||||||
// publish current user's pulse cookie for target user
|
// publish current user's pulse cookie for target user
|
||||||
if src, err := discoverPulseCookie(sys); err != nil {
|
if src, err := discoverPulseCookie(sys); err != nil {
|
||||||
@ -405,9 +428,9 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
fmsg.Verbose(strings.TrimSpace(err.(*fmsg.BaseError).Message()))
|
fmsg.Verbose(strings.TrimSpace(err.(*fmsg.BaseError).Message()))
|
||||||
} else {
|
} else {
|
||||||
innerDst := fst.Tmp + "/pulse-cookie"
|
innerDst := fst.Tmp + "/pulse-cookie"
|
||||||
seal.container.SetEnv[pulseCookie] = innerDst
|
seal.env[pulseCookie] = innerDst
|
||||||
payload := new([]byte)
|
var payload *[]byte
|
||||||
seal.container.CopyBindRef(innerDst, &payload)
|
seal.container.PlaceP(innerDst, &payload)
|
||||||
seal.sys.CopyFile(payload, src, 256, 256)
|
seal.sys.CopyFile(payload, src, 256, 256)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,13 +460,13 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
|
|
||||||
// share proxy sockets
|
// share proxy sockets
|
||||||
sessionInner := path.Join(innerRuntimeDir, "bus")
|
sessionInner := path.Join(innerRuntimeDir, "bus")
|
||||||
seal.container.SetEnv[dbusSessionBusAddress] = "unix:path=" + sessionInner
|
seal.env[dbusSessionBusAddress] = "unix:path=" + sessionInner
|
||||||
seal.container.Bind(sessionPath, sessionInner)
|
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.Confinement.SystemBus != nil {
|
||||||
systemInner := "/run/dbus/system_bus_socket"
|
systemInner := "/run/dbus/system_bus_socket"
|
||||||
seal.container.SetEnv[dbusSystemBusAddress] = "unix:path=" + systemInner
|
seal.env[dbusSystemBusAddress] = "unix:path=" + systemInner
|
||||||
seal.container.Bind(systemPath, systemInner)
|
seal.container.Bind(systemPath, systemInner, 0)
|
||||||
seal.sys.UpdatePerm(systemPath, acl.Read, acl.Write)
|
seal.sys.UpdatePerm(systemPath, acl.Read, acl.Write)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,9 +475,8 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
Miscellaneous
|
Miscellaneous
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// queue overriding tmpfs at the end of seal.container.Filesystem
|
for _, dest := range config.Confinement.Sandbox.Cover {
|
||||||
for _, dest := range config.Confinement.Sandbox.Override {
|
seal.container.Tmpfs(dest, 1<<13, 0755)
|
||||||
seal.container.Tmpfs(dest, 8*1024)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// append ExtraPerms last
|
// append ExtraPerms last
|
||||||
@ -480,12 +502,13 @@ func (seal *outcome) finalise(sys sys.State, config *fst.Config) error {
|
|||||||
seal.sys.UpdatePermType(system.User, p.Path, perms...)
|
seal.sys.UpdatePermType(system.User, p.Path, perms...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mount fortify in sandbox for init
|
// flatten and sort env for deterministic behaviour
|
||||||
seal.container.Bind(sys.MustExecutable(), path.Join(fst.Tmp, "sbin/fortify"))
|
seal.container.Env = make([]string, 0, len(seal.env))
|
||||||
seal.container.Symlink("fortify", path.Join(fst.Tmp, "sbin/init0"))
|
maps.All(seal.env)(func(k string, v string) bool { seal.container.Env = append(seal.container.Env, k+"="+v); return true })
|
||||||
|
slices.Sort(seal.container.Env)
|
||||||
|
|
||||||
fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, command: %s",
|
fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, argv: %s",
|
||||||
seal.user.uid, seal.user.username, config.Confinement.Groups, config.Command)
|
seal.user.uid, seal.user.username, config.Confinement.Groups, seal.container.Args)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -7,18 +7,26 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
|
||||||
"git.gensokyo.uk/security/fortify/helper"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/app/init0"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/sandbox"
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const Env = "FORTIFY_SHIM"
|
||||||
|
|
||||||
|
type Params struct {
|
||||||
|
// finalised container params
|
||||||
|
Container *sandbox.Params
|
||||||
|
// path to outer home directory
|
||||||
|
Home string
|
||||||
|
|
||||||
|
// verbosity pass through
|
||||||
|
Verbose bool
|
||||||
|
}
|
||||||
|
|
||||||
// everything beyond this point runs as unconstrained target user
|
// everything beyond this point runs as unconstrained target user
|
||||||
// proceed with caution!
|
// proceed with caution!
|
||||||
|
|
||||||
@ -27,17 +35,15 @@ func Main() {
|
|||||||
// USE WITH CAUTION
|
// USE WITH CAUTION
|
||||||
fmsg.Prepare("shim")
|
fmsg.Prepare("shim")
|
||||||
|
|
||||||
// setting this prevents ptrace
|
|
||||||
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
||||||
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive setup payload
|
|
||||||
var (
|
var (
|
||||||
payload Payload
|
params Params
|
||||||
closeSetup func() error
|
closeSetup func() error
|
||||||
)
|
)
|
||||||
if f, err := sandbox.Receive(Env, &payload, nil); err != nil {
|
if f, err := sandbox.Receive(Env, ¶ms, nil); err != nil {
|
||||||
if errors.Is(err, sandbox.ErrInvalid) {
|
if errors.Is(err, sandbox.ErrInvalid) {
|
||||||
log.Fatal("invalid config descriptor")
|
log.Fatal("invalid config descriptor")
|
||||||
}
|
}
|
||||||
@ -45,32 +51,26 @@ func Main() {
|
|||||||
log.Fatal("FORTIFY_SHIM not set")
|
log.Fatal("FORTIFY_SHIM not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Fatalf("cannot decode shim setup payload: %v", err)
|
log.Fatalf("cannot receive shim setup params: %v", err)
|
||||||
} else {
|
} else {
|
||||||
internal.InstallFmsg(payload.Verbose)
|
internal.InstallFmsg(params.Verbose)
|
||||||
closeSetup = f
|
closeSetup = f
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.Bwrap == nil {
|
if params.Container == nil || params.Container.Ops == nil {
|
||||||
log.Fatal("bwrap config not supplied")
|
log.Fatal("invalid container params")
|
||||||
}
|
|
||||||
|
|
||||||
// restore bwrap sync fd
|
|
||||||
var syncFd *os.File
|
|
||||||
if payload.Sync != nil {
|
|
||||||
syncFd = os.NewFile(*payload.Sync, "sync")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close setup socket
|
// close setup socket
|
||||||
if err := closeSetup(); err != nil {
|
if err := closeSetup(); err != nil {
|
||||||
log.Println("cannot close setup pipe:", err)
|
log.Printf("cannot close setup pipe: %v", err)
|
||||||
// not fatal
|
// not fatal
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure home directory as target user
|
// ensure home directory as target user
|
||||||
if s, err := os.Stat(payload.Home); err != nil {
|
if s, err := os.Stat(params.Home); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
if err = os.Mkdir(payload.Home, 0700); err != nil {
|
if err = os.Mkdir(params.Home, 0700); err != nil {
|
||||||
log.Fatalf("cannot create home directory: %v", err)
|
log.Fatalf("cannot create home directory: %v", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -79,72 +79,37 @@ func Main() {
|
|||||||
|
|
||||||
// home directory is created, proceed
|
// home directory is created, proceed
|
||||||
} else if !s.IsDir() {
|
} else if !s.IsDir() {
|
||||||
log.Fatalf("data path %q is not a directory", payload.Home)
|
log.Fatalf("path %q is not a directory", params.Home)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ic init0.Payload
|
var name string
|
||||||
|
if len(params.Container.Args) > 0 {
|
||||||
// resolve argv0
|
name = params.Container.Args[0]
|
||||||
ic.Argv = payload.Argv
|
|
||||||
if len(ic.Argv) > 0 {
|
|
||||||
// looked up from $PATH by parent
|
|
||||||
ic.Argv0 = payload.Exec[1]
|
|
||||||
} else {
|
|
||||||
// no argv, look up shell instead
|
|
||||||
var ok bool
|
|
||||||
if payload.Bwrap.SetEnv == nil {
|
|
||||||
log.Fatal("no command was specified and environment is unset")
|
|
||||||
}
|
|
||||||
if ic.Argv0, ok = payload.Bwrap.SetEnv["SHELL"]; !ok {
|
|
||||||
log.Fatal("no command was specified and $SHELL was unset")
|
|
||||||
}
|
|
||||||
|
|
||||||
ic.Argv = []string{ic.Argv0}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := payload.Bwrap
|
|
||||||
|
|
||||||
var extraFiles []*os.File
|
|
||||||
|
|
||||||
// serve setup payload
|
|
||||||
if fd, encoder, err := sandbox.Setup(&extraFiles); err != nil {
|
|
||||||
log.Fatalf("cannot pipe: %v", err)
|
|
||||||
} else {
|
|
||||||
conf.SetEnv[init0.Env] = strconv.Itoa(fd)
|
|
||||||
go func() {
|
|
||||||
fmsg.Verbose("transmitting config to init")
|
|
||||||
if err = encoder.Encode(&ic); err != nil {
|
|
||||||
log.Fatalf("cannot transmit init config: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
helper.BubblewrapName = payload.Exec[0] // resolved bwrap path by parent
|
|
||||||
|
|
||||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||||
defer stop() // unreachable
|
defer stop() // unreachable
|
||||||
if b, err := helper.NewBwrap(
|
container := sandbox.New(ctx, name)
|
||||||
ctx, path.Join(fst.Tmp, "sbin/init0"),
|
container.Params = *params.Container
|
||||||
nil, false,
|
container.Stdin, container.Stdout, container.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
func(int, int) []string { return make([]string, 0) },
|
container.Cancel = func(cmd *exec.Cmd) error { return cmd.Process.Signal(os.Interrupt) }
|
||||||
func(cmd *exec.Cmd) { cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr },
|
container.WaitDelay = 2 * time.Second
|
||||||
extraFiles,
|
|
||||||
conf, syncFd,
|
if err := container.Start(); err != nil {
|
||||||
); err != nil {
|
fmsg.PrintBaseError(err, "cannot start container:")
|
||||||
log.Fatalf("malformed sandbox config: %v", err)
|
os.Exit(1)
|
||||||
} else {
|
}
|
||||||
// run and pass through exit code
|
if err := container.Serve(); err != nil {
|
||||||
if err = b.Start(); err != nil {
|
fmsg.PrintBaseError(err, "cannot configure container:")
|
||||||
log.Fatalf("cannot start target process: %v", err)
|
}
|
||||||
} else if err = b.Wait(); err != nil {
|
if err := container.Wait(); err != nil {
|
||||||
var exitError *exec.ExitError
|
var exitError *exec.ExitError
|
||||||
if !errors.As(err, &exitError) {
|
if !errors.As(err, &exitError) {
|
||||||
log.Printf("wait: %v", err)
|
if errors.Is(err, context.Canceled) {
|
||||||
internal.Exit(127)
|
os.Exit(2)
|
||||||
panic("unreachable")
|
|
||||||
}
|
}
|
||||||
internal.Exit(exitError.ExitCode())
|
log.Printf("wait: %v", err)
|
||||||
panic("unreachable")
|
os.Exit(127)
|
||||||
}
|
}
|
||||||
|
os.Exit(exitError.ExitCode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
package shim
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
)
|
|
||||||
|
|
||||||
const Env = "FORTIFY_SHIM"
|
|
||||||
|
|
||||||
type Payload struct {
|
|
||||||
// child full argv
|
|
||||||
Argv []string
|
|
||||||
// bwrap, target full exec path
|
|
||||||
Exec [2]string
|
|
||||||
// bwrap config
|
|
||||||
Bwrap *bwrap.Config
|
|
||||||
// path to outer home directory
|
|
||||||
Home string
|
|
||||||
// sync fd
|
|
||||||
Sync *uintptr
|
|
||||||
|
|
||||||
// verbosity pass through
|
|
||||||
Verbose bool
|
|
||||||
}
|
|
@ -8,9 +8,9 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/helper/proc"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/sandbox"
|
"git.gensokyo.uk/security/fortify/sandbox"
|
||||||
@ -25,10 +25,11 @@ type Shim struct {
|
|||||||
killFallback chan error
|
killFallback chan error
|
||||||
// monitor to shim encoder
|
// monitor to shim encoder
|
||||||
encoder *gob.Encoder
|
encoder *gob.Encoder
|
||||||
// bwrap --sync-fd value
|
|
||||||
sync *uintptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shim) Unwrap() *exec.Cmd { return s.cmd }
|
||||||
|
func (s *Shim) Fallback() chan error { return s.killFallback }
|
||||||
|
|
||||||
func (s *Shim) String() string {
|
func (s *Shim) String() string {
|
||||||
if s.cmd == nil {
|
if s.cmd == nil {
|
||||||
return "(unused shim manager)"
|
return "(unused shim manager)"
|
||||||
@ -36,21 +37,9 @@ func (s *Shim) String() string {
|
|||||||
return s.cmd.String()
|
return s.cmd.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shim) Unwrap() *exec.Cmd {
|
|
||||||
return s.cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Shim) WaitFallback() chan error {
|
|
||||||
return s.killFallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Shim) Start(
|
func (s *Shim) Start(
|
||||||
// string representation of application id
|
|
||||||
aid string,
|
aid string,
|
||||||
// string representation of supplementary group ids
|
|
||||||
supp []string,
|
supp []string,
|
||||||
// bwrap --sync-fd
|
|
||||||
syncFd *os.File,
|
|
||||||
) (*time.Time, error) {
|
) (*time.Time, error) {
|
||||||
// prepare user switcher invocation
|
// prepare user switcher invocation
|
||||||
fsuPath := internal.MustFsuPath()
|
fsuPath := internal.MustFsuPath()
|
||||||
@ -76,12 +65,6 @@ func (s *Shim) Start(
|
|||||||
s.cmd.Stdin, s.cmd.Stdout, s.cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
s.cmd.Stdin, s.cmd.Stdout, s.cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
s.cmd.Dir = "/"
|
s.cmd.Dir = "/"
|
||||||
|
|
||||||
// pass sync fd if set
|
|
||||||
if syncFd != nil {
|
|
||||||
fd := proc.ExtraFile(s.cmd, syncFd)
|
|
||||||
s.sync = &fd
|
|
||||||
}
|
|
||||||
|
|
||||||
fmsg.Verbose("starting shim via fsu:", s.cmd)
|
fmsg.Verbose("starting shim via fsu:", s.cmd)
|
||||||
// withhold messages to stderr
|
// withhold messages to stderr
|
||||||
fmsg.Suspend()
|
fmsg.Suspend()
|
||||||
@ -90,10 +73,11 @@ func (s *Shim) Start(
|
|||||||
"cannot start fsu:")
|
"cannot start fsu:")
|
||||||
}
|
}
|
||||||
startTime := time.Now().UTC()
|
startTime := time.Now().UTC()
|
||||||
|
|
||||||
return &startTime, nil
|
return &startTime, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shim) Serve(ctx context.Context, payload *Payload) error {
|
func (s *Shim) Serve(ctx context.Context, params *Params) error {
|
||||||
// kill shim if something goes wrong and an error is returned
|
// kill shim if something goes wrong and an error is returned
|
||||||
s.killFallback = make(chan error, 1)
|
s.killFallback = make(chan error, 1)
|
||||||
killShim := func() {
|
killShim := func() {
|
||||||
@ -103,9 +87,8 @@ func (s *Shim) Serve(ctx context.Context, payload *Payload) error {
|
|||||||
}
|
}
|
||||||
defer func() { killShim() }()
|
defer func() { killShim() }()
|
||||||
|
|
||||||
payload.Sync = s.sync
|
|
||||||
encodeErr := make(chan error)
|
encodeErr := make(chan error)
|
||||||
go func() { encodeErr <- s.encoder.Encode(payload) }()
|
go func() { encodeErr <- s.encoder.Encode(params) }()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
// encode return indicates setup completion
|
// encode return indicates setup completion
|
||||||
@ -121,11 +104,11 @@ func (s *Shim) Serve(ctx context.Context, payload *Payload) error {
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
err := ctx.Err()
|
err := ctx.Err()
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return fmsg.WrapError(errors.New("shim setup canceled"),
|
return fmsg.WrapError(syscall.ECANCELED,
|
||||||
"shim setup canceled")
|
"shim setup canceled")
|
||||||
}
|
}
|
||||||
if errors.Is(err, context.DeadlineExceeded) {
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
return fmsg.WrapError(errors.New("deadline exceeded waiting for shim"),
|
return fmsg.WrapError(syscall.ETIMEDOUT,
|
||||||
"deadline exceeded waiting for shim")
|
"deadline exceeded waiting for shim")
|
||||||
}
|
}
|
||||||
// unreachable
|
// unreachable
|
@ -96,7 +96,7 @@ func testStore(t *testing.T, s state.Store) {
|
|||||||
} else {
|
} else {
|
||||||
slices.Sort(aids)
|
slices.Sort(aids)
|
||||||
want := []int{0, 1}
|
want := []int{0, 1}
|
||||||
if slices.Compare(aids, want) != 0 {
|
if !slices.Equal(aids, want) {
|
||||||
t.Fatalf("List() = %#v, want %#v", aids, want)
|
t.Fatalf("List() = %#v, want %#v", aids, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
main.go
20
main.go
@ -20,7 +20,6 @@ import (
|
|||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/app"
|
"git.gensokyo.uk/security/fortify/internal/app"
|
||||||
"git.gensokyo.uk/security/fortify/internal/app/init0"
|
|
||||||
"git.gensokyo.uk/security/fortify/internal/app/shim"
|
"git.gensokyo.uk/security/fortify/internal/app/shim"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/internal/state"
|
"git.gensokyo.uk/security/fortify/internal/state"
|
||||||
@ -43,7 +42,6 @@ var std sys.State = new(sys.Std)
|
|||||||
func main() {
|
func main() {
|
||||||
// early init path, skips root check and duplicate PR_SET_DUMPABLE
|
// early init path, skips root check and duplicate PR_SET_DUMPABLE
|
||||||
sandbox.TryArgv0(fmsg.Output{}, fmsg.Prepare, internal.InstallFmsg)
|
sandbox.TryArgv0(fmsg.Output{}, fmsg.Prepare, internal.InstallFmsg)
|
||||||
init0.TryArgv0()
|
|
||||||
|
|
||||||
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
||||||
log.Printf("cannot set SUID_DUMP_DISABLE: %s", err)
|
log.Printf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||||
@ -76,9 +74,7 @@ func buildCommand(out io.Writer) command.Command {
|
|||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console").
|
Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console").
|
||||||
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output as JSON when applicable")
|
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output as JSON when applicable")
|
||||||
|
|
||||||
// internal commands
|
|
||||||
c.Command("shim", command.UsageInternal, func([]string) error { shim.Main(); return errSuccess })
|
c.Command("shim", command.UsageInternal, func([]string) error { shim.Main(); return errSuccess })
|
||||||
c.Command("init", command.UsageInternal, func([]string) error { init0.Main(); return errSuccess })
|
|
||||||
|
|
||||||
c.Command("app", "Launch app defined by the specified config file", func(args []string) error {
|
c.Command("app", "Launch app defined by the specified config file", func(args []string) error {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
@ -87,10 +83,9 @@ func buildCommand(out io.Writer) command.Command {
|
|||||||
|
|
||||||
// config extraArgs...
|
// config extraArgs...
|
||||||
config := tryPath(args[0])
|
config := tryPath(args[0])
|
||||||
config.Command = append(config.Command, args[1:]...)
|
config.Args = append(config.Args, args[1:]...)
|
||||||
|
|
||||||
// invoke app
|
runApp(config)
|
||||||
runApp(app.MustNew(std), config)
|
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -112,8 +107,8 @@ func buildCommand(out io.Writer) command.Command {
|
|||||||
c.NewCommand("run", "Configure and start a permissive default sandbox", func(args []string) error {
|
c.NewCommand("run", "Configure and start a permissive default sandbox", func(args []string) error {
|
||||||
// initialise config from flags
|
// initialise config from flags
|
||||||
config := &fst.Config{
|
config := &fst.Config{
|
||||||
ID: fid,
|
ID: fid,
|
||||||
Command: args,
|
Args: args,
|
||||||
}
|
}
|
||||||
|
|
||||||
if aid < 0 || aid > 9999 {
|
if aid < 0 || aid > 9999 {
|
||||||
@ -199,7 +194,7 @@ func buildCommand(out io.Writer) command.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// invoke app
|
// invoke app
|
||||||
runApp(app.MustNew(std), config)
|
runApp(config)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}).
|
}).
|
||||||
Flag(&dbusConfigSession, "dbus-config", command.StringFlag("builtin"),
|
Flag(&dbusConfigSession, "dbus-config", command.StringFlag("builtin"),
|
||||||
@ -279,10 +274,11 @@ func buildCommand(out io.Writer) command.Command {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func runApp(a fst.App, config *fst.Config) {
|
func runApp(config *fst.Config) {
|
||||||
ctx, stop := signal.NotifyContext(context.Background(),
|
ctx, stop := signal.NotifyContext(context.Background(),
|
||||||
syscall.SIGINT, syscall.SIGTERM)
|
syscall.SIGINT, syscall.SIGTERM)
|
||||||
defer stop() // unreachable
|
defer stop() // unreachable
|
||||||
|
a := app.MustNew(ctx, std)
|
||||||
|
|
||||||
rs := new(fst.RunState)
|
rs := new(fst.RunState)
|
||||||
if sa, err := a.Seal(config); err != nil {
|
if sa, err := a.Seal(config); err != nil {
|
||||||
@ -290,7 +286,7 @@ func runApp(a fst.App, config *fst.Config) {
|
|||||||
rs.ExitCode = 1
|
rs.ExitCode = 1
|
||||||
} else {
|
} else {
|
||||||
// this updates ExitCode
|
// this updates ExitCode
|
||||||
app.PrintRunStateErr(rs, sa.Run(ctx, rs))
|
app.PrintRunStateErr(rs, sa.Run(rs))
|
||||||
}
|
}
|
||||||
internal.Exit(rs.ExitCode)
|
internal.Exit(rs.ExitCode)
|
||||||
}
|
}
|
||||||
|
21
nixos.nix
21
nixos.nix
@ -86,12 +86,11 @@ in
|
|||||||
enablements = with app.capability; (if wayland then 1 else 0) + (if x11 then 2 else 0) + (if dbus then 4 else 0) + (if pulse then 8 else 0);
|
enablements = with app.capability; (if wayland then 1 else 0) + (if x11 then 2 else 0) + (if dbus then 4 else 0) + (if pulse then 8 else 0);
|
||||||
conf = {
|
conf = {
|
||||||
inherit (app) id;
|
inherit (app) id;
|
||||||
command = [
|
path = pkgs.writeScript "${app.name}-start" ''
|
||||||
(pkgs.writeScript "${app.name}-start" ''
|
#!${pkgs.zsh}${pkgs.zsh.shellPath}
|
||||||
#!${pkgs.zsh}${pkgs.zsh.shellPath}
|
${script}
|
||||||
${script}
|
'';
|
||||||
'')
|
args = [ "${app.name}-start" ];
|
||||||
];
|
|
||||||
confinement = {
|
confinement = {
|
||||||
app_id = aid;
|
app_id = aid;
|
||||||
inherit (app) groups;
|
inherit (app) groups;
|
||||||
@ -99,17 +98,15 @@ in
|
|||||||
home = getsubhome fid aid;
|
home = getsubhome fid aid;
|
||||||
sandbox = {
|
sandbox = {
|
||||||
inherit (app)
|
inherit (app)
|
||||||
|
devel
|
||||||
userns
|
userns
|
||||||
net
|
net
|
||||||
dev
|
dev
|
||||||
|
tty
|
||||||
|
multiarch
|
||||||
env
|
env
|
||||||
;
|
;
|
||||||
syscall = {
|
|
||||||
inherit (app) compat multiarch bluetooth;
|
|
||||||
deny_devel = !app.devel;
|
|
||||||
};
|
|
||||||
map_real_uid = app.mapRealUid;
|
map_real_uid = app.mapRealUid;
|
||||||
no_new_session = app.tty;
|
|
||||||
direct_wayland = app.insecureWayland;
|
direct_wayland = app.insecureWayland;
|
||||||
filesystem =
|
filesystem =
|
||||||
let
|
let
|
||||||
@ -149,7 +146,7 @@ in
|
|||||||
]
|
]
|
||||||
++ app.extraPaths;
|
++ app.extraPaths;
|
||||||
auto_etc = true;
|
auto_etc = true;
|
||||||
override = [ "/var/run/nscd" ];
|
cover = [ "/var/run/nscd" ];
|
||||||
};
|
};
|
||||||
inherit enablements;
|
inherit enablements;
|
||||||
inherit (dbusConfig) session_bus system_bus;
|
inherit (dbusConfig) session_bus system_bus;
|
||||||
|
16
options.nix
16
options.nix
@ -148,21 +148,19 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
nix = mkEnableOption "nix daemon";
|
devel = mkEnableOption "debugging-related kernel interfaces";
|
||||||
userns = mkEnableOption "user namespace";
|
userns = mkEnableOption "user namespace creation";
|
||||||
mapRealUid = mkEnableOption "mapping to priv-user uid";
|
|
||||||
dev = mkEnableOption "access to all devices";
|
|
||||||
tty = mkEnableOption "access to the controlling terminal";
|
tty = mkEnableOption "access to the controlling terminal";
|
||||||
insecureWayland = mkEnableOption "direct access to the Wayland socket";
|
multiarch = mkEnableOption "multiarch kernel-level support";
|
||||||
|
|
||||||
net = mkEnableOption "network access" // {
|
net = mkEnableOption "network access" // {
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
compat = mkEnableOption "disable syscall filter extensions";
|
nix = mkEnableOption "nix daemon access";
|
||||||
devel = mkEnableOption "development kernel APIs";
|
mapRealUid = mkEnableOption "mapping to priv-user uid";
|
||||||
multiarch = mkEnableOption "multiarch kernel support";
|
dev = mkEnableOption "access to all devices";
|
||||||
bluetooth = mkEnableOption "AF_BLUETOOTH socket operations";
|
insecureWayland = mkEnableOption "direct access to the Wayland socket";
|
||||||
|
|
||||||
gpu = mkOption {
|
gpu = mkOption {
|
||||||
type = nullOr bool;
|
type = nullOr bool;
|
||||||
|
12
print.go
12
print.go
@ -89,10 +89,10 @@ func printShowInstance(
|
|||||||
flags = append(flags, name)
|
flags = append(flags, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeFlag("userns", sandbox.UserNS)
|
writeFlag("userns", sandbox.Userns)
|
||||||
writeFlag("net", sandbox.Net)
|
writeFlag("net", sandbox.Net)
|
||||||
writeFlag("dev", sandbox.Dev)
|
writeFlag("dev", sandbox.Dev)
|
||||||
writeFlag("tty", sandbox.NoNewSession)
|
writeFlag("tty", sandbox.Tty)
|
||||||
writeFlag("mapuid", sandbox.MapRealUID)
|
writeFlag("mapuid", sandbox.MapRealUID)
|
||||||
writeFlag("directwl", sandbox.DirectWayland)
|
writeFlag("directwl", sandbox.DirectWayland)
|
||||||
writeFlag("autoetc", sandbox.AutoEtc)
|
writeFlag("autoetc", sandbox.AutoEtc)
|
||||||
@ -107,14 +107,14 @@ func printShowInstance(
|
|||||||
}
|
}
|
||||||
t.Printf(" Etc:\t%s\n", etc)
|
t.Printf(" Etc:\t%s\n", etc)
|
||||||
|
|
||||||
if len(sandbox.Override) > 0 {
|
if len(sandbox.Cover) > 0 {
|
||||||
t.Printf(" Overrides:\t%s\n", strings.Join(sandbox.Override, " "))
|
t.Printf(" Cover:\t%s\n", strings.Join(sandbox.Cover, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Env map[string]string `json:"env"`
|
// Env map[string]string `json:"env"`
|
||||||
// Link [][2]string `json:"symlink"`
|
// Link [][2]string `json:"symlink"`
|
||||||
}
|
}
|
||||||
t.Printf(" Command:\t%s\n", strings.Join(config.Command, " "))
|
t.Printf(" Command:\t%s\n", strings.Join(config.Args, " "))
|
||||||
t.Printf("\n")
|
t.Printf("\n")
|
||||||
|
|
||||||
if !short {
|
if !short {
|
||||||
@ -256,7 +256,7 @@ func printPs(output io.Writer, now time.Time, s state.Store, short, flagJSON boo
|
|||||||
)
|
)
|
||||||
if e.Config != nil {
|
if e.Config != nil {
|
||||||
es = e.Config.Confinement.Enablements.String()
|
es = e.Config.Confinement.Enablements.String()
|
||||||
cs = fmt.Sprintf("%q", e.Config.Command)
|
cs = fmt.Sprintf("%q", e.Config.Args)
|
||||||
as = strconv.Itoa(e.Config.Confinement.AppID)
|
as = strconv.Itoa(e.Config.Confinement.AppID)
|
||||||
}
|
}
|
||||||
t.Printf("\t%s\t%d\t%s\t%s\t%s\t%s\n",
|
t.Printf("\t%s\t%d\t%s\t%s\t%s\t%s\n",
|
||||||
|
@ -43,7 +43,7 @@ func Test_printShowInstance(t *testing.T) {
|
|||||||
Hostname: "localhost"
|
Hostname: "localhost"
|
||||||
Flags: userns net dev tty mapuid autoetc
|
Flags: userns net dev tty mapuid autoetc
|
||||||
Etc: /etc
|
Etc: /etc
|
||||||
Overrides: /var/run/nscd
|
Cover: /var/run/nscd
|
||||||
Command: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
Command: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
||||||
|
|
||||||
Filesystem
|
Filesystem
|
||||||
@ -127,7 +127,7 @@ App
|
|||||||
Hostname: "localhost"
|
Hostname: "localhost"
|
||||||
Flags: userns net dev tty mapuid autoetc
|
Flags: userns net dev tty mapuid autoetc
|
||||||
Etc: /etc
|
Etc: /etc
|
||||||
Overrides: /var/run/nscd
|
Cover: /var/run/nscd
|
||||||
Command: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
Command: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
||||||
|
|
||||||
Filesystem
|
Filesystem
|
||||||
@ -192,7 +192,8 @@ App
|
|||||||
"pid": 3735928559,
|
"pid": 3735928559,
|
||||||
"config": {
|
"config": {
|
||||||
"id": "org.chromium.Chromium",
|
"id": "org.chromium.Chromium",
|
||||||
"command": [
|
"path": "/run/current-system/sw/bin/chromium",
|
||||||
|
"args": [
|
||||||
"chromium",
|
"chromium",
|
||||||
"--ignore-gpu-blocklist",
|
"--ignore-gpu-blocklist",
|
||||||
"--disable-smooth-scrolling",
|
"--disable-smooth-scrolling",
|
||||||
@ -209,24 +210,19 @@ App
|
|||||||
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"hostname": "localhost",
|
"hostname": "localhost",
|
||||||
|
"seccomp": 32,
|
||||||
|
"devel": true,
|
||||||
"userns": true,
|
"userns": true,
|
||||||
"net": true,
|
"net": true,
|
||||||
"dev": true,
|
"tty": true,
|
||||||
"syscall": {
|
"multiarch": true,
|
||||||
"compat": false,
|
|
||||||
"deny_devel": true,
|
|
||||||
"multiarch": true,
|
|
||||||
"linux32": false,
|
|
||||||
"can": false,
|
|
||||||
"bluetooth": false
|
|
||||||
},
|
|
||||||
"no_new_session": true,
|
|
||||||
"map_real_uid": true,
|
|
||||||
"env": {
|
"env": {
|
||||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||||
},
|
},
|
||||||
|
"map_real_uid": true,
|
||||||
|
"dev": true,
|
||||||
"filesystem": [
|
"filesystem": [
|
||||||
{
|
{
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
@ -259,7 +255,7 @@ App
|
|||||||
],
|
],
|
||||||
"etc": "/etc",
|
"etc": "/etc",
|
||||||
"auto_etc": true,
|
"auto_etc": true,
|
||||||
"override": [
|
"cover": [
|
||||||
"/var/run/nscd"
|
"/var/run/nscd"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -320,7 +316,8 @@ App
|
|||||||
`},
|
`},
|
||||||
{"json config", nil, fst.Template(), false, true, `{
|
{"json config", nil, fst.Template(), false, true, `{
|
||||||
"id": "org.chromium.Chromium",
|
"id": "org.chromium.Chromium",
|
||||||
"command": [
|
"path": "/run/current-system/sw/bin/chromium",
|
||||||
|
"args": [
|
||||||
"chromium",
|
"chromium",
|
||||||
"--ignore-gpu-blocklist",
|
"--ignore-gpu-blocklist",
|
||||||
"--disable-smooth-scrolling",
|
"--disable-smooth-scrolling",
|
||||||
@ -337,24 +334,19 @@ App
|
|||||||
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"hostname": "localhost",
|
"hostname": "localhost",
|
||||||
|
"seccomp": 32,
|
||||||
|
"devel": true,
|
||||||
"userns": true,
|
"userns": true,
|
||||||
"net": true,
|
"net": true,
|
||||||
"dev": true,
|
"tty": true,
|
||||||
"syscall": {
|
"multiarch": true,
|
||||||
"compat": false,
|
|
||||||
"deny_devel": true,
|
|
||||||
"multiarch": true,
|
|
||||||
"linux32": false,
|
|
||||||
"can": false,
|
|
||||||
"bluetooth": false
|
|
||||||
},
|
|
||||||
"no_new_session": true,
|
|
||||||
"map_real_uid": true,
|
|
||||||
"env": {
|
"env": {
|
||||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||||
},
|
},
|
||||||
|
"map_real_uid": true,
|
||||||
|
"dev": true,
|
||||||
"filesystem": [
|
"filesystem": [
|
||||||
{
|
{
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
@ -387,7 +379,7 @@ App
|
|||||||
],
|
],
|
||||||
"etc": "/etc",
|
"etc": "/etc",
|
||||||
"auto_etc": true,
|
"auto_etc": true,
|
||||||
"override": [
|
"cover": [
|
||||||
"/var/run/nscd"
|
"/var/run/nscd"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -506,7 +498,8 @@ func Test_printPs(t *testing.T) {
|
|||||||
"pid": 3735928559,
|
"pid": 3735928559,
|
||||||
"config": {
|
"config": {
|
||||||
"id": "org.chromium.Chromium",
|
"id": "org.chromium.Chromium",
|
||||||
"command": [
|
"path": "/run/current-system/sw/bin/chromium",
|
||||||
|
"args": [
|
||||||
"chromium",
|
"chromium",
|
||||||
"--ignore-gpu-blocklist",
|
"--ignore-gpu-blocklist",
|
||||||
"--disable-smooth-scrolling",
|
"--disable-smooth-scrolling",
|
||||||
@ -523,24 +516,19 @@ func Test_printPs(t *testing.T) {
|
|||||||
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"hostname": "localhost",
|
"hostname": "localhost",
|
||||||
|
"seccomp": 32,
|
||||||
|
"devel": true,
|
||||||
"userns": true,
|
"userns": true,
|
||||||
"net": true,
|
"net": true,
|
||||||
"dev": true,
|
"tty": true,
|
||||||
"syscall": {
|
"multiarch": true,
|
||||||
"compat": false,
|
|
||||||
"deny_devel": true,
|
|
||||||
"multiarch": true,
|
|
||||||
"linux32": false,
|
|
||||||
"can": false,
|
|
||||||
"bluetooth": false
|
|
||||||
},
|
|
||||||
"no_new_session": true,
|
|
||||||
"map_real_uid": true,
|
|
||||||
"env": {
|
"env": {
|
||||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||||
},
|
},
|
||||||
|
"map_real_uid": true,
|
||||||
|
"dev": true,
|
||||||
"filesystem": [
|
"filesystem": [
|
||||||
{
|
{
|
||||||
"src": "/nix/store"
|
"src": "/nix/store"
|
||||||
@ -573,7 +561,7 @@ func Test_printPs(t *testing.T) {
|
|||||||
],
|
],
|
||||||
"etc": "/etc",
|
"etc": "/etc",
|
||||||
"auto_etc": true,
|
"auto_etc": true,
|
||||||
"override": [
|
"cover": [
|
||||||
"/var/run/nscd"
|
"/var/run/nscd"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -93,7 +93,7 @@ func TestExport(t *testing.T) {
|
|||||||
t.Errorf("Close: error = %v", err)
|
t.Errorf("Close: error = %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if got := digest.Sum(nil); slices.Compare(got, tc.want) != 0 {
|
if got := digest.Sum(nil); !slices.Equal(got, tc.want) {
|
||||||
t.Fatalf("Export() hash = %x, want %x",
|
t.Fatalf("Export() hash = %x, want %x",
|
||||||
got, tc.want)
|
got, tc.want)
|
||||||
return
|
return
|
||||||
|
@ -22,14 +22,6 @@ func SetDumpable(dumpable uintptr) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetPdeathsig(sig syscall.Signal) error {
|
|
||||||
if _, _, errno := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(sig), 0); errno != 0 {
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IgnoringEINTR makes a function call and repeats it if it returns an
|
// IgnoringEINTR makes a function call and repeats it if it returns an
|
||||||
// EINTR error. This appears to be required even though we install all
|
// EINTR error. This appears to be required even though we install all
|
||||||
// signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
|
// signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
|
||||||
|
@ -12,14 +12,9 @@
|
|||||||
fs = fs "dead" {
|
fs = fs "dead" {
|
||||||
".fortify" = fs "800001ed" {
|
".fortify" = fs "800001ed" {
|
||||||
etc = fs "800001ed" null null;
|
etc = fs "800001ed" null null;
|
||||||
sbin = fs "800001c0" {
|
|
||||||
fortify = fs "16d" null null;
|
|
||||||
init0 = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
} null;
|
} null;
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
||||||
dev = fs "800001ed" {
|
dev = fs "800001ed" {
|
||||||
console = fs "4200190" null null;
|
|
||||||
core = fs "80001ff" null null;
|
core = fs "80001ff" null null;
|
||||||
dri = fs "800001ed" {
|
dri = fs "800001ed" {
|
||||||
by-path = fs "800001ed" {
|
by-path = fs "800001ed" {
|
||||||
@ -59,7 +54,7 @@
|
|||||||
"fstab" = fs "80001ff" null null;
|
"fstab" = fs "80001ff" null null;
|
||||||
"fsurc" = fs "80001ff" null null;
|
"fsurc" = fs "80001ff" null null;
|
||||||
"fuse.conf" = fs "80001ff" null null;
|
"fuse.conf" = fs "80001ff" null null;
|
||||||
"group" = fs "180" null "fortify:x:1000:\n";
|
"group" = fs "180" null "fortify:x:100:\n";
|
||||||
"host.conf" = fs "80001ff" null null;
|
"host.conf" = fs "80001ff" null null;
|
||||||
"hostname" = fs "80001ff" null null;
|
"hostname" = fs "80001ff" null null;
|
||||||
"hosts" = fs "80001ff" null null;
|
"hosts" = fs "80001ff" null null;
|
||||||
@ -84,7 +79,7 @@
|
|||||||
"os-release" = fs "80001ff" null null;
|
"os-release" = fs "80001ff" null null;
|
||||||
"pam" = fs "80001ff" null null;
|
"pam" = fs "80001ff" null null;
|
||||||
"pam.d" = fs "80001ff" null null;
|
"pam.d" = fs "80001ff" null null;
|
||||||
"passwd" = fs "180" null "u0_a3:x:1000:1000:Fortify:/var/lib/fortify/u0/a3:/run/current-system/sw/bin/bash\n";
|
"passwd" = fs "180" null "u0_a3:x:1000:100:Fortify:/var/lib/fortify/u0/a3:/run/current-system/sw/bin/bash\n";
|
||||||
"pipewire" = fs "80001ff" null null;
|
"pipewire" = fs "80001ff" null null;
|
||||||
"pki" = fs "80001ff" null null;
|
"pki" = fs "80001ff" null null;
|
||||||
"polkit-1" = fs "80001ff" null null;
|
"polkit-1" = fs "80001ff" null null;
|
||||||
@ -185,10 +180,10 @@
|
|||||||
} null;
|
} null;
|
||||||
|
|
||||||
mount = [
|
mount = [
|
||||||
(ent "/newroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000003,gid=1000003")
|
(ent "/sysroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000003,gid=1000003")
|
||||||
(ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
|
(ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
|
||||||
(ent "/" "/.fortify" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000003,gid=1000003")
|
(ent "/" "/.fortify" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000003,gid=1000003")
|
||||||
(ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,mode=755,uid=1000003,gid=1000003")
|
(ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000003,gid=1000003")
|
||||||
(ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
@ -196,8 +191,7 @@
|
|||||||
(ent "/urandom" "/dev/urandom" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/urandom" "/dev/urandom" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/tty" "/dev/tty" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/tty" "/dev/tty" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/" "/dev/pts" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,mode=620,ptmxmode=666")
|
(ent "/" "/dev/pts" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,mode=620,ptmxmode=666")
|
||||||
(ent ignore "/dev/console" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,gid=3,mode=620,ptmxmode=666")
|
(ent "/" "/dev/mqueue" "rw,nosuid,nodev,noexec,relatime" "mqueue" "mqueue" "rw")
|
||||||
(ent "/" "/dev/mqueue" "rw,relatime" "mqueue" "mqueue" "rw")
|
|
||||||
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
||||||
@ -210,17 +204,16 @@
|
|||||||
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
||||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=1024k,mode=755,uid=1000003,gid=1000003")
|
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000003,gid=1000003")
|
||||||
(ent "/" "/run/user/1000" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8192k,mode=755,uid=1000003,gid=1000003")
|
(ent "/" "/run/user/1000" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8192k,mode=755,uid=1000003,gid=1000003")
|
||||||
(ent "/tmp/fortify.1000/tmpdir/3" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/tmp/fortify.1000/tmpdir/3" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/var/lib/fortify/u0/a3" "/var/lib/fortify/u0/a3" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/var/lib/fortify/u0/a3" "/var/lib/fortify/u0/a3" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000003,gid=1000003")
|
(ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000003,gid=1000003")
|
||||||
(ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000003,gid=1000003")
|
(ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000003,gid=1000003")
|
||||||
(ent ignore "/run/user/1000/wayland-0" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent ignore "/run/user/1000/wayland-0" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent ignore "/run/user/1000/pulse/native" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" ignore)
|
(ent ignore "/run/user/1000/pulse/native" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" ignore)
|
||||||
(ent ignore "/run/user/1000/bus" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent ignore "/run/user/1000/bus" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/var/run/nscd" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8k,mode=755,uid=1000003,gid=1000003")
|
(ent "/" "/var/run/nscd" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8k,mode=755,uid=1000003,gid=1000003")
|
||||||
(ent ignore "/.fortify/sbin/fortify" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
|
||||||
];
|
];
|
||||||
|
|
||||||
seccomp = true;
|
seccomp = true;
|
||||||
|
@ -12,14 +12,9 @@
|
|||||||
fs = fs "dead" {
|
fs = fs "dead" {
|
||||||
".fortify" = fs "800001ed" {
|
".fortify" = fs "800001ed" {
|
||||||
etc = fs "800001ed" null null;
|
etc = fs "800001ed" null null;
|
||||||
sbin = fs "800001c0" {
|
|
||||||
fortify = fs "16d" null null;
|
|
||||||
init0 = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
} null;
|
} null;
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
||||||
dev = fs "800001ed" {
|
dev = fs "800001ed" {
|
||||||
console = fs "4200190" null null;
|
|
||||||
core = fs "80001ff" null null;
|
core = fs "80001ff" null null;
|
||||||
dri = fs "800001ed" {
|
dri = fs "800001ed" {
|
||||||
by-path = fs "800001ed" {
|
by-path = fs "800001ed" {
|
||||||
@ -185,10 +180,10 @@
|
|||||||
} null;
|
} null;
|
||||||
|
|
||||||
mount = [
|
mount = [
|
||||||
(ent "/newroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000001,gid=1000001")
|
(ent "/sysroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000001,gid=1000001")
|
||||||
(ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
|
(ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
|
||||||
(ent "/" "/.fortify" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000001,gid=1000001")
|
(ent "/" "/.fortify" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000001,gid=1000001")
|
||||||
(ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,mode=755,uid=1000001,gid=1000001")
|
(ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000001,gid=1000001")
|
||||||
(ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
@ -196,8 +191,7 @@
|
|||||||
(ent "/urandom" "/dev/urandom" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/urandom" "/dev/urandom" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/tty" "/dev/tty" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/tty" "/dev/tty" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/" "/dev/pts" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,mode=620,ptmxmode=666")
|
(ent "/" "/dev/pts" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,mode=620,ptmxmode=666")
|
||||||
(ent ignore "/dev/console" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,gid=3,mode=620,ptmxmode=666")
|
(ent "/" "/dev/mqueue" "rw,nosuid,nodev,noexec,relatime" "mqueue" "mqueue" "rw")
|
||||||
(ent "/" "/dev/mqueue" "rw,relatime" "mqueue" "mqueue" "rw")
|
|
||||||
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
||||||
@ -210,17 +204,16 @@
|
|||||||
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
||||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=1024k,mode=755,uid=1000001,gid=1000001")
|
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000001,gid=1000001")
|
||||||
(ent "/" "/run/user/65534" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8192k,mode=755,uid=1000001,gid=1000001")
|
(ent "/" "/run/user/65534" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8192k,mode=755,uid=1000001,gid=1000001")
|
||||||
(ent "/tmp/fortify.1000/tmpdir/1" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/tmp/fortify.1000/tmpdir/1" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/var/lib/fortify/u0/a1" "/var/lib/fortify/u0/a1" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/var/lib/fortify/u0/a1" "/var/lib/fortify/u0/a1" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000001,gid=1000001")
|
(ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000001,gid=1000001")
|
||||||
(ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000001,gid=1000001")
|
(ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000001,gid=1000001")
|
||||||
(ent ignore "/run/user/65534/wayland-0" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent ignore "/run/user/65534/wayland-0" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent ignore "/run/user/65534/pulse/native" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" ignore)
|
(ent ignore "/run/user/65534/pulse/native" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" ignore)
|
||||||
(ent ignore "/run/user/65534/bus" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent ignore "/run/user/65534/bus" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/var/run/nscd" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8k,mode=755,uid=1000001,gid=1000001")
|
(ent "/" "/var/run/nscd" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8k,mode=755,uid=1000001,gid=1000001")
|
||||||
(ent ignore "/.fortify/sbin/fortify" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
|
||||||
];
|
];
|
||||||
|
|
||||||
seccomp = true;
|
seccomp = true;
|
||||||
|
@ -12,10 +12,6 @@
|
|||||||
fs = fs "dead" {
|
fs = fs "dead" {
|
||||||
".fortify" = fs "800001ed" {
|
".fortify" = fs "800001ed" {
|
||||||
etc = fs "800001ed" null null;
|
etc = fs "800001ed" null null;
|
||||||
sbin = fs "800001c0" {
|
|
||||||
fortify = fs "16d" null null;
|
|
||||||
init0 = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
} null;
|
} null;
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
||||||
dev = fs "800001ed" {
|
dev = fs "800001ed" {
|
||||||
@ -185,10 +181,10 @@
|
|||||||
} null;
|
} null;
|
||||||
|
|
||||||
mount = [
|
mount = [
|
||||||
(ent "/newroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000002,gid=1000002")
|
(ent "/sysroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000002,gid=1000002")
|
||||||
(ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
|
(ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
|
||||||
(ent "/" "/.fortify" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000002,gid=1000002")
|
(ent "/" "/.fortify" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000002,gid=1000002")
|
||||||
(ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,mode=755,uid=1000002,gid=1000002")
|
(ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000002,gid=1000002")
|
||||||
(ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
@ -197,7 +193,7 @@
|
|||||||
(ent "/tty" "/dev/tty" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/tty" "/dev/tty" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/" "/dev/pts" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,mode=620,ptmxmode=666")
|
(ent "/" "/dev/pts" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,mode=620,ptmxmode=666")
|
||||||
(ent ignore "/dev/console" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,gid=3,mode=620,ptmxmode=666")
|
(ent ignore "/dev/console" "rw,nosuid,noexec,relatime" "devpts" "devpts" "rw,gid=3,mode=620,ptmxmode=666")
|
||||||
(ent "/" "/dev/mqueue" "rw,relatime" "mqueue" "mqueue" "rw")
|
(ent "/" "/dev/mqueue" "rw,nosuid,nodev,noexec,relatime" "mqueue" "mqueue" "rw")
|
||||||
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/bin" "/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/usr/bin" "/usr/bin" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
(ent "/" "/nix/store" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
||||||
@ -210,17 +206,16 @@
|
|||||||
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
(ent ignore "/run/opengl-driver" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
||||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||||
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/etc" "/.fortify/etc" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=1024k,mode=755,uid=1000002,gid=1000002")
|
(ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000002,gid=1000002")
|
||||||
(ent "/" "/run/user/65534" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8192k,mode=755,uid=1000002,gid=1000002")
|
(ent "/" "/run/user/65534" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8192k,mode=755,uid=1000002,gid=1000002")
|
||||||
(ent "/tmp/fortify.1000/tmpdir/2" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/tmp/fortify.1000/tmpdir/2" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/var/lib/fortify/u0/a2" "/var/lib/fortify/u0/a2" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent "/var/lib/fortify/u0/a2" "/var/lib/fortify/u0/a2" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000002,gid=1000002")
|
(ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000002,gid=1000002")
|
||||||
(ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,uid=1000002,gid=1000002")
|
(ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000002,gid=1000002")
|
||||||
(ent ignore "/run/user/65534/wayland-0" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent ignore "/run/user/65534/wayland-0" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent ignore "/run/user/65534/pulse/native" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" ignore)
|
(ent ignore "/run/user/65534/pulse/native" "ro,nosuid,nodev,relatime" "tmpfs" "tmpfs" ignore)
|
||||||
(ent ignore "/run/user/65534/bus" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
(ent ignore "/run/user/65534/bus" "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
|
||||||
(ent "/" "/var/run/nscd" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8k,mode=755,uid=1000002,gid=1000002")
|
(ent "/" "/var/run/nscd" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=8k,mode=755,uid=1000002,gid=1000002")
|
||||||
(ent ignore "/.fortify/sbin/fortify" "ro,nosuid,nodev,relatime" "overlay" "overlay" "rw,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on")
|
|
||||||
];
|
];
|
||||||
|
|
||||||
seccomp = true;
|
seccomp = true;
|
||||||
|
@ -62,9 +62,12 @@ def check_state(name, enablements):
|
|||||||
|
|
||||||
config = instance['config']
|
config = instance['config']
|
||||||
|
|
||||||
if len(config['command']) != 1 or not (config['command'][0].startswith("/nix/store/")) or not (
|
command = f"{name}-start"
|
||||||
config['command'][0].endswith(f"{name}-start")):
|
if not (config['path'].startswith("/nix/store/")) or not (config['path'].endswith(command)):
|
||||||
raise Exception(f"unexpected command {instance['config']['command']}")
|
raise Exception(f"unexpected path {config['path']}")
|
||||||
|
|
||||||
|
if len(config['args']) != 1 or config['args'][0] != command:
|
||||||
|
raise Exception(f"unexpected args {config['args']}")
|
||||||
|
|
||||||
if config['confinement']['enablements'] != enablements:
|
if config['confinement']['enablements'] != enablements:
|
||||||
raise Exception(f"unexpected enablements {instance['config']['confinement']['enablements']}")
|
raise Exception(f"unexpected enablements {instance['config']['confinement']['enablements']}")
|
||||||
|
Loading…
Reference in New Issue
Block a user