test/sandbox: verify seccomp on all test cases
Some checks failed
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m1s
Test / Hakurei (push) Successful in 2m47s
Test / Planterette (push) Successful in 3m35s
Test / Sandbox (race detector) (push) Successful in 3m45s
Test / Hakurei (race detector) (push) Successful in 4m21s
Test / Flake checks (push) Failing after 1m15s
Some checks failed
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m1s
Test / Hakurei (push) Successful in 2m47s
Test / Planterette (push) Successful in 3m35s
Test / Sandbox (race detector) (push) Successful in 3m45s
Test / Hakurei (race detector) (push) Successful in 4m21s
Test / Flake checks (push) Failing after 1m15s
This change also makes seccomp hashes cross-platform. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
2b44493e8a
commit
6f5833bf41
@ -19,4 +19,6 @@ var bpfExpected = bpfLookup{
|
|||||||
"39871b93ffafc8b979fcedc0b0c37b9e03922f5b02748dc5c3c17c92527f6e022ede1f48bff59246ea452c0d1de54827808b1a6f84f32bbde1aa02ae30eedcfa"),
|
"39871b93ffafc8b979fcedc0b0c37b9e03922f5b02748dc5c3c17c92527f6e022ede1f48bff59246ea452c0d1de54827808b1a6f84f32bbde1aa02ae30eedcfa"),
|
||||||
{0, PresetExt | PresetDenyDevel}: toHash(
|
{0, PresetExt | PresetDenyDevel}: toHash(
|
||||||
"c698b081ff957afe17a6d94374537d37f2a63f6f9dd75da7546542407a9e32476ebda3312ba7785d7f618542bcfaf27ca27dcc2dddba852069d28bcfe8cad39a"),
|
"c698b081ff957afe17a6d94374537d37f2a63f6f9dd75da7546542407a9e32476ebda3312ba7785d7f618542bcfaf27ca27dcc2dddba852069d28bcfe8cad39a"),
|
||||||
|
{0, PresetExt | PresetDenyNS | PresetDenyDevel}: toHash(
|
||||||
|
"0b76007476c1c9e25dbf674c29fdf609a1656a70063e49327654e1b5360ad3da06e1a3e32bf80e961c5516ad83d4b9e7e9bde876a93797e27627d2555c25858b"),
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ func TestExport(t *testing.T) {
|
|||||||
{"strict", 0, PresetStrict, false},
|
{"strict", 0, PresetStrict, false},
|
||||||
{"strict compat", 0, PresetDenyNS | PresetDenyTTY | PresetDenyDevel, false},
|
{"strict compat", 0, PresetDenyNS | PresetDenyTTY | PresetDenyDevel, false},
|
||||||
{"hakurei default", 0, PresetExt | PresetDenyDevel, false},
|
{"hakurei default", 0, PresetExt | PresetDenyDevel, false},
|
||||||
|
{"hakurei tty", 0, PresetExt | PresetDenyNS | PresetDenyDevel, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, 8)
|
buf := make([]byte, 8)
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -42,13 +41,10 @@ type T struct {
|
|||||||
MountsPath string
|
MountsPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *T) MustCheckFile(wantFilePath, markerPath string) {
|
func (t *T) MustCheckFile(wantFilePath string) {
|
||||||
var want *TestCase
|
var want *TestCase
|
||||||
mustDecode(wantFilePath, &want)
|
mustDecode(wantFilePath, &want)
|
||||||
t.MustCheck(want)
|
t.MustCheck(want)
|
||||||
if _, err := os.Create(markerPath); err != nil {
|
|
||||||
fatalf("cannot create success marker: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *T) MustCheck(want *TestCase) {
|
func (t *T) MustCheck(want *TestCase) {
|
||||||
@ -167,31 +163,10 @@ func CheckFilter(pid int, want string) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
h := sha512.New()
|
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),
|
if buf, err := getFilter[[8]byte](pid, 0); err != nil {
|
||||||
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
|
return err
|
||||||
}
|
} else {
|
||||||
|
|
||||||
for _, b := range buf {
|
for _, b := range buf {
|
||||||
h.Write(b[:])
|
h.Write(b[:])
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
lib: testProgram:
|
system: lib: testProgram:
|
||||||
let
|
let
|
||||||
fs = mode: dir: data: {
|
fs = mode: dir: data: {
|
||||||
mode = lib.fromHexString mode;
|
mode = lib.fromHexString mode;
|
||||||
@ -43,13 +43,17 @@ let
|
|||||||
device
|
device
|
||||||
mapRealUid
|
mapRealUid
|
||||||
useCommonPaths
|
useCommonPaths
|
||||||
|
userns
|
||||||
;
|
;
|
||||||
share = testProgram;
|
share = testProgram;
|
||||||
packages = [ ];
|
packages = [ ];
|
||||||
path = "${testProgram}/bin/hakurei-test";
|
path = "${testProgram}/bin/hakurei-test";
|
||||||
args = [
|
args = [
|
||||||
"test"
|
"test"
|
||||||
|
"-t"
|
||||||
(toString (builtins.toFile "hakurei-${tc.name}-want.json" (builtins.toJSON tc.want)))
|
(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 "tty"} = callTestCase ./tty.nix 2;
|
||||||
${testCaseName "mapuid"} = callTestCase ./mapuid.nix 3;
|
${testCaseName "mapuid"} = callTestCase ./mapuid.nix 3;
|
||||||
${testCaseName "device"} = callTestCase ./device.nix 4;
|
${testCaseName "device"} = callTestCase ./device.nix 4;
|
||||||
|
${testCaseName "pdlike"} = callTestCase ./pdlike.nix 5;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
device = true;
|
device = true;
|
||||||
mapRealUid = false;
|
mapRealUid = false;
|
||||||
useCommonPaths = true;
|
useCommonPaths = true;
|
||||||
|
userns = false;
|
||||||
|
|
||||||
|
expectedFilter = { # 0, PresetStrict
|
||||||
|
x86_64-linux = "e880298df2bd6751d0040fc21bc0ed4c00f95dc0d7ba506c244d8b8cf6866dba8ef4a33296f287b66cccc1d78e97026597f84cc7dec1573e148960fbd35cd735";
|
||||||
|
};
|
||||||
|
|
||||||
want = {
|
want = {
|
||||||
env = [
|
env = [
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
device = false;
|
device = false;
|
||||||
mapRealUid = true;
|
mapRealUid = true;
|
||||||
useCommonPaths = true;
|
useCommonPaths = true;
|
||||||
|
userns = false;
|
||||||
|
|
||||||
|
expectedFilter = { # 0, PresetStrict
|
||||||
|
x86_64-linux = "e880298df2bd6751d0040fc21bc0ed4c00f95dc0d7ba506c244d8b8cf6866dba8ef4a33296f287b66cccc1d78e97026597f84cc7dec1573e148960fbd35cd735";
|
||||||
|
};
|
||||||
|
|
||||||
want = {
|
want = {
|
||||||
env = [
|
env = [
|
||||||
|
253
test/sandbox/case/pdlike.nix
Normal file
253
test/sandbox/case/pdlike.nix
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
{
|
||||||
|
fs,
|
||||||
|
ent,
|
||||||
|
ignore,
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
name = "pdlike";
|
||||||
|
tty = true;
|
||||||
|
device = false;
|
||||||
|
mapRealUid = false;
|
||||||
|
useCommonPaths = false;
|
||||||
|
userns = true;
|
||||||
|
|
||||||
|
expectedFilter = { # 0, PresetExt | PresetDenyDevel
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
@ -9,6 +9,11 @@
|
|||||||
device = false;
|
device = false;
|
||||||
mapRealUid = false;
|
mapRealUid = false;
|
||||||
useCommonPaths = false;
|
useCommonPaths = false;
|
||||||
|
userns = false;
|
||||||
|
|
||||||
|
expectedFilter = { # 0, PresetStrict
|
||||||
|
x86_64-linux = "e880298df2bd6751d0040fc21bc0ed4c00f95dc0d7ba506c244d8b8cf6866dba8ef4a33296f287b66cccc1d78e97026597f84cc7dec1573e148960fbd35cd735";
|
||||||
|
};
|
||||||
|
|
||||||
want = {
|
want = {
|
||||||
env = [
|
env = [
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
device = false;
|
device = false;
|
||||||
mapRealUid = false;
|
mapRealUid = false;
|
||||||
useCommonPaths = true;
|
useCommonPaths = true;
|
||||||
|
userns = false;
|
||||||
|
|
||||||
|
expectedFilter = { # 0, PresetExt | PresetDenyNS | PresetDenyDevel
|
||||||
|
x86_64-linux = "0b76007476c1c9e25dbf674c29fdf609a1656a70063e49327654e1b5360ad3da06e1a3e32bf80e961c5516ad83d4b9e7e9bde876a93797e27627d2555c25858b";
|
||||||
|
};
|
||||||
|
|
||||||
want = {
|
want = {
|
||||||
env = [
|
env = [
|
||||||
|
@ -75,6 +75,6 @@ in
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
apps = import ./case lib testProgram;
|
apps = import ./case pkgs.system lib testProgram;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,9 @@
|
|||||||
package sandbox
|
package sandbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,50 +37,20 @@ func ptrace(op uintptr, pid, addr int, data unsafe.Pointer) (r uintptr, errno sy
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ptraceAttach(pid int) error {
|
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 {
|
if _, errno := ptrace(PTRACE_ATTACH, pid, 0, nil); errno != 0 {
|
||||||
return &ptraceError{"PTRACE_ATTACH", errno}
|
return &ptraceError{"PTRACE_ATTACH", errno}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ugly! but there does not appear to be another way
|
var status syscall.WaitStatus
|
||||||
for {
|
for {
|
||||||
time.Sleep(10 * time.Millisecond)
|
if _, err := syscall.Wait4(pid, &status, syscall.WALL, nil); err != nil {
|
||||||
|
if errors.Is(err, syscall.EINTR) {
|
||||||
if _, err := r.Seek(0, io.SeekStart); err != nil {
|
continue
|
||||||
return err
|
}
|
||||||
|
fatalf("cannot waitpid: %v", err)
|
||||||
}
|
}
|
||||||
s := bufio.NewScanner(r)
|
|
||||||
|
|
||||||
var found bool
|
|
||||||
for s.Scan() {
|
|
||||||
found = strings.HasPrefix(s.Text(), statePrefix)
|
|
||||||
if found {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return syscall.EBADE
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasSuffix(s.Text(), stateSuffix) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,12 @@ def swaymsg(command: str = "", succeed=True, type="command"):
|
|||||||
return parsed
|
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()
|
start_all()
|
||||||
machine.wait_for_unit("multi-user.target")
|
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("/run/user/1000/wayland-1")
|
||||||
machine.wait_for_file("/tmp/sway-ipc.sock")
|
machine.wait_for_file("/tmp/sway-ipc.sock")
|
||||||
|
|
||||||
# Check seccomp outcome:
|
# Check pd seccomp outcome:
|
||||||
swaymsg("exec hakurei run cat")
|
swaymsg("exec hakurei run cat")
|
||||||
pid = int(machine.wait_until_succeeds("pgrep -U 1000000 -x cat", timeout=5))
|
check_filter(0, "pdlike", "cat")
|
||||||
print(machine.succeed(f"hakurei-test filter {pid} c698b081ff957afe17a6d94374537d37f2a63f6f9dd75da7546542407a9e32476ebda3312ba7785d7f618542bcfaf27ca27dcc2dddba852069d28bcfe8cad39a &>/dev/stdout", timeout=5))
|
|
||||||
machine.succeed(f"kill -TERM {pid}")
|
|
||||||
|
|
||||||
# Verify capabilities/securebits in user namespace:
|
# Verify capabilities/securebits in user namespace:
|
||||||
print(machine.succeed("sudo -u alice -i hakurei run capsh --print"))
|
print(machine.succeed("sudo -u alice -i hakurei run capsh --print"))
|
||||||
@ -57,12 +61,14 @@ def check_sandbox(name):
|
|||||||
check_offset += 1
|
check_offset += 1
|
||||||
swaymsg(f"exec script /dev/null -E always -qec check-sandbox-{name}")
|
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)
|
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("preset")
|
||||||
check_sandbox("tty")
|
check_sandbox("tty")
|
||||||
check_sandbox("mapuid")
|
check_sandbox("mapuid")
|
||||||
check_sandbox("device")
|
check_sandbox("device")
|
||||||
|
check_sandbox("pdlike")
|
||||||
|
|
||||||
# Exit Sway and verify process exit status 0:
|
# Exit Sway and verify process exit status 0:
|
||||||
swaymsg("exit", succeed=False)
|
swaymsg("exit", succeed=False)
|
||||||
|
@ -3,39 +3,69 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/test/sandbox"
|
"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() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
log.SetPrefix("test: ")
|
log.SetPrefix("test: ")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
if len(os.Args) < 2 {
|
args := flag.Args()
|
||||||
log.Fatal("invalid argument")
|
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":
|
case "filter":
|
||||||
if len(os.Args) != 4 {
|
if len(args) != 2 {
|
||||||
log.Fatal("invalid argument")
|
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)
|
log.Fatalf("%s", err)
|
||||||
} else if pid < 1 {
|
} else if pid < 1 {
|
||||||
log.Fatalf("%d out of range", pid)
|
log.Fatalf("%d out of range", pid)
|
||||||
} else {
|
} else {
|
||||||
sandbox.MustCheckFilter(pid, os.Args[3])
|
sandbox.MustCheckFilter(pid, flagBpfHash)
|
||||||
return
|
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:
|
default:
|
||||||
(&sandbox.T{FS: os.DirFS("/")}).MustCheckFile(os.Args[1], "/tmp/sandbox-ok")
|
log.Fatal("invalid argument")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user