From 3ce63e95d7691450f7b368e639d984a223a764b1 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Tue, 7 Oct 2025 18:28:20 +0900 Subject: [PATCH] container: move seccomp preset bits This allows holding the bits without cgo. Signed-off-by: Ophestra --- container/bits/seccomp.go | 20 ++++++++ container/container.go | 5 +- container/container_test.go | 27 +++++----- container/init_test.go | 77 ++++++++++++++-------------- container/seccomp/hash_amd64_test.go | 5 +- container/seccomp/hash_arm64_test.go | 5 +- container/seccomp/hash_test.go | 3 +- container/seccomp/libseccomp_test.go | 1 + container/seccomp/presets.go | 41 +++++---------- container/seccomp/proc.go | 4 -- internal/app/app_test.go | 8 +-- internal/app/shim.go | 3 +- internal/app/spcontainer.go | 9 ++-- ldd/exec.go | 3 +- system/dbus/proc.go | 3 +- 15 files changed, 116 insertions(+), 98 deletions(-) create mode 100644 container/bits/seccomp.go diff --git a/container/bits/seccomp.go b/container/bits/seccomp.go new file mode 100644 index 0000000..57e3e12 --- /dev/null +++ b/container/bits/seccomp.go @@ -0,0 +1,20 @@ +package bits + +// FilterPreset specifies parts of the syscall filter preset to enable. +type FilterPreset int + +const ( + // PresetExt are project-specific extensions. + PresetExt FilterPreset = 1 << iota + // PresetDenyNS denies namespace setup syscalls. + PresetDenyNS + // PresetDenyTTY denies faking input. + PresetDenyTTY + // PresetDenyDevel denies development-related syscalls. + PresetDenyDevel + // PresetLinux32 sets PER_LINUX32. + PresetLinux32 + + // PresetStrict is a strict preset useful as a default value. + PresetStrict = PresetExt | PresetDenyNS | PresetDenyTTY | PresetDenyDevel +) diff --git a/container/container.go b/container/container.go index c19c2e7..e54afb9 100644 --- a/container/container.go +++ b/container/container.go @@ -14,6 +14,7 @@ import ( . "syscall" "time" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" ) @@ -82,7 +83,7 @@ type ( // Extra seccomp flags. SeccompFlags seccomp.ExportFlag // Seccomp presets. Has no effect unless SeccompRules is zero-length. - SeccompPresets seccomp.FilterPreset + SeccompPresets bits.FilterPreset // Do not load seccomp program. SeccompDisable bool @@ -170,7 +171,7 @@ func (p *Container) Start() error { } if !p.RetainSession { - p.SeccompPresets |= seccomp.PresetDenyTTY + p.SeccompPresets |= bits.PresetDenyTTY } if p.AdoptWaitDelay == 0 { diff --git a/container/container_test.go b/container/container_test.go index 2235648..762b147 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -20,6 +20,7 @@ import ( "hakurei.app/command" "hakurei.app/container" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" "hakurei.app/container/vfs" "hakurei.app/hst" @@ -199,20 +200,20 @@ var containerTestCases = []struct { rules []seccomp.NativeRule flags seccomp.ExportFlag - presets seccomp.FilterPreset + presets bits.FilterPreset }{ {"minimal", true, false, false, true, emptyOps, emptyMnt, - 1000, 100, nil, 0, seccomp.PresetStrict}, + 1000, 100, nil, 0, bits.PresetStrict}, {"allow", true, true, true, false, emptyOps, emptyMnt, - 1000, 100, nil, 0, seccomp.PresetExt | seccomp.PresetDenyDevel}, + 1000, 100, nil, 0, bits.PresetExt | bits.PresetDenyDevel}, {"no filter", false, true, true, true, emptyOps, emptyMnt, - 1000, 100, nil, 0, seccomp.PresetExt}, + 1000, 100, nil, 0, bits.PresetExt}, {"custom rules", true, true, true, false, emptyOps, emptyMnt, - 1, 31, []seccomp.NativeRule{{Syscall: seccomp.ScmpSyscall(syscall.SYS_SETUID), Errno: seccomp.ScmpErrno(syscall.EPERM)}}, 0, seccomp.PresetExt}, + 1, 31, []seccomp.NativeRule{{Syscall: seccomp.ScmpSyscall(syscall.SYS_SETUID), Errno: seccomp.ScmpErrno(syscall.EPERM)}}, 0, bits.PresetExt}, {"tmpfs", true, false, false, true, earlyOps(new(container.Ops). @@ -221,7 +222,7 @@ var containerTestCases = []struct { earlyMnt( ent("/", hst.Tmp, "rw,nosuid,nodev,relatime", "tmpfs", "ephemeral", ignore), ), - 9, 9, nil, 0, seccomp.PresetStrict}, + 9, 9, nil, 0, bits.PresetStrict}, {"dev", true, true /* go test output is not a tty */, false, false, earlyOps(new(container.Ops). @@ -239,7 +240,7 @@ var containerTestCases = []struct { ent("/", "/dev/mqueue", "rw,nosuid,nodev,noexec,relatime", "mqueue", "mqueue", "rw"), ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore), ), - 1971, 100, nil, 0, seccomp.PresetStrict}, + 1971, 100, nil, 0, bits.PresetStrict}, {"dev no mqueue", true, true /* go test output is not a tty */, false, false, earlyOps(new(container.Ops). @@ -256,7 +257,7 @@ var containerTestCases = []struct { ent("/", "/dev/pts", "rw,nosuid,noexec,relatime", "devpts", "devpts", "rw,mode=620,ptmxmode=666"), ent("/", "/dev/shm", "rw,nosuid,nodev,relatime", "tmpfs", "tmpfs", ignore), ), - 1971, 100, nil, 0, seccomp.PresetStrict}, + 1971, 100, nil, 0, bits.PresetStrict}, {"overlay", true, false, false, true, func(t *testing.T) (*container.Ops, context.Context) { @@ -293,7 +294,7 @@ var containerTestCases = []struct { ",redirect_dir=nofollow,uuid=on,userxattr"), } }, - 1 << 3, 1 << 14, nil, 0, seccomp.PresetStrict}, + 1 << 3, 1 << 14, nil, 0, bits.PresetStrict}, {"overlay ephemeral", true, false, false, true, func(t *testing.T) (*container.Ops, context.Context) { @@ -317,7 +318,7 @@ var containerTestCases = []struct { ent("/", hst.Tmp, "rw", "overlay", "overlay", ignore), } }, - 1 << 3, 1 << 14, nil, 0, seccomp.PresetStrict}, + 1 << 3, 1 << 14, nil, 0, bits.PresetStrict}, {"overlay readonly", true, false, false, true, func(t *testing.T) (*container.Ops, context.Context) { @@ -345,7 +346,7 @@ var containerTestCases = []struct { ",redirect_dir=nofollow,userxattr"), } }, - 1 << 3, 1 << 14, nil, 0, seccomp.PresetStrict}, + 1 << 3, 1 << 14, nil, 0, bits.PresetStrict}, } func TestContainer(t *testing.T) { @@ -547,9 +548,9 @@ func TestContainerString(t *testing.T) { c := container.NewCommand(t.Context(), msg, container.MustAbs("/run/current-system/sw/bin/ldd"), "ldd", "/usr/bin/env") c.SeccompFlags |= seccomp.AllowMultiarch c.SeccompRules = seccomp.Preset( - seccomp.PresetExt|seccomp.PresetDenyNS|seccomp.PresetDenyTTY, + bits.PresetExt|bits.PresetDenyNS|bits.PresetDenyTTY, c.SeccompFlags) - c.SeccompPresets = seccomp.PresetStrict + c.SeccompPresets = bits.PresetStrict want := `argv: ["ldd" "/usr/bin/env"], filter: true, rules: 65, flags: 0x1, presets: 0xf` if got := c.String(); got != want { t.Errorf("String: %s, want %s", got, want) diff --git a/container/init_test.go b/container/init_test.go index 162afad..57cdd44 100644 --- a/container/init_test.go +++ b/container/init_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" "hakurei.app/container/stub" ) @@ -67,7 +68,7 @@ func TestInitEntrypoint(t *testing.T) { Gid: 1 << 31, Hostname: "hakurei-check", SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(79), nil), @@ -92,7 +93,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(78), nil), @@ -120,7 +121,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(76), nil), @@ -149,7 +150,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(74), nil), @@ -179,7 +180,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(72), nil), @@ -210,7 +211,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(70), nil), @@ -242,7 +243,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(68), nil), @@ -276,7 +277,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(66), nil), @@ -312,7 +313,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: (*Ops)(sliceAddr(make(Ops, 1))), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(64), nil), @@ -350,7 +351,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(nil, nil, BindDevice), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(63), nil), @@ -388,7 +389,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(62), nil), @@ -427,7 +428,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(60), nil), @@ -466,7 +467,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(59), nil), @@ -506,7 +507,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(57), nil), @@ -547,7 +548,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(55), nil), @@ -589,7 +590,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(53), nil), @@ -632,7 +633,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(51), nil), @@ -676,7 +677,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(49), nil), @@ -721,7 +722,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(47), nil), @@ -767,7 +768,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(45), nil), @@ -822,7 +823,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(43), nil), @@ -877,7 +878,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(42), nil), @@ -933,7 +934,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(40), nil), @@ -990,7 +991,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(38), nil), @@ -1049,7 +1050,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(36), nil), @@ -1109,7 +1110,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(34), nil), @@ -1170,7 +1171,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(32), nil), @@ -1232,7 +1233,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(30), nil), @@ -1295,7 +1296,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(28), nil), @@ -1359,7 +1360,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(26), nil), @@ -1424,7 +1425,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(24), nil), @@ -1490,7 +1491,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(22), nil), @@ -1564,7 +1565,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(20), nil), @@ -1671,7 +1672,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(18), nil), @@ -1779,7 +1780,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(16), nil), @@ -1866,7 +1867,7 @@ func TestInitEntrypoint(t *testing.T) { call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil), call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil), call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil), - call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{seccomp.FilterPreset(0xf)}}, nil, nil), + call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{bits.FilterPreset(0xf)}}, nil, nil), call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, stub.UniqueError(15)), call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(15)}}, nil, nil), }, @@ -2523,7 +2524,7 @@ func TestInitEntrypoint(t *testing.T) { Hostname: "hakurei-check", Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), SeccompRules: make([]seccomp.NativeRule, 0), - SeccompPresets: seccomp.PresetStrict, + SeccompPresets: bits.PresetStrict, RetainSession: true, Privileged: true, }, 1000, 100, 3, true}, uintptr(9)}, stub.UniqueError(0), nil), @@ -2610,7 +2611,7 @@ func TestInitEntrypoint(t *testing.T) { call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil), call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil), call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil), - call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{seccomp.FilterPreset(0xf)}}, nil, nil), + call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{bits.FilterPreset(0xf)}}, nil, nil), call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, nil), call("verbosef", stub.ExpectArgs{"%d filter rules loaded", []any{73}}, nil, nil), call("newFile", stub.ExpectArgs{uintptr(10), "extra file 0"}, (*os.File)(nil), nil), diff --git a/container/seccomp/hash_amd64_test.go b/container/seccomp/hash_amd64_test.go index 7ef2b1d..5a5e543 100644 --- a/container/seccomp/hash_amd64_test.go +++ b/container/seccomp/hash_amd64_test.go @@ -1,6 +1,9 @@ package seccomp_test -import . "hakurei.app/container/seccomp" +import ( + . "hakurei.app/container/bits" + . "hakurei.app/container/seccomp" +) var bpfExpected = bpfLookup{ {AllowMultiarch | AllowCAN | diff --git a/container/seccomp/hash_arm64_test.go b/container/seccomp/hash_arm64_test.go index d8ffa18..2395bce 100644 --- a/container/seccomp/hash_arm64_test.go +++ b/container/seccomp/hash_arm64_test.go @@ -1,6 +1,9 @@ package seccomp_test -import . "hakurei.app/container/seccomp" +import ( + . "hakurei.app/container/bits" + . "hakurei.app/container/seccomp" +) var bpfExpected = bpfLookup{ {AllowMultiarch | AllowCAN | diff --git a/container/seccomp/hash_test.go b/container/seccomp/hash_test.go index 1d31ac0..24f6b1c 100644 --- a/container/seccomp/hash_test.go +++ b/container/seccomp/hash_test.go @@ -3,13 +3,14 @@ package seccomp_test import ( "encoding/hex" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" ) type ( bpfPreset = struct { seccomp.ExportFlag - seccomp.FilterPreset + bits.FilterPreset } bpfLookup map[bpfPreset][]byte ) diff --git a/container/seccomp/libseccomp_test.go b/container/seccomp/libseccomp_test.go index 1ae3f76..81f5251 100644 --- a/container/seccomp/libseccomp_test.go +++ b/container/seccomp/libseccomp_test.go @@ -8,6 +8,7 @@ import ( "syscall" "testing" + . "hakurei.app/container/bits" . "hakurei.app/container/seccomp" ) diff --git a/container/seccomp/presets.go b/container/seccomp/presets.go index 4a01d2b..abd3d5c 100644 --- a/container/seccomp/presets.go +++ b/container/seccomp/presets.go @@ -4,46 +4,33 @@ package seccomp import ( . "syscall" + + "hakurei.app/container/bits" ) -type FilterPreset int - -const ( - // PresetExt are project-specific extensions. - PresetExt FilterPreset = 1 << iota - // PresetDenyNS denies namespace setup syscalls. - PresetDenyNS - // PresetDenyTTY denies faking input. - PresetDenyTTY - // PresetDenyDevel denies development-related syscalls. - PresetDenyDevel - // PresetLinux32 sets PER_LINUX32. - PresetLinux32 -) - -func Preset(presets FilterPreset, flags ExportFlag) (rules []NativeRule) { +func Preset(presets bits.FilterPreset, flags ExportFlag) (rules []NativeRule) { allowedPersonality := PER_LINUX - if presets&PresetLinux32 != 0 { + if presets&bits.PresetLinux32 != 0 { allowedPersonality = PER_LINUX32 } presetDevelFinal := presetDevel(ScmpDatum(allowedPersonality)) l := len(presetCommon) - if presets&PresetDenyNS != 0 { + if presets&bits.PresetDenyNS != 0 { l += len(presetNamespace) } - if presets&PresetDenyTTY != 0 { + if presets&bits.PresetDenyTTY != 0 { l += len(presetTTY) } - if presets&PresetDenyDevel != 0 { + if presets&bits.PresetDenyDevel != 0 { l += len(presetDevelFinal) } if flags&AllowMultiarch == 0 { l += len(presetEmu) } - if presets&PresetExt != 0 { + if presets&bits.PresetExt != 0 { l += len(presetCommonExt) - if presets&PresetDenyNS != 0 { + if presets&bits.PresetDenyNS != 0 { l += len(presetNamespaceExt) } if flags&AllowMultiarch == 0 { @@ -53,21 +40,21 @@ func Preset(presets FilterPreset, flags ExportFlag) (rules []NativeRule) { rules = make([]NativeRule, 0, l) rules = append(rules, presetCommon...) - if presets&PresetDenyNS != 0 { + if presets&bits.PresetDenyNS != 0 { rules = append(rules, presetNamespace...) } - if presets&PresetDenyTTY != 0 { + if presets&bits.PresetDenyTTY != 0 { rules = append(rules, presetTTY...) } - if presets&PresetDenyDevel != 0 { + if presets&bits.PresetDenyDevel != 0 { rules = append(rules, presetDevelFinal...) } if flags&AllowMultiarch == 0 { rules = append(rules, presetEmu...) } - if presets&PresetExt != 0 { + if presets&bits.PresetExt != 0 { rules = append(rules, presetCommonExt...) - if presets&PresetDenyNS != 0 { + if presets&bits.PresetDenyNS != 0 { rules = append(rules, presetNamespaceExt...) } if flags&AllowMultiarch == 0 { diff --git a/container/seccomp/proc.go b/container/seccomp/proc.go index 76773b2..7027cc6 100644 --- a/container/seccomp/proc.go +++ b/container/seccomp/proc.go @@ -8,10 +8,6 @@ import ( "hakurei.app/helper/proc" ) -const ( - PresetStrict = PresetExt | PresetDenyNS | PresetDenyTTY | PresetDenyDevel -) - // New returns an inactive Encoder instance. func New(rules []NativeRule, flags ExportFlag) *Encoder { return &Encoder{newExporter(rules, flags)} } diff --git a/internal/app/app_test.go b/internal/app/app_test.go index a031d43..bcca558 100644 --- a/internal/app/app_test.go +++ b/internal/app/app_test.go @@ -15,7 +15,7 @@ import ( "time" "hakurei.app/container" - "hakurei.app/container/seccomp" + "hakurei.app/container/bits" "hakurei.app/hst" "hakurei.app/internal/app/state" "hakurei.app/system" @@ -109,7 +109,7 @@ func TestApp(t *testing.T) { 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")). Remount(m("/"), syscall.MS_RDONLY), - SeccompPresets: seccomp.PresetExt | seccomp.PresetDenyDevel, + SeccompPresets: bits.PresetExt | bits.PresetDenyDevel, HostNet: true, HostAbstract: true, RetainSession: true, @@ -282,7 +282,7 @@ func TestApp(t *testing.T) { Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), m("/run/user/65534/bus"), 0). Bind(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), m("/run/dbus/system_bus_socket"), 0). Remount(m("/"), syscall.MS_RDONLY), - SeccompPresets: seccomp.PresetExt | seccomp.PresetDenyDevel, + SeccompPresets: bits.PresetExt | bits.PresetDenyDevel, HostNet: true, HostAbstract: true, RetainSession: true, @@ -432,7 +432,7 @@ func TestApp(t *testing.T) { Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), m("/run/user/1971/bus"), 0). Bind(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), m("/run/dbus/system_bus_socket"), 0). Remount(m("/"), syscall.MS_RDONLY), - SeccompPresets: seccomp.PresetExt | seccomp.PresetDenyTTY | seccomp.PresetDenyDevel, + SeccompPresets: bits.PresetExt | bits.PresetDenyTTY | bits.PresetDenyDevel, HostNet: true, ForwardCancel: true, }, diff --git a/internal/app/shim.go b/internal/app/shim.go index 4927f5c..3a8a551 100644 --- a/internal/app/shim.go +++ b/internal/app/shim.go @@ -14,6 +14,7 @@ import ( "time" "hakurei.app/container" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" "hakurei.app/hst" ) @@ -150,7 +151,7 @@ func ShimMain() { } if err := seccomp.Load( - seccomp.Preset(seccomp.PresetStrict, seccomp.AllowMultiarch), + seccomp.Preset(bits.PresetStrict, seccomp.AllowMultiarch), seccomp.AllowMultiarch, ); err != nil { log.Fatalf("cannot load syscall filter: %v", err) diff --git a/internal/app/spcontainer.go b/internal/app/spcontainer.go index 4381fd7..ffbee7d 100644 --- a/internal/app/spcontainer.go +++ b/internal/app/spcontainer.go @@ -8,6 +8,7 @@ import ( "syscall" "hakurei.app/container" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" "hakurei.app/hst" "hakurei.app/system/dbus" @@ -64,16 +65,16 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error { } if !state.Container.SeccompCompat { - state.params.SeccompPresets |= seccomp.PresetExt + state.params.SeccompPresets |= bits.PresetExt } if !state.Container.Devel { - state.params.SeccompPresets |= seccomp.PresetDenyDevel + state.params.SeccompPresets |= bits.PresetDenyDevel } if !state.Container.Userns { - state.params.SeccompPresets |= seccomp.PresetDenyNS + state.params.SeccompPresets |= bits.PresetDenyNS } if !state.Container.Tty { - state.params.SeccompPresets |= seccomp.PresetDenyTTY + state.params.SeccompPresets |= bits.PresetDenyTTY } if state.Container.MapRealUID { diff --git a/ldd/exec.go b/ldd/exec.go index bdd8fa9..b562316 100644 --- a/ldd/exec.go +++ b/ldd/exec.go @@ -9,6 +9,7 @@ import ( "time" "hakurei.app/container" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" ) @@ -36,7 +37,7 @@ func Exec(ctx context.Context, msg container.Msg, p string) ([]*Entry, error) { z := container.NewCommand(c, msg, toolPath, lddName, p) z.Hostname = "hakurei-" + lddName z.SeccompFlags |= seccomp.AllowMultiarch - z.SeccompPresets |= seccomp.PresetStrict + z.SeccompPresets |= bits.PresetStrict stdout, stderr := new(bytes.Buffer), new(bytes.Buffer) z.Stdout = stdout z.Stderr = stderr diff --git a/system/dbus/proc.go b/system/dbus/proc.go index 24f8c40..01e836d 100644 --- a/system/dbus/proc.go +++ b/system/dbus/proc.go @@ -9,6 +9,7 @@ import ( "syscall" "hakurei.app/container" + "hakurei.app/container/bits" "hakurei.app/container/seccomp" "hakurei.app/helper" "hakurei.app/ldd" @@ -63,7 +64,7 @@ func (p *Proxy) Start() error { p.final, true, argF, func(z *container.Container) { z.SeccompFlags |= seccomp.AllowMultiarch - z.SeccompPresets |= seccomp.PresetStrict + z.SeccompPresets |= bits.PresetStrict z.Hostname = "hakurei-dbus" if p.output != nil { z.Stdout, z.Stderr = p.output, p.output