diff --git a/sandbox/container_test.go b/sandbox/container_test.go index 1306360..ddacbcb 100644 --- a/sandbox/container_test.go +++ b/sandbox/container_test.go @@ -117,11 +117,14 @@ func TestContainer(t *testing.T) { mnt = append(mnt, &check.Mntent{FSName: "\x00", Dir: name, Type: "\x00", Opts: "\x00", Freq: -1, Passno: -1}) } mnt = append(mnt, &check.Mntent{FSName: "proc", Dir: "/proc", Type: "proc", Opts: "rw,nosuid,nodev,noexec,relatime"}) - mntentWant := new(bytes.Buffer) - if err := json.NewEncoder(mntentWant).Encode(mnt); err != nil { - t.Fatalf("cannot serialise mntent: %v", err) + want := new(bytes.Buffer) + if err := json.NewEncoder(want).Encode(&check.TestCase{ + Mount: mnt, + Seccomp: true, + }); err != nil { + t.Fatalf("cannot serialise want: %v", err) } - container.Stdin = mntentWant + container.Stdin = want // needs /proc to check mntent container.Proc("/proc") @@ -185,8 +188,7 @@ func TestHelperCheckContainer(t *testing.T) { t.Errorf("/etc/hostname: %q, want %q", string(p), os.Args[5]) } }) - t.Run("seccomp", func(t *testing.T) { check.MustAssertSeccomp() }) - t.Run("mntent", func(t *testing.T) { check.MustAssertMounts("", "/proc/mounts", "/proc/self/fd/0") }) + t.Run("sandbox", func(t *testing.T) { (&check.T{PMountsPath: "/proc/mounts"}).MustCheckFile("/proc/self/fd/0") }) } func commandContext(ctx context.Context) *exec.Cmd { diff --git a/test/configuration.nix b/test/configuration.nix index f6c3d14..6bdc13e 100644 --- a/test/configuration.nix +++ b/test/configuration.nix @@ -4,6 +4,12 @@ config, ... }: +let + testCases = import ./sandbox/case { + inherit (pkgs) lib callPackage foot; + inherit (config.environment.fortify.package) version; + }; +in { users.users = { alice = { @@ -102,21 +108,8 @@ home-manager = _: _: { home.stateVersion = "23.05"; }; apps = [ - { - name = "check-sandbox"; - verbose = true; - share = pkgs.foot; - packages = [ ]; - command = "${pkgs.callPackage ./sandbox { - inherit (config.environment.fortify.package) version; - }}"; - extraPaths = [ - { - src = "/proc/mounts"; - dst = "/.fortify/mounts"; - } - ]; - } + testCases.moduleDefault + { name = "ne-foot"; verbose = true; diff --git a/test/sandbox/assert.go b/test/sandbox/assert.go index 3a7b31e..99ac9e8 100644 --- a/test/sandbox/assert.go +++ b/test/sandbox/assert.go @@ -5,6 +5,7 @@ import ( "io/fs" "log" "os" + "slices" ) var ( @@ -16,76 +17,103 @@ var ( func printf(format string, v ...any) { printfFunc(format, v...) } func fatalf(format string, v ...any) { fatalfFunc(format, v...) } -func mustDecode(wantFile string, v any) { - if f, err := os.Open(wantFile); err != nil { - fatalf("cannot open %q: %v", wantFile, err) - } else if err = json.NewDecoder(f).Decode(v); err != nil { - fatalf("cannot decode %q: %v", wantFile, err) - } else if err = f.Close(); err != nil { - fatalf("cannot close %q: %v", wantFile, err) - } +type TestCase struct { + FS *FS `json:"fs"` + Mount []*Mntent `json:"mount"` + Seccomp bool `json:"seccomp"` } -func MustAssertMounts(name, hostMountsFile, wantFile string) { - hostMounts := make([]*Mntent, 0, 128) - if err := IterMounts(hostMountsFile, func(e *Mntent) { - hostMounts = append(hostMounts, e) - }); err != nil { - fatalf("cannot parse host mounts: %v", err) +type T struct { + FS fs.FS + + MountsPath, PMountsPath string +} + +func (t *T) MustCheckFile(wantFilePath string) { + var want *TestCase + mustDecode(wantFilePath, &want) + t.MustCheck(want) +} + +func (t *T) MustCheck(want *TestCase) { + if want.FS != nil && t.FS != nil { + if err := want.FS.Compare(".", t.FS); err != nil { + fatalf("%v", err) + } + } else { + printf("[SKIP] skipping fs check") } - var want []Mntent - mustDecode(wantFile, &want) + if want.Mount != nil && t.PMountsPath != "" { + pm := mustOpenMounts(t.PMountsPath) + passthruMounts := slices.AppendSeq(make([]*Mntent, 0, 128), pm.Entries()) + if err := pm.Err(); err != nil { + fatalf("cannot parse host mounts: %v", err) + } - for i := range want { - if want[i].Opts == "host_passthrough" { - for _, ent := range hostMounts { - if want[i].FSName == ent.FSName && want[i].Type == ent.Type { - // special case for tmpfs bind mounts - if want[i].FSName == "tmpfs" && want[i].Dir != ent.Dir { - continue + for _, e := range want.Mount { + if e.Opts == "host_passthrough" { + for _, ent := range passthruMounts { + if e.FSName == ent.FSName && e.Type == ent.Type { + // special case for tmpfs bind mounts + if e.FSName == "tmpfs" && e.Dir != ent.Dir { + continue + } + + e.Opts = ent.Opts + goto out } - - want[i].Opts = ent.Opts - goto out } + fatalf("host passthrough missing %q", e.FSName) + out: } - fatalf("host passthrough missing %q", want[i].FSName) - out: } + + f := mustOpenMounts(t.MountsPath) + i := 0 + for e := range f.Entries() { + if i == len(want.Mount) { + fatalf("got more than %d entries", i) + } + if !e.Is(want.Mount[i]) { + fatalf("entry %d\n got: %s\nwant: %s", i, + e, want.Mount[i]) + } + printf("[ OK ] %s", e) + + i++ + } + if err := f.Err(); err != nil { + fatalf("cannot parse mounts: %v", err) + } + } else { + printf("[SKIP] skipping mounts check") } - i := 0 - if err := IterMounts(name, func(e *Mntent) { - if i == len(want) { - fatalf("got more than %d entries", i) + if want.Seccomp { + if TrySyscalls() != nil { + os.Exit(1) } - if !e.Is(&want[i]) { - fatalf("entry %d\n got: %s\nwant: %s", i, - e, &want[i]) - } - - printf("%s", e) - i++ - }); err != nil { - fatalf("cannot iterate mounts: %v", err) + } else { + printf("[SKIP] skipping seccomp check") } } -func MustAssertFS(e fs.FS, wantFile string) { - var want *FS - mustDecode(wantFile, &want) - if want == nil { - fatalf("invalid payload") - } - - if err := want.Compare(".", e); err != nil { - fatalf("%v", err) +func mustDecode(wantFilePath string, v any) { + if f, err := os.Open(wantFilePath); err != nil { + fatalf("cannot open %q: %v", wantFilePath, err) + } else if err = json.NewDecoder(f).Decode(v); err != nil { + fatalf("cannot decode %q: %v", wantFilePath, err) + } else if err = f.Close(); err != nil { + fatalf("cannot close %q: %v", wantFilePath, err) } } -func MustAssertSeccomp() { - if TrySyscalls() != nil { - os.Exit(1) +func mustOpenMounts(name string) *MountsFile { + if f, err := OpenMounts(name); err != nil { + fatalf("cannot open mounts %q: %v", name, err) + panic("unreachable") + } else { + return f } } diff --git a/test/sandbox/seccomp.nix b/test/sandbox/assert.nix similarity index 57% rename from test/sandbox/seccomp.nix rename to test/sandbox/assert.nix index 3cf9b58..d45e4cb 100644 --- a/test/sandbox/seccomp.nix +++ b/test/sandbox/assert.nix @@ -3,18 +3,22 @@ buildGoModule, version, + name, + want, }: let + wantFile = writeText "fortify-${name}-want.json" (builtins.toJSON want); mainFile = writeText "main.go" '' package main + import "os" import "git.gensokyo.uk/security/fortify/test/sandbox" - func main() { sandbox.MustAssertSeccomp() } + func main() { (&sandbox.T{FS: os.DirFS("/"), PMountsPath: "/.fortify/mounts"}).MustCheckFile("${wantFile}") } ''; in buildGoModule { - pname = "check-seccomp"; + pname = "fortify-${name}-check-sandbox"; inherit version; src = ../.; diff --git a/test/sandbox/case/default.nix b/test/sandbox/case/default.nix new file mode 100644 index 0000000..b65b6ed --- /dev/null +++ b/test/sandbox/case/default.nix @@ -0,0 +1,57 @@ +{ + lib, + callPackage, + foot, + + version, +}: +let + fs = mode: dir: data: { + mode = lib.fromHexString mode; + inherit + dir + data + ; + }; + + ent = fsname: dir: type: opts: freq: passno: { + inherit + fsname + dir + type + opts + freq + passno + ; + }; + + callTestCase = + path: + let + tc = import path { + inherit + fs + ent + ; + }; + in + { + name = "check-sandbox-${tc.name}"; + verbose = true; + share = foot; + packages = [ ]; + command = "${callPackage ../. { + inherit (tc) name want; + inherit version; + }}"; + extraPaths = [ + { + src = "/proc/mounts"; + dst = "/.fortify/mounts"; + } + ]; + }; +in +{ + moduleDefault = callTestCase ./module-default.nix; +} diff --git a/test/sandbox/fs.nix b/test/sandbox/case/module-default.nix similarity index 66% rename from test/sandbox/fs.nix rename to test/sandbox/case/module-default.nix index 9714a82..caca674 100644 --- a/test/sandbox/fs.nix +++ b/test/sandbox/case/module-default.nix @@ -1,22 +1,9 @@ +{ fs, ent }: { - lib, - writeText, - buildGoModule, + name = "module-default"; - version, -}: -let - wantFS = - let - fs = mode: dir: data: { - mode = lib.fromHexString mode; - inherit - dir - data - ; - }; - in - fs "dead" { + want = { + fs = fs "dead" { ".fortify" = fs "800001ed" { etc = fs "800001ed" null null; sbin = fs "800001c0" { @@ -191,24 +178,45 @@ let } null; } null; - mainFile = writeText "main.go" '' - package main + mount = [ + (ent "tmpfs" "/" "tmpfs" "rw,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) + (ent "proc" "/proc" "proc" "rw,nosuid,nodev,noexec,relatime" 0 0) + (ent "tmpfs" "/.fortify" "tmpfs" "rw,nosuid,nodev,relatime,size=4k,mode=755,uid=1000001,gid=1000001" 0 0) + (ent "tmpfs" "/dev" "tmpfs" "rw,nosuid,nodev,relatime,mode=755,uid=1000001,gid=1000001" 0 0) + (ent "devtmpfs" "/dev/null" "devtmpfs" "host_passthrough" 0 0) + (ent "devtmpfs" "/dev/zero" "devtmpfs" "host_passthrough" 0 0) + (ent "devtmpfs" "/dev/full" "devtmpfs" "host_passthrough" 0 0) + (ent "devtmpfs" "/dev/random" "devtmpfs" "host_passthrough" 0 0) + (ent "devtmpfs" "/dev/urandom" "devtmpfs" "host_passthrough" 0 0) + (ent "devtmpfs" "/dev/tty" "devtmpfs" "host_passthrough" 0 0) + (ent "devpts" "/dev/pts" "devpts" "rw,nosuid,noexec,relatime,mode=620,ptmxmode=666" 0 0) + (ent "mqueue" "/dev/mqueue" "mqueue" "rw,relatime" 0 0) + (ent "/dev/disk/by-label/nixos" "/bin" "ext4" "ro,nosuid,nodev,relatime" 0 0) + (ent "/dev/disk/by-label/nixos" "/usr/bin" "ext4" "ro,nosuid,nodev,relatime" 0 0) + (ent "overlay" "/nix/store" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) + (ent "overlay" "/run/current-system" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) + (ent "sysfs" "/sys/block" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) + (ent "sysfs" "/sys/bus" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) + (ent "sysfs" "/sys/class" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) + (ent "sysfs" "/sys/dev" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) + (ent "sysfs" "/sys/devices" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) + (ent "overlay" "/run/opengl-driver" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) + (ent "devtmpfs" "/dev/dri" "devtmpfs" "host_passthrough" 0 0) + (ent "proc" "/.fortify/mounts" "proc" "ro,nosuid,nodev,noexec,relatime" 0 0) + (ent "/dev/disk/by-label/nixos" "/.fortify/etc" "ext4" "ro,nosuid,nodev,relatime" 0 0) + (ent "tmpfs" "/run/user" "tmpfs" "rw,nosuid,nodev,relatime,size=1024k,mode=755,uid=1000001,gid=1000001" 0 0) + (ent "tmpfs" "/run/user/65534" "tmpfs" "rw,nosuid,nodev,relatime,size=8192k,mode=755,uid=1000001,gid=1000001" 0 0) + (ent "/dev/disk/by-label/nixos" "/tmp" "ext4" "rw,nosuid,nodev,relatime" 0 0) + (ent "/dev/disk/by-label/nixos" "/var/lib/fortify/u0/a1" "ext4" "rw,nosuid,nodev,relatime" 0 0) + (ent "tmpfs" "/etc/passwd" "tmpfs" "ro,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) + (ent "tmpfs" "/etc/group" "tmpfs" "ro,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) + (ent "/dev/disk/by-label/nixos" "/run/user/65534/wayland-0" "ext4" "ro,nosuid,nodev,relatime" 0 0) + (ent "tmpfs" "/run/user/65534/pulse/native" "tmpfs" "host_passthrough" 0 0) + (ent "/dev/disk/by-label/nixos" "/run/user/65534/bus" "ext4" "ro,nosuid,nodev,relatime" 0 0) + (ent "tmpfs" "/var/run/nscd" "tmpfs" "rw,nosuid,nodev,relatime,size=8k,mode=755,uid=1000001,gid=1000001" 0 0) + (ent "overlay" "/.fortify/sbin/fortify" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) + ]; - import "os" - import "git.gensokyo.uk/security/fortify/test/sandbox" - - func main() { sandbox.MustAssertFS(os.DirFS("/"), "${writeText "want-fs.json" (builtins.toJSON wantFS)}") } - ''; -in -buildGoModule { - pname = "check-fs"; - inherit version; - - src = ../.; - vendorHash = null; - - preBuild = '' - go mod init git.gensokyo.uk/security/fortify/test >& /dev/null - cp ${mainFile} main.go - ''; + seccomp = true; + }; } diff --git a/test/sandbox/default.nix b/test/sandbox/default.nix index 8543493..9e7f12b 100644 --- a/test/sandbox/default.nix +++ b/test/sandbox/default.nix @@ -2,13 +2,12 @@ writeShellScript, callPackage, + name, version, + want, }: -writeShellScript "check-sandbox" '' +writeShellScript "fortify-${name}-check-sandbox-script" '' set -e - ${callPackage ./mount.nix { inherit version; }}/bin/test - ${callPackage ./fs.nix { inherit version; }}/bin/test - ${callPackage ./seccomp.nix { inherit version; }}/bin/test - + ${callPackage ./assert.nix { inherit name version want; }}/bin/test touch /tmp/sandbox-ok '' diff --git a/test/sandbox/fs_test.go b/test/sandbox/fs_test.go index 5ac31df..1262dda 100644 --- a/test/sandbox/fs_test.go +++ b/test/sandbox/fs_test.go @@ -75,10 +75,4 @@ func TestCompare(t *testing.T) { } }) } - - t.Run("assert", func(t *testing.T) { - oldFatal := sandbox.SwapFatal(t.Fatalf) - t.Cleanup(func() { sandbox.SwapFatal(oldFatal) }) - sandbox.MustAssertFS(make(fstest.MapFS), sandbox.MustWantFile(t, &sandbox.FS{Mode: 0xDEADBEEF})) - }) } diff --git a/test/sandbox/mount.go b/test/sandbox/mount.go index 9a3b58c..d65824f 100644 --- a/test/sandbox/mount.go +++ b/test/sandbox/mount.go @@ -12,6 +12,7 @@ import "C" import ( "fmt" + "iter" "runtime" "sync" "unsafe" @@ -49,21 +50,38 @@ func (e *Mntent) Is(want *Mntent) bool { (e.Passno == want.Passno || want.Passno == -1) } -func IterMounts(name string, f func(e *Mntent)) error { - m := new(mounts) - m.p = name - if err := m.open(); err != nil { - return err - } +type MountsFile struct { + m *mounts + mu sync.Mutex + done bool +} - for m.scan() { - e := new(Mntent) - m.copy(e) - f(e) - } +func OpenMounts(name string) (*MountsFile, error) { + f := new(MountsFile) + f.m = new(mounts) + f.m.p = name + return f, f.m.open() +} - m.close() - return m.Err() +func (f *MountsFile) Err() error { return f.m.Err() } +func (f *MountsFile) Entries() iter.Seq[*Mntent] { + return func(yield func(*Mntent) bool) { + f.mu.Lock() + defer f.mu.Unlock() + if f.done { + return + } + + for f.m.scan() { + e := new(Mntent) + f.m.copy(e) + if !yield(e) { + return + } + } + f.done = true + f.m.close() + } } type mounts struct { diff --git a/test/sandbox/mount.nix b/test/sandbox/mount.nix deleted file mode 100644 index 0c1bda1..0000000 --- a/test/sandbox/mount.nix +++ /dev/null @@ -1,79 +0,0 @@ -{ - writeText, - buildGoModule, - - version, -}: -let - wantMounts = - let - ent = fsname: dir: type: opts: freq: passno: { - inherit - fsname - dir - type - opts - freq - passno - ; - }; - in - [ - (ent "tmpfs" "/" "tmpfs" "rw,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) - (ent "proc" "/proc" "proc" "rw,nosuid,nodev,noexec,relatime" 0 0) - (ent "tmpfs" "/.fortify" "tmpfs" "rw,nosuid,nodev,relatime,size=4k,mode=755,uid=1000001,gid=1000001" 0 0) - (ent "tmpfs" "/dev" "tmpfs" "rw,nosuid,nodev,relatime,mode=755,uid=1000001,gid=1000001" 0 0) - (ent "devtmpfs" "/dev/null" "devtmpfs" "host_passthrough" 0 0) - (ent "devtmpfs" "/dev/zero" "devtmpfs" "host_passthrough" 0 0) - (ent "devtmpfs" "/dev/full" "devtmpfs" "host_passthrough" 0 0) - (ent "devtmpfs" "/dev/random" "devtmpfs" "host_passthrough" 0 0) - (ent "devtmpfs" "/dev/urandom" "devtmpfs" "host_passthrough" 0 0) - (ent "devtmpfs" "/dev/tty" "devtmpfs" "host_passthrough" 0 0) - (ent "devpts" "/dev/pts" "devpts" "rw,nosuid,noexec,relatime,mode=620,ptmxmode=666" 0 0) - (ent "mqueue" "/dev/mqueue" "mqueue" "rw,relatime" 0 0) - (ent "/dev/disk/by-label/nixos" "/bin" "ext4" "ro,nosuid,nodev,relatime" 0 0) - (ent "/dev/disk/by-label/nixos" "/usr/bin" "ext4" "ro,nosuid,nodev,relatime" 0 0) - (ent "overlay" "/nix/store" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) - (ent "overlay" "/run/current-system" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) - (ent "sysfs" "/sys/block" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) - (ent "sysfs" "/sys/bus" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) - (ent "sysfs" "/sys/class" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) - (ent "sysfs" "/sys/dev" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) - (ent "sysfs" "/sys/devices" "sysfs" "ro,nosuid,nodev,noexec,relatime" 0 0) - (ent "overlay" "/run/opengl-driver" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) - (ent "devtmpfs" "/dev/dri" "devtmpfs" "host_passthrough" 0 0) - (ent "proc" "/.fortify/mounts" "proc" "ro,nosuid,nodev,noexec,relatime" 0 0) - (ent "/dev/disk/by-label/nixos" "/.fortify/etc" "ext4" "ro,nosuid,nodev,relatime" 0 0) - (ent "tmpfs" "/run/user" "tmpfs" "rw,nosuid,nodev,relatime,size=1024k,mode=755,uid=1000001,gid=1000001" 0 0) - (ent "tmpfs" "/run/user/65534" "tmpfs" "rw,nosuid,nodev,relatime,size=8192k,mode=755,uid=1000001,gid=1000001" 0 0) - (ent "/dev/disk/by-label/nixos" "/tmp" "ext4" "rw,nosuid,nodev,relatime" 0 0) - (ent "/dev/disk/by-label/nixos" "/var/lib/fortify/u0/a1" "ext4" "rw,nosuid,nodev,relatime" 0 0) - (ent "tmpfs" "/etc/passwd" "tmpfs" "ro,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) - (ent "tmpfs" "/etc/group" "tmpfs" "ro,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) - (ent "/dev/disk/by-label/nixos" "/run/user/65534/wayland-0" "ext4" "ro,nosuid,nodev,relatime" 0 0) - (ent "tmpfs" "/run/user/65534/pulse/native" "tmpfs" "host_passthrough" 0 0) - (ent "/dev/disk/by-label/nixos" "/run/user/65534/bus" "ext4" "ro,nosuid,nodev,relatime" 0 0) - (ent "tmpfs" "/var/run/nscd" "tmpfs" "rw,nosuid,nodev,relatime,size=8k,mode=755,uid=1000001,gid=1000001" 0 0) - (ent "overlay" "/.fortify/sbin/fortify" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0) - ]; - - mainFile = writeText "main.go" '' - package main - - import "git.gensokyo.uk/security/fortify/test/sandbox" - - func main() { sandbox.MustAssertMounts("", "/.fortify/mounts", "${writeText "want-mounts.json" (builtins.toJSON wantMounts)}") } - ''; -in -buildGoModule { - pname = "check-mounts"; - inherit version; - - src = ../.; - vendorHash = null; - - preBuild = '' - go mod init git.gensokyo.uk/security/fortify/test >& /dev/null - cp ${mainFile} main.go - ''; -} diff --git a/test/sandbox/mount_test.go b/test/sandbox/mount_test.go index 47df210..23a58fb 100644 --- a/test/sandbox/mount_test.go +++ b/test/sandbox/mount_test.go @@ -92,27 +92,29 @@ overlay /.fortify/sbin/fortify overlay ro,nosuid,nodev,relatime,lowerdir=/mnt-ro } t.Run(tc.name, func(t *testing.T) { + f, err := sandbox.OpenMounts(name) + if err != nil { + t.Fatalf("OpenMounts: error = %v", err) + } + i := 0 - if err := sandbox.IterMounts(name, func(e *sandbox.Mntent) { + for e := range f.Entries() { if i == len(tc.want) { - t.Errorf("IterMounts: got more than %d entries", i) + t.Errorf("Entries: got more than %d entries", i) t.FailNow() } if *e != tc.want[i] { - t.Errorf("IterMounts: entry %d\n got: %s\nwant: %s", i, + t.Errorf("Entries: entry %d\n got: %s\nwant: %s", i, e, &tc.want[i]) t.FailNow() } - i++ - }); err != nil { - t.Fatalf("IterMounts: error = %v", err) - } - }) - t.Run(tc.name+" assert", func(t *testing.T) { - oldFatal := sandbox.SwapFatal(t.Fatalf) - t.Cleanup(func() { sandbox.SwapFatal(oldFatal) }) - sandbox.MustAssertMounts(name, name, sandbox.MustWantFile(t, tc.want)) + i++ + } + + if err = f.Err(); err != nil { + t.Fatalf("MountsFile: error = %v", err) + } }) if err := os.Remove(name); err != nil { diff --git a/test/test.py b/test/test.py index 99b2f16..7f106a9 100644 --- a/test/test.py +++ b/test/test.py @@ -102,8 +102,8 @@ if denyOutput != "fsu: uid 1001 is not in the fsurc file\n": if denyOutputVerbose != "fsu: uid 1001 is not in the fsurc file\nfortify: *cannot obtain uid from fsu: permission denied\n": raise Exception(f"unexpected deny verbose output:\n{denyOutputVerbose}") -# Check sandbox state: -swaymsg("exec check-sandbox") +# Check sandbox outcome: +swaymsg("exec check-sandbox-module-default") machine.wait_for_file("/tmp/fortify.1000/tmpdir/1/sandbox-ok", timeout=15) # Start fortify permissive defaults outside Wayland session: