Compare commits

...

11 Commits

Author SHA1 Message Date
34ccda84b2
release: 0.3.0
All checks were successful
Release / Create release (push) Successful in 39s
Test / Sandbox (push) Successful in 39s
Test / Hakurei (push) Successful in 3m20s
Test / Create distribution (push) Successful in 24s
Test / Sandbox (race detector) (push) Successful in 4m0s
Test / Hpkg (push) Successful in 3m37s
Test / Hakurei (race detector) (push) Successful in 4m53s
Test / Flake checks (push) Successful in 1m37s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-06 01:37:15 +09:00
042013bb04
container/std: syscall JSON adapter
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Sandbox (push) Successful in 39s
Test / Hakurei (push) Successful in 43s
Test / Hakurei (race detector) (push) Successful in 43s
Test / Sandbox (race detector) (push) Successful in 39s
Test / Hpkg (push) Successful in 40s
Test / Flake checks (push) Successful in 1m36s
This provides cross-platform JSON adapter for syscall number.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-06 00:57:53 +09:00
5c2b63a7f1
container: add 386 constants
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m17s
Test / Hakurei (push) Successful in 3m11s
Test / Hpkg (push) Successful in 4m0s
Test / Sandbox (race detector) (push) Successful in 4m16s
Test / Hakurei (race detector) (push) Successful in 5m2s
Test / Flake checks (push) Successful in 1m24s
While it is unlikely a use case for hakurei on i686 exists, it does not hurt to have this support.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 20:21:14 +09:00
9fd97e71d0
treewide: fit test untyped int literals in 32-bit
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m17s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 3m56s
Test / Sandbox (race detector) (push) Successful in 4m6s
Test / Hakurei (race detector) (push) Successful in 5m2s
Test / Flake checks (push) Successful in 1m24s
This enables hakurei test suite to run on 32-bit targets.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 20:13:19 +09:00
fba201c995
container/std: relocate rule types
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m10s
Test / Hakurei (push) Successful in 3m13s
Test / Hpkg (push) Successful in 3m56s
Test / Sandbox (race detector) (push) Successful in 4m14s
Test / Hakurei (race detector) (push) Successful in 5m3s
Test / Flake checks (push) Successful in 1m28s
This enables its use in hst for #15.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 06:00:39 +09:00
7f27a6dc51
container/seccomp: use native types
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m16s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 4m12s
Test / Hakurei (race detector) (push) Successful in 5m1s
Test / Flake checks (push) Successful in 1m30s
This prepares NativeRule for relocation to std for #15.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 05:48:59 +09:00
b65aba9446
container/seccomp: alias libseccomp types
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m14s
Test / Hakurei (push) Successful in 3m18s
Test / Hpkg (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 4m20s
Test / Hakurei (race detector) (push) Successful in 5m2s
Test / Flake checks (push) Successful in 1m29s
This enables tests to refer to these types and check its size.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 05:21:43 +09:00
becaf8b6d7
std: relocate seccomp lookup tables
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 4m9s
Test / Hakurei (race detector) (push) Successful in 5m0s
Test / Flake checks (push) Successful in 1m28s
This should enable resolving NativeRule in hst.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 04:48:05 +09:00
54c0d6bf48
container/seccomp/pnr: define pseudo syscalls
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m21s
Test / Hakurei (push) Successful in 3m12s
Test / Hpkg (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 4m5s
Test / Hakurei (race detector) (push) Successful in 4m58s
Test / Flake checks (push) Successful in 1m27s
This eliminates the cgo dependency from syscall lookup.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 04:32:41 +09:00
c1399f5030
std: rename from comp
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m12s
Test / Hakurei (push) Successful in 3m9s
Test / Hpkg (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 4m10s
Test / Hakurei (race detector) (push) Successful in 5m4s
Test / Flake checks (push) Successful in 1m28s
Seccomp lookup tables are going to be relocated here, and PNR constants.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 02:47:43 +09:00
9ac63aac0c
hst/grp_pwd: add extra test cases
All checks were successful
Test / Create distribution (push) Successful in 45s
Test / Sandbox (push) Successful in 2m31s
Test / Hakurei (push) Successful in 3m37s
Test / Hpkg (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 4m21s
Test / Hakurei (race detector) (push) Successful in 5m16s
Test / Flake checks (push) Successful in 1m26s
Does not change coverage but this helps me crosscheck with my phone.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-05 01:42:42 +09:00
78 changed files with 1909 additions and 826 deletions

View File

@ -58,8 +58,8 @@ func TestTryIdentifier(t *testing.T) {
} }
sampleEntry := hst.State{ sampleEntry := hst.State{
ID: id, ID: id,
PID: 0xcafebabe, PID: 0xcafe,
ShimPID: 0xdeadbeef, ShimPID: 0xdead,
Config: hst.Template(), Config: hst.Template(),
} }

View File

@ -22,8 +22,8 @@ var (
} }
testState = hst.State{ testState = hst.State{
ID: testID, ID: testID,
PID: 0xcafebabe, PID: 0xcafe,
ShimPID: 0xdeadbeef, ShimPID: 0xdead,
Config: hst.Template(), Config: hst.Template(),
Time: testAppTime, Time: testAppTime,
} }
@ -154,7 +154,7 @@ Session bus
`, false}, `, false},
{"instance", &testState, hst.Template(), false, false, `State {"instance", &testState, hst.Template(), false, false, `State
Instance: 8e2c76b066dabe574cf073bdb46eb5c1 (3405691582 -> 3735928559) Instance: 8e2c76b066dabe574cf073bdb46eb5c1 (51966 -> 57005)
Uptime: 1h2m32s Uptime: 1h2m32s
App App
@ -196,7 +196,7 @@ System bus
{"instance pd", &testState, new(hst.Config), false, false, `Error: configuration missing container state! {"instance pd", &testState, new(hst.Config), false, false, `Error: configuration missing container state!
State State
Instance: 8e2c76b066dabe574cf073bdb46eb5c1 (3405691582 -> 3735928559) Instance: 8e2c76b066dabe574cf073bdb46eb5c1 (51966 -> 57005)
Uptime: 1h2m32s Uptime: 1h2m32s
App App
@ -209,8 +209,8 @@ App
`, true}, `, true},
{"json instance", &testState, nil, false, true, `{ {"json instance", &testState, nil, false, true, `{
"instance": "8e2c76b066dabe574cf073bdb46eb5c1", "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
"pid": 3405691582, "pid": 51966,
"shim_pid": 3735928559, "shim_pid": 57005,
"id": "org.chromium.Chromium", "id": "org.chromium.Chromium",
"enablements": { "enablements": {
"wayland": true, "wayland": true,
@ -545,11 +545,11 @@ func TestPrintPs(t *testing.T) {
{"invalid config", []hst.State{{ID: testID, PID: 1 << 8, Config: new(hst.Config), Time: testAppTime}}, false, false, " Instance PID Application Uptime\n", "check: configuration missing container state\n"}, {"invalid config", []hst.State{{ID: testID, PID: 1 << 8, Config: new(hst.Config), Time: testAppTime}}, false, false, " Instance PID Application Uptime\n", "check: configuration missing container state\n"},
{"valid", []hst.State{testStateSmall, testState}, false, false, ` Instance PID Application Uptime {"valid", []hst.State{testStateSmall, testState}, false, false, ` Instance PID Application Uptime
4cf073bd 3405691582 9 (org.chromium.Chromium) 1h2m32s 4cf073bd 51966 9 (org.chromium.Chromium) 1h2m32s
aaaaaaaa 48879 1 (app.hakurei.aaaaaaaa) 1h2m28s aaaaaaaa 48879 1 (app.hakurei.aaaaaaaa) 1h2m28s
`, ""}, `, ""},
{"valid single", []hst.State{testState}, false, false, ` Instance PID Application Uptime {"valid single", []hst.State{testState}, false, false, ` Instance PID Application Uptime
4cf073bd 3405691582 9 (org.chromium.Chromium) 1h2m32s 4cf073bd 51966 9 (org.chromium.Chromium) 1h2m32s
`, ""}, `, ""},
{"valid short", []hst.State{testStateSmall, testState}, true, false, "4cf073bd\naaaaaaaa\n", ""}, {"valid short", []hst.State{testStateSmall, testState}, true, false, "4cf073bd\naaaaaaaa\n", ""},
@ -558,8 +558,8 @@ func TestPrintPs(t *testing.T) {
{"valid json", []hst.State{testState, testStateSmall}, false, true, `[ {"valid json", []hst.State{testState, testStateSmall}, false, true, `[
{ {
"instance": "8e2c76b066dabe574cf073bdb46eb5c1", "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
"pid": 3405691582, "pid": 51966,
"shim_pid": 3735928559, "shim_pid": 57005,
"id": "org.chromium.Chromium", "id": "org.chromium.Chromium",
"enablements": { "enablements": {
"wayland": true, "wayland": true,

View File

@ -6,7 +6,7 @@ import (
"testing" "testing"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp" "hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/message" "hakurei.app/message"
) )
@ -23,14 +23,14 @@ func TestAutoRootOp(t *testing.T) {
checkOpBehaviour(t, []opBehaviourTestCase{ checkOpBehaviour(t, []opBehaviourTestCase{
{"readdir", &Params{ParentPerm: 0750}, &AutoRootOp{ {"readdir", &Params{ParentPerm: 0750}, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, []stub.Call{ }, []stub.Call{
call("readdir", stub.ExpectArgs{"/"}, stubDir(), stub.UniqueError(2)), call("readdir", stub.ExpectArgs{"/"}, stubDir(), stub.UniqueError(2)),
}, stub.UniqueError(2), nil, nil}, }, stub.UniqueError(2), nil, nil},
{"early", &Params{ParentPerm: 0750}, &AutoRootOp{ {"early", &Params{ParentPerm: 0750}, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, []stub.Call{ }, []stub.Call{
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64", call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil), "lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
@ -39,7 +39,7 @@ func TestAutoRootOp(t *testing.T) {
{"apply", &Params{ParentPerm: 0750}, &AutoRootOp{ {"apply", &Params{ParentPerm: 0750}, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, []stub.Call{ }, []stub.Call{
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64", call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil), "lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
@ -60,7 +60,7 @@ func TestAutoRootOp(t *testing.T) {
{"success pd", &Params{ParentPerm: 0750}, &AutoRootOp{ {"success pd", &Params{ParentPerm: 0750}, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, []stub.Call{ }, []stub.Call{
call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64", call("readdir", stub.ExpectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64",
"lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil), "lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil),
@ -127,10 +127,10 @@ func TestAutoRootOp(t *testing.T) {
}) })
checkOpsBuilder(t, []opsBuilderTestCase{ checkOpsBuilder(t, []opsBuilderTestCase{
{"pd", new(Ops).Root(check.MustAbs("/"), comp.BindWritable), Ops{ {"pd", new(Ops).Root(check.MustAbs("/"), std.BindWritable), Ops{
&AutoRootOp{ &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, },
}}, }},
}) })
@ -140,42 +140,42 @@ func TestAutoRootOp(t *testing.T) {
{"internal ne", &AutoRootOp{ {"internal ne", &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, &AutoRootOp{ }, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
resolved: []*BindMountOp{new(BindMountOp)}, resolved: []*BindMountOp{new(BindMountOp)},
}, true}, }, true},
{"flags differs", &AutoRootOp{ {"flags differs", &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable | comp.BindDevice, Flags: std.BindWritable | std.BindDevice,
}, &AutoRootOp{ }, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, false}, }, false},
{"host differs", &AutoRootOp{ {"host differs", &AutoRootOp{
Host: check.MustAbs("/tmp/"), Host: check.MustAbs("/tmp/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, &AutoRootOp{ }, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, false}, }, false},
{"equals", &AutoRootOp{ {"equals", &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, &AutoRootOp{ }, &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, true}, }, true},
}) })
checkOpMeta(t, []opMetaTestCase{ checkOpMeta(t, []opMetaTestCase{
{"root", &AutoRootOp{ {"root", &AutoRootOp{
Host: check.MustAbs("/"), Host: check.MustAbs("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}, "setting up", `auto root "/" flags 0x2`}, }, "setting up", `auto root "/" flags 0x2`},
}) })
} }

View File

@ -147,7 +147,7 @@ func TestAbsoluteIs(t *testing.T) {
type sCheck struct { type sCheck struct {
Pathname *Absolute `json:"val"` Pathname *Absolute `json:"val"`
Magic int `json:"magic"` Magic uint64 `json:"magic"`
} }
func TestCodecAbsolute(t *testing.T) { func TestCodecAbsolute(t *testing.T) {
@ -169,19 +169,19 @@ func TestCodecAbsolute(t *testing.T) {
{"good", MustAbs("/etc"), {"good", MustAbs("/etc"),
nil, nil,
"\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\b\xff\x80\x00\x04/etc", "\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\b\xff\x80\x00\x04/etc",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x04\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x10\xff\x84\x01\x04/etc\x01\xfb\x01\x81\xda\x00\x00\x00", ",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x04/etc\x01\xfc\xc0\xed\x00\x00\x00",
`"/etc"`, `{"val":"/etc","magic":3236757504}`}, `"/etc"`, `{"val":"/etc","magic":3236757504}`},
{"not absolute", nil, {"not absolute", nil,
&AbsoluteError{Pathname: "etc"}, &AbsoluteError{Pathname: "etc"},
"\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\a\xff\x80\x00\x03etc", "\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\a\xff\x80\x00\x03etc",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x04\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x03etc\x01\xfb\x01\x81\xda\x00\x00\x00", ",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x0f\xff\x84\x01\x03etc\x01\xfb\x01\x81\xda\x00\x00\x00",
`"etc"`, `{"val":"etc","magic":3236757504}`}, `"etc"`, `{"val":"etc","magic":3236757504}`},
{"zero", nil, {"zero", nil,
new(AbsoluteError), new(AbsoluteError),
"\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x04\xff\x80\x00\x00", "\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\x04\xff\x80\x00\x00",
",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x04\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\f\xff\x84\x01\x00\x01\xfb\x01\x81\xda\x00\x00\x00", ",\xff\x83\x03\x01\x01\x06sCheck\x01\xff\x84\x00\x01\x02\x01\bPathname\x01\xff\x80\x00\x01\x05Magic\x01\x06\x00\x00\x00\t\x7f\x05\x01\x02\xff\x82\x00\x00\x00\f\xff\x84\x01\x00\x01\xfb\x01\x81\xda\x00\x00\x00",
`""`, `{"val":"","magic":3236757504}`}, `""`, `{"val":"","magic":3236757504}`},
} }

View File

@ -15,9 +15,9 @@ import (
"time" "time"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/message" "hakurei.app/message"
) )
@ -85,11 +85,11 @@ type (
*Ops *Ops
// Seccomp system call filter rules. // Seccomp system call filter rules.
SeccompRules []seccomp.NativeRule SeccompRules []std.NativeRule
// Extra seccomp flags. // Extra seccomp flags.
SeccompFlags seccomp.ExportFlag SeccompFlags seccomp.ExportFlag
// Seccomp presets. Has no effect unless SeccompRules is zero-length. // Seccomp presets. Has no effect unless SeccompRules is zero-length.
SeccompPresets comp.FilterPreset SeccompPresets std.FilterPreset
// Do not load seccomp program. // Do not load seccomp program.
SeccompDisable bool SeccompDisable bool
@ -177,7 +177,7 @@ func (p *Container) Start() error {
} }
if !p.RetainSession { if !p.RetainSession {
p.SeccompPresets |= comp.PresetDenyTTY p.SeccompPresets |= std.PresetDenyTTY
} }
if p.AdoptWaitDelay == 0 { if p.AdoptWaitDelay == 0 {
@ -327,7 +327,7 @@ func (p *Container) Serve() error {
p.Dir = fhs.AbsRoot p.Dir = fhs.AbsRoot
} }
if p.SeccompRules == nil { if p.SeccompRules == nil {
p.SeccompRules = make([]seccomp.NativeRule, 0) p.SeccompRules = make([]std.NativeRule, 0)
} }
err := gob.NewEncoder(setup).Encode(&initParams{ err := gob.NewEncoder(setup).Encode(&initParams{

View File

@ -21,8 +21,8 @@ import (
"hakurei.app/command" "hakurei.app/command"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/container/vfs" "hakurei.app/container/vfs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/ldd" "hakurei.app/ldd"
@ -204,22 +204,22 @@ var containerTestCases = []struct {
uid int uid int
gid int gid int
rules []seccomp.NativeRule rules []std.NativeRule
flags seccomp.ExportFlag flags seccomp.ExportFlag
presets comp.FilterPreset presets std.FilterPreset
}{ }{
{"minimal", true, false, false, true, {"minimal", true, false, false, true,
emptyOps, emptyMnt, emptyOps, emptyMnt,
1000, 100, nil, 0, comp.PresetStrict}, 1000, 100, nil, 0, std.PresetStrict},
{"allow", true, true, true, false, {"allow", true, true, true, false,
emptyOps, emptyMnt, emptyOps, emptyMnt,
1000, 100, nil, 0, comp.PresetExt | comp.PresetDenyDevel}, 1000, 100, nil, 0, std.PresetExt | std.PresetDenyDevel},
{"no filter", false, true, true, true, {"no filter", false, true, true, true,
emptyOps, emptyMnt, emptyOps, emptyMnt,
1000, 100, nil, 0, comp.PresetExt}, 1000, 100, nil, 0, std.PresetExt},
{"custom rules", true, true, true, false, {"custom rules", true, true, true, false,
emptyOps, emptyMnt, emptyOps, emptyMnt,
1, 31, []seccomp.NativeRule{{Syscall: seccomp.ScmpSyscall(syscall.SYS_SETUID), Errno: seccomp.ScmpErrno(syscall.EPERM)}}, 0, comp.PresetExt}, 1, 31, []std.NativeRule{{Syscall: std.ScmpSyscall(syscall.SYS_SETUID), Errno: std.ScmpErrno(syscall.EPERM)}}, 0, std.PresetExt},
{"tmpfs", true, false, false, true, {"tmpfs", true, false, false, true,
earlyOps(new(container.Ops). earlyOps(new(container.Ops).
@ -228,7 +228,7 @@ var containerTestCases = []struct {
earlyMnt( earlyMnt(
ent("/", hst.PrivateTmp, "rw,nosuid,nodev,relatime", "tmpfs", "ephemeral", ignore), ent("/", hst.PrivateTmp, "rw,nosuid,nodev,relatime", "tmpfs", "ephemeral", ignore),
), ),
9, 9, nil, 0, comp.PresetStrict}, 9, 9, nil, 0, std.PresetStrict},
{"dev", true, true /* go test output is not a tty */, false, false, {"dev", true, true /* go test output is not a tty */, false, false,
earlyOps(new(container.Ops). earlyOps(new(container.Ops).
@ -246,7 +246,7 @@ var containerTestCases = []struct {
ent("/", "/dev/mqueue", "rw,nosuid,nodev,noexec,relatime", "mqueue", "mqueue", "rw"), ent("/", "/dev/mqueue", "rw,nosuid,nodev,noexec,relatime", "mqueue", "mqueue", "rw"),
ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore), ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore),
), ),
1971, 100, nil, 0, comp.PresetStrict}, 1971, 100, nil, 0, std.PresetStrict},
{"dev no mqueue", true, true /* go test output is not a tty */, false, false, {"dev no mqueue", true, true /* go test output is not a tty */, false, false,
earlyOps(new(container.Ops). earlyOps(new(container.Ops).
@ -263,7 +263,7 @@ var containerTestCases = []struct {
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("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore), ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore),
), ),
1971, 100, nil, 0, comp.PresetStrict}, 1971, 100, nil, 0, std.PresetStrict},
{"overlay", true, false, false, true, {"overlay", true, false, false, true,
func(t *testing.T) (*container.Ops, context.Context) { func(t *testing.T) (*container.Ops, context.Context) {
@ -300,7 +300,7 @@ var containerTestCases = []struct {
",redirect_dir=nofollow,uuid=on,userxattr"), ",redirect_dir=nofollow,uuid=on,userxattr"),
} }
}, },
1 << 3, 1 << 14, nil, 0, comp.PresetStrict}, 1 << 3, 1 << 14, nil, 0, std.PresetStrict},
{"overlay ephemeral", true, false, false, true, {"overlay ephemeral", true, false, false, true,
func(t *testing.T) (*container.Ops, context.Context) { func(t *testing.T) (*container.Ops, context.Context) {
@ -324,7 +324,7 @@ var containerTestCases = []struct {
ent("/", hst.PrivateTmp, "rw", "overlay", "overlay", ignore), ent("/", hst.PrivateTmp, "rw", "overlay", "overlay", ignore),
} }
}, },
1 << 3, 1 << 14, nil, 0, comp.PresetStrict}, 1 << 3, 1 << 14, nil, 0, std.PresetStrict},
{"overlay readonly", true, false, false, true, {"overlay readonly", true, false, false, true,
func(t *testing.T) (*container.Ops, context.Context) { func(t *testing.T) (*container.Ops, context.Context) {
@ -352,7 +352,7 @@ var containerTestCases = []struct {
",redirect_dir=nofollow,userxattr"), ",redirect_dir=nofollow,userxattr"),
} }
}, },
1 << 3, 1 << 14, nil, 0, comp.PresetStrict}, 1 << 3, 1 << 14, nil, 0, std.PresetStrict},
} }
func TestContainer(t *testing.T) { func TestContainer(t *testing.T) {
@ -560,9 +560,9 @@ func TestContainerString(t *testing.T) {
c := container.NewCommand(t.Context(), msg, check.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env") c := container.NewCommand(t.Context(), msg, check.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env")
c.SeccompFlags |= seccomp.AllowMultiarch c.SeccompFlags |= seccomp.AllowMultiarch
c.SeccompRules = seccomp.Preset( c.SeccompRules = seccomp.Preset(
comp.PresetExt|comp.PresetDenyNS|comp.PresetDenyTTY, std.PresetExt|std.PresetDenyNS|std.PresetDenyTTY,
c.SeccompFlags) c.SeccompFlags)
c.SeccompPresets = comp.PresetStrict c.SeccompPresets = std.PresetStrict
want := `argv: ["ldd" "/usr/bin/env"], filter: true, rules: 65, flags: 0x1, presets: 0xf` want := `argv: ["ldd" "/usr/bin/env"], filter: true, rules: 65, flags: 0x1, presets: 0xf`
if got := c.String(); got != want { if got := c.String(); got != want {
t.Errorf("String: %s, want %s", got, want) t.Errorf("String: %s, want %s", got, want)

View File

@ -11,6 +11,7 @@ import (
"syscall" "syscall"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/message" "hakurei.app/message"
) )
@ -62,7 +63,7 @@ type syscallDispatcher interface {
ensureFile(name string, perm, pperm os.FileMode) error ensureFile(name string, perm, pperm os.FileMode) error
// seccompLoad provides [seccomp.Load]. // seccompLoad provides [seccomp.Load].
seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error
// notify provides [signal.Notify]. // notify provides [signal.Notify].
notify(c chan<- os.Signal, sig ...os.Signal) notify(c chan<- os.Signal, sig ...os.Signal)
// start starts [os/exec.Cmd]. // start starts [os/exec.Cmd].
@ -164,7 +165,7 @@ func (direct) ensureFile(name string, perm, pperm os.FileMode) error {
return ensureFile(name, perm, pperm) return ensureFile(name, perm, pperm)
} }
func (direct) seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error { func (direct) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error {
return seccomp.Load(rules, flags) return seccomp.Load(rules, flags)
} }
func (direct) notify(c chan<- os.Signal, sig ...os.Signal) { signal.Notify(c, sig...) } func (direct) notify(c chan<- os.Signal, sig ...os.Signal) { signal.Notify(c, sig...) }

View File

@ -17,6 +17,7 @@ import (
"time" "time"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/message" "hakurei.app/message"
) )
@ -456,7 +457,7 @@ func (k *kstub) ensureFile(name string, perm, pperm os.FileMode) error {
stub.CheckArg(k.Stub, "pperm", pperm, 2)) stub.CheckArg(k.Stub, "pperm", pperm, 2))
} }
func (k *kstub) seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error { func (k *kstub) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error {
k.Helper() k.Helper()
return k.Expects("seccompLoad").Error( return k.Expects("seccompLoad").Error(
stub.CheckArgReflect(k.Stub, "rules", rules, 0), stub.CheckArgReflect(k.Stub, "rules", rules, 0),

View File

@ -46,8 +46,8 @@ func TestMessageFromError(t *testing.T) {
{"state", OpStateError("overlay"), {"state", OpStateError("overlay"),
"impossible overlay state reached", true}, "impossible overlay state reached", true},
{"vfs parse", &vfs.DecoderError{Op: "parse", Line: 0xdeadbeef, Err: &strconv.NumError{Func: "Atoi", Num: "meow", Err: strconv.ErrSyntax}}, {"vfs parse", &vfs.DecoderError{Op: "parse", Line: 0xdead, Err: &strconv.NumError{Func: "Atoi", Num: "meow", Err: strconv.ErrSyntax}},
`cannot parse mountinfo at line 3735928559: numeric field "meow" invalid syntax`, true}, `cannot parse mountinfo at line 57005: numeric field "meow" invalid syntax`, true},
{"tmpfs", TmpfsSizeError(-1), {"tmpfs", TmpfsSizeError(-1),
"tmpfs size -1 out of bounds", true}, "tmpfs size -1 out of bounds", true},

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ import (
"syscall" "syscall"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp" "hakurei.app/container/std"
) )
func init() { gob.Register(new(BindMountOp)) } func init() { gob.Register(new(BindMountOp)) }
@ -29,18 +29,18 @@ type BindMountOp struct {
func (b *BindMountOp) Valid() bool { func (b *BindMountOp) Valid() bool {
return b != nil && return b != nil &&
b.Source != nil && b.Target != nil && b.Source != nil && b.Target != nil &&
b.Flags&(comp.BindOptional|comp.BindEnsure) != (comp.BindOptional|comp.BindEnsure) b.Flags&(std.BindOptional|std.BindEnsure) != (std.BindOptional|std.BindEnsure)
} }
func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error { func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error {
if b.Flags&comp.BindEnsure != 0 { if b.Flags&std.BindEnsure != 0 {
if err := k.mkdirAll(b.Source.String(), 0700); err != nil { if err := k.mkdirAll(b.Source.String(), 0700); err != nil {
return err return err
} }
} }
if pathname, err := k.evalSymlinks(b.Source.String()); err != nil { if pathname, err := k.evalSymlinks(b.Source.String()); err != nil {
if os.IsNotExist(err) && b.Flags&comp.BindOptional != 0 { if os.IsNotExist(err) && b.Flags&std.BindOptional != 0 {
// leave sourceFinal as nil // leave sourceFinal as nil
return nil return nil
} }
@ -53,7 +53,7 @@ func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error {
func (b *BindMountOp) apply(state *setupState, k syscallDispatcher) error { func (b *BindMountOp) apply(state *setupState, k syscallDispatcher) error {
if b.sourceFinal == nil { if b.sourceFinal == nil {
if b.Flags&comp.BindOptional == 0 { if b.Flags&std.BindOptional == 0 {
// unreachable // unreachable
return OpStateError("bind") return OpStateError("bind")
} }
@ -76,10 +76,10 @@ func (b *BindMountOp) apply(state *setupState, k syscallDispatcher) error {
} }
var flags uintptr = syscall.MS_REC var flags uintptr = syscall.MS_REC
if b.Flags&comp.BindWritable == 0 { if b.Flags&std.BindWritable == 0 {
flags |= syscall.MS_RDONLY flags |= syscall.MS_RDONLY
} }
if b.Flags&comp.BindDevice == 0 { if b.Flags&std.BindDevice == 0 {
flags |= syscall.MS_NODEV flags |= syscall.MS_NODEV
} }

View File

@ -7,7 +7,7 @@ import (
"testing" "testing"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp" "hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
) )
@ -25,7 +25,7 @@ func TestBindMountOp(t *testing.T) {
{"skip optional", new(Params), &BindMountOp{ {"skip optional", new(Params), &BindMountOp{
Source: check.MustAbs("/bin/"), Source: check.MustAbs("/bin/"),
Target: check.MustAbs("/bin/"), Target: check.MustAbs("/bin/"),
Flags: comp.BindOptional, Flags: std.BindOptional,
}, []stub.Call{ }, []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "", syscall.ENOENT), call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "", syscall.ENOENT),
}, nil, nil, nil}, }, nil, nil, nil},
@ -33,7 +33,7 @@ func TestBindMountOp(t *testing.T) {
{"success optional", new(Params), &BindMountOp{ {"success optional", new(Params), &BindMountOp{
Source: check.MustAbs("/bin/"), Source: check.MustAbs("/bin/"),
Target: check.MustAbs("/bin/"), Target: check.MustAbs("/bin/"),
Flags: comp.BindOptional, Flags: std.BindOptional,
}, []stub.Call{ }, []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil), call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -46,7 +46,7 @@ func TestBindMountOp(t *testing.T) {
{"ensureFile device", new(Params), &BindMountOp{ {"ensureFile device", new(Params), &BindMountOp{
Source: check.MustAbs("/dev/null"), Source: check.MustAbs("/dev/null"),
Target: check.MustAbs("/dev/null"), Target: check.MustAbs("/dev/null"),
Flags: comp.BindWritable | comp.BindDevice, Flags: std.BindWritable | std.BindDevice,
}, []stub.Call{ }, []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil), call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -57,7 +57,7 @@ func TestBindMountOp(t *testing.T) {
{"mkdirAll ensure", new(Params), &BindMountOp{ {"mkdirAll ensure", new(Params), &BindMountOp{
Source: check.MustAbs("/bin/"), Source: check.MustAbs("/bin/"),
Target: check.MustAbs("/bin/"), Target: check.MustAbs("/bin/"),
Flags: comp.BindEnsure, Flags: std.BindEnsure,
}, []stub.Call{ }, []stub.Call{
call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, stub.UniqueError(4)), call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, stub.UniqueError(4)),
}, stub.UniqueError(4), nil, nil}, }, stub.UniqueError(4), nil, nil},
@ -65,7 +65,7 @@ func TestBindMountOp(t *testing.T) {
{"success ensure", new(Params), &BindMountOp{ {"success ensure", new(Params), &BindMountOp{
Source: check.MustAbs("/bin/"), Source: check.MustAbs("/bin/"),
Target: check.MustAbs("/usr/bin/"), Target: check.MustAbs("/usr/bin/"),
Flags: comp.BindEnsure, Flags: std.BindEnsure,
}, []stub.Call{ }, []stub.Call{
call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, nil), call("mkdirAll", stub.ExpectArgs{"/bin/", os.FileMode(0700)}, nil, nil),
call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil), call("evalSymlinks", stub.ExpectArgs{"/bin/"}, "/usr/bin", nil),
@ -79,7 +79,7 @@ func TestBindMountOp(t *testing.T) {
{"success device ro", new(Params), &BindMountOp{ {"success device ro", new(Params), &BindMountOp{
Source: check.MustAbs("/dev/null"), Source: check.MustAbs("/dev/null"),
Target: check.MustAbs("/dev/null"), Target: check.MustAbs("/dev/null"),
Flags: comp.BindDevice, Flags: std.BindDevice,
}, []stub.Call{ }, []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil), call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -92,7 +92,7 @@ func TestBindMountOp(t *testing.T) {
{"success device", new(Params), &BindMountOp{ {"success device", new(Params), &BindMountOp{
Source: check.MustAbs("/dev/null"), Source: check.MustAbs("/dev/null"),
Target: check.MustAbs("/dev/null"), Target: check.MustAbs("/dev/null"),
Flags: comp.BindWritable | comp.BindDevice, Flags: std.BindWritable | std.BindDevice,
}, []stub.Call{ }, []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil), call("evalSymlinks", stub.ExpectArgs{"/dev/null"}, "/dev/null", nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -182,7 +182,7 @@ func TestBindMountOp(t *testing.T) {
{"zero", new(BindMountOp), false}, {"zero", new(BindMountOp), false},
{"nil source", &BindMountOp{Target: check.MustAbs("/")}, false}, {"nil source", &BindMountOp{Target: check.MustAbs("/")}, false},
{"nil target", &BindMountOp{Source: check.MustAbs("/")}, false}, {"nil target", &BindMountOp{Source: check.MustAbs("/")}, false},
{"flag optional ensure", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/"), Flags: comp.BindOptional | comp.BindEnsure}, false}, {"flag optional ensure", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/"), Flags: std.BindOptional | std.BindEnsure}, false},
{"valid", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/")}, true}, {"valid", &BindMountOp{Source: check.MustAbs("/"), Target: check.MustAbs("/")}, true},
}) })
@ -217,7 +217,7 @@ func TestBindMountOp(t *testing.T) {
}, &BindMountOp{ }, &BindMountOp{
Source: check.MustAbs("/etc/"), Source: check.MustAbs("/etc/"),
Target: check.MustAbs("/etc/.host/048090b6ed8f9ebb10e275ff5d8c0659"), Target: check.MustAbs("/etc/.host/048090b6ed8f9ebb10e275ff5d8c0659"),
Flags: comp.BindOptional, Flags: std.BindOptional,
}, false}, }, false},
{"source differs", &BindMountOp{ {"source differs", &BindMountOp{
@ -256,7 +256,7 @@ func TestBindMountOp(t *testing.T) {
{"hostdev", &BindMountOp{ {"hostdev", &BindMountOp{
Source: check.MustAbs("/dev/"), Source: check.MustAbs("/dev/"),
Target: check.MustAbs("/dev/"), Target: check.MustAbs("/dev/"),
Flags: comp.BindWritable | comp.BindDevice, Flags: std.BindWritable | std.BindDevice,
}, "mounting", `"/dev/" flags 0x6`}, }, "mounting", `"/dev/" flags 0x6`},
}) })
} }

View File

@ -5,7 +5,7 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"hakurei.app/container/seccomp" "hakurei.app/container/std"
) )
// include/uapi/linux/landlock.h // include/uapi/linux/landlock.h
@ -14,7 +14,8 @@ const (
LANDLOCK_CREATE_RULESET_VERSION = 1 << iota LANDLOCK_CREATE_RULESET_VERSION = 1 << iota
) )
type LandlockAccessFS uintptr // LandlockAccessFS is bitmask of handled filesystem actions.
type LandlockAccessFS uint64
const ( const (
LANDLOCK_ACCESS_FS_EXECUTE LandlockAccessFS = 1 << iota LANDLOCK_ACCESS_FS_EXECUTE LandlockAccessFS = 1 << iota
@ -105,7 +106,8 @@ func (f LandlockAccessFS) String() string {
} }
} }
type LandlockAccessNet uintptr // LandlockAccessNet is bitmask of handled network actions.
type LandlockAccessNet uint64
const ( const (
LANDLOCK_ACCESS_NET_BIND_TCP LandlockAccessNet = 1 << iota LANDLOCK_ACCESS_NET_BIND_TCP LandlockAccessNet = 1 << iota
@ -140,7 +142,8 @@ func (f LandlockAccessNet) String() string {
} }
} }
type LandlockScope uintptr // LandlockScope is bitmask of scopes restricting a Landlock domain from accessing outside resources.
type LandlockScope uint64
const ( const (
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET LandlockScope = 1 << iota LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET LandlockScope = 1 << iota
@ -175,6 +178,7 @@ func (f LandlockScope) String() string {
} }
} }
// RulesetAttr is equivalent to struct landlock_ruleset_attr.
type RulesetAttr struct { type RulesetAttr struct {
// Bitmask of handled filesystem actions. // Bitmask of handled filesystem actions.
HandledAccessFS LandlockAccessFS HandledAccessFS LandlockAccessFS
@ -212,7 +216,7 @@ func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) {
size = unsafe.Sizeof(*rulesetAttr) size = unsafe.Sizeof(*rulesetAttr)
} }
rulesetFd, _, errno := syscall.Syscall(seccomp.SYS_LANDLOCK_CREATE_RULESET, pointer, size, flags) rulesetFd, _, errno := syscall.Syscall(std.SYS_LANDLOCK_CREATE_RULESET, pointer, size, flags)
fd = int(rulesetFd) fd = int(rulesetFd)
err = errno err = errno
@ -231,7 +235,7 @@ func LandlockGetABI() (int, error) {
} }
func LandlockRestrictSelf(rulesetFd int, flags uintptr) error { func LandlockRestrictSelf(rulesetFd int, flags uintptr) error {
r, _, errno := syscall.Syscall(seccomp.SYS_LANDLOCK_RESTRICT_SELF, uintptr(rulesetFd), flags, 0) r, _, errno := syscall.Syscall(std.SYS_LANDLOCK_RESTRICT_SELF, uintptr(rulesetFd), flags, 0)
if r != 0 { if r != 0 {
return errno return errno
} }

View File

@ -91,24 +91,24 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, stub.UniqueError(5)), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, stub.UniqueError(5)),
}}, &os.PathError{Op: "open", Path: "/sysroot/nix", Err: stub.UniqueError(5)}}, }}, &os.PathError{Op: "open", Path: "/sysroot/nix", Err: stub.UniqueError(5)}},
{"readlink", func(k *kstub) error { {"readlink", func(k *kstub) error {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", stub.UniqueError(4)), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", stub.UniqueError(4)),
}}, stub.UniqueError(4)}, }}, stub.UniqueError(4)},
{"close", func(k *kstub) error { {"close", func(k *kstub) error {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, stub.UniqueError(3)), call("close", stub.ExpectArgs{0xdead}, nil, stub.UniqueError(3)),
}}, &os.PathError{Op: "close", Path: "/sysroot/nix", Err: stub.UniqueError(3)}}, }}, &os.PathError{Op: "close", Path: "/sysroot/nix", Err: stub.UniqueError(3)}},
{"mountinfo no match", func(k *kstub) error { {"mountinfo no match", func(k *kstub) error {
@ -116,9 +116,9 @@ func TestRemount(t *testing.T) {
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/.hakurei", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/.hakurei", nil),
call("verbosef", stub.ExpectArgs{"target resolves to %q", []any{"/sysroot/.hakurei"}}, nil, nil), call("verbosef", stub.ExpectArgs{"target resolves to %q", []any{"/sysroot/.hakurei"}}, nil, nil),
call("open", stub.ExpectArgs{"/sysroot/.hakurei", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/.hakurei", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/.hakurei", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/.hakurei", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
}}, &vfs.DecoderError{Op: "unfold", Line: -1, Err: vfs.UnfoldTargetError("/sysroot/.hakurei")}}, }}, &vfs.DecoderError{Op: "unfold", Line: -1, Err: vfs.UnfoldTargetError("/sysroot/.hakurei")}},
@ -126,9 +126,9 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile("\x00"), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile("\x00"), nil),
}}, &vfs.DecoderError{Op: "parse", Line: 0, Err: vfs.ErrMountInfoFields}}, }}, &vfs.DecoderError{Op: "parse", Line: 0, Err: vfs.ErrMountInfoFields}},
@ -136,9 +136,9 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, stub.UniqueError(2)), call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, stub.UniqueError(2)),
}}, stub.UniqueError(2)}, }}, stub.UniqueError(2)},
@ -147,9 +147,9 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, stub.UniqueError(1)), call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, stub.UniqueError(1)),
@ -170,9 +170,9 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, syscall.EACCES), call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, syscall.EACCES),
@ -183,9 +183,9 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil),
}}, nil}, }}, nil},
@ -194,9 +194,9 @@ func TestRemount(t *testing.T) {
return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) return newProcPaths(k, hostPath).remount(nil, "/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV)
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/nix"}, "/sysroot/nix", nil),
call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, nil),
@ -208,9 +208,9 @@ func TestRemount(t *testing.T) {
}, stub.Expect{Calls: []stub.Call{ }, stub.Expect{Calls: []stub.Call{
call("evalSymlinks", stub.ExpectArgs{"/sysroot/.nix"}, "/sysroot/NIX", nil), call("evalSymlinks", stub.ExpectArgs{"/sysroot/.nix"}, "/sysroot/NIX", nil),
call("verbosef", stub.ExpectArgs{"target resolves to %q", []any{"/sysroot/NIX"}}, nil, nil), call("verbosef", stub.ExpectArgs{"target resolves to %q", []any{"/sysroot/NIX"}}, nil, nil),
call("open", stub.ExpectArgs{"/sysroot/NIX", 0x280000, uint32(0)}, 0xdeadbeef, nil), call("open", stub.ExpectArgs{"/sysroot/NIX", 0x280000, uint32(0)}, 0xdead, nil),
call("readlink", stub.ExpectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil), call("readlink", stub.ExpectArgs{"/host/proc/self/fd/57005"}, "/sysroot/nix", nil),
call("close", stub.ExpectArgs{0xdeadbeef}, nil, nil), call("close", stub.ExpectArgs{0xdead}, nil, nil),
call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil), call("openNew", stub.ExpectArgs{"/host/proc/self/mountinfo"}, newConstFile(sampleMountinfoNix), nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix", "", uintptr(0x209027), ""}, nil, nil),
call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, nil), call("mount", stub.ExpectArgs{"none", "/sysroot/nix/.ro-store", "", uintptr(0x209027), ""}, nil, nil),

View File

@ -56,7 +56,7 @@ func TestSetupReceive(t *testing.T) {
t.Run("setup receive", func(t *testing.T) { t.Run("setup receive", func(t *testing.T) {
check := func(t *testing.T, useNilFdp bool) { check := func(t *testing.T, useNilFdp bool) {
const key = "TEST_SETUP_RECEIVE" const key = "TEST_SETUP_RECEIVE"
payload := []int{syscall.MS_MGC_VAL, syscall.MS_MGC_MSK, syscall.MS_ASYNC, syscall.MS_ACTIVE} payload := []uint64{syscall.MS_MGC_VAL, syscall.MS_MGC_MSK, syscall.MS_ASYNC, syscall.MS_ACTIVE}
encoderDone := make(chan error, 1) encoderDone := make(chan error, 1)
extraFiles := make([]*os.File, 0, 1) extraFiles := make([]*os.File, 0, 1)
@ -86,7 +86,7 @@ func TestSetupReceive(t *testing.T) {
} }
var ( var (
gotPayload []int gotPayload []uint64
fdp *uintptr fdp *uintptr
) )
if !useNilFdp { if !useNilFdp {

View File

@ -173,8 +173,8 @@ func TestProcPaths(t *testing.T) {
} }
}) })
t.Run("fd", func(t *testing.T) { t.Run("fd", func(t *testing.T) {
want := "/host/proc/self/fd/9223372036854775807" want := "/host/proc/self/fd/2147483647"
if got := hostProc.fd(math.MaxInt64); got != want { if got := hostProc.fd(math.MaxInt32); got != want {
t.Errorf("stdout: %q, want %q", got, want) t.Errorf("stdout: %q, want %q", got, want)
} }
}) })

View File

@ -14,6 +14,8 @@ import (
"runtime/cgo" "runtime/cgo"
"syscall" "syscall"
"unsafe" "unsafe"
"hakurei.app/container/std"
) )
// ErrInvalidRules is returned for a zero-length rules slice. // ErrInvalidRules is returned for a zero-length rules slice.
@ -54,22 +56,16 @@ func (e *LibraryError) Is(err error) bool {
} }
type ( type (
// ScmpSyscall represents a syscall number passed to libseccomp via [NativeRule.Syscall]. // scmpUint is equivalent to [std.ScmpUint].
ScmpSyscall = C.int scmpUint = C.uint
// ScmpErrno represents an errno value passed to libseccomp via [NativeRule.Errno]. // scmpInt is equivalent to [std.ScmpInt].
ScmpErrno = C.int scmpInt = C.int
// syscallRule is equivalent to [std.NativeRule].
syscallRule = C.struct_hakurei_syscall_rule
) )
// A NativeRule specifies an arch-specific action taken by seccomp under certain conditions. // ExportFlag configures filter behaviour that are not implemented as rules.
type NativeRule struct {
// Syscall is the arch-dependent syscall number to act against.
Syscall ScmpSyscall
// Errno is the errno value to return when the condition is satisfied.
Errno ScmpErrno
// Arg is the optional struct scmp_arg_cmp passed to libseccomp.
Arg *ScmpArgCmp
}
type ExportFlag = C.hakurei_export_flag type ExportFlag = C.hakurei_export_flag
const ( const (
@ -102,9 +98,9 @@ func hakurei_scmp_allocate(f C.uintptr_t, len C.size_t) (buf unsafe.Pointer) {
return cgo.Handle(f).Value().(cbAllocateBuffer)(len) return cgo.Handle(f).Value().(cbAllocateBuffer)(len)
} }
// makeFilter generates a bpf program from a slice of [NativeRule] and writes the resulting byte slice to p. // makeFilter generates a bpf program from a slice of [std.NativeRule] and writes the resulting byte slice to p.
// The filter is installed to the current process if p is nil. // The filter is installed to the current process if p is nil.
func makeFilter(rules []NativeRule, flags ExportFlag, p *[]byte) error { func makeFilter(rules []std.NativeRule, flags ExportFlag, p *[]byte) error {
if len(rules) == 0 { if len(rules) == 0 {
return ErrInvalidRules return ErrInvalidRules
} }
@ -152,7 +148,7 @@ func makeFilter(rules []NativeRule, flags ExportFlag, p *[]byte) error {
res, err := C.hakurei_scmp_make_filter( res, err := C.hakurei_scmp_make_filter(
&ret, C.uintptr_t(allocateP), &ret, C.uintptr_t(allocateP),
arch, multiarch, arch, multiarch,
(*C.struct_hakurei_syscall_rule)(unsafe.Pointer(&rules[0])), (*syscallRule)(unsafe.Pointer(&rules[0])),
C.size_t(len(rules)), C.size_t(len(rules)),
flags, flags,
) )
@ -167,20 +163,27 @@ func makeFilter(rules []NativeRule, flags ExportFlag, p *[]byte) error {
return err return err
} }
// Export generates a bpf program from a slice of [NativeRule]. // Export generates a bpf program from a slice of [std.NativeRule].
// Errors returned by libseccomp is wrapped in [LibraryError]. // Errors returned by libseccomp is wrapped in [LibraryError].
func Export(rules []NativeRule, flags ExportFlag) (data []byte, err error) { func Export(rules []std.NativeRule, flags ExportFlag) (data []byte, err error) {
err = makeFilter(rules, flags, &data) err = makeFilter(rules, flags, &data)
return return
} }
// Load generates a bpf program from a slice of [NativeRule] and enforces it on the current process. // Load generates a bpf program from a slice of [std.NativeRule] and enforces it on the current process.
// Errors returned by libseccomp is wrapped in [LibraryError]. // Errors returned by libseccomp is wrapped in [LibraryError].
func Load(rules []NativeRule, flags ExportFlag) error { return makeFilter(rules, flags, nil) } func Load(rules []std.NativeRule, flags ExportFlag) error { return makeFilter(rules, flags, nil) }
// ScmpCompare is the equivalent of scmp_compare; type (
// Comparison operators // Comparison operators.
type ScmpCompare = C.enum_scmp_compare scmpCompare = C.enum_scmp_compare
// Argument datum.
scmpDatum = C.scmp_datum_t
// Argument / Value comparison definition.
scmpArgCmp = C.struct_scmp_arg_cmp
)
const ( const (
_SCMP_CMP_MIN = C._SCMP_CMP_MIN _SCMP_CMP_MIN = C._SCMP_CMP_MIN
@ -203,33 +206,19 @@ const (
_SCMP_CMP_MAX = C._SCMP_CMP_MAX _SCMP_CMP_MAX = C._SCMP_CMP_MAX
) )
// ScmpDatum is the equivalent of scmp_datum_t;
// Argument datum
type ScmpDatum uint64
// ScmpArgCmp is the equivalent of struct scmp_arg_cmp;
// Argument / Value comparison definition
type ScmpArgCmp struct {
// argument number, starting at 0
Arg C.uint
// the comparison op, e.g. SCMP_CMP_*
Op ScmpCompare
DatumA, DatumB ScmpDatum
}
const ( const (
// PersonaLinux is passed in a [ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY. // PersonaLinux is passed in a [std.ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY.
PersonaLinux = C.PER_LINUX PersonaLinux = C.PER_LINUX
// PersonaLinux32 is passed in a [ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY. // PersonaLinux32 is passed in a [std.ScmpDatum] for filtering calls to syscall.SYS_PERSONALITY.
PersonaLinux32 = C.PER_LINUX32 PersonaLinux32 = C.PER_LINUX32
) )
// syscallResolveName resolves a syscall number by name via seccomp_syscall_resolve_name. // syscallResolveName resolves a syscall number by name via seccomp_syscall_resolve_name.
// This function is only for testing the lookup tables and included here for convenience. // This function is only for testing the lookup tables and included here for convenience.
func syscallResolveName(s string) (trap int) { func syscallResolveName(s string) (trap int, ok bool) {
v := C.CString(s) v := C.CString(s)
trap = int(C.seccomp_syscall_resolve_name(v)) trap = int(C.seccomp_syscall_resolve_name(v))
C.free(unsafe.Pointer(v)) C.free(unsafe.Pointer(v))
ok = trap != C.__NR_SCMP_ERROR
return return
} }

View File

@ -6,8 +6,8 @@ import (
"syscall" "syscall"
"testing" "testing"
. "hakurei.app/container/comp"
. "hakurei.app/container/seccomp" . "hakurei.app/container/seccomp"
. "hakurei.app/container/std"
) )
func TestLibraryError(t *testing.T) { func TestLibraryError(t *testing.T) {

View File

@ -5,32 +5,32 @@ package seccomp
import ( import (
. "syscall" . "syscall"
"hakurei.app/container/comp" . "hakurei.app/container/std"
) )
func Preset(presets comp.FilterPreset, flags ExportFlag) (rules []NativeRule) { func Preset(presets FilterPreset, flags ExportFlag) (rules []NativeRule) {
allowedPersonality := PersonaLinux allowedPersonality := PersonaLinux
if presets&comp.PresetLinux32 != 0 { if presets&PresetLinux32 != 0 {
allowedPersonality = PersonaLinux32 allowedPersonality = PersonaLinux32
} }
presetDevelFinal := presetDevel(ScmpDatum(allowedPersonality)) presetDevelFinal := presetDevel(ScmpDatum(allowedPersonality))
l := len(presetCommon) l := len(presetCommon)
if presets&comp.PresetDenyNS != 0 { if presets&PresetDenyNS != 0 {
l += len(presetNamespace) l += len(presetNamespace)
} }
if presets&comp.PresetDenyTTY != 0 { if presets&PresetDenyTTY != 0 {
l += len(presetTTY) l += len(presetTTY)
} }
if presets&comp.PresetDenyDevel != 0 { if presets&PresetDenyDevel != 0 {
l += len(presetDevelFinal) l += len(presetDevelFinal)
} }
if flags&AllowMultiarch == 0 { if flags&AllowMultiarch == 0 {
l += len(presetEmu) l += len(presetEmu)
} }
if presets&comp.PresetExt != 0 { if presets&PresetExt != 0 {
l += len(presetCommonExt) l += len(presetCommonExt)
if presets&comp.PresetDenyNS != 0 { if presets&PresetDenyNS != 0 {
l += len(presetNamespaceExt) l += len(presetNamespaceExt)
} }
if flags&AllowMultiarch == 0 { if flags&AllowMultiarch == 0 {
@ -40,21 +40,21 @@ func Preset(presets comp.FilterPreset, flags ExportFlag) (rules []NativeRule) {
rules = make([]NativeRule, 0, l) rules = make([]NativeRule, 0, l)
rules = append(rules, presetCommon...) rules = append(rules, presetCommon...)
if presets&comp.PresetDenyNS != 0 { if presets&PresetDenyNS != 0 {
rules = append(rules, presetNamespace...) rules = append(rules, presetNamespace...)
} }
if presets&comp.PresetDenyTTY != 0 { if presets&PresetDenyTTY != 0 {
rules = append(rules, presetTTY...) rules = append(rules, presetTTY...)
} }
if presets&comp.PresetDenyDevel != 0 { if presets&PresetDenyDevel != 0 {
rules = append(rules, presetDevelFinal...) rules = append(rules, presetDevelFinal...)
} }
if flags&AllowMultiarch == 0 { if flags&AllowMultiarch == 0 {
rules = append(rules, presetEmu...) rules = append(rules, presetEmu...)
} }
if presets&comp.PresetExt != 0 { if presets&PresetExt != 0 {
rules = append(rules, presetCommonExt...) rules = append(rules, presetCommonExt...)
if presets&comp.PresetDenyNS != 0 { if presets&PresetDenyNS != 0 {
rules = append(rules, presetNamespaceExt...) rules = append(rules, presetNamespaceExt...)
} }
if flags&AllowMultiarch == 0 { if flags&AllowMultiarch == 0 {

View File

@ -0,0 +1,27 @@
package seccomp_test
import (
. "hakurei.app/container/seccomp"
. "hakurei.app/container/std"
)
var bpfExpected = bpfLookup{
{AllowMultiarch | AllowCAN |
AllowBluetooth, PresetExt |
PresetDenyNS | PresetDenyTTY | PresetDenyDevel |
PresetLinux32}: toHash(
"e67735d24caba42b6801e829ea4393727a36c5e37b8a51e5648e7886047e8454484ff06872aaef810799c29cbd0c1b361f423ad0ef518e33f68436372cc90eb1"),
{0, 0}: toHash(
"5dbcc08a4a1ccd8c12dd0cf6d9817ea6d4f40246e1db7a60e71a50111c4897d69f6fb6d710382d70c18910c2e4fa2d2aeb2daed835dd2fabe3f71def628ade59"),
{0, PresetExt}: toHash(
"d6c0f130dbb5c793d1c10f730455701875778138bd2d03ca009d674842fd97a10815a8c539b76b7801a73de19463938701216b756c053ec91cfe304cba04a0ed"),
{0, PresetStrict}: toHash(
"af7d7b66f2e83f9a850472170c1b83d1371426faa9d0dee4e85b179d3ec75ca92828cb8529eb3012b559497494b2eab4d4b140605e3a26c70dfdbe5efe33c105"),
{0, PresetDenyNS | PresetDenyTTY | PresetDenyDevel}: toHash(
"adfb4397e6eeae8c477d315d58204aae854d60071687b8df4c758e297780e02deee1af48328cef80e16e4d6ab1a66ef13e42247c3475cf447923f15cbc17a6a6"),
{0, PresetExt | PresetDenyDevel}: toHash(
"5d641321460cf54a7036a40a08e845082e1f6d65b9dee75db85ef179f2732f321b16aee2258b74273b04e0d24562e8b1e727930a7e787f41eb5c8aaa0bc22793"),
{0, PresetExt | PresetDenyNS | PresetDenyDevel}: toHash(
"b1f802d39de5897b1e4cb0e82a199f53df0a803ea88e2fd19491fb8c90387c9e2eaa7e323f565fecaa0202a579eb050531f22e6748e04cfd935b8faac35983ec"),
}

View File

@ -1,8 +1,8 @@
package seccomp_test package seccomp_test
import ( import (
. "hakurei.app/container/comp"
. "hakurei.app/container/seccomp" . "hakurei.app/container/seccomp"
. "hakurei.app/container/std"
) )
var bpfExpected = bpfLookup{ var bpfExpected = bpfLookup{

View File

@ -1,8 +1,8 @@
package seccomp_test package seccomp_test
import ( import (
. "hakurei.app/container/comp"
. "hakurei.app/container/seccomp" . "hakurei.app/container/seccomp"
. "hakurei.app/container/std"
) )
var bpfExpected = bpfLookup{ var bpfExpected = bpfLookup{

View File

@ -4,14 +4,14 @@ import (
"crypto/sha512" "crypto/sha512"
"encoding/hex" "encoding/hex"
"hakurei.app/container/comp"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
) )
type ( type (
bpfPreset = struct { bpfPreset = struct {
seccomp.ExportFlag seccomp.ExportFlag
comp.FilterPreset std.FilterPreset
} }
bpfLookup map[bpfPreset][sha512.Size]byte bpfLookup map[bpfPreset][sha512.Size]byte
) )

View File

@ -0,0 +1,63 @@
package seccomp
import (
"reflect"
"testing"
"unsafe"
"hakurei.app/container/std"
)
func TestSyscallResolveName(t *testing.T) {
t.Parallel()
for name, want := range std.Syscalls() {
t.Run(name, func(t *testing.T) {
t.Parallel()
// this checks the std implementation against libseccomp.
if got, ok := syscallResolveName(name); !ok || got != want {
t.Errorf("syscallResolveName(%q) = %d, want %d", name, got, want)
}
})
}
}
func TestRuleType(t *testing.T) {
assertKind[std.ScmpUint, scmpUint](t)
assertKind[std.ScmpInt, scmpInt](t)
assertSize[std.NativeRule, syscallRule](t)
assertKind[std.ScmpDatum, scmpDatum](t)
assertKind[std.ScmpCompare, scmpCompare](t)
assertSize[std.ScmpArgCmp, scmpArgCmp](t)
}
// assertSize asserts that native and equivalent are of the same size.
func assertSize[native, equivalent any](t *testing.T) {
t.Helper()
got, want := unsafe.Sizeof(*new(native)), unsafe.Sizeof(*new(equivalent))
if got != want {
t.Fatalf("%s: %d, want %d", reflect.TypeFor[native]().Name(), got, want)
}
}
// assertKind asserts that native and equivalent are of the same kind.
func assertKind[native, equivalent any](t *testing.T) {
t.Helper()
assertSize[native, equivalent](t)
nativeType, equivalentType := reflect.TypeFor[native](), reflect.TypeFor[equivalent]()
got, want := nativeType.Kind(), equivalentType.Kind()
if got == reflect.Invalid || want == reflect.Invalid {
t.Fatalf("%s: invalid call to assertKind", nativeType.Name())
}
if got == reflect.Struct {
t.Fatalf("%s: struct is unsupported by assertKind", nativeType.Name())
}
if got != want {
t.Fatalf("%s: %s, want %s", nativeType.Name(), nativeType.Kind(), equivalentType.Kind())
}
}

View File

@ -1,48 +0,0 @@
package seccomp
/*
#cgo linux pkg-config: --static libseccomp
#include <seccomp.h>
*/
import "C"
var syscallNumExtra = map[string]int{
"umount": SYS_UMOUNT,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
"vm86": SYS_VM86,
"vm86old": SYS_VM86OLD,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"chown32": SYS_CHOWN32,
"fchown32": SYS_FCHOWN32,
"lchown32": SYS_LCHOWN32,
"setgid32": SYS_SETGID32,
"setgroups32": SYS_SETGROUPS32,
"setregid32": SYS_SETREGID32,
"setresgid32": SYS_SETRESGID32,
"setresuid32": SYS_SETRESUID32,
"setreuid32": SYS_SETREUID32,
"setuid32": SYS_SETUID32,
}
const (
SYS_UMOUNT = C.__SNR_umount
SYS_SUBPAGE_PROT = C.__SNR_subpage_prot
SYS_SWITCH_ENDIAN = C.__SNR_switch_endian
SYS_VM86 = C.__SNR_vm86
SYS_VM86OLD = C.__SNR_vm86old
SYS_CLOCK_ADJTIME64 = C.__SNR_clock_adjtime64
SYS_CLOCK_SETTIME64 = C.__SNR_clock_settime64
SYS_CHOWN32 = C.__SNR_chown32
SYS_FCHOWN32 = C.__SNR_fchown32
SYS_LCHOWN32 = C.__SNR_lchown32
SYS_SETGID32 = C.__SNR_setgid32
SYS_SETGROUPS32 = C.__SNR_setgroups32
SYS_SETREGID32 = C.__SNR_setregid32
SYS_SETRESGID32 = C.__SNR_setresgid32
SYS_SETRESUID32 = C.__SNR_setresuid32
SYS_SETREUID32 = C.__SNR_setreuid32
SYS_SETUID32 = C.__SNR_setuid32
)

View File

@ -1,61 +0,0 @@
package seccomp
/*
#cgo linux pkg-config: --static libseccomp
#include <seccomp.h>
*/
import "C"
import "syscall"
const (
SYS_NEWFSTATAT = syscall.SYS_FSTATAT
)
var syscallNumExtra = map[string]int{
"uselib": SYS_USELIB,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"umount": SYS_UMOUNT,
"chown": SYS_CHOWN,
"chown32": SYS_CHOWN32,
"fchown32": SYS_FCHOWN32,
"lchown": SYS_LCHOWN,
"lchown32": SYS_LCHOWN32,
"setgid32": SYS_SETGID32,
"setgroups32": SYS_SETGROUPS32,
"setregid32": SYS_SETREGID32,
"setresgid32": SYS_SETRESGID32,
"setresuid32": SYS_SETRESUID32,
"setreuid32": SYS_SETREUID32,
"setuid32": SYS_SETUID32,
"modify_ldt": SYS_MODIFY_LDT,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
"vm86": SYS_VM86,
"vm86old": SYS_VM86OLD,
}
const (
SYS_USELIB = C.__SNR_uselib
SYS_CLOCK_ADJTIME64 = C.__SNR_clock_adjtime64
SYS_CLOCK_SETTIME64 = C.__SNR_clock_settime64
SYS_UMOUNT = C.__SNR_umount
SYS_CHOWN = C.__SNR_chown
SYS_CHOWN32 = C.__SNR_chown32
SYS_FCHOWN32 = C.__SNR_fchown32
SYS_LCHOWN = C.__SNR_lchown
SYS_LCHOWN32 = C.__SNR_lchown32
SYS_SETGID32 = C.__SNR_setgid32
SYS_SETGROUPS32 = C.__SNR_setgroups32
SYS_SETREGID32 = C.__SNR_setregid32
SYS_SETRESGID32 = C.__SNR_setresgid32
SYS_SETRESUID32 = C.__SNR_setresuid32
SYS_SETREUID32 = C.__SNR_setreuid32
SYS_SETUID32 = C.__SNR_setuid32
SYS_MODIFY_LDT = C.__SNR_modify_ldt
SYS_SUBPAGE_PROT = C.__SNR_subpage_prot
SYS_SWITCH_ENDIAN = C.__SNR_switch_endian
SYS_VM86 = C.__SNR_vm86
SYS_VM86OLD = C.__SNR_vm86old
)

View File

@ -1,22 +0,0 @@
package seccomp
import (
"testing"
)
func TestSyscallResolveName(t *testing.T) {
t.Parallel()
for name, want := range Syscalls() {
t.Run(name, func(t *testing.T) {
t.Parallel()
if got := syscallResolveName(name); got != want {
t.Errorf("syscallResolveName(%q) = %d, want %d", name, got, want)
}
if got, ok := SyscallResolveName(name); !ok || got != want {
t.Errorf("SyscallResolveName(%q) = %d, want %d", name, got, want)
}
})
}
}

View File

@ -1,5 +1,5 @@
// Package comp contains constants from container packages without depending on cgo. // Package std contains constants from container packages without depending on cgo.
package comp package std
const ( const (
// BindOptional skips nonexistent host paths. // BindOptional skips nonexistent host paths.

View File

@ -9,6 +9,7 @@ use POSIX ();
my $command = "mksysnum_linux.pl ". join(' ', @ARGV); my $command = "mksysnum_linux.pl ". join(' ', @ARGV);
my $uname_arch = (POSIX::uname)[4]; my $uname_arch = (POSIX::uname)[4];
my %syscall_cutoff_arch = ( my %syscall_cutoff_arch = (
"x86" => 340,
"x86_64" => 302, "x86_64" => 302,
"aarch64" => 281, "aarch64" => 281,
); );
@ -17,7 +18,7 @@ print <<EOF;
// $command // $command
// Code generated by the command above; DO NOT EDIT. // Code generated by the command above; DO NOT EDIT.
package seccomp package std
import . "syscall" import . "syscall"

267
container/std/pnr.go Normal file
View File

@ -0,0 +1,267 @@
// Code generated from include/seccomp-syscalls.h; DO NOT EDIT.
package std
/*
* pseudo syscall definitions
*/
const (
/* socket syscalls */
__PNR_socket = -101
__PNR_bind = -102
__PNR_connect = -103
__PNR_listen = -104
__PNR_accept = -105
__PNR_getsockname = -106
__PNR_getpeername = -107
__PNR_socketpair = -108
__PNR_send = -109
__PNR_recv = -110
__PNR_sendto = -111
__PNR_recvfrom = -112
__PNR_shutdown = -113
__PNR_setsockopt = -114
__PNR_getsockopt = -115
__PNR_sendmsg = -116
__PNR_recvmsg = -117
__PNR_accept4 = -118
__PNR_recvmmsg = -119
__PNR_sendmmsg = -120
/* ipc syscalls */
__PNR_semop = -201
__PNR_semget = -202
__PNR_semctl = -203
__PNR_semtimedop = -204
__PNR_msgsnd = -211
__PNR_msgrcv = -212
__PNR_msgget = -213
__PNR_msgctl = -214
__PNR_shmat = -221
__PNR_shmdt = -222
__PNR_shmget = -223
__PNR_shmctl = -224
/* single syscalls */
__PNR_arch_prctl = -10001
__PNR_bdflush = -10002
__PNR_break = -10003
__PNR_chown32 = -10004
__PNR_epoll_ctl_old = -10005
__PNR_epoll_wait_old = -10006
__PNR_fadvise64_64 = -10007
__PNR_fchown32 = -10008
__PNR_fcntl64 = -10009
__PNR_fstat64 = -10010
__PNR_fstatat64 = -10011
__PNR_fstatfs64 = -10012
__PNR_ftime = -10013
__PNR_ftruncate64 = -10014
__PNR_getegid32 = -10015
__PNR_geteuid32 = -10016
__PNR_getgid32 = -10017
__PNR_getgroups32 = -10018
__PNR_getresgid32 = -10019
__PNR_getresuid32 = -10020
__PNR_getuid32 = -10021
__PNR_gtty = -10022
__PNR_idle = -10023
__PNR_ipc = -10024
__PNR_lchown32 = -10025
__PNR__llseek = -10026
__PNR_lock = -10027
__PNR_lstat64 = -10028
__PNR_mmap2 = -10029
__PNR_mpx = -10030
__PNR_newfstatat = -10031
__PNR__newselect = -10032
__PNR_nice = -10033
__PNR_oldfstat = -10034
__PNR_oldlstat = -10035
__PNR_oldolduname = -10036
__PNR_oldstat = -10037
__PNR_olduname = -10038
__PNR_prof = -10039
__PNR_profil = -10040
__PNR_readdir = -10041
__PNR_security = -10042
__PNR_sendfile64 = -10043
__PNR_setfsgid32 = -10044
__PNR_setfsuid32 = -10045
__PNR_setgid32 = -10046
__PNR_setgroups32 = -10047
__PNR_setregid32 = -10048
__PNR_setresgid32 = -10049
__PNR_setresuid32 = -10050
__PNR_setreuid32 = -10051
__PNR_setuid32 = -10052
__PNR_sgetmask = -10053
__PNR_sigaction = -10054
__PNR_signal = -10055
__PNR_sigpending = -10056
__PNR_sigprocmask = -10057
__PNR_sigreturn = -10058
__PNR_sigsuspend = -10059
__PNR_socketcall = -10060
__PNR_ssetmask = -10061
__PNR_stat64 = -10062
__PNR_statfs64 = -10063
__PNR_stime = -10064
__PNR_stty = -10065
__PNR_truncate64 = -10066
__PNR_tuxcall = -10067
__PNR_ugetrlimit = -10068
__PNR_ulimit = -10069
__PNR_umount = -10070
__PNR_vm86 = -10071
__PNR_vm86old = -10072
__PNR_waitpid = -10073
__PNR_create_module = -10074
__PNR_get_kernel_syms = -10075
__PNR_get_thread_area = -10076
__PNR_nfsservctl = -10077
__PNR_query_module = -10078
__PNR_set_thread_area = -10079
__PNR__sysctl = -10080
__PNR_uselib = -10081
__PNR_vserver = -10082
__PNR_arm_fadvise64_64 = -10083
__PNR_arm_sync_file_range = -10084
__PNR_pciconfig_iobase = -10086
__PNR_pciconfig_read = -10087
__PNR_pciconfig_write = -10088
__PNR_sync_file_range2 = -10089
__PNR_syscall = -10090
__PNR_afs_syscall = -10091
__PNR_fadvise64 = -10092
__PNR_getpmsg = -10093
__PNR_ioperm = -10094
__PNR_iopl = -10095
__PNR_migrate_pages = -10097
__PNR_modify_ldt = -10098
__PNR_putpmsg = -10099
__PNR_sync_file_range = -10100
__PNR_select = -10101
__PNR_vfork = -10102
__PNR_cachectl = -10103
__PNR_cacheflush = -10104
__PNR_sysmips = -10106
__PNR_timerfd = -10107
__PNR_time = -10108
__PNR_getrandom = -10109
__PNR_memfd_create = -10110
__PNR_kexec_file_load = -10111
__PNR_sysfs = -10145
__PNR_oldwait4 = -10146
__PNR_access = -10147
__PNR_alarm = -10148
__PNR_chmod = -10149
__PNR_chown = -10150
__PNR_creat = -10151
__PNR_dup2 = -10152
__PNR_epoll_create = -10153
__PNR_epoll_wait = -10154
__PNR_eventfd = -10155
__PNR_fork = -10156
__PNR_futimesat = -10157
__PNR_getdents = -10158
__PNR_getpgrp = -10159
__PNR_inotify_init = -10160
__PNR_lchown = -10161
__PNR_link = -10162
__PNR_lstat = -10163
__PNR_mkdir = -10164
__PNR_mknod = -10165
__PNR_open = -10166
__PNR_pause = -10167
__PNR_pipe = -10168
__PNR_poll = -10169
__PNR_readlink = -10170
__PNR_rename = -10171
__PNR_rmdir = -10172
__PNR_signalfd = -10173
__PNR_stat = -10174
__PNR_symlink = -10175
__PNR_unlink = -10176
__PNR_ustat = -10177
__PNR_utime = -10178
__PNR_utimes = -10179
__PNR_getrlimit = -10180
__PNR_mmap = -10181
__PNR_breakpoint = -10182
__PNR_set_tls = -10183
__PNR_usr26 = -10184
__PNR_usr32 = -10185
__PNR_multiplexer = -10186
__PNR_rtas = -10187
__PNR_spu_create = -10188
__PNR_spu_run = -10189
__PNR_swapcontext = -10190
__PNR_sys_debug_setcontext = -10191
__PNR_switch_endian = -10191
__PNR_get_mempolicy = -10192
__PNR_move_pages = -10193
__PNR_mbind = -10194
__PNR_set_mempolicy = -10195
__PNR_s390_runtime_instr = -10196
__PNR_s390_pci_mmio_read = -10197
__PNR_s390_pci_mmio_write = -10198
__PNR_membarrier = -10199
__PNR_userfaultfd = -10200
__PNR_pkey_mprotect = -10201
__PNR_pkey_alloc = -10202
__PNR_pkey_free = -10203
__PNR_get_tls = -10204
__PNR_s390_guarded_storage = -10205
__PNR_s390_sthyi = -10206
__PNR_subpage_prot = -10207
__PNR_statx = -10208
__PNR_io_pgetevents = -10209
__PNR_rseq = -10210
__PNR_setrlimit = -10211
__PNR_clock_adjtime64 = -10212
__PNR_clock_getres_time64 = -10213
__PNR_clock_gettime64 = -10214
__PNR_clock_nanosleep_time64 = -10215
__PNR_clock_settime64 = -10216
__PNR_clone3 = -10217
__PNR_fsconfig = -10218
__PNR_fsmount = -10219
__PNR_fsopen = -10220
__PNR_fspick = -10221
__PNR_futex_time64 = -10222
__PNR_io_pgetevents_time64 = -10223
__PNR_move_mount = -10224
__PNR_mq_timedreceive_time64 = -10225
__PNR_mq_timedsend_time64 = -10226
__PNR_open_tree = -10227
__PNR_pidfd_open = -10228
__PNR_pidfd_send_signal = -10229
__PNR_ppoll_time64 = -10230
__PNR_pselect6_time64 = -10231
__PNR_recvmmsg_time64 = -10232
__PNR_rt_sigtimedwait_time64 = -10233
__PNR_sched_rr_get_interval_time64 = -10234
__PNR_semtimedop_time64 = -10235
__PNR_timer_gettime64 = -10236
__PNR_timer_settime64 = -10237
__PNR_timerfd_gettime64 = -10238
__PNR_timerfd_settime64 = -10239
__PNR_utimensat_time64 = -10240
__PNR_ppoll = -10241
__PNR_renameat = -10242
__PNR_riscv_flush_icache = -10243
__PNR_memfd_secret = -10244
__PNR_map_shadow_stack = -10245
__PNR_fstat = -10246
__PNR_atomic_barrier = -10247
__PNR_atomic_cmpxchg_32 = -10248
__PNR_getpagesize = -10249
__PNR_riscv_hwprobe = -10250
__PNR_uretprobe = -10251
)

76
container/std/seccomp.go Normal file
View File

@ -0,0 +1,76 @@
package std
import (
"encoding/json"
"strconv"
)
type (
// ScmpUint is equivalent to C.uint.
ScmpUint uint32
// ScmpInt is equivalent to C.int.
ScmpInt int32
// ScmpSyscall represents a syscall number passed to libseccomp via [NativeRule.Syscall].
ScmpSyscall ScmpInt
// ScmpErrno represents an errno value passed to libseccomp via [NativeRule.Errno].
ScmpErrno ScmpInt
// ScmpCompare is equivalent to enum scmp_compare;
ScmpCompare ScmpUint
// ScmpDatum is equivalent to scmp_datum_t.
ScmpDatum uint64
// ScmpArgCmp is equivalent to struct scmp_arg_cmp.
ScmpArgCmp struct {
// argument number, starting at 0
Arg ScmpUint `json:"arg"`
// the comparison op, e.g. SCMP_CMP_*
Op ScmpCompare `json:"op"`
DatumA ScmpDatum `json:"a,omitempty"`
DatumB ScmpDatum `json:"b,omitempty"`
}
// A NativeRule specifies an arch-specific action taken by seccomp under certain conditions.
NativeRule struct {
// Syscall is the arch-dependent syscall number to act against.
Syscall ScmpSyscall `json:"syscall"`
// Errno is the errno value to return when the condition is satisfied.
Errno ScmpErrno `json:"errno"`
// Arg is the optional struct scmp_arg_cmp passed to libseccomp.
Arg *ScmpArgCmp `json:"arg,omitempty"`
}
)
// MarshalJSON resolves the name of [ScmpSyscall] and encodes it as a [json] string.
// If such a name does not exist, the syscall number is encoded instead.
func (num *ScmpSyscall) MarshalJSON() ([]byte, error) {
n := int(*num)
for name, cur := range Syscalls() {
if cur == n {
return json.Marshal(name)
}
}
return json.Marshal(n)
}
// SyscallNameError is returned when trying to unmarshal an invalid syscall name into [ScmpSyscall].
type SyscallNameError string
func (e SyscallNameError) Error() string { return "invalid syscall name " + strconv.Quote(string(e)) }
// UnmarshalJSON looks up the syscall number corresponding to name encoded in data
// by calling [SyscallResolveName].
func (num *ScmpSyscall) UnmarshalJSON(data []byte) error {
var name string
if err := json.Unmarshal(data, &name); err != nil {
return err
}
if n, ok := SyscallResolveName(name); !ok {
return SyscallNameError(name)
} else {
*num = ScmpSyscall(n)
return nil
}
}

View File

@ -0,0 +1,63 @@
package std_test
import (
"encoding/json"
"errors"
"math"
"reflect"
"syscall"
"testing"
"hakurei.app/container/std"
)
func TestScmpSyscall(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
data string
want std.ScmpSyscall
err error
}{
{"select", `"select"`, syscall.SYS_SELECT, nil},
{"clone3", `"clone3"`, std.SYS_CLONE3, nil},
{"oob", `-2147483647`, -math.MaxInt32,
&json.UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[string](), Offset: 11}},
{"name", `"nonexistent_syscall"`, -math.MaxInt32,
std.SyscallNameError("nonexistent_syscall")},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
t.Run("decode", func(t *testing.T) {
var got std.ScmpSyscall
if err := json.Unmarshal([]byte(tc.data), &got); !reflect.DeepEqual(err, tc.err) {
t.Fatalf("Unmarshal: error = %#v, want %#v", err, tc.err)
} else if err == nil && got != tc.want {
t.Errorf("Unmarshal: %v, want %v", got, tc.want)
}
})
if errors.As(tc.err, new(std.SyscallNameError)) {
return
}
t.Run("encode", func(t *testing.T) {
if got, err := json.Marshal(&tc.want); err != nil {
t.Fatalf("Marshal: error = %v", err)
} else if string(got) != tc.data {
t.Errorf("Marshal: %s, want %s", string(got), tc.data)
}
})
})
}
t.Run("error", func(t *testing.T) {
const want = `invalid syscall name "\x00"`
if got := std.SyscallNameError("\x00").Error(); got != want {
t.Fatalf("Error: %q, want %q", got, want)
}
})
}

View File

@ -1,4 +1,4 @@
package seccomp package std
import "iter" import "iter"

View File

@ -0,0 +1,13 @@
package std
var syscallNumExtra = map[string]int{
"kexec_file_load": SYS_KEXEC_FILE_LOAD,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
}
const (
SYS_KEXEC_FILE_LOAD = __PNR_kexec_file_load
SYS_SUBPAGE_PROT = __PNR_subpage_prot
SYS_SWITCH_ENDIAN = __PNR_switch_endian
)

View File

@ -0,0 +1,41 @@
package std
var syscallNumExtra = map[string]int{
"umount": SYS_UMOUNT,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
"vm86": SYS_VM86,
"vm86old": SYS_VM86OLD,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"chown32": SYS_CHOWN32,
"fchown32": SYS_FCHOWN32,
"lchown32": SYS_LCHOWN32,
"setgid32": SYS_SETGID32,
"setgroups32": SYS_SETGROUPS32,
"setregid32": SYS_SETREGID32,
"setresgid32": SYS_SETRESGID32,
"setresuid32": SYS_SETRESUID32,
"setreuid32": SYS_SETREUID32,
"setuid32": SYS_SETUID32,
}
const (
SYS_UMOUNT = __PNR_umount
SYS_SUBPAGE_PROT = __PNR_subpage_prot
SYS_SWITCH_ENDIAN = __PNR_switch_endian
SYS_VM86 = __PNR_vm86
SYS_VM86OLD = __PNR_vm86old
SYS_CLOCK_ADJTIME64 = __PNR_clock_adjtime64
SYS_CLOCK_SETTIME64 = __PNR_clock_settime64
SYS_CHOWN32 = __PNR_chown32
SYS_FCHOWN32 = __PNR_fchown32
SYS_LCHOWN32 = __PNR_lchown32
SYS_SETGID32 = __PNR_setgid32
SYS_SETGROUPS32 = __PNR_setgroups32
SYS_SETREGID32 = __PNR_setregid32
SYS_SETRESGID32 = __PNR_setresgid32
SYS_SETRESUID32 = __PNR_setresuid32
SYS_SETREUID32 = __PNR_setreuid32
SYS_SETUID32 = __PNR_setuid32
)

View File

@ -0,0 +1,55 @@
package std
import "syscall"
const (
SYS_NEWFSTATAT = syscall.SYS_FSTATAT
)
var syscallNumExtra = map[string]int{
"uselib": SYS_USELIB,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"umount": SYS_UMOUNT,
"chown": SYS_CHOWN,
"chown32": SYS_CHOWN32,
"fchown32": SYS_FCHOWN32,
"lchown": SYS_LCHOWN,
"lchown32": SYS_LCHOWN32,
"setgid32": SYS_SETGID32,
"setgroups32": SYS_SETGROUPS32,
"setregid32": SYS_SETREGID32,
"setresgid32": SYS_SETRESGID32,
"setresuid32": SYS_SETRESUID32,
"setreuid32": SYS_SETREUID32,
"setuid32": SYS_SETUID32,
"modify_ldt": SYS_MODIFY_LDT,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
"vm86": SYS_VM86,
"vm86old": SYS_VM86OLD,
}
const (
SYS_USELIB = __PNR_uselib
SYS_CLOCK_ADJTIME64 = __PNR_clock_adjtime64
SYS_CLOCK_SETTIME64 = __PNR_clock_settime64
SYS_UMOUNT = __PNR_umount
SYS_CHOWN = __PNR_chown
SYS_CHOWN32 = __PNR_chown32
SYS_FCHOWN32 = __PNR_fchown32
SYS_LCHOWN = __PNR_lchown
SYS_LCHOWN32 = __PNR_lchown32
SYS_SETGID32 = __PNR_setgid32
SYS_SETGROUPS32 = __PNR_setgroups32
SYS_SETREGID32 = __PNR_setregid32
SYS_SETRESGID32 = __PNR_setresgid32
SYS_SETRESUID32 = __PNR_setresuid32
SYS_SETREUID32 = __PNR_setreuid32
SYS_SETUID32 = __PNR_setuid32
SYS_MODIFY_LDT = __PNR_modify_ldt
SYS_SUBPAGE_PROT = __PNR_subpage_prot
SYS_SWITCH_ENDIAN = __PNR_switch_endian
SYS_VM86 = __PNR_vm86
SYS_VM86OLD = __PNR_vm86old
)

View File

@ -0,0 +1,579 @@
// mksysnum_linux.pl /usr/include/asm/unistd_32.h
// Code generated by the command above; DO NOT EDIT.
package std
import . "syscall"
var syscallNum = map[string]int{
"restart_syscall": SYS_RESTART_SYSCALL,
"exit": SYS_EXIT,
"fork": SYS_FORK,
"read": SYS_READ,
"write": SYS_WRITE,
"open": SYS_OPEN,
"close": SYS_CLOSE,
"waitpid": SYS_WAITPID,
"creat": SYS_CREAT,
"link": SYS_LINK,
"unlink": SYS_UNLINK,
"execve": SYS_EXECVE,
"chdir": SYS_CHDIR,
"time": SYS_TIME,
"mknod": SYS_MKNOD,
"chmod": SYS_CHMOD,
"lchown": SYS_LCHOWN,
"break": SYS_BREAK,
"oldstat": SYS_OLDSTAT,
"lseek": SYS_LSEEK,
"getpid": SYS_GETPID,
"mount": SYS_MOUNT,
"umount": SYS_UMOUNT,
"setuid": SYS_SETUID,
"getuid": SYS_GETUID,
"stime": SYS_STIME,
"ptrace": SYS_PTRACE,
"alarm": SYS_ALARM,
"oldfstat": SYS_OLDFSTAT,
"pause": SYS_PAUSE,
"utime": SYS_UTIME,
"stty": SYS_STTY,
"gtty": SYS_GTTY,
"access": SYS_ACCESS,
"nice": SYS_NICE,
"ftime": SYS_FTIME,
"sync": SYS_SYNC,
"kill": SYS_KILL,
"rename": SYS_RENAME,
"mkdir": SYS_MKDIR,
"rmdir": SYS_RMDIR,
"dup": SYS_DUP,
"pipe": SYS_PIPE,
"times": SYS_TIMES,
"prof": SYS_PROF,
"brk": SYS_BRK,
"setgid": SYS_SETGID,
"getgid": SYS_GETGID,
"signal": SYS_SIGNAL,
"geteuid": SYS_GETEUID,
"getegid": SYS_GETEGID,
"acct": SYS_ACCT,
"umount2": SYS_UMOUNT2,
"lock": SYS_LOCK,
"ioctl": SYS_IOCTL,
"fcntl": SYS_FCNTL,
"mpx": SYS_MPX,
"setpgid": SYS_SETPGID,
"ulimit": SYS_ULIMIT,
"oldolduname": SYS_OLDOLDUNAME,
"umask": SYS_UMASK,
"chroot": SYS_CHROOT,
"ustat": SYS_USTAT,
"dup2": SYS_DUP2,
"getppid": SYS_GETPPID,
"getpgrp": SYS_GETPGRP,
"setsid": SYS_SETSID,
"sigaction": SYS_SIGACTION,
"sgetmask": SYS_SGETMASK,
"ssetmask": SYS_SSETMASK,
"setreuid": SYS_SETREUID,
"setregid": SYS_SETREGID,
"sigsuspend": SYS_SIGSUSPEND,
"sigpending": SYS_SIGPENDING,
"sethostname": SYS_SETHOSTNAME,
"setrlimit": SYS_SETRLIMIT,
"getrlimit": SYS_GETRLIMIT,
"getrusage": SYS_GETRUSAGE,
"gettimeofday": SYS_GETTIMEOFDAY,
"settimeofday": SYS_SETTIMEOFDAY,
"getgroups": SYS_GETGROUPS,
"setgroups": SYS_SETGROUPS,
"select": SYS_SELECT,
"symlink": SYS_SYMLINK,
"oldlstat": SYS_OLDLSTAT,
"readlink": SYS_READLINK,
"uselib": SYS_USELIB,
"swapon": SYS_SWAPON,
"reboot": SYS_REBOOT,
"readdir": SYS_READDIR,
"mmap": SYS_MMAP,
"munmap": SYS_MUNMAP,
"truncate": SYS_TRUNCATE,
"ftruncate": SYS_FTRUNCATE,
"fchmod": SYS_FCHMOD,
"fchown": SYS_FCHOWN,
"getpriority": SYS_GETPRIORITY,
"setpriority": SYS_SETPRIORITY,
"profil": SYS_PROFIL,
"statfs": SYS_STATFS,
"fstatfs": SYS_FSTATFS,
"ioperm": SYS_IOPERM,
"socketcall": SYS_SOCKETCALL,
"syslog": SYS_SYSLOG,
"setitimer": SYS_SETITIMER,
"getitimer": SYS_GETITIMER,
"stat": SYS_STAT,
"lstat": SYS_LSTAT,
"fstat": SYS_FSTAT,
"olduname": SYS_OLDUNAME,
"iopl": SYS_IOPL,
"vhangup": SYS_VHANGUP,
"idle": SYS_IDLE,
"vm86old": SYS_VM86OLD,
"wait4": SYS_WAIT4,
"swapoff": SYS_SWAPOFF,
"sysinfo": SYS_SYSINFO,
"ipc": SYS_IPC,
"fsync": SYS_FSYNC,
"sigreturn": SYS_SIGRETURN,
"clone": SYS_CLONE,
"setdomainname": SYS_SETDOMAINNAME,
"uname": SYS_UNAME,
"modify_ldt": SYS_MODIFY_LDT,
"adjtimex": SYS_ADJTIMEX,
"mprotect": SYS_MPROTECT,
"sigprocmask": SYS_SIGPROCMASK,
"create_module": SYS_CREATE_MODULE,
"init_module": SYS_INIT_MODULE,
"delete_module": SYS_DELETE_MODULE,
"get_kernel_syms": SYS_GET_KERNEL_SYMS,
"quotactl": SYS_QUOTACTL,
"getpgid": SYS_GETPGID,
"fchdir": SYS_FCHDIR,
"bdflush": SYS_BDFLUSH,
"sysfs": SYS_SYSFS,
"personality": SYS_PERSONALITY,
"afs_syscall": SYS_AFS_SYSCALL,
"setfsuid": SYS_SETFSUID,
"setfsgid": SYS_SETFSGID,
"_llseek": SYS__LLSEEK,
"getdents": SYS_GETDENTS,
"_newselect": SYS__NEWSELECT,
"flock": SYS_FLOCK,
"msync": SYS_MSYNC,
"readv": SYS_READV,
"writev": SYS_WRITEV,
"getsid": SYS_GETSID,
"fdatasync": SYS_FDATASYNC,
"_sysctl": SYS__SYSCTL,
"mlock": SYS_MLOCK,
"munlock": SYS_MUNLOCK,
"mlockall": SYS_MLOCKALL,
"munlockall": SYS_MUNLOCKALL,
"sched_setparam": SYS_SCHED_SETPARAM,
"sched_getparam": SYS_SCHED_GETPARAM,
"sched_setscheduler": SYS_SCHED_SETSCHEDULER,
"sched_getscheduler": SYS_SCHED_GETSCHEDULER,
"sched_yield": SYS_SCHED_YIELD,
"sched_get_priority_max": SYS_SCHED_GET_PRIORITY_MAX,
"sched_get_priority_min": SYS_SCHED_GET_PRIORITY_MIN,
"sched_rr_get_interval": SYS_SCHED_RR_GET_INTERVAL,
"nanosleep": SYS_NANOSLEEP,
"mremap": SYS_MREMAP,
"setresuid": SYS_SETRESUID,
"getresuid": SYS_GETRESUID,
"vm86": SYS_VM86,
"query_module": SYS_QUERY_MODULE,
"poll": SYS_POLL,
"nfsservctl": SYS_NFSSERVCTL,
"setresgid": SYS_SETRESGID,
"getresgid": SYS_GETRESGID,
"prctl": SYS_PRCTL,
"rt_sigreturn": SYS_RT_SIGRETURN,
"rt_sigaction": SYS_RT_SIGACTION,
"rt_sigprocmask": SYS_RT_SIGPROCMASK,
"rt_sigpending": SYS_RT_SIGPENDING,
"rt_sigtimedwait": SYS_RT_SIGTIMEDWAIT,
"rt_sigqueueinfo": SYS_RT_SIGQUEUEINFO,
"rt_sigsuspend": SYS_RT_SIGSUSPEND,
"pread64": SYS_PREAD64,
"pwrite64": SYS_PWRITE64,
"chown": SYS_CHOWN,
"getcwd": SYS_GETCWD,
"capget": SYS_CAPGET,
"capset": SYS_CAPSET,
"sigaltstack": SYS_SIGALTSTACK,
"sendfile": SYS_SENDFILE,
"getpmsg": SYS_GETPMSG,
"putpmsg": SYS_PUTPMSG,
"vfork": SYS_VFORK,
"ugetrlimit": SYS_UGETRLIMIT,
"mmap2": SYS_MMAP2,
"truncate64": SYS_TRUNCATE64,
"ftruncate64": SYS_FTRUNCATE64,
"stat64": SYS_STAT64,
"lstat64": SYS_LSTAT64,
"fstat64": SYS_FSTAT64,
"lchown32": SYS_LCHOWN32,
"getuid32": SYS_GETUID32,
"getgid32": SYS_GETGID32,
"geteuid32": SYS_GETEUID32,
"getegid32": SYS_GETEGID32,
"setreuid32": SYS_SETREUID32,
"setregid32": SYS_SETREGID32,
"getgroups32": SYS_GETGROUPS32,
"setgroups32": SYS_SETGROUPS32,
"fchown32": SYS_FCHOWN32,
"setresuid32": SYS_SETRESUID32,
"getresuid32": SYS_GETRESUID32,
"setresgid32": SYS_SETRESGID32,
"getresgid32": SYS_GETRESGID32,
"chown32": SYS_CHOWN32,
"setuid32": SYS_SETUID32,
"setgid32": SYS_SETGID32,
"setfsuid32": SYS_SETFSUID32,
"setfsgid32": SYS_SETFSGID32,
"pivot_root": SYS_PIVOT_ROOT,
"mincore": SYS_MINCORE,
"madvise": SYS_MADVISE,
"getdents64": SYS_GETDENTS64,
"fcntl64": SYS_FCNTL64,
"gettid": SYS_GETTID,
"readahead": SYS_READAHEAD,
"setxattr": SYS_SETXATTR,
"lsetxattr": SYS_LSETXATTR,
"fsetxattr": SYS_FSETXATTR,
"getxattr": SYS_GETXATTR,
"lgetxattr": SYS_LGETXATTR,
"fgetxattr": SYS_FGETXATTR,
"listxattr": SYS_LISTXATTR,
"llistxattr": SYS_LLISTXATTR,
"flistxattr": SYS_FLISTXATTR,
"removexattr": SYS_REMOVEXATTR,
"lremovexattr": SYS_LREMOVEXATTR,
"fremovexattr": SYS_FREMOVEXATTR,
"tkill": SYS_TKILL,
"sendfile64": SYS_SENDFILE64,
"futex": SYS_FUTEX,
"sched_setaffinity": SYS_SCHED_SETAFFINITY,
"sched_getaffinity": SYS_SCHED_GETAFFINITY,
"set_thread_area": SYS_SET_THREAD_AREA,
"get_thread_area": SYS_GET_THREAD_AREA,
"io_setup": SYS_IO_SETUP,
"io_destroy": SYS_IO_DESTROY,
"io_getevents": SYS_IO_GETEVENTS,
"io_submit": SYS_IO_SUBMIT,
"io_cancel": SYS_IO_CANCEL,
"fadvise64": SYS_FADVISE64,
"exit_group": SYS_EXIT_GROUP,
"lookup_dcookie": SYS_LOOKUP_DCOOKIE,
"epoll_create": SYS_EPOLL_CREATE,
"epoll_ctl": SYS_EPOLL_CTL,
"epoll_wait": SYS_EPOLL_WAIT,
"remap_file_pages": SYS_REMAP_FILE_PAGES,
"set_tid_address": SYS_SET_TID_ADDRESS,
"timer_create": SYS_TIMER_CREATE,
"timer_settime": SYS_TIMER_SETTIME,
"timer_gettime": SYS_TIMER_GETTIME,
"timer_getoverrun": SYS_TIMER_GETOVERRUN,
"timer_delete": SYS_TIMER_DELETE,
"clock_settime": SYS_CLOCK_SETTIME,
"clock_gettime": SYS_CLOCK_GETTIME,
"clock_getres": SYS_CLOCK_GETRES,
"clock_nanosleep": SYS_CLOCK_NANOSLEEP,
"statfs64": SYS_STATFS64,
"fstatfs64": SYS_FSTATFS64,
"tgkill": SYS_TGKILL,
"utimes": SYS_UTIMES,
"fadvise64_64": SYS_FADVISE64_64,
"vserver": SYS_VSERVER,
"mbind": SYS_MBIND,
"get_mempolicy": SYS_GET_MEMPOLICY,
"set_mempolicy": SYS_SET_MEMPOLICY,
"mq_open": SYS_MQ_OPEN,
"mq_unlink": SYS_MQ_UNLINK,
"mq_timedsend": SYS_MQ_TIMEDSEND,
"mq_timedreceive": SYS_MQ_TIMEDRECEIVE,
"mq_notify": SYS_MQ_NOTIFY,
"mq_getsetattr": SYS_MQ_GETSETATTR,
"kexec_load": SYS_KEXEC_LOAD,
"waitid": SYS_WAITID,
"add_key": SYS_ADD_KEY,
"request_key": SYS_REQUEST_KEY,
"keyctl": SYS_KEYCTL,
"ioprio_set": SYS_IOPRIO_SET,
"ioprio_get": SYS_IOPRIO_GET,
"inotify_init": SYS_INOTIFY_INIT,
"inotify_add_watch": SYS_INOTIFY_ADD_WATCH,
"inotify_rm_watch": SYS_INOTIFY_RM_WATCH,
"migrate_pages": SYS_MIGRATE_PAGES,
"openat": SYS_OPENAT,
"mkdirat": SYS_MKDIRAT,
"mknodat": SYS_MKNODAT,
"fchownat": SYS_FCHOWNAT,
"futimesat": SYS_FUTIMESAT,
"fstatat64": SYS_FSTATAT64,
"unlinkat": SYS_UNLINKAT,
"renameat": SYS_RENAMEAT,
"linkat": SYS_LINKAT,
"symlinkat": SYS_SYMLINKAT,
"readlinkat": SYS_READLINKAT,
"fchmodat": SYS_FCHMODAT,
"faccessat": SYS_FACCESSAT,
"pselect6": SYS_PSELECT6,
"ppoll": SYS_PPOLL,
"unshare": SYS_UNSHARE,
"set_robust_list": SYS_SET_ROBUST_LIST,
"get_robust_list": SYS_GET_ROBUST_LIST,
"splice": SYS_SPLICE,
"sync_file_range": SYS_SYNC_FILE_RANGE,
"tee": SYS_TEE,
"vmsplice": SYS_VMSPLICE,
"move_pages": SYS_MOVE_PAGES,
"getcpu": SYS_GETCPU,
"epoll_pwait": SYS_EPOLL_PWAIT,
"utimensat": SYS_UTIMENSAT,
"signalfd": SYS_SIGNALFD,
"timerfd_create": SYS_TIMERFD_CREATE,
"eventfd": SYS_EVENTFD,
"fallocate": SYS_FALLOCATE,
"timerfd_settime": SYS_TIMERFD_SETTIME,
"timerfd_gettime": SYS_TIMERFD_GETTIME,
"signalfd4": SYS_SIGNALFD4,
"eventfd2": SYS_EVENTFD2,
"epoll_create1": SYS_EPOLL_CREATE1,
"dup3": SYS_DUP3,
"pipe2": SYS_PIPE2,
"inotify_init1": SYS_INOTIFY_INIT1,
"preadv": SYS_PREADV,
"pwritev": SYS_PWRITEV,
"rt_tgsigqueueinfo": SYS_RT_TGSIGQUEUEINFO,
"perf_event_open": SYS_PERF_EVENT_OPEN,
"recvmmsg": __PNR_recvmmsg,
"fanotify_init": SYS_FANOTIFY_INIT,
"fanotify_mark": SYS_FANOTIFY_MARK,
"prlimit64": SYS_PRLIMIT64,
"name_to_handle_at": SYS_NAME_TO_HANDLE_AT,
"open_by_handle_at": SYS_OPEN_BY_HANDLE_AT,
"clock_adjtime": SYS_CLOCK_ADJTIME,
"syncfs": SYS_SYNCFS,
"sendmmsg": __PNR_sendmmsg,
"setns": SYS_SETNS,
"process_vm_readv": SYS_PROCESS_VM_READV,
"process_vm_writev": SYS_PROCESS_VM_WRITEV,
"kcmp": SYS_KCMP,
"finit_module": SYS_FINIT_MODULE,
"sched_setattr": SYS_SCHED_SETATTR,
"sched_getattr": SYS_SCHED_GETATTR,
"renameat2": SYS_RENAMEAT2,
"seccomp": SYS_SECCOMP,
"getrandom": SYS_GETRANDOM,
"memfd_create": SYS_MEMFD_CREATE,
"bpf": SYS_BPF,
"execveat": SYS_EXECVEAT,
"socket": __PNR_socket,
"socketpair": __PNR_socketpair,
"bind": __PNR_bind,
"connect": __PNR_connect,
"listen": __PNR_listen,
"accept4": __PNR_accept4,
"getsockopt": __PNR_getsockopt,
"setsockopt": __PNR_setsockopt,
"getsockname": __PNR_getsockname,
"getpeername": __PNR_getpeername,
"sendto": __PNR_sendto,
"sendmsg": __PNR_sendmsg,
"recvfrom": __PNR_recvfrom,
"recvmsg": __PNR_recvmsg,
"shutdown": __PNR_shutdown,
"userfaultfd": SYS_USERFAULTFD,
"membarrier": SYS_MEMBARRIER,
"mlock2": SYS_MLOCK2,
"copy_file_range": SYS_COPY_FILE_RANGE,
"preadv2": SYS_PREADV2,
"pwritev2": SYS_PWRITEV2,
"pkey_mprotect": SYS_PKEY_MPROTECT,
"pkey_alloc": SYS_PKEY_ALLOC,
"pkey_free": SYS_PKEY_FREE,
"statx": SYS_STATX,
"arch_prctl": SYS_ARCH_PRCTL,
"io_pgetevents": SYS_IO_PGETEVENTS,
"rseq": SYS_RSEQ,
"semget": __PNR_semget,
"semctl": __PNR_semctl,
"shmget": __PNR_shmget,
"shmctl": __PNR_shmctl,
"shmat": __PNR_shmat,
"shmdt": __PNR_shmdt,
"msgget": __PNR_msgget,
"msgsnd": __PNR_msgsnd,
"msgrcv": __PNR_msgrcv,
"msgctl": __PNR_msgctl,
"clock_gettime64": SYS_CLOCK_GETTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_getres_time64": SYS_CLOCK_GETRES_TIME64,
"clock_nanosleep_time64": SYS_CLOCK_NANOSLEEP_TIME64,
"timer_gettime64": SYS_TIMER_GETTIME64,
"timer_settime64": SYS_TIMER_SETTIME64,
"timerfd_gettime64": SYS_TIMERFD_GETTIME64,
"timerfd_settime64": SYS_TIMERFD_SETTIME64,
"utimensat_time64": SYS_UTIMENSAT_TIME64,
"pselect6_time64": SYS_PSELECT6_TIME64,
"ppoll_time64": SYS_PPOLL_TIME64,
"io_pgetevents_time64": SYS_IO_PGETEVENTS_TIME64,
"recvmmsg_time64": SYS_RECVMMSG_TIME64,
"mq_timedsend_time64": SYS_MQ_TIMEDSEND_TIME64,
"mq_timedreceive_time64": SYS_MQ_TIMEDRECEIVE_TIME64,
"semtimedop_time64": SYS_SEMTIMEDOP_TIME64,
"rt_sigtimedwait_time64": SYS_RT_SIGTIMEDWAIT_TIME64,
"futex_time64": SYS_FUTEX_TIME64,
"sched_rr_get_interval_time64": SYS_SCHED_RR_GET_INTERVAL_TIME64,
"pidfd_send_signal": SYS_PIDFD_SEND_SIGNAL,
"io_uring_setup": SYS_IO_URING_SETUP,
"io_uring_enter": SYS_IO_URING_ENTER,
"io_uring_register": SYS_IO_URING_REGISTER,
"open_tree": SYS_OPEN_TREE,
"move_mount": SYS_MOVE_MOUNT,
"fsopen": SYS_FSOPEN,
"fsconfig": SYS_FSCONFIG,
"fsmount": SYS_FSMOUNT,
"fspick": SYS_FSPICK,
"pidfd_open": SYS_PIDFD_OPEN,
"clone3": SYS_CLONE3,
"close_range": SYS_CLOSE_RANGE,
"openat2": SYS_OPENAT2,
"pidfd_getfd": SYS_PIDFD_GETFD,
"faccessat2": SYS_FACCESSAT2,
"process_madvise": SYS_PROCESS_MADVISE,
"epoll_pwait2": SYS_EPOLL_PWAIT2,
"mount_setattr": SYS_MOUNT_SETATTR,
"quotactl_fd": SYS_QUOTACTL_FD,
"landlock_create_ruleset": SYS_LANDLOCK_CREATE_RULESET,
"landlock_add_rule": SYS_LANDLOCK_ADD_RULE,
"landlock_restrict_self": SYS_LANDLOCK_RESTRICT_SELF,
"memfd_secret": SYS_MEMFD_SECRET,
"process_mrelease": SYS_PROCESS_MRELEASE,
"futex_waitv": SYS_FUTEX_WAITV,
"set_mempolicy_home_node": SYS_SET_MEMPOLICY_HOME_NODE,
"cachestat": SYS_CACHESTAT,
"fchmodat2": SYS_FCHMODAT2,
"map_shadow_stack": SYS_MAP_SHADOW_STACK,
"futex_wake": SYS_FUTEX_WAKE,
"futex_wait": SYS_FUTEX_WAIT,
"futex_requeue": SYS_FUTEX_REQUEUE,
"statmount": SYS_STATMOUNT,
"listmount": SYS_LISTMOUNT,
"lsm_get_self_attr": SYS_LSM_GET_SELF_ATTR,
"lsm_set_self_attr": SYS_LSM_SET_SELF_ATTR,
"lsm_list_modules": SYS_LSM_LIST_MODULES,
"mseal": SYS_MSEAL,
}
const (
SYS_NAME_TO_HANDLE_AT = 341
SYS_OPEN_BY_HANDLE_AT = 342
SYS_CLOCK_ADJTIME = 343
SYS_SYNCFS = 344
SYS_SENDMMSG = 345
SYS_SETNS = 346
SYS_PROCESS_VM_READV = 347
SYS_PROCESS_VM_WRITEV = 348
SYS_KCMP = 349
SYS_FINIT_MODULE = 350
SYS_SCHED_SETATTR = 351
SYS_SCHED_GETATTR = 352
SYS_RENAMEAT2 = 353
SYS_SECCOMP = 354
SYS_GETRANDOM = 355
SYS_MEMFD_CREATE = 356
SYS_BPF = 357
SYS_EXECVEAT = 358
SYS_SOCKET = 359
SYS_SOCKETPAIR = 360
SYS_BIND = 361
SYS_CONNECT = 362
SYS_LISTEN = 363
SYS_ACCEPT4 = 364
SYS_GETSOCKOPT = 365
SYS_SETSOCKOPT = 366
SYS_GETSOCKNAME = 367
SYS_GETPEERNAME = 368
SYS_SENDTO = 369
SYS_SENDMSG = 370
SYS_RECVFROM = 371
SYS_RECVMSG = 372
SYS_SHUTDOWN = 373
SYS_USERFAULTFD = 374
SYS_MEMBARRIER = 375
SYS_MLOCK2 = 376
SYS_COPY_FILE_RANGE = 377
SYS_PREADV2 = 378
SYS_PWRITEV2 = 379
SYS_PKEY_MPROTECT = 380
SYS_PKEY_ALLOC = 381
SYS_PKEY_FREE = 382
SYS_STATX = 383
SYS_ARCH_PRCTL = 384
SYS_IO_PGETEVENTS = 385
SYS_RSEQ = 386
SYS_SEMGET = 393
SYS_SEMCTL = 394
SYS_SHMGET = 395
SYS_SHMCTL = 396
SYS_SHMAT = 397
SYS_SHMDT = 398
SYS_MSGGET = 399
SYS_MSGSND = 400
SYS_MSGRCV = 401
SYS_MSGCTL = 402
SYS_CLOCK_GETTIME64 = 403
SYS_CLOCK_SETTIME64 = 404
SYS_CLOCK_ADJTIME64 = 405
SYS_CLOCK_GETRES_TIME64 = 406
SYS_CLOCK_NANOSLEEP_TIME64 = 407
SYS_TIMER_GETTIME64 = 408
SYS_TIMER_SETTIME64 = 409
SYS_TIMERFD_GETTIME64 = 410
SYS_TIMERFD_SETTIME64 = 411
SYS_UTIMENSAT_TIME64 = 412
SYS_PSELECT6_TIME64 = 413
SYS_PPOLL_TIME64 = 414
SYS_IO_PGETEVENTS_TIME64 = 416
SYS_RECVMMSG_TIME64 = 417
SYS_MQ_TIMEDSEND_TIME64 = 418
SYS_MQ_TIMEDRECEIVE_TIME64 = 419
SYS_SEMTIMEDOP_TIME64 = 420
SYS_RT_SIGTIMEDWAIT_TIME64 = 421
SYS_FUTEX_TIME64 = 422
SYS_SCHED_RR_GET_INTERVAL_TIME64 = 423
SYS_PIDFD_SEND_SIGNAL = 424
SYS_IO_URING_SETUP = 425
SYS_IO_URING_ENTER = 426
SYS_IO_URING_REGISTER = 427
SYS_OPEN_TREE = 428
SYS_MOVE_MOUNT = 429
SYS_FSOPEN = 430
SYS_FSCONFIG = 431
SYS_FSMOUNT = 432
SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435
SYS_CLOSE_RANGE = 436
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
SYS_FACCESSAT2 = 439
SYS_PROCESS_MADVISE = 440
SYS_EPOLL_PWAIT2 = 441
SYS_MOUNT_SETATTR = 442
SYS_QUOTACTL_FD = 443
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
SYS_STATMOUNT = 457
SYS_LISTMOUNT = 458
SYS_LSM_GET_SELF_ATTR = 459
SYS_LSM_SET_SELF_ATTR = 460
SYS_LSM_LIST_MODULES = 461
SYS_MSEAL = 462
)

View File

@ -1,7 +1,7 @@
// mksysnum_linux.pl /usr/include/asm/unistd_64.h // mksysnum_linux.pl /usr/include/asm/unistd_64.h
// Code generated by the command above; DO NOT EDIT. // Code generated by the command above; DO NOT EDIT.
package seccomp package std
import . "syscall" import . "syscall"

View File

@ -1,7 +1,7 @@
// mksysnum_linux.pl /usr/include/asm/unistd_64.h // mksysnum_linux.pl /usr/include/asm/unistd_64.h
// Code generated by the command above; DO NOT EDIT. // Code generated by the command above; DO NOT EDIT.
package seccomp package std
import . "syscall" import . "syscall"

View File

@ -0,0 +1,21 @@
package std_test
import (
"testing"
"hakurei.app/container/std"
)
func TestSyscallResolveName(t *testing.T) {
t.Parallel()
for name, want := range std.Syscalls() {
t.Run(name, func(t *testing.T) {
t.Parallel()
if got, ok := std.SyscallResolveName(name); !ok || got != want {
t.Errorf("SyscallResolveName(%q) = %d, want %d", name, got, want)
}
})
}
}

View File

@ -13,7 +13,7 @@ var (
type UniqueError uintptr type UniqueError uintptr
func (e UniqueError) Error() string { func (e UniqueError) Error() string {
return "unique error " + strconv.Itoa(int(e)) + " injected by the test suite" return "unique error " + strconv.FormatUint(uint64(e), 10) + " injected by the test suite"
} }
func (e UniqueError) Is(target error) bool { func (e UniqueError) Is(target error) bool {

View File

@ -3,10 +3,10 @@ package stub
import "testing" import "testing"
// PanicExit is a magic panic value treated as a simulated exit. // PanicExit is a magic panic value treated as a simulated exit.
const PanicExit = 0xdeadbeef const PanicExit = 0xdead
const ( const (
panicFailNow = 0xcafe0000 + iota panicFailNow = 0xcafe0 + iota
panicFatal panicFatal
panicFatalf panicFatalf
) )

View File

@ -53,7 +53,7 @@ func TestHandleExit(t *testing.T) {
} }
}() }()
defer stub.HandleExit(ot) defer stub.HandleExit(ot)
panic(0xcafe0000) panic(0xcafe0)
}) })
t.Run("Fail", func(t *testing.T) { t.Run("Fail", func(t *testing.T) {
@ -66,7 +66,7 @@ func TestHandleExit(t *testing.T) {
} }
}() }()
defer handleExitNew(ot) defer handleExitNew(ot)
panic(0xcafe0000) panic(0xcafe0)
}) })
}) })
@ -82,14 +82,14 @@ func TestHandleExit(t *testing.T) {
t.Parallel() t.Parallel()
defer func() { defer func() {
want := 0xcafebabe want := 0xcafe
if r := recover(); r != want { if r := recover(); r != want {
t.Errorf("recover: %v, want %v", r, want) t.Errorf("recover: %v, want %v", r, want)
} }
}() }()
defer stub.HandleExit(t) defer stub.HandleExit(t)
panic(0xcafebabe) panic(0xcafe)
}) })
t.Run("new", func(t *testing.T) { t.Run("new", func(t *testing.T) {

7
container/syscall_386.go Normal file
View File

@ -0,0 +1,7 @@
package container
const (
O_PATH = 0x200000
PR_SET_NO_NEW_PRIVS = 0x26
)

View File

@ -26,11 +26,11 @@ func TestDecoderError(t *testing.T) {
target error target error
targetF error targetF error
}{ }{
{"errno", &vfs.DecoderError{Op: "parse", Line: 0xdeadbeef, Err: syscall.ENOTRECOVERABLE}, {"errno", &vfs.DecoderError{Op: "parse", Line: 0xdead, Err: syscall.ENOTRECOVERABLE},
"parse mountinfo at line 3735928559: state not recoverable", syscall.ENOTRECOVERABLE, syscall.EROFS}, "parse mountinfo at line 57005: state not recoverable", syscall.ENOTRECOVERABLE, syscall.EROFS},
{"strconv", &vfs.DecoderError{Op: "parse", Line: 0xdeadbeef, Err: &strconv.NumError{Func: "Atoi", Num: "meow", Err: strconv.ErrSyntax}}, {"strconv", &vfs.DecoderError{Op: "parse", Line: 0xdead, Err: &strconv.NumError{Func: "Atoi", Num: "meow", Err: strconv.ErrSyntax}},
`parse mountinfo at line 3735928559: numeric field "meow" invalid syntax`, strconv.ErrSyntax, os.ErrInvalid}, `parse mountinfo at line 57005: numeric field "meow" invalid syntax`, strconv.ErrSyntax, os.ErrInvalid},
{"unfold", &vfs.DecoderError{Op: "unfold", Line: -1, Err: vfs.UnfoldTargetError("/proc/nonexistent")}, {"unfold", &vfs.DecoderError{Op: "unfold", Line: -1, Err: vfs.UnfoldTargetError("/proc/nonexistent")},
"unfold mountinfo: mount point /proc/nonexistent never appeared in mountinfo", vfs.UnfoldTargetError("/proc/nonexistent"), os.ErrNotExist}, "unfold mountinfo: mount point /proc/nonexistent never appeared in mountinfo", vfs.UnfoldTargetError("/proc/nonexistent"), os.ErrNotExist},

View File

@ -244,10 +244,10 @@
shellHook = "exec ${pkgs.writeShellScript "generate-syscall-table" '' shellHook = "exec ${pkgs.writeShellScript "generate-syscall-table" ''
set -e set -e
${pkgs.perl}/bin/perl \ ${pkgs.perl}/bin/perl \
container/seccomp/mksysnum_linux.pl \ container/std/mksysnum_linux.pl \
${pkgs.linuxHeaders}/include/asm/unistd_64.h | \ ${pkgs.linuxHeaders}/include/asm/unistd_64.h | \
${pkgs.go}/bin/gofmt > \ ${pkgs.go}/bin/gofmt > \
container/seccomp/syscall_linux_${GOARCH.${system}}.go container/std/syscall_linux_${GOARCH.${system}}.go
''}"; ''}";
}; };
} }

View File

@ -80,7 +80,7 @@ func TestEnablements(t *testing.T) {
if got, err := json.Marshal(struct { if got, err := json.Marshal(struct {
Value *hst.Enablements `json:"value"` Value *hst.Enablements `json:"value"`
Magic int `json:"magic"` Magic uint64 `json:"magic"`
}{tc.e, syscall.MS_MGC_VAL}); err != nil { }{tc.e, syscall.MS_MGC_VAL}); err != nil {
t.Fatalf("Marshal: error = %v", err) t.Fatalf("Marshal: error = %v", err)
} else if string(got) != tc.sData { } else if string(got) != tc.sData {
@ -108,7 +108,7 @@ func TestEnablements(t *testing.T) {
{ {
got := *(new(struct { got := *(new(struct {
Value *hst.Enablements `json:"value"` Value *hst.Enablements `json:"value"`
Magic int `json:"magic"` Magic uint64 `json:"magic"`
})) }))
if err := json.Unmarshal([]byte(tc.sData), &got); err != nil { if err := json.Unmarshal([]byte(tc.sData), &got); err != nil {
t.Fatalf("Unmarshal: error = %v", err) t.Fatalf("Unmarshal: error = %v", err)

View File

@ -241,7 +241,7 @@ func (s stubFS) String() string { return "<invalid " + s.typeName + ">"
type sCheck struct { type sCheck struct {
FS hst.FilesystemConfigJSON `json:"fs"` FS hst.FilesystemConfigJSON `json:"fs"`
Magic int `json:"magic"` Magic uint64 `json:"magic"`
} }
type fsTestCase struct { type fsTestCase struct {

View File

@ -5,8 +5,8 @@ import (
"strings" "strings"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/std"
) )
func init() { gob.Register(new(FSBind)) } func init() { gob.Register(new(FSBind)) }
@ -97,16 +97,16 @@ func (b *FSBind) Apply(z *ApplyState) {
} }
var flags int var flags int
if b.Write { if b.Write {
flags |= comp.BindWritable flags |= std.BindWritable
} }
if b.Device { if b.Device {
flags |= comp.BindDevice | comp.BindWritable flags |= std.BindDevice | std.BindWritable
} }
if b.Ensure { if b.Ensure {
flags |= comp.BindEnsure flags |= std.BindEnsure
} }
if b.Optional { if b.Optional {
flags |= comp.BindOptional flags |= std.BindOptional
} }
switch { switch {

View File

@ -4,7 +4,7 @@ import (
"testing" "testing"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/comp" "hakurei.app/container/std"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -24,7 +24,7 @@ func TestFSBind(t *testing.T) {
}, true, container.Ops{&container.BindMountOp{ }, true, container.Ops{&container.BindMountOp{
Source: m("/mnt/dev"), Source: m("/mnt/dev"),
Target: m("/dev"), Target: m("/dev"),
Flags: comp.BindWritable | comp.BindDevice | comp.BindOptional, Flags: std.BindWritable | std.BindDevice | std.BindOptional,
}}, m("/dev"), ms("/mnt/dev"), }}, m("/dev"), ms("/mnt/dev"),
"d+/mnt/dev:/dev"}, "d+/mnt/dev:/dev"},
@ -36,7 +36,7 @@ func TestFSBind(t *testing.T) {
}, true, container.Ops{&container.BindMountOp{ }, true, container.Ops{&container.BindMountOp{
Source: m("/mnt/dev"), Source: m("/mnt/dev"),
Target: m("/dev"), Target: m("/dev"),
Flags: comp.BindWritable | comp.BindDevice | comp.BindEnsure, Flags: std.BindWritable | std.BindDevice | std.BindEnsure,
}}, m("/dev"), ms("/mnt/dev"), }}, m("/dev"), ms("/mnt/dev"),
"d-/mnt/dev:/dev"}, "d-/mnt/dev:/dev"},
@ -48,7 +48,7 @@ func TestFSBind(t *testing.T) {
}, true, container.Ops{&container.BindMountOp{ }, true, container.Ops{&container.BindMountOp{
Source: m("/mnt/dev"), Source: m("/mnt/dev"),
Target: m("/dev"), Target: m("/dev"),
Flags: comp.BindWritable | comp.BindDevice, Flags: std.BindWritable | std.BindDevice,
}}, m("/dev"), ms("/mnt/dev"), }}, m("/dev"), ms("/mnt/dev"),
"d*/mnt/dev:/dev"}, "d*/mnt/dev:/dev"},
@ -59,7 +59,7 @@ func TestFSBind(t *testing.T) {
}, true, container.Ops{&container.BindMountOp{ }, true, container.Ops{&container.BindMountOp{
Source: m("/mnt/tmp"), Source: m("/mnt/tmp"),
Target: m("/tmp"), Target: m("/tmp"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}}, m("/tmp"), ms("/mnt/tmp"), }}, m("/tmp"), ms("/mnt/tmp"),
"w*/mnt/tmp:/tmp"}, "w*/mnt/tmp:/tmp"},
@ -98,7 +98,7 @@ func TestFSBind(t *testing.T) {
Special: true, Special: true,
}, true, container.Ops{&container.AutoRootOp{ }, true, container.Ops{&container.AutoRootOp{
Host: m("/"), Host: m("/"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}}, m("/"), ms("/"), "autoroot:w"}, }}, m("/"), ms("/"), "autoroot:w"},
{"autoroot silly", &hst.FSBind{ {"autoroot silly", &hst.FSBind{
@ -108,7 +108,7 @@ func TestFSBind(t *testing.T) {
Special: true, Special: true,
}, true, container.Ops{&container.AutoRootOp{ }, true, container.Ops{&container.AutoRootOp{
Host: m("/etc"), Host: m("/etc"),
Flags: comp.BindWritable, Flags: std.BindWritable,
}}, m("/"), ms("/etc"), "autoroot:w:/etc"}, }}, m("/"), ms("/etc"), "autoroot:w:/etc"},
{"autoetc", &hst.FSBind{ {"autoetc", &hst.FSBind{

View File

@ -20,6 +20,9 @@ func TestUIDString(t *testing.T) {
{hst.IsolatedStart + hst.IdentityStart, "u0_i0"}, // isolatedStart {hst.IsolatedStart + hst.IdentityStart, "u0_i0"}, // isolatedStart
{(hst.RangeSize-1)*hst.UserOffset + hst.IsolatedEnd, "u9999_i9999"}, // isolatedEnd {(hst.RangeSize-1)*hst.UserOffset + hst.IsolatedEnd, "u9999_i9999"}, // isolatedEnd
{hst.ToUser[uint32](10, 127), "u10_a127"},
{hst.ToUser[uint32](11, 127), "u11_a127"},
{0, "0"}, // out of bounds {0, "0"}, // out of bounds
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@ -34,9 +34,9 @@ func TestPaths(t *testing.T) {
TempDir: fhs.AbsTmp, TempDir: fhs.AbsTmp,
}, hst.Paths{ }, hst.Paths{
TempDir: fhs.AbsTmp, TempDir: fhs.AbsTmp,
SharePath: fhs.AbsTmp.Append("hakurei.3735928559"), SharePath: fhs.AbsTmp.Append("hakurei.57005"),
RuntimePath: fhs.AbsTmp.Append("hakurei.3735928559/compat"), RuntimePath: fhs.AbsTmp.Append("hakurei.57005/compat"),
RunDirPath: fhs.AbsTmp.Append("hakurei.3735928559/compat/hakurei"), RunDirPath: fhs.AbsTmp.Append("hakurei.57005/compat/hakurei"),
}, ""}, }, ""},
{"full", &env.Paths{ {"full", &env.Paths{
@ -44,7 +44,7 @@ func TestPaths(t *testing.T) {
RuntimePath: fhs.AbsRunUser.Append("1000"), RuntimePath: fhs.AbsRunUser.Append("1000"),
}, hst.Paths{ }, hst.Paths{
TempDir: fhs.AbsTmp, TempDir: fhs.AbsTmp,
SharePath: fhs.AbsTmp.Append("hakurei.3735928559"), SharePath: fhs.AbsTmp.Append("hakurei.57005"),
RuntimePath: fhs.AbsRunUser.Append("1000"), RuntimePath: fhs.AbsRunUser.Append("1000"),
RunDirPath: fhs.AbsRunUser.Append("1000/hakurei"), RunDirPath: fhs.AbsRunUser.Append("1000/hakurei"),
}, ""}, }, ""},
@ -61,7 +61,7 @@ func TestPaths(t *testing.T) {
} }
var sc hst.Paths var sc hst.Paths
tc.env.Copy(&sc, 0xdeadbeef) tc.env.Copy(&sc, 0xdead)
if !reflect.DeepEqual(&sc, &tc.want) { if !reflect.DeepEqual(&sc, &tc.want) {
t.Errorf("Copy: %#v, want %#v", sc, tc.want) t.Errorf("Copy: %#v, want %#v", sc, tc.want)
} }

View File

@ -13,6 +13,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/internal" "hakurei.app/internal"
"hakurei.app/message" "hakurei.app/message"
"hakurei.app/system/dbus" "hakurei.app/system/dbus"
@ -86,7 +87,7 @@ type syscallDispatcher interface {
containerWait(z *container.Container) error containerWait(z *container.Container) error
// seccompLoad provides [seccomp.Load]. // seccompLoad provides [seccomp.Load].
seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error
// mustHsuPath provides [internal.MustHsuPath]. // mustHsuPath provides [internal.MustHsuPath].
mustHsuPath() *check.Absolute mustHsuPath() *check.Absolute
@ -151,7 +152,7 @@ func (direct) containerStart(z *container.Container) error { return z.Start() }
func (direct) containerServe(z *container.Container) error { return z.Serve() } func (direct) containerServe(z *container.Container) error { return z.Serve() }
func (direct) containerWait(z *container.Container) error { return z.Wait() } func (direct) containerWait(z *container.Container) error { return z.Wait() }
func (direct) seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error { func (direct) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error {
return seccomp.Load(rules, flags) return seccomp.Load(rules, flags)
} }

View File

@ -21,6 +21,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/message" "hakurei.app/message"
@ -35,7 +36,7 @@ func call(name string, args stub.ExpectArgs, ret any, err error) stub.Call {
const ( const (
// checkExpectUid is the uid value used by checkOpBehaviour to initialise [system.I]. // checkExpectUid is the uid value used by checkOpBehaviour to initialise [system.I].
checkExpectUid = 0xcafebabe checkExpectUid = 0xcafe
// wantAutoEtcPrefix is the autoetc prefix corresponding to checkExpectInstanceId. // wantAutoEtcPrefix is the autoetc prefix corresponding to checkExpectInstanceId.
wantAutoEtcPrefix = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" wantAutoEtcPrefix = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
// wantInstancePrefix is the SharePath corresponding to checkExpectInstanceId. // wantInstancePrefix is the SharePath corresponding to checkExpectInstanceId.
@ -435,7 +436,7 @@ func (k *kstub) containerWait(z *container.Container) error {
return k.expectCheckContainer(k.Expects("containerWait"), z) return k.expectCheckContainer(k.Expects("containerWait"), z)
} }
func (k *kstub) seccompLoad(rules []seccomp.NativeRule, flags seccomp.ExportFlag) error { func (k *kstub) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error {
k.Helper() k.Helper()
return k.Expects("seccompLoad").Error( return k.Expects("seccompLoad").Error(
stub.CheckArgReflect(k.Stub, "rules", rules, 0), stub.CheckArgReflect(k.Stub, "rules", rules, 0),
@ -722,6 +723,6 @@ func (panicDispatcher) fatalf(string, ...any) { pa
func (panicDispatcher) notifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc) { func (panicDispatcher) notifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc) {
panic("unreachable") panic("unreachable")
} }
func (panicDispatcher) seccompLoad([]seccomp.NativeRule, seccomp.ExportFlag) error { func (panicDispatcher) seccompLoad([]std.NativeRule, seccomp.ExportFlag) error {
panic("unreachable") panic("unreachable")
} }

View File

@ -86,12 +86,12 @@ func (h *Hsu) MustID(msg message.Msg) int {
msg.Verbose("*"+fallback, err) msg.Verbose("*"+fallback, err)
} }
os.Exit(1) os.Exit(1)
return -0xdeadbeef // not reached return -0xbad // not reached
} else if m, ok := message.GetMessage(err); ok { } else if m, ok := message.GetMessage(err); ok {
log.Fatal(m) log.Fatal(m)
return -0xdeadbeef // not reached return -0xbad // not reached
} else { } else {
log.Fatalln(fallback, err) log.Fatalln(fallback, err)
return -0xdeadbeef // not reached return -0xbad // not reached
} }
} }

View File

@ -17,9 +17,9 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/message" "hakurei.app/message"
"hakurei.app/system" "hakurei.app/system"
@ -136,19 +136,19 @@ func TestOutcomeMain(t *testing.T) {
Ops: new(container.Ops). Ops: new(container.Ops).
// resolveRoot // resolveRoot
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable). Root(m("/var/lib/hakurei/base/org.debian"), std.BindWritable).
// spParamsOp // spParamsOp
Proc(fhs.AbsProc). Proc(fhs.AbsProc).
Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755). Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice). Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777). Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777).
// spRuntimeOp // spRuntimeOp
Tmpfs(fhs.AbsRunUser, 1<<12, 0755). Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/1971"), comp.BindWritable). Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/1971"), std.BindWritable).
// spTmpdirOp // spTmpdirOp
Bind(m("/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, comp.BindWritable). Bind(m("/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, std.BindWritable).
// spAccountOp // spAccountOp
Place(m("/etc/passwd"), []byte("chronos:x:1971:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")). Place(m("/etc/passwd"), []byte("chronos:x:1971:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
@ -176,9 +176,9 @@ func TestOutcomeMain(t *testing.T) {
Link(m("/run/opengl-driver"), "/run/opengl-driver", true). Link(m("/run/opengl-driver"), "/run/opengl-driver", true).
Bind(fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"), Bind(fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
m("/data/data/org.chromium.Chromium"), m("/data/data/org.chromium.Chromium"),
comp.BindWritable|comp.BindEnsure). std.BindWritable|std.BindEnsure).
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"),
comp.BindOptional|comp.BindWritable|comp.BindDevice). std.BindOptional|std.BindWritable|std.BindDevice).
Remount(fhs.AbsRoot, syscall.MS_RDONLY), Remount(fhs.AbsRoot, syscall.MS_RDONLY),
}}, }},
@ -239,24 +239,24 @@ func TestOutcomeMain(t *testing.T) {
"XDG_SESSION_TYPE=tty", "XDG_SESSION_TYPE=tty",
}, },
Ops: new(container.Ops). Ops: new(container.Ops).
Root(m("/"), comp.BindWritable). Root(m("/"), std.BindWritable).
Proc(m("/proc/")). Proc(m("/proc/")).
Tmpfs(hst.AbsPrivateTmp, 4096, 0755). Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
DevWritable(m("/dev/"), true). DevWritable(m("/dev/"), true).
Tmpfs(m("/dev/shm"), 0, 01777). Tmpfs(m("/dev/shm"), 0, 01777).
Tmpfs(m("/run/user/"), 4096, 0755). Tmpfs(m("/run/user/"), 4096, 0755).
Bind(m("/tmp/hakurei.0/runtime/0"), m("/run/user/65534"), comp.BindWritable). Bind(m("/tmp/hakurei.0/runtime/0"), m("/run/user/65534"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/0"), m("/tmp/"), comp.BindWritable). Bind(m("/tmp/hakurei.0/tmpdir/0"), m("/tmp/"), std.BindWritable).
Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")). Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:65534:\n")). Place(m("/etc/group"), []byte("hakurei:x:65534:\n")).
Bind(m("/dev/kvm"), m("/dev/kvm"), comp.BindWritable|comp.BindDevice|comp.BindOptional). Bind(m("/dev/kvm"), m("/dev/kvm"), std.BindWritable|std.BindDevice|std.BindOptional).
Etc(m("/etc/"), "4a450b6596d7bc15bd01780eb9a607ac"). Etc(m("/etc/"), "4a450b6596d7bc15bd01780eb9a607ac").
Tmpfs(m("/run/user/1971"), 8192, 0755). Tmpfs(m("/run/user/1971"), 8192, 0755).
Tmpfs(m("/run/nscd"), 8192, 0755). Tmpfs(m("/run/nscd"), 8192, 0755).
Tmpfs(m("/run/dbus"), 8192, 0755). Tmpfs(m("/run/dbus"), 8192, 0755).
Remount(m("/dev/"), syscall.MS_RDONLY). Remount(m("/dev/"), syscall.MS_RDONLY).
Remount(m("/"), syscall.MS_RDONLY), Remount(m("/"), syscall.MS_RDONLY),
SeccompPresets: comp.PresetExt | comp.PresetDenyDevel, SeccompPresets: std.PresetExt | std.PresetDenyDevel,
HostNet: true, HostNet: true,
HostAbstract: true, HostAbstract: true,
RetainSession: true, RetainSession: true,
@ -408,14 +408,14 @@ func TestOutcomeMain(t *testing.T) {
"XDG_SESSION_TYPE=wayland", "XDG_SESSION_TYPE=wayland",
}, },
Ops: new(container.Ops). Ops: new(container.Ops).
Root(m("/"), comp.BindWritable). Root(m("/"), std.BindWritable).
Proc(m("/proc/")). Proc(m("/proc/")).
Tmpfs(hst.AbsPrivateTmp, 4096, 0755). Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
DevWritable(m("/dev/"), true). DevWritable(m("/dev/"), true).
Tmpfs(m("/dev/shm"), 0, 01777). Tmpfs(m("/dev/shm"), 0, 01777).
Tmpfs(m("/run/user/"), 4096, 0755). Tmpfs(m("/run/user/"), 4096, 0755).
Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/65534"), comp.BindWritable). Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/65534"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/9"), m("/tmp/"), comp.BindWritable). Bind(m("/tmp/hakurei.0/tmpdir/9"), m("/tmp/"), std.BindWritable).
Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")). Place(m("/etc/passwd"), []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:65534:\n")). Place(m("/etc/group"), []byte("hakurei:x:65534:\n")).
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/65534/wayland-0"), 0). Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/65534/wayland-0"), 0).
@ -423,15 +423,15 @@ func TestOutcomeMain(t *testing.T) {
Place(m(hst.PrivateTmp+"/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)). Place(m(hst.PrivateTmp+"/pulse-cookie"), bytes.Repeat([]byte{0}, pulseCookieSizeMax)).
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), m("/run/user/65534/bus"), 0). Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), m("/run/user/65534/bus"), 0).
Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0). Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
Bind(m("/dev/dri"), m("/dev/dri"), comp.BindWritable|comp.BindDevice|comp.BindOptional). Bind(m("/dev/dri"), m("/dev/dri"), std.BindWritable|std.BindDevice|std.BindOptional).
Bind(m("/dev/kvm"), m("/dev/kvm"), comp.BindWritable|comp.BindDevice|comp.BindOptional). Bind(m("/dev/kvm"), m("/dev/kvm"), std.BindWritable|std.BindDevice|std.BindOptional).
Etc(m("/etc/"), "ebf083d1b175911782d413369b64ce7c"). Etc(m("/etc/"), "ebf083d1b175911782d413369b64ce7c").
Tmpfs(m("/run/user/1971"), 8192, 0755). Tmpfs(m("/run/user/1971"), 8192, 0755).
Tmpfs(m("/run/nscd"), 8192, 0755). Tmpfs(m("/run/nscd"), 8192, 0755).
Tmpfs(m("/run/dbus"), 8192, 0755). Tmpfs(m("/run/dbus"), 8192, 0755).
Remount(m("/dev/"), syscall.MS_RDONLY). Remount(m("/dev/"), syscall.MS_RDONLY).
Remount(m("/"), syscall.MS_RDONLY), Remount(m("/"), syscall.MS_RDONLY),
SeccompPresets: comp.PresetExt | comp.PresetDenyDevel, SeccompPresets: std.PresetExt | std.PresetDenyDevel,
HostNet: true, HostNet: true,
HostAbstract: true, HostAbstract: true,
RetainSession: true, RetainSession: true,
@ -560,8 +560,8 @@ func TestOutcomeMain(t *testing.T) {
DevWritable(m("/dev/"), true). DevWritable(m("/dev/"), true).
Tmpfs(m("/dev/shm"), 0, 01777). Tmpfs(m("/dev/shm"), 0, 01777).
Tmpfs(m("/run/user/"), 4096, 0755). Tmpfs(m("/run/user/"), 4096, 0755).
Bind(m("/tmp/hakurei.0/runtime/1"), m("/run/user/1971"), comp.BindWritable). Bind(m("/tmp/hakurei.0/runtime/1"), m("/run/user/1971"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/1"), m("/tmp/"), comp.BindWritable). Bind(m("/tmp/hakurei.0/tmpdir/1"), m("/tmp/"), std.BindWritable).
Place(m("/etc/passwd"), []byte("u0_a1:x:1971:100:Hakurei:/var/lib/persist/module/hakurei/0/1:/run/current-system/sw/bin/zsh\n")). Place(m("/etc/passwd"), []byte("u0_a1:x:1971:100:Hakurei:/var/lib/persist/module/hakurei/0/1:/run/current-system/sw/bin/zsh\n")).
Place(m("/etc/group"), []byte("hakurei:x:100:\n")). Place(m("/etc/group"), []byte("hakurei:x:100:\n")).
Bind(m("/run/user/1971/wayland-0"), m("/run/user/1971/wayland-0"), 0). Bind(m("/run/user/1971/wayland-0"), m("/run/user/1971/wayland-0"), 0).
@ -573,18 +573,18 @@ func TestOutcomeMain(t *testing.T) {
Bind(m("/usr/bin/"), m("/usr/bin/"), 0). Bind(m("/usr/bin/"), m("/usr/bin/"), 0).
Bind(m("/nix/store"), m("/nix/store"), 0). Bind(m("/nix/store"), m("/nix/store"), 0).
Bind(m("/run/current-system"), m("/run/current-system"), 0). Bind(m("/run/current-system"), m("/run/current-system"), 0).
Bind(m("/sys/block"), m("/sys/block"), comp.BindOptional). Bind(m("/sys/block"), m("/sys/block"), std.BindOptional).
Bind(m("/sys/bus"), m("/sys/bus"), comp.BindOptional). Bind(m("/sys/bus"), m("/sys/bus"), std.BindOptional).
Bind(m("/sys/class"), m("/sys/class"), comp.BindOptional). Bind(m("/sys/class"), m("/sys/class"), std.BindOptional).
Bind(m("/sys/dev"), m("/sys/dev"), comp.BindOptional). Bind(m("/sys/dev"), m("/sys/dev"), std.BindOptional).
Bind(m("/sys/devices"), m("/sys/devices"), comp.BindOptional). Bind(m("/sys/devices"), m("/sys/devices"), std.BindOptional).
Bind(m("/run/opengl-driver"), m("/run/opengl-driver"), 0). Bind(m("/run/opengl-driver"), m("/run/opengl-driver"), 0).
Bind(m("/dev/dri"), m("/dev/dri"), comp.BindDevice|comp.BindWritable|comp.BindOptional). Bind(m("/dev/dri"), m("/dev/dri"), std.BindDevice|std.BindWritable|std.BindOptional).
Etc(m("/etc/"), "8e2c76b066dabe574cf073bdb46eb5c1"). Etc(m("/etc/"), "8e2c76b066dabe574cf073bdb46eb5c1").
Bind(m("/var/lib/persist/module/hakurei/0/1"), m("/var/lib/persist/module/hakurei/0/1"), comp.BindWritable|comp.BindEnsure). Bind(m("/var/lib/persist/module/hakurei/0/1"), m("/var/lib/persist/module/hakurei/0/1"), std.BindWritable|std.BindEnsure).
Remount(m("/dev/"), syscall.MS_RDONLY). Remount(m("/dev/"), syscall.MS_RDONLY).
Remount(m("/"), syscall.MS_RDONLY), Remount(m("/"), syscall.MS_RDONLY),
SeccompPresets: comp.PresetExt | comp.PresetDenyTTY | comp.PresetDenyDevel, SeccompPresets: std.PresetExt | std.PresetDenyTTY | std.PresetDenyDevel,
HostNet: true, HostNet: true,
ForwardCancel: true, ForwardCancel: true,
}}, }},
@ -701,7 +701,7 @@ type stubNixOS struct {
} }
func (k *stubNixOS) getppid() int { return 0xbad } func (k *stubNixOS) getppid() int { return 0xbad }
func (k *stubNixOS) getpid() int { return 0xdeadbeef } func (k *stubNixOS) getpid() int { return 0xdead }
func (k *stubNixOS) getuid() int { return 1971 } func (k *stubNixOS) getuid() int { return 1971 }
func (k *stubNixOS) getgid() int { return 100 } func (k *stubNixOS) getgid() int { return 100 }

View File

@ -14,8 +14,8 @@ import (
"time" "time"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/comp"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/message" "hakurei.app/message"
) )
@ -233,7 +233,7 @@ func shimEntrypoint(k syscallDispatcher) {
} }
if err := k.seccompLoad( if err := k.seccompLoad(
seccomp.Preset(comp.PresetStrict, seccomp.AllowMultiarch), seccomp.Preset(std.PresetStrict, seccomp.AllowMultiarch),
seccomp.AllowMultiarch, seccomp.AllowMultiarch,
); err != nil { ); err != nil {
k.fatalf("cannot load syscall filter: %v", err) k.fatalf("cannot load syscall filter: %v", err)

View File

@ -10,9 +10,9 @@ import (
"testing" "testing"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/env" "hakurei.app/internal/env"
@ -20,7 +20,7 @@ import (
func TestShimEntrypoint(t *testing.T) { func TestShimEntrypoint(t *testing.T) {
t.Parallel() t.Parallel()
shimPreset := seccomp.Preset(comp.PresetStrict, seccomp.AllowMultiarch) shimPreset := seccomp.Preset(std.PresetStrict, seccomp.AllowMultiarch)
templateParams := &container.Params{ templateParams := &container.Params{
Dir: m("/data/data/org.chromium.Chromium"), Dir: m("/data/data/org.chromium.Chromium"),
Env: []string{ Env: []string{
@ -61,19 +61,19 @@ func TestShimEntrypoint(t *testing.T) {
Ops: new(container.Ops). Ops: new(container.Ops).
// resolveRoot // resolveRoot
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable). Root(m("/var/lib/hakurei/base/org.debian"), std.BindWritable).
// spParamsOp // spParamsOp
Proc(fhs.AbsProc). Proc(fhs.AbsProc).
Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755). Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice). Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777). Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777).
// spRuntimeOp // spRuntimeOp
Tmpfs(fhs.AbsRunUser, 1<<12, 0755). Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
Bind(m("/tmp/hakurei.10/runtime/9999"), m("/run/user/1000"), comp.BindWritable). Bind(m("/tmp/hakurei.10/runtime/9999"), m("/run/user/1000"), std.BindWritable).
// spTmpdirOp // spTmpdirOp
Bind(m("/tmp/hakurei.10/tmpdir/9999"), fhs.AbsTmp, comp.BindWritable). Bind(m("/tmp/hakurei.10/tmpdir/9999"), fhs.AbsTmp, std.BindWritable).
// spAccountOp // spAccountOp
Place(m("/etc/passwd"), []byte("chronos:x:1000:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")). Place(m("/etc/passwd"), []byte("chronos:x:1000:100:Hakurei:/data/data/org.chromium.Chromium:/run/current-system/sw/bin/zsh\n")).
@ -101,9 +101,9 @@ func TestShimEntrypoint(t *testing.T) {
Link(m("/run/opengl-driver"), "/run/opengl-driver", true). Link(m("/run/opengl-driver"), "/run/opengl-driver", true).
Bind(fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"), Bind(fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
m("/data/data/org.chromium.Chromium"), m("/data/data/org.chromium.Chromium"),
comp.BindWritable|comp.BindEnsure). std.BindWritable|std.BindEnsure).
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"),
comp.BindOptional|comp.BindWritable|comp.BindDevice). std.BindOptional|std.BindWritable|std.BindDevice).
Remount(fhs.AbsRoot, syscall.MS_RDONLY), Remount(fhs.AbsRoot, syscall.MS_RDONLY),
} }

View File

@ -12,9 +12,9 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/validate" "hakurei.app/internal/validate"
"hakurei.app/message" "hakurei.app/message"
@ -76,16 +76,16 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
} }
if state.Container.Flags&hst.FSeccompCompat == 0 { if state.Container.Flags&hst.FSeccompCompat == 0 {
state.params.SeccompPresets |= comp.PresetExt state.params.SeccompPresets |= std.PresetExt
} }
if state.Container.Flags&hst.FDevel == 0 { if state.Container.Flags&hst.FDevel == 0 {
state.params.SeccompPresets |= comp.PresetDenyDevel state.params.SeccompPresets |= std.PresetDenyDevel
} }
if state.Container.Flags&hst.FUserns == 0 { if state.Container.Flags&hst.FUserns == 0 {
state.params.SeccompPresets |= comp.PresetDenyNS state.params.SeccompPresets |= std.PresetDenyNS
} }
if state.Container.Flags&hst.FTty == 0 { if state.Container.Flags&hst.FTty == 0 {
state.params.SeccompPresets |= comp.PresetDenyTTY state.params.SeccompPresets |= std.PresetDenyTTY
} }
if state.Container.Flags&hst.FMapRealUID != 0 { if state.Container.Flags&hst.FMapRealUID != 0 {
@ -113,7 +113,7 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
if state.Container.Flags&hst.FDevice == 0 { if state.Container.Flags&hst.FDevice == 0 {
state.params.DevWritable(fhs.AbsDev, true) state.params.DevWritable(fhs.AbsDev, true)
} else { } else {
state.params.Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice) state.params.Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice)
} }
// /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it // /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it
state.params.Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777) state.params.Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777)

View File

@ -9,9 +9,9 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
@ -65,11 +65,11 @@ func TestSpParamsOp(t *testing.T) {
HostAbstract: true, HostAbstract: true,
Path: config.Container.Path, Path: config.Container.Path,
Args: []string{config.Container.Path.String()}, Args: []string{config.Container.Path.String()},
SeccompPresets: comp.PresetExt | comp.PresetDenyDevel | comp.PresetDenyNS | comp.PresetDenyTTY, SeccompPresets: std.PresetExt | std.PresetDenyDevel | std.PresetDenyNS | std.PresetDenyTTY,
Uid: 1000, Uid: 1000,
Gid: 100, Gid: 100,
Ops: new(container.Ops). Ops: new(container.Ops).
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable). Root(m("/var/lib/hakurei/base/org.debian"), std.BindWritable).
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755). Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
DevWritable(fhs.AbsDev, true). DevWritable(fhs.AbsDev, true).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777), Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
@ -107,9 +107,9 @@ func TestSpParamsOp(t *testing.T) {
Uid: 1000, Uid: 1000,
Gid: 100, Gid: 100,
Ops: new(container.Ops). Ops: new(container.Ops).
Root(m("/var/lib/hakurei/base/org.debian"), comp.BindWritable). Root(m("/var/lib/hakurei/base/org.debian"), std.BindWritable).
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755). Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
Bind(fhs.AbsDev, fhs.AbsDev, comp.BindWritable|comp.BindDevice). Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777), Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
}, paramsWantEnv(config, map[string]string{ }, paramsWantEnv(config, map[string]string{
"TERM": "xterm", "TERM": "xterm",
@ -425,8 +425,8 @@ func TestSpFilesystemOp(t *testing.T) {
Bind( Bind(
fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"), fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
check.MustAbs("/data/data/org.chromium.Chromium"), check.MustAbs("/data/data/org.chromium.Chromium"),
comp.BindWritable|comp.BindEnsure). std.BindWritable|std.BindEnsure).
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), comp.BindDevice|comp.BindWritable|comp.BindOptional). Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), std.BindDevice|std.BindWritable|std.BindOptional).
Remount(fhs.AbsRoot, syscall.MS_RDONLY), Remount(fhs.AbsRoot, syscall.MS_RDONLY),
}, nil, nil}, }, nil, nil},
}) })

