aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-07-09 03:47:16 +0900
committerOphestra <cat@gensokyo.uk>2025-07-09 04:21:35 +0900
commite574042d765f135814c5afabaf24cb7109fab175 (patch)
tree6301ab836acc681c90891ca199c5dcc8cdca9ad3 /test
parent2b44493e8a255b40a9809208f5c751ca7c539027 (diff)
test/sandbox: verify seccomp on all test cases
This change also makes seccomp hashes cross-platform. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test')
-rw-r--r--test/sandbox/assert.go33
-rw-r--r--test/sandbox/case/default.nix7
-rw-r--r--test/sandbox/case/device.nix6
-rw-r--r--test/sandbox/case/mapuid.nix6
-rw-r--r--test/sandbox/case/pdlike.nix254
-rw-r--r--test/sandbox/case/preset.nix6
-rw-r--r--test/sandbox/case/tty.nix6
-rw-r--r--test/sandbox/configuration.nix2
-rw-r--r--test/sandbox/ptrace.go48
-rw-r--r--test/sandbox/test.py14
-rw-r--r--test/sandbox/tool/main.go48
11 files changed, 345 insertions, 85 deletions
diff --git a/test/sandbox/assert.go b/test/sandbox/assert.go
index 388d2328..57d17039 100644
--- a/test/sandbox/assert.go
+++ b/test/sandbox/assert.go
@@ -17,7 +17,6 @@ import (
"log"
"os"
"syscall"
- "time"
)
var (
@@ -42,13 +41,10 @@ type T struct {
MountsPath string
}
-func (t *T) MustCheckFile(wantFilePath, markerPath string) {
+func (t *T) MustCheckFile(wantFilePath string) {
var want *TestCase
mustDecode(wantFilePath, &want)
t.MustCheck(want)
- if _, err := os.Create(markerPath); err != nil {
- fatalf("cannot create success marker: %v", err)
- }
}
func (t *T) MustCheck(want *TestCase) {
@@ -167,31 +163,10 @@ func CheckFilter(pid int, want string) error {
}()
h := sha512.New()
- {
- getFilter:
- buf, err := getFilter[[8]byte](pid, 0)
- /* this is not how ESRCH should be handled: the manpage advises the
- use of waitpid, however that is not applicable for attaching to an
- arbitrary process, and spawning target process here is not easily
- possible under the current testing framework;
-
- despite checking for /proc/pid/status indicating state t (tracing stop),
- it does not appear to be directly related to the internal state used to
- determine whether a process is ready to accept ptrace operations, it also
- introduces a TOCTOU that is irrelevant in the testing vm; this behaviour
- is kept anyway as it reduces the average iterations required here;
-
- since this code is only ever compiled into the test program, whatever
- implications this ugliness might have should not hurt anyone */
- if errors.Is(err, syscall.ESRCH) {
- time.Sleep(100 * time.Millisecond)
- goto getFilter
- }
-
- if err != nil {
- return err
- }
+ if buf, err := getFilter[[8]byte](pid, 0); err != nil {
+ return err
+ } else {
for _, b := range buf {
h.Write(b[:])
}
diff --git a/test/sandbox/case/default.nix b/test/sandbox/case/default.nix
index 05a13de1..6c7cf127 100644
--- a/test/sandbox/case/default.nix
+++ b/test/sandbox/case/default.nix
@@ -1,4 +1,4 @@
-lib: testProgram:
+system: lib: testProgram:
let
fs = mode: dir: data: {
mode = lib.fromHexString mode;
@@ -43,13 +43,17 @@ let
device
mapRealUid
useCommonPaths
+ userns
;
share = testProgram;
packages = [ ];
path = "${testProgram}/bin/hakurei-test";
args = [
"test"
+ "-t"
(toString (builtins.toFile "hakurei-${tc.name}-want.json" (builtins.toJSON tc.want)))
+ "-s"
+ tc.expectedFilter.${system}
];
};
@@ -60,4 +64,5 @@ in
${testCaseName "tty"} = callTestCase ./tty.nix 2;
${testCaseName "mapuid"} = callTestCase ./mapuid.nix 3;
${testCaseName "device"} = callTestCase ./device.nix 4;
+ ${testCaseName "pdlike"} = callTestCase ./pdlike.nix 5;
}
diff --git a/test/sandbox/case/device.nix b/test/sandbox/case/device.nix
index 9765fd58..cba608f1 100644
--- a/test/sandbox/case/device.nix
+++ b/test/sandbox/case/device.nix
@@ -9,6 +9,12 @@
device = true;
mapRealUid = false;
useCommonPaths = true;
+ userns = false;
+
+ # 0, PresetStrict
+ expectedFilter = {
+ x86_64-linux = "e880298df2bd6751d0040fc21bc0ed4c00f95dc0d7ba506c244d8b8cf6866dba8ef4a33296f287b66cccc1d78e97026597f84cc7dec1573e148960fbd35cd735";
+ };
want = {
env = [
diff --git a/test/sandbox/case/mapuid.nix b/test/sandbox/case/mapuid.nix
index af70cb30..78f23dc8 100644
--- a/test/sandbox/case/mapuid.nix
+++ b/test/sandbox/case/mapuid.nix
@@ -9,6 +9,12 @@
device = false;
mapRealUid = true;
useCommonPaths = true;
+ userns = false;
+
+ # 0, PresetStrict
+ expectedFilter = {
+ x86_64-linux = "e880298df2bd6751d0040fc21bc0ed4c00f95dc0d7ba506c244d8b8cf6866dba8ef4a33296f287b66cccc1d78e97026597f84cc7dec1573e148960fbd35cd735";
+ };
want = {
env = [
diff --git a/test/sandbox/case/pdlike.nix b/test/sandbox/case/pdlike.nix
new file mode 100644
index 00000000..6c42e9d4
--- /dev/null
+++ b/test/sandbox/case/pdlike.nix
@@ -0,0 +1,254 @@
+{
+ fs,
+ ent,
+ ignore,
+}:
+{
+ name = "pdlike";
+ tty = true;
+ device = false;
+ mapRealUid = false;
+ useCommonPaths = false;
+ userns = true;
+
+ # 0, PresetExt | PresetDenyDevel
+ expectedFilter = {
+ x86_64-linux = "c698b081ff957afe17a6d94374537d37f2a63f6f9dd75da7546542407a9e32476ebda3312ba7785d7f618542bcfaf27ca27dcc2dddba852069d28bcfe8cad39a";
+ };
+
+ want = {
+ env = [
+ "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/65534/bus"
+ "HOME=/var/lib/hakurei/u0/a5"
+ "PULSE_SERVER=unix:/run/user/65534/pulse/native"
+ "SHELL=/run/current-system/sw/bin/bash"
+ "TERM=linux"
+ "USER=u0_a5"
+ "WAYLAND_DISPLAY=wayland-0"
+ "XDG_RUNTIME_DIR=/run/user/65534"
+ "XDG_SESSION_CLASS=user"
+ "XDG_SESSION_TYPE=tty"
+ ];
+
+ fs = fs "dead" {
+ ".hakurei" = fs "800001ed" { } null;
+ bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
+ dev = fs "800001ed" {
+ console = fs "4200190" null null;
+ core = fs "80001ff" null null;
+ dri = fs "800001ed" {
+ by-path = fs "800001ed" {
+ "pci-0000:00:09.0-card" = fs "80001ff" null null;
+ "pci-0000:00:09.0-render" = fs "80001ff" null null;
+ } null;
+ card0 = fs "42001b0" null null;
+ renderD128 = fs "42001b6" null null;
+ } null;
+ fd = fs "80001ff" null null;
+ full = fs "42001b6" null null;
+ mqueue = fs "801001ff" { } null;
+ null = fs "42001b6" null "";
+ ptmx = fs "80001ff" null null;
+ pts = fs "800001ed" { ptmx = fs "42001b6" null null; } null;
+ random = fs "42001b6" null null;
+ shm = fs "800001ed" { } null;
+ stderr = fs "80001ff" null null;
+ stdin = fs "80001ff" null null;
+ stdout = fs "80001ff" null null;
+ tty = fs "42001b6" null null;
+ urandom = fs "42001b6" null null;
+ zero = fs "42001b6" null null;
+ } null;
+ etc = fs "800001ed" {
+ ".clean" = fs "80001ff" null null;
+ ".host" = fs "800001c0" null null;
+ ".updated" = fs "80001ff" null null;
+ "NIXOS" = fs "80001ff" null null;
+ "X11" = fs "80001ff" null null;
+ "alsa" = fs "80001ff" null null;
+ "bash_logout" = fs "80001ff" null null;
+ "bashrc" = fs "80001ff" null null;
+ "binfmt.d" = fs "80001ff" null null;
+ "dbus-1" = fs "80001ff" null null;
+ "default" = fs "80001ff" null null;
+ "dhcpcd.exit-hook" = fs "80001ff" null null;
+ "fonts" = fs "80001ff" null null;
+ "fstab" = fs "80001ff" null null;
+ "hsurc" = fs "80001ff" null null;
+ "fuse.conf" = fs "80001ff" null null;
+ "group" = fs "180" null "hakurei:x:65534:\n";
+ "host.conf" = fs "80001ff" null null;
+ "hostname" = fs "80001ff" null null;
+ "hosts" = fs "80001ff" null null;
+ "inputrc" = fs "80001ff" null null;
+ "issue" = fs "80001ff" null null;
+ "kbd" = fs "80001ff" null null;
+ "locale.conf" = fs "80001ff" null null;
+ "login.defs" = fs "80001ff" null null;
+ "lsb-release" = fs "80001ff" null null;
+ "lvm" = fs "80001ff" null null;
+ "machine-id" = fs "80001ff" null null;
+ "man_db.conf" = fs "80001ff" null null;
+ "modprobe.d" = fs "80001ff" null null;
+ "modules-load.d" = fs "80001ff" null null;
+ "mtab" = fs "80001ff" null null;
+ "nanorc" = fs "80001ff" null null;
+ "netgroup" = fs "80001ff" null null;
+ "nix" = fs "80001ff" null null;
+ "nixos" = fs "80001ff" null null;
+ "nscd.conf" = fs "80001ff" null null;
+ "nsswitch.conf" = fs "80001ff" null null;
+ "os-release" = fs "80001ff" null null;
+ "pam" = fs "80001ff" null null;
+ "pam.d" = fs "80001ff" null null;
+ "passwd" = fs "180" null "u0_a5:x:65534:65534:Hakurei:/var/lib/hakurei/u0/a5:/run/current-system/sw/bin/bash\n";
+ "pipewire" = fs "80001ff" null null;
+ "pki" = fs "80001ff" null null;
+ "polkit-1" = fs "80001ff" null null;
+ "profile" = fs "80001ff" null null;
+ "protocols" = fs "80001ff" null null;
+ "resolv.conf" = fs "80001ff" null null;
+ "resolvconf.conf" = fs "80001ff" null null;
+ "rpc" = fs "80001ff" null null;
+ "services" = fs "80001ff" null null;
+ "set-environment" = fs "80001ff" null null;
+ "shadow" = fs "80001ff" null null;
+ "shells" = fs "80001ff" null null;
+ "ssh" = fs "80001ff" null null;
+ "ssl" = fs "80001ff" null null;
+ "static" = fs "80001ff" null null;
+ "subgid" = fs "80001ff" null null;
+ "subuid" = fs "80001ff" null null;
+ "sudoers" = fs "80001ff" null null;
+ "sway" = fs "80001ff" null null;
+ "sysctl.d" = fs "80001ff" null null;
+ "systemd" = fs "80001ff" null null;
+ "terminfo" = fs "80001ff" null null;
+ "tmpfiles.d" = fs "80001ff" null null;
+ "udev" = fs "80001ff" null null;
+ "vconsole.conf" = fs "80001ff" null null;
+ "xdg" = fs "80001ff" null null;
+ "zoneinfo" = fs "80001ff" null null;
+ } null;
+ nix = fs "800001c0" { store = fs "801001fd" null null; } null;
+ proc = fs "8000016d" null null;
+ run = fs "800001ed" {
+ current-system = fs "80001ff" null null;
+ opengl-driver = fs "80001ff" null null;
+ user = fs "800001ed" {
+ "65534" = fs "800001f8" {
+ bus = fs "10001fd" null null;
+ pulse = fs "800001c0" { native = fs "10001b6" null null; } null;
+ wayland-0 = fs "1000038" null null;
+ } null;
+ } null;
+ } null;
+ sys = fs "800001c0" {
+ block = fs "800001ed" {
+ fd0 = fs "80001ff" null null;
+ loop0 = fs "80001ff" null null;
+ loop1 = fs "80001ff" null null;
+ loop2 = fs "80001ff" null null;
+ loop3 = fs "80001ff" null null;
+ loop4 = fs "80001ff" null null;
+ loop5 = fs "80001ff" null null;
+ loop6 = fs "80001ff" null null;
+ loop7 = fs "80001ff" null null;
+ sr0 = fs "80001ff" null null;
+ vda = fs "80001ff" null null;
+ } null;
+ bus = fs "800001ed" null null;
+ class = fs "800001ed" null null;
+ dev = fs "800001ed" {
+ block = fs "800001ed" null null;
+ char = fs "800001ed" null null;
+ } null;
+ devices = fs "800001ed" null null;
+ } null;
+ tmp = fs "800001f8" { } null;
+ usr = fs "800001c0" { bin = fs "800001ed" { env = fs "80001ff" null null; } null; } null;
+ var = fs "800001c0" {
+ lib = fs "800001c0" {
+ hakurei = fs "800001c0" {
+ u0 = fs "800001c0" {
+ a5 = fs "800001c0" {
+ ".cache" = fs "800001ed" { ".keep" = fs "80001ff" null ""; } null;
+ ".config" = fs "800001ed" {
+ "environment.d" = fs "800001ed" { "10-home-manager.conf" = fs "80001ff" null null; } null;
+ systemd = fs "800001ed" {
+ user = fs "800001ed" { "tray.target" = fs "80001ff" null null; } null;
+ } null;
+ } null;
+ ".local" = fs "800001ed" {
+ share = fs "800001ed" {
+ dbus-1 = fs "800001ed" {
+ services = fs "800001ed" {
+ "ca.desrt.dconf.service" = fs "80001ff" null null;
+ } null;
+ } null;
+ } null;
+ state = fs "800001ed" {
+ ".keep" = fs "80001ff" null "";
+ home-manager = fs "800001ed" { gcroots = fs "800001ed" { current-home = fs "80001ff" null null; } null; } null;
+ nix = fs "800001ed" {
+ profiles = fs "800001ed" {
+ home-manager = fs "80001ff" null null;
+ home-manager-1-link = fs "80001ff" null null;
+ profile = fs "80001ff" null null;
+ profile-1-link = fs "80001ff" null null;
+ } null;
+ } null;
+ } null;
+ } null;
+ ".nix-defexpr" = fs "800001ed" {
+ channels = fs "80001ff" null null;
+ channels_root = fs "80001ff" null null;
+ } null;
+ ".nix-profile" = fs "80001ff" null null;
+ } null;
+ } null;
+ } null;
+ } null;
+ run = fs "800001ed" { nscd = fs "800001ed" { } null; } null;
+ } null;
+ } null;
+
+ mount = [
+ (ent "/sysroot" "/" "rw,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000005,gid=1000005")
+ (ent "/" "/proc" "rw,nosuid,nodev,noexec,relatime" "proc" "proc" "rw")
+ (ent "/" "/.hakurei" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000005,gid=1000005")
+ (ent "/" "/dev" "rw,nosuid,nodev,relatime" "tmpfs" "devtmpfs" "rw,mode=755,uid=1000005,gid=1000005")
+ (ent "/null" "/dev/null" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
+ (ent "/zero" "/dev/zero" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
+ (ent "/full" "/dev/full" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
+ (ent "/random" "/dev/random" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
+ (ent "/urandom" "/dev/urandom" "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 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 "/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 "/" "/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 "/block" "/sys/block" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
+ (ent "/bus" "/sys/bus" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
+ (ent "/class" "/sys/class" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
+ (ent "/dev" "/sys/dev" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
+ (ent "/devices" "/sys/devices" "ro,nosuid,nodev,noexec,relatime" "sysfs" "sysfs" "rw")
+ (ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
+ (ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
+ (ent "/" "/run/user" "rw,nosuid,nodev,relatime" "tmpfs" "tmpfs" "rw,size=4k,mode=755,uid=1000005,gid=1000005")
+ (ent "/tmp/hakurei.1000/runtime/5" "/run/user/65534" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
+ (ent "/tmp/hakurei.1000/tmpdir/5" "/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
+ (ent "/var/lib/hakurei/u0/a5" "/var/lib/hakurei/u0/a5" "rw,nosuid,nodev,relatime" "ext4" "/dev/disk/by-label/nixos" "rw")
+ (ent ignore "/etc/passwd" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000005,gid=1000005")
+ (ent ignore "/etc/group" "ro,nosuid,nodev,relatime" "tmpfs" "rootfs" "rw,uid=1000005,gid=1000005")
+ (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/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=1000005,gid=1000005")
+ ];
+
+ seccomp = true;
+ };
+}
diff --git a/test/sandbox/case/preset.nix b/test/sandbox/case/preset.nix
index a2c2eb4f..ded31755 100644
--- a/test/sandbox/case/preset.nix
+++ b/test/sandbox/case/preset.nix
@@ -9,6 +9,12 @@
device = false;
mapRealUid = false;
useCommonPaths = false;
+ userns = false;
+
+ # 0, PresetStrict
+ expectedFilter = {
+ x86_64-linux = "e880298df2bd6751d0040fc21bc0ed4c00f95dc0d7ba506c244d8b8cf6866dba8ef4a33296f287b66cccc1d78e97026597f84cc7dec1573e148960fbd35cd735";
+ };
want = {
env = [
diff --git a/test/sandbox/case/tty.nix b/test/sandbox/case/tty.nix
index 3132d257..55de7e93 100644
--- a/test/sandbox/case/tty.nix
+++ b/test/sandbox/case/tty.nix
@@ -9,6 +9,12 @@
device = false;
mapRealUid = false;
useCommonPaths = true;
+ userns = false;
+
+ # 0, PresetExt | PresetDenyNS | PresetDenyDevel
+ expectedFilter = {
+ x86_64-linux = "0b76007476c1c9e25dbf674c29fdf609a1656a70063e49327654e1b5360ad3da06e1a3e32bf80e961c5516ad83d4b9e7e9bde876a93797e27627d2555c25858b";
+ };
want = {
env = [
diff --git a/test/sandbox/configuration.nix b/test/sandbox/configuration.nix
index c50363cc..cfc1364e 100644
--- a/test/sandbox/configuration.nix
+++ b/test/sandbox/configuration.nix
@@ -75,6 +75,6 @@ in
}
];
- apps = import ./case lib testProgram;
+ apps = import ./case pkgs.system lib testProgram;
};
}
diff --git a/test/sandbox/ptrace.go b/test/sandbox/ptrace.go
index 3f1acad5..8272ff5b 100644
--- a/test/sandbox/ptrace.go
+++ b/test/sandbox/ptrace.go
@@ -3,13 +3,9 @@
package sandbox
import (
- "bufio"
+ "errors"
"fmt"
- "io"
- "os"
- "strings"
"syscall"
- "time"
"unsafe"
)
@@ -41,49 +37,19 @@ func ptrace(op uintptr, pid, addr int, data unsafe.Pointer) (r uintptr, errno sy
}
func ptraceAttach(pid int) error {
- const (
- statePrefix = "State:"
- stateSuffix = "t (tracing stop)"
- )
-
- var r io.ReadSeekCloser
- if f, err := os.Open(fmt.Sprintf("/proc/%d/status", pid)); err != nil {
- return err
- } else {
- r = f
- }
-
if _, errno := ptrace(PTRACE_ATTACH, pid, 0, nil); errno != 0 {
return &ptraceError{"PTRACE_ATTACH", errno}
}
- // ugly! but there does not appear to be another way
+ var status syscall.WaitStatus
for {
- time.Sleep(10 * time.Millisecond)
-
- if _, err := r.Seek(0, io.SeekStart); err != nil {
- return err
- }
- s := bufio.NewScanner(r)
-
- var found bool
- for s.Scan() {
- found = strings.HasPrefix(s.Text(), statePrefix)
- if found {
- break
+ if _, err := syscall.Wait4(pid, &status, syscall.WALL, nil); err != nil {
+ if errors.Is(err, syscall.EINTR) {
+ continue
}
+ fatalf("cannot waitpid: %v", err)
}
- if err := s.Err(); err != nil {
- return err
- }
-
- if !found {
- return syscall.EBADE
- }
-
- if strings.HasSuffix(s.Text(), stateSuffix) {
- break
- }
+ break
}
return nil
diff --git a/test/sandbox/test.py b/test/sandbox/test.py
index 93fb8247..f06e2b50 100644
--- a/test/sandbox/test.py
+++ b/test/sandbox/test.py
@@ -25,6 +25,12 @@ def swaymsg(command: str = "", succeed=True, type="command"):
return parsed
+def check_filter(check_offset, name, pname):
+ pid = int(machine.wait_until_succeeds(f"pgrep -U {1000000+check_offset} -x {pname}", timeout=15))
+ hash = machine.succeed(f"sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-1 check-sandbox-{name} hash 2>/dev/null")
+ print(machine.succeed(f"hakurei-test -s {hash} filter {pid}"))
+
+
start_all()
machine.wait_for_unit("multi-user.target")
@@ -35,11 +41,9 @@ print(machine.succeed("sudo -u alice -i hakurei version"))
machine.wait_for_file("/run/user/1000/wayland-1")
machine.wait_for_file("/tmp/sway-ipc.sock")
-# Check seccomp outcome:
+# Check pd seccomp outcome:
swaymsg("exec hakurei run cat")
-pid = int(machine.wait_until_succeeds("pgrep -U 1000000 -x cat", timeout=5))
-print(machine.succeed(f"hakurei-test filter {pid} c698b081ff957afe17a6d94374537d37f2a63f6f9dd75da7546542407a9e32476ebda3312ba7785d7f618542bcfaf27ca27dcc2dddba852069d28bcfe8cad39a &>/dev/stdout", timeout=5))
-machine.succeed(f"kill -TERM {pid}")
+check_filter(0, "pdlike", "cat")
# Verify capabilities/securebits in user namespace:
print(machine.succeed("sudo -u alice -i hakurei run capsh --print"))
@@ -57,12 +61,14 @@ def check_sandbox(name):
check_offset += 1
swaymsg(f"exec script /dev/null -E always -qec check-sandbox-{name}")
machine.wait_for_file(f"/tmp/hakurei.1000/tmpdir/{check_offset}/sandbox-ok", timeout=15)
+ check_filter(check_offset, name, "hakurei-test")
check_sandbox("preset")
check_sandbox("tty")
check_sandbox("mapuid")
check_sandbox("device")
+check_sandbox("pdlike")
# Exit Sway and verify process exit status 0:
swaymsg("exit", succeed=False)
diff --git a/test/sandbox/tool/main.go b/test/sandbox/tool/main.go
index f53950ce..37167abd 100644
--- a/test/sandbox/tool/main.go
+++ b/test/sandbox/tool/main.go
@@ -3,39 +3,69 @@
package main
import (
+ "flag"
+ "fmt"
"log"
"os"
+ "os/signal"
"strconv"
"strings"
+ "syscall"
"hakurei.app/test/sandbox"
)
+var (
+ flagTestCase string
+ flagBpfHash string
+)
+
+func init() {
+ flag.StringVar(&flagTestCase, "t", "", "Nix store path to test case file")
+ flag.StringVar(&flagBpfHash, "s", "", "String representation of expected bpf sha512 hash")
+}
+
func main() {
log.SetFlags(0)
log.SetPrefix("test: ")
+ flag.Parse()
- if len(os.Args) < 2 {
- log.Fatal("invalid argument")
+ args := flag.Args()
+ if len(args) < 1 {
+ s := make(chan os.Signal, 1)
+ signal.Notify(s, syscall.SIGINT)
+ go func() { <-s; log.Println("exiting on signal (likely from verifier)"); os.Exit(0) }()
+
+ (&sandbox.T{FS: os.DirFS("/")}).MustCheckFile(flagTestCase)
+ if _, err := os.Create("/tmp/sandbox-ok"); err != nil {
+ log.Fatalf("cannot create success marker: %v", err)
+ }
+ log.Println("blocking for seccomp check")
+ select {}
+ return
}
- switch os.Args[1] {
+ switch args[0] {
case "filter":
- if len(os.Args) != 4 {
+ if len(args) != 2 {
log.Fatal("invalid argument")
}
- if pid, err := strconv.Atoi(strings.TrimSpace(os.Args[2])); err != nil {
+ if pid, err := strconv.Atoi(strings.TrimSpace(args[1])); err != nil {
log.Fatalf("%s", err)
} else if pid < 1 {
log.Fatalf("%d out of range", pid)
} else {
- sandbox.MustCheckFilter(pid, os.Args[3])
- return
+ sandbox.MustCheckFilter(pid, flagBpfHash)
+ if err = syscall.Kill(pid, syscall.SIGINT); err != nil {
+ log.Fatalf("cannot signal check process: %v", err)
+ }
}
+ case "hash": // this eases the pain of passing the hash to python
+ fmt.Print(flagBpfHash)
+
default:
- (&sandbox.T{FS: os.DirFS("/")}).MustCheckFile(os.Args[1], "/tmp/sandbox-ok")
- return
+ log.Fatal("invalid argument")
}
}