View File

@ -4,8 +4,8 @@ import (
"encoding/gob" "encoding/gob"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/std"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
"hakurei.app/system/acl" "hakurei.app/system/acl"
@ -111,7 +111,7 @@ func (s *spRuntimeOp) toContainer(state *outcomeStateParams) error {
state.params.Tmpfs(fhs.AbsRunUser, 1<<12, 0755) state.params.Tmpfs(fhs.AbsRunUser, 1<<12, 0755)
if state.Container.Flags&hst.FShareRuntime != 0 { if state.Container.Flags&hst.FShareRuntime != 0 {
_, runtimeDirInst := s.commonPaths(state.outcomeState) _, runtimeDirInst := s.commonPaths(state.outcomeState)
state.params.Bind(runtimeDirInst, state.runtimeDir, comp.BindWritable) state.params.Bind(runtimeDirInst, state.runtimeDir, std.BindWritable)
} else { } else {
state.params.Mkdir(state.runtimeDir, 0700) state.params.Mkdir(state.runtimeDir, 0700)
} }

View File

@ -4,8 +4,8 @@ import (
"testing" "testing"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
@ -41,7 +41,7 @@ func TestSpRuntimeOp(t *testing.T) {
}, &container.Params{ }, &container.Params{
Ops: new(container.Ops). Ops: new(container.Ops).
Tmpfs(fhs.AbsRunUser, 1<<12, 0755). Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable), Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable),
}, paramsWantEnv(config, map[string]string{ }, paramsWantEnv(config, map[string]string{
"XDG_RUNTIME_DIR": "/run/user/1000", "XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_SESSION_CLASS": "user", "XDG_SESSION_CLASS": "user",
@ -68,7 +68,7 @@ func TestSpRuntimeOp(t *testing.T) {
}, &container.Params{ }, &container.Params{
Ops: new(container.Ops). Ops: new(container.Ops).
Tmpfs(fhs.AbsRunUser, 1<<12, 0755). Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable), Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable),
}, paramsWantEnv(config, map[string]string{ }, paramsWantEnv(config, map[string]string{
"XDG_RUNTIME_DIR": "/run/user/1000", "XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_SESSION_CLASS": "user", "XDG_SESSION_CLASS": "user",
@ -95,7 +95,7 @@ func TestSpRuntimeOp(t *testing.T) {
}, &container.Params{ }, &container.Params{
Ops: new(container.Ops). Ops: new(container.Ops).
Tmpfs(fhs.AbsRunUser, 1<<12, 0755). Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable), Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable),
}, paramsWantEnv(config, map[string]string{ }, paramsWantEnv(config, map[string]string{
"XDG_RUNTIME_DIR": "/run/user/1000", "XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_SESSION_CLASS": "user", "XDG_SESSION_CLASS": "user",
@ -118,7 +118,7 @@ func TestSpRuntimeOp(t *testing.T) {
}, &container.Params{ }, &container.Params{
Ops: new(container.Ops). Ops: new(container.Ops).
Tmpfs(fhs.AbsRunUser, 1<<12, 0755). Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), comp.BindWritable), Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable),
}, paramsWantEnv(config, map[string]string{ }, paramsWantEnv(config, map[string]string{
"XDG_RUNTIME_DIR": "/run/user/1000", "XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_SESSION_CLASS": "user", "XDG_SESSION_CLASS": "user",

View File

@ -4,8 +4,8 @@ import (
"encoding/gob" "encoding/gob"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/std"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
"hakurei.app/system/acl" "hakurei.app/system/acl"
@ -30,7 +30,7 @@ func (s spTmpdirOp) toSystem(state *outcomeStateSys) error {
func (s spTmpdirOp) toContainer(state *outcomeStateParams) error { func (s spTmpdirOp) toContainer(state *outcomeStateParams) error {
if state.Container.Flags&hst.FShareTmpdir != 0 { if state.Container.Flags&hst.FShareTmpdir != 0 {
_, tmpdirInst := s.commonPaths(state.outcomeState) _, tmpdirInst := s.commonPaths(state.outcomeState)
state.params.Bind(tmpdirInst, fhs.AbsTmp, comp.BindWritable) state.params.Bind(tmpdirInst, fhs.AbsTmp, std.BindWritable)
} else { } else {
state.params.Tmpfs(fhs.AbsTmp, 0, 01777) state.params.Tmpfs(fhs.AbsTmp, 0, 01777)
} }

View File

@ -4,8 +4,8 @@ import (
"testing" "testing"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/std"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
@ -28,7 +28,7 @@ func TestSpTmpdirOp(t *testing.T) {
// this op configures the container state and does not make calls during toContainer // this op configures the container state and does not make calls during toContainer
}, &container.Params{ }, &container.Params{
Ops: new(container.Ops). Ops: new(container.Ops).
Bind(m("/proc/nonexistent/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, comp.BindWritable), Bind(m("/proc/nonexistent/tmp/hakurei.0/tmpdir/9"), fhs.AbsTmp, std.BindWritable),
}, nil, nil}, }, nil, nil},
}) })
} }

View File

@ -127,8 +127,8 @@ func TestEntryData(t *testing.T) {
func newTemplateState() *hst.State { func newTemplateState() *hst.State {
return &hst.State{ return &hst.State{
ID: hst.ID(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))), ID: hst.ID(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))),
PID: 0xcafebabe, PID: 0xcafe,
ShimPID: 0xdeadbeef, ShimPID: 0xdead,
Config: hst.Template(), Config: hst.Template(),
Time: time.Unix(0, 0), Time: time.Unix(0, 0),
} }

View File

@ -10,9 +10,9 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/fhs" "hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/message" "hakurei.app/message"
) )
@ -40,7 +40,7 @@ func Exec(ctx context.Context, msg message.Msg, p string) ([]*Entry, error) {
z := container.NewCommand(c, msg, toolPath, lddName, p) z := container.NewCommand(c, msg, toolPath, lddName, p)
z.Hostname = "hakurei-" + lddName z.Hostname = "hakurei-" + lddName
z.SeccompFlags |= seccomp.AllowMultiarch z.SeccompFlags |= seccomp.AllowMultiarch
z.SeccompPresets |= comp.PresetStrict z.SeccompPresets |= std.PresetStrict
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer) stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
z.Stdout = stdout z.Stdout = stdout
z.Stderr = stderr z.Stderr = stderr

View File

@ -63,7 +63,7 @@ func TestDefaultMsg(t *testing.T) {
}) })
t.Run("takeover", func(t *testing.T) { t.Run("takeover", func(t *testing.T) {
l := log.New(io.Discard, "\x00", 0xdeadbeef) l := log.New(io.Discard, "\x00", 0xbeef)
got := message.New(l) got := message.New(l)
if logger := got.GetLogger(); logger != l { if logger := got.GetLogger(); logger != l {

View File

@ -31,7 +31,7 @@
buildGoModule rec { buildGoModule rec {
pname = "hakurei"; pname = "hakurei";
version = "0.2.2"; version = "0.3.0";
srcFiltered = builtins.path { srcFiltered = builtins.path {
name = "${pname}-src"; name = "${pname}-src";

View File

@ -46,7 +46,7 @@ func TestNewAclPathError(t *testing.T) {
{"acl", container.Nonexistent, -13, syscall.ENOTRECOVERABLE, {"acl", container.Nonexistent, -13, syscall.ENOTRECOVERABLE,
&os.PathError{Op: "setfacl", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}}, &os.PathError{Op: "setfacl", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
{"invalid", container.Nonexistent, -0xdeadbeef, nil, {"invalid", container.Nonexistent, -0xdead, nil,
&os.PathError{Op: "setfacl", Path: container.Nonexistent}}, &os.PathError{Op: "setfacl", Path: container.Nonexistent}},
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@ -14,52 +14,52 @@ func TestACLUpdateOp(t *testing.T) {
t.Parallel() t.Parallel()
checkOpBehaviour(t, []opBehaviourTestCase{ checkOpBehaviour(t, []opBehaviourTestCase{
{"apply aclUpdate", 0xdeadbeef, 0xff, {"apply aclUpdate", 0xbeef, 0xff,
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{ &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, stub.UniqueError(1)), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, stub.UniqueError(1)),
}, &OpError{Op: "acl", Err: stub.UniqueError(1)}, nil, nil}, }, &OpError{Op: "acl", Err: stub.UniqueError(1)}, nil, nil},
{"revert aclUpdate", 0xdeadbeef, 0xff, {"revert aclUpdate", 0xbeef, 0xff,
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{ &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, ([]acl.Perm)(nil)}, nil, stub.UniqueError(0)), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, ([]acl.Perm)(nil)}, nil, stub.UniqueError(0)),
}, &OpError{Op: "acl", Err: stub.UniqueError(0), Revert: true}}, }, &OpError{Op: "acl", Err: stub.UniqueError(0), Revert: true}},
{"success revert skip", 0xdeadbeef, Process, {"success revert skip", 0xbeef, Process,
&aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{ &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"skipping ACL", &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"skipping ACL", &aclUpdateOp{User, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
}, nil}, }, nil},
{"success revert aclUpdate ENOENT", 0xdeadbeef, 0xff, {"success revert aclUpdate ENOENT", 0xbeef, 0xff,
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{ &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, ([]acl.Perm)(nil)}, nil, &os.PathError{Op: "acl_get_file", Path: "/proc/nonexistent", Err: syscall.ENOENT}), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, ([]acl.Perm)(nil)}, nil, &os.PathError{Op: "acl_get_file", Path: "/proc/nonexistent", Err: syscall.ENOENT}),
call("verbosef", stub.ExpectArgs{"target of ACL %s no longer exists", []any{&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbosef", stub.ExpectArgs{"target of ACL %s no longer exists", []any{&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
}, nil}, }, nil},
{"success", 0xdeadbeef, 0xff, {"success", 0xbeef, 0xff,
&aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{ &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"applying ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"stripping ACL", &aclUpdateOp{Process, "/proc/nonexistent", []acl.Perm{acl.Read, acl.Write, acl.Execute}}}}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xdeadbeef, ([]acl.Perm)(nil)}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/proc/nonexistent", 0xbeef, ([]acl.Perm)(nil)}, nil, nil),
}, nil}, }, nil},
}) })
checkOpsBuilder(t, "UpdatePermType", []opsBuilderTestCase{ checkOpsBuilder(t, "UpdatePermType", []opsBuilderTestCase{
{"simple", {"simple",
0xdeadbeef, 0xbeef,
func(_ *testing.T, sys *I) { func(_ *testing.T, sys *I) {
sys. sys.
UpdatePerm(m("/run/user/1971/hakurei"), acl.Execute). UpdatePerm(m("/run/user/1971/hakurei"), acl.Execute).
@ -69,25 +69,25 @@ func TestACLUpdateOp(t *testing.T) {
&aclUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, &aclUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"tmpdirp", 0xdeadbeef, func(_ *testing.T, sys *I) { {"tmpdirp", 0xbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(User, m("/tmp/hakurei.0/tmpdir"), acl.Execute) sys.UpdatePermType(User, m("/tmp/hakurei.0/tmpdir"), acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{User, "/tmp/hakurei.0/tmpdir", []acl.Perm{acl.Execute}}, &aclUpdateOp{User, "/tmp/hakurei.0/tmpdir", []acl.Perm{acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"tmpdir", 0xdeadbeef, func(_ *testing.T, sys *I) { {"tmpdir", 0xbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(User, m("/tmp/hakurei.0/tmpdir/150"), acl.Read, acl.Write, acl.Execute) sys.UpdatePermType(User, m("/tmp/hakurei.0/tmpdir/150"), acl.Read, acl.Write, acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{User, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, &aclUpdateOp{User, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"share", 0xdeadbeef, func(_ *testing.T, sys *I) { {"share", 0xbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(Process, m("/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5"), acl.Execute) sys.UpdatePermType(Process, m("/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5"), acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", []acl.Perm{acl.Execute}}, &aclUpdateOp{Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", []acl.Perm{acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"passwd", 0xdeadbeef, func(_ *testing.T, sys *I) { {"passwd", 0xbeef, func(_ *testing.T, sys *I) {
sys. sys.
UpdatePermType(Process, m("/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd"), acl.Read). UpdatePermType(Process, m("/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd"), acl.Read).
UpdatePermType(Process, m("/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group"), acl.Read) UpdatePermType(Process, m("/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group"), acl.Read)
@ -96,7 +96,7 @@ func TestACLUpdateOp(t *testing.T) {
&aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", []acl.Perm{acl.Read}}, &aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", []acl.Perm{acl.Read}},
}, stub.Expect{}}, }, stub.Expect{}},
{"wayland", 0xdeadbeef, func(_ *testing.T, sys *I) { {"wayland", 0xbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(hst.EWayland, m("/run/user/1971/wayland-0"), acl.Read, acl.Write, acl.Execute) sys.UpdatePermType(hst.EWayland, m("/run/user/1971/wayland-0"), acl.Read, acl.Write, acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{hst.EWayland, "/run/user/1971/wayland-0", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, &aclUpdateOp{hst.EWayland, "/run/user/1971/wayland-0", []acl.Perm{acl.Read, acl.Write, acl.Execute}},

View File

@ -10,8 +10,8 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/comp"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/helper" "hakurei.app/helper"
"hakurei.app/ldd" "hakurei.app/ldd"
) )
@ -65,7 +65,7 @@ func (p *Proxy) Start() error {
p.final, true, p.final, true,
argF, func(z *container.Container) { argF, func(z *container.Container) {
z.SeccompFlags |= seccomp.AllowMultiarch z.SeccompFlags |= seccomp.AllowMultiarch
z.SeccompPresets |= comp.PresetStrict z.SeccompPresets |= std.PresetStrict
z.Hostname = "hakurei-dbus" z.Hostname = "hakurei-dbus"
if p.output != nil { if p.output != nil {
z.Stdout, z.Stderr = p.output, p.output z.Stdout, z.Stderr = p.output, p.output
@ -114,7 +114,7 @@ func (p *Proxy) Start() error {
check.SortAbs(sockDirPaths) check.SortAbs(sockDirPaths)
sockDirPaths = check.CompactAbs(sockDirPaths) sockDirPaths = check.CompactAbs(sockDirPaths)
for _, name := range sockDirPaths { for _, name := range sockDirPaths {
z.Bind(name, name, comp.BindWritable) z.Bind(name, name, std.BindWritable)
} }
// xdg-dbus-proxy bin path // xdg-dbus-proxy bin path

View File

@ -19,7 +19,7 @@ func TestDBusProxyOp(t *testing.T) {
t.Parallel() t.Parallel()
checkOpBehaviour(t, []opBehaviourTestCase{ checkOpBehaviour(t, []opBehaviourTestCase{
{"dbusProxyStart", 0xdeadbeef, 0xff, &dbusProxyOp{ {"dbusProxyStart", 0xdead, 0xff, &dbusProxyOp{
final: dbusNewFinalSample(4), final: dbusNewFinalSample(4),
out: new(linePrefixWriter), // panics on write out: new(linePrefixWriter), // panics on write
system: true, system: true,
@ -32,7 +32,7 @@ func TestDBusProxyOp(t *testing.T) {
Msg: "cannot start message bus proxy: unique error 2 injected by the test suite", Msg: "cannot start message bus proxy: unique error 2 injected by the test suite",
}, nil, nil}, }, nil, nil},
{"dbusProxyWait", 0xdeadbeef, 0xff, &dbusProxyOp{ {"dbusProxyWait", 0xdead, 0xff, &dbusProxyOp{
final: dbusNewFinalSample(3), final: dbusNewFinalSample(3),
}, []stub.Call{ }, []stub.Call{
call("verbosef", stub.ExpectArgs{"session bus proxy on %q for upstream %q", []any{"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus", "unix:path=/run/user/1000/bus"}}, nil, nil), call("verbosef", stub.ExpectArgs{"session bus proxy on %q for upstream %q", []any{"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus", "unix:path=/run/user/1000/bus"}}, nil, nil),
@ -48,7 +48,7 @@ func TestDBusProxyOp(t *testing.T) {
Msg: "message bus proxy error: unique error 1 injected by the test suite", Msg: "message bus proxy error: unique error 1 injected by the test suite",
}}, }},
{"success dbusProxyWait cancel", 0xdeadbeef, 0xff, &dbusProxyOp{ {"success dbusProxyWait cancel", 0xdead, 0xff, &dbusProxyOp{
final: dbusNewFinalSample(2), final: dbusNewFinalSample(2),
system: true, system: true,
}, []stub.Call{ }, []stub.Call{
@ -63,7 +63,7 @@ func TestDBusProxyOp(t *testing.T) {
call("verbose", stub.ExpectArgs{[]any{"message bus proxy canceled upstream"}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"message bus proxy canceled upstream"}}, nil, nil),
}, nil}, }, nil},
{"success", 0xdeadbeef, 0xff, &dbusProxyOp{ {"success", 0xdead, 0xff, &dbusProxyOp{
final: dbusNewFinalSample(1), final: dbusNewFinalSample(1),
system: true, system: true,
}, []stub.Call{ }, []stub.Call{
@ -80,7 +80,7 @@ func TestDBusProxyOp(t *testing.T) {
}) })
checkOpsBuilder(t, "ProxyDBus", []opsBuilderTestCase{ checkOpsBuilder(t, "ProxyDBus", []opsBuilderTestCase{
{"nil session", 0xcafebabe, func(t *testing.T, sys *I) { {"nil session", 0xcafe, func(t *testing.T, sys *I) {
wantErr := &OpError{ wantErr := &OpError{
Op: "dbus", Err: ErrDBusConfig, Op: "dbus", Err: ErrDBusConfig,
Msg: "attempted to create message bus proxy args without session bus config", Msg: "attempted to create message bus proxy args without session bus config",
@ -90,7 +90,7 @@ func TestDBusProxyOp(t *testing.T) {
} }
}, nil, stub.Expect{}}, }, nil, stub.Expect{}},
{"dbusFinalise NUL", 0xcafebabe, func(_ *testing.T, sys *I) { {"dbusFinalise NUL", 0xcafe, func(_ *testing.T, sys *I) {
defer func() { defer func() {
want := "message bus proxy configuration contains NUL byte" want := "message bus proxy configuration contains NUL byte"
if r := recover(); r != want { if r := recover(); r != want {
@ -121,7 +121,7 @@ func TestDBusProxyOp(t *testing.T) {
}, (*dbus.Final)(nil), syscall.EINVAL), }, (*dbus.Final)(nil), syscall.EINVAL),
}}}, }}},
{"dbusFinalise", 0xcafebabe, func(_ *testing.T, sys *I) { {"dbusFinalise", 0xcafe, func(_ *testing.T, sys *I) {
wantErr := &OpError{ wantErr := &OpError{
Op: "dbus", Err: stub.UniqueError(0), Op: "dbus", Err: stub.UniqueError(0),
Msg: "cannot finalise message bus proxy: unique error 0 injected by the test suite", Msg: "cannot finalise message bus proxy: unique error 0 injected by the test suite",
@ -151,7 +151,7 @@ func TestDBusProxyOp(t *testing.T) {
}, (*dbus.Final)(nil), stub.UniqueError(0)), }, (*dbus.Final)(nil), stub.UniqueError(0)),
}}}, }}},
{"full", 0xcafebabe, func(_ *testing.T, sys *I) { {"full", 0xcafe, func(_ *testing.T, sys *I) {
sys.MustProxyDBus( sys.MustProxyDBus(
&hst.BusConfig{ &hst.BusConfig{
// use impossible value here as an implicit assert that it goes through the stub // use impossible value here as an implicit assert that it goes through the stub

View File

@ -11,12 +11,12 @@ func TestHardlinkOp(t *testing.T) {
t.Parallel() t.Parallel()
checkOpBehaviour(t, []opBehaviourTestCase{ checkOpBehaviour(t, []opBehaviourTestCase{
{"link", 0xdeadbeef, 0xff, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{ {"link", 0xbeef, 0xff, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, stub.UniqueError(1)), call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, stub.UniqueError(1)),
}, &OpError{Op: "hardlink", Err: stub.UniqueError(1)}, nil, nil}, }, &OpError{Op: "hardlink", Err: stub.UniqueError(1)}, nil, nil},
{"remove", 0xdeadbeef, 0xff, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{ {"remove", 0xbeef, 0xff, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil), call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -24,14 +24,14 @@ func TestHardlinkOp(t *testing.T) {
call("remove", stub.ExpectArgs{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, stub.UniqueError(0)), call("remove", stub.ExpectArgs{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, stub.UniqueError(0)),
}, &OpError{Op: "hardlink", Err: stub.UniqueError(0), Revert: true}}, }, &OpError{Op: "hardlink", Err: stub.UniqueError(0), Revert: true}},
{"success skip", 0xdeadbeef, hst.EWayland | hst.EX11, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{ {"success skip", 0xbeef, hst.EWayland | hst.EX11, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil), call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbosef", stub.ExpectArgs{"skipping hard link %q", []any{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}}, nil, nil), call("verbosef", stub.ExpectArgs{"skipping hard link %q", []any{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}}, nil, nil),
}, nil}, }, nil},
{"success", 0xdeadbeef, 0xff, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{ {"success", 0xbeef, 0xff, &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{hst.EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil), call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -41,13 +41,13 @@ func TestHardlinkOp(t *testing.T) {
}) })
checkOpsBuilder(t, "LinkFileType", []opsBuilderTestCase{ checkOpsBuilder(t, "LinkFileType", []opsBuilderTestCase{
{"type", 0xcafebabe, func(_ *testing.T, sys *I) { {"type", 0xcafe, func(_ *testing.T, sys *I) {
sys.LinkFileType(User, m("/run/user/1000/pulse/native"), m("/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse")) sys.LinkFileType(User, m("/run/user/1000/pulse/native"), m("/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"))
}, []Op{ }, []Op{
&hardlinkOp{User, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, &hardlinkOp{User, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
}, stub.Expect{}}, }, stub.Expect{}},
{"link", 0xcafebabe, func(_ *testing.T, sys *I) { {"link", 0xcafe, func(_ *testing.T, sys *I) {
sys.Link(m("/run/user/1000/pulse/native"), m("/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse")) sys.Link(m("/run/user/1000/pulse/native"), m("/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"))
}, []Op{ }, []Op{
&hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},

View File

@ -11,18 +11,18 @@ func TestMkdirOp(t *testing.T) {
t.Parallel() t.Parallel()
checkOpBehaviour(t, []opBehaviourTestCase{ checkOpBehaviour(t, []opBehaviourTestCase{
{"mkdir", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ {"mkdir", 0xbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, stub.UniqueError(2)), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, stub.UniqueError(2)),
}, &OpError{Op: "mkdir", Err: stub.UniqueError(2)}, nil, nil}, }, &OpError{Op: "mkdir", Err: stub.UniqueError(2)}, nil, nil},
{"chmod", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ {"chmod", 0xbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, os.ErrExist), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, os.ErrExist),
call("chmod", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, stub.UniqueError(1)), call("chmod", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, stub.UniqueError(1)),
}, &OpError{Op: "mkdir", Err: stub.UniqueError(1)}, nil, nil}, }, &OpError{Op: "mkdir", Err: stub.UniqueError(1)}, nil, nil},
{"remove", 0xdeadbeef, 0xff, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{ {"remove", 0xbeef, 0xff, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -30,25 +30,25 @@ func TestMkdirOp(t *testing.T) {
call("remove", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"}, nil, stub.UniqueError(0)), call("remove", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"}, nil, stub.UniqueError(0)),
}, &OpError{Op: "mkdir", Err: stub.UniqueError(0), Revert: true}}, }, &OpError{Op: "mkdir", Err: stub.UniqueError(0), Revert: true}},
{"success exist chmod", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ {"success exist chmod", 0xbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, os.ErrExist), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, os.ErrExist),
call("chmod", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), call("chmod", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil),
}, nil, nil, nil}, }, nil, nil, nil},
{"success ensure", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{ {"success ensure", 0xbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, false}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil),
}, nil, nil, nil}, }, nil, nil, nil},
{"success skip", 0xdeadbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{ {"success skip", 0xbeef, 0xff, &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"skipping ephemeral directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"skipping ephemeral directory", &mkdirOp{User, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
}, nil}, }, nil},
{"success", 0xdeadbeef, 0xff, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{ {"success", 0xbeef, 0xff, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil), call("mkdir", stub.ExpectArgs{"/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", os.FileMode(0711)}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
@ -58,13 +58,13 @@ func TestMkdirOp(t *testing.T) {
}) })
checkOpsBuilder(t, "EnsureEphemeral", []opsBuilderTestCase{ checkOpsBuilder(t, "EnsureEphemeral", []opsBuilderTestCase{
{"ensure", 0xcafebabe, func(_ *testing.T, sys *I) { {"ensure", 0xcafe, func(_ *testing.T, sys *I) {
sys.Ensure(m("/tmp/hakurei.0"), 0700) sys.Ensure(m("/tmp/hakurei.0"), 0700)
}, []Op{ }, []Op{
&mkdirOp{User, "/tmp/hakurei.0", 0700, false}, &mkdirOp{User, "/tmp/hakurei.0", 0700, false},
}, stub.Expect{}}, }, stub.Expect{}},
{"ephemeral", 0xcafebabe, func(_ *testing.T, sys *I) { {"ephemeral", 0xcafe, func(_ *testing.T, sys *I) {
sys.Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711) sys.Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711)
}, []Op{ }, []Op{
&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true},

View File

@ -106,11 +106,11 @@ func TestNew(t *testing.T) {
}) })
}) })
sys := New(t.Context(), message.New(nil), 0xdeadbeef) sys := New(t.Context(), message.New(nil), 0xbeef)
if sys.ctx == nil { if sys.ctx == nil {
t.Error("New: ctx = nil") t.Error("New: ctx = nil")
} }
if got := sys.UID(); got != 0xdeadbeef { if got := sys.UID(); got != 0xbeef {
t.Errorf("UID: %d", got) t.Errorf("UID: %d", got)
} }
} }

View File

@ -89,7 +89,7 @@ func TestWaylandOp(t *testing.T) {
t.Parallel() t.Parallel()
checkOpBehaviour(t, []opBehaviourTestCase{ checkOpBehaviour(t, []opBehaviourTestCase{
{"attach", 0xdeadbeef, 0xff, &waylandOp{nil, {"attach", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -100,7 +100,7 @@ func TestWaylandOp(t *testing.T) {
attachErr: stub.UniqueError(5)}, attachErr: stub.UniqueError(5)},
}, nil, &OpError{Op: "wayland", Err: stub.UniqueError(5)}, nil, nil}, }, nil, &OpError{Op: "wayland", Err: stub.UniqueError(5)}, nil, nil},
{"bind", 0xdeadbeef, 0xff, &waylandOp{nil, {"bind", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -113,7 +113,7 @@ func TestWaylandOp(t *testing.T) {
call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
}, &OpError{Op: "wayland", Err: stub.UniqueError(4)}, nil, nil}, }, &OpError{Op: "wayland", Err: stub.UniqueError(4)}, nil, nil},
{"chmod", 0xdeadbeef, 0xff, &waylandOp{nil, {"chmod", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -127,7 +127,7 @@ func TestWaylandOp(t *testing.T) {
call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, stub.UniqueError(3)), call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, stub.UniqueError(3)),
}, &OpError{Op: "wayland", Err: stub.UniqueError(3)}, nil, nil}, }, &OpError{Op: "wayland", Err: stub.UniqueError(3)}, nil, nil},
{"aclUpdate", 0xdeadbeef, 0xff, &waylandOp{nil, {"aclUpdate", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -139,10 +139,10 @@ func TestWaylandOp(t *testing.T) {
call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),
call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil), call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, stub.UniqueError(2)), call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, stub.UniqueError(2)),
}, &OpError{Op: "wayland", Err: stub.UniqueError(2)}, nil, nil}, }, &OpError{Op: "wayland", Err: stub.UniqueError(2)}, nil, nil},
{"remove", 0xdeadbeef, 0xff, &waylandOp{nil, {"remove", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -154,14 +154,14 @@ func TestWaylandOp(t *testing.T) {
call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),
call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil), call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbosef", stub.ExpectArgs{"detaching from wayland on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"detaching from wayland on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"removing wayland socket on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"removing wayland socket on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),
call("remove", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}, nil, stub.UniqueError(1)), call("remove", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}, nil, stub.UniqueError(1)),
}, &OpError{Op: "wayland", Err: errors.Join(stub.UniqueError(1)), Revert: true}}, }, &OpError{Op: "wayland", Err: errors.Join(stub.UniqueError(1)), Revert: true}},
{"close", 0xdeadbeef, 0xff, &waylandOp{nil, {"close", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -174,14 +174,14 @@ func TestWaylandOp(t *testing.T) {
call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),
call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil), call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbosef", stub.ExpectArgs{"detaching from wayland on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"detaching from wayland on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"removing wayland socket on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"removing wayland socket on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),
call("remove", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}, nil, nil), call("remove", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}, nil, nil),
}, &OpError{Op: "wayland", Err: errors.Join(stub.UniqueError(0)), Revert: true}}, }, &OpError{Op: "wayland", Err: errors.Join(stub.UniqueError(0)), Revert: true}},
{"success", 0xdeadbeef, 0xff, &waylandOp{nil, {"success", 0xbeef, 0xff, &waylandOp{nil,
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland",
"/run/user/1971/wayland-0", "/run/user/1971/wayland-0",
"org.chromium.Chromium", "org.chromium.Chromium",
@ -193,7 +193,7 @@ func TestWaylandOp(t *testing.T) {
call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland attached on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"wayland listening on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),
call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil), call("chmod", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", os.FileMode(0)}, nil, nil),
call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xdeadbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil), call("aclUpdate", stub.ExpectArgs{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", 0xbeef, []acl.Perm{acl.Read, acl.Write, acl.Execute}}, nil, nil),
}, nil, []stub.Call{ }, nil, []stub.Call{
call("verbosef", stub.ExpectArgs{"detaching from wayland on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil), call("verbosef", stub.ExpectArgs{"detaching from wayland on %q", []any{"/run/user/1971/wayland-0"}}, nil, nil),
call("verbosef", stub.ExpectArgs{"removing wayland socket on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil), call("verbosef", stub.ExpectArgs{"removing wayland socket on %q", []any{"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"}}, nil, nil),

View File

@ -42,7 +42,7 @@ func TestXHostOp(t *testing.T) {
}) })
checkOpsBuilder(t, "ChangeHosts", []opsBuilderTestCase{ checkOpsBuilder(t, "ChangeHosts", []opsBuilderTestCase{
{"xhost", 0xcafebabe, func(_ *testing.T, sys *I) { {"xhost", 0xcafe, func(_ *testing.T, sys *I) {
sys.ChangeHosts("chronos") sys.ChangeHosts("chronos")
}, []Op{ }, []Op{
xhostOp("chronos"), xhostOp("chronos"),

View File

@ -84,7 +84,7 @@
virtualisation = { virtualisation = {
# Hopefully reduces spurious test failures: # Hopefully reduces spurious test failures:
memorySize = 8192; memorySize = if pkgs.hostPlatform.is32bit then 2046 else 8192;
qemu.options = [ qemu.options = [
# Need to switch to a different GPU driver than the default one (-vga std) so that Sway can launch: # Need to switch to a different GPU driver than the default one (-vga std) so that Sway can launch: