From d2c3d1bfbd17aff2fe801105e73ff346f2e6bb65 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 12 Mar 2025 14:12:21 +0900 Subject: [PATCH] test/sandbox/mount: work around /run tmpfs nondeterminism The special case is ugly and does not work for all paths, but it is guaranteed to work in the test. Signed-off-by: Ophestra --- helper/seccomp/api.go | 3 +++ helper/seccomp/export.go | 2 +- .../{seccomp-export.c => seccomp-build.c} | 23 +++++++++++++------ .../{seccomp-export.h => seccomp-build.h} | 2 +- helper/seccomp/seccomp.go | 7 +++--- test/sandbox/assert.go | 7 ++++++ test/sandbox/mount.nix | 2 +- 7 files changed, 33 insertions(+), 13 deletions(-) rename helper/seccomp/{seccomp-export.c => seccomp-build.c} (96%) rename helper/seccomp/{seccomp-export.h => seccomp-build.h} (86%) diff --git a/helper/seccomp/api.go b/helper/seccomp/api.go index 2799fc9..697b09f 100644 --- a/helper/seccomp/api.go +++ b/helper/seccomp/api.go @@ -11,6 +11,9 @@ import ( // New returns an inactive Encoder instance. func New(opts SyscallOpts) *Encoder { return &Encoder{newExporter(opts)} } +// Load loads a filter into the kernel. +func Load(opts SyscallOpts) error { return buildFilter(-1, opts) } + /* An Encoder writes a BPF program to an output stream. diff --git a/helper/seccomp/export.go b/helper/seccomp/export.go index 9efee3b..9568423 100644 --- a/helper/seccomp/export.go +++ b/helper/seccomp/export.go @@ -28,7 +28,7 @@ func (e *exporter) prepare() error { ec := make(chan error, 1) go func(fd uintptr) { - ec <- exportFilter(fd, e.opts) + ec <- buildFilter(int(fd), e.opts) close(ec) _ = e.closeWrite() runtime.KeepAlive(e.w) diff --git a/helper/seccomp/seccomp-export.c b/helper/seccomp/seccomp-build.c similarity index 96% rename from helper/seccomp/seccomp-export.c rename to helper/seccomp/seccomp-build.c index 5a3a56b..827d3b8 100644 --- a/helper/seccomp/seccomp-export.c +++ b/helper/seccomp/seccomp-build.c @@ -2,7 +2,7 @@ #define _GNU_SOURCE // CLONE_NEWUSER #endif -#include "seccomp-export.h" +#include "seccomp-build.h" #include #include #include @@ -48,7 +48,7 @@ struct f_syscall_act { } \ } while (0) -int32_t f_export_bpf(int fd, uint32_t arch, uint32_t multiarch, f_syscall_opts opts) { +int32_t f_build_filter(int fd, uint32_t arch, uint32_t multiarch, f_syscall_opts opts) { int32_t res = 0; // refer to resErr for meaning int allow_multiarch = opts & F_MULTIARCH; int allowed_personality = PER_LINUX; @@ -285,11 +285,20 @@ int32_t f_export_bpf(int fd, uint32_t arch, uint32_t multiarch, f_syscall_opts o // Blocklist the rest seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_GE, last_allowed_family + 1)); - ret = seccomp_export_bpf(ctx, fd); - if (ret != 0) { - res = 6; - errno = -ret; - goto out; + if (fd < 0) { + ret = seccomp_load(ctx); + if (ret != 0) { + res = 7; + errno = -ret; + goto out; + } + } else { + ret = seccomp_export_bpf(ctx, fd); + if (ret != 0) { + res = 6; + errno = -ret; + goto out; + } } out: diff --git a/helper/seccomp/seccomp-export.h b/helper/seccomp/seccomp-build.h similarity index 86% rename from helper/seccomp/seccomp-export.h rename to helper/seccomp/seccomp-build.h index df158d9..0ae201d 100644 --- a/helper/seccomp/seccomp-export.h +++ b/helper/seccomp/seccomp-build.h @@ -20,4 +20,4 @@ typedef enum { } f_syscall_opts; extern void F_println(char *v); -int32_t f_export_bpf(int fd, uint32_t arch, uint32_t multiarch, f_syscall_opts opts); \ No newline at end of file +int32_t f_build_filter(int fd, uint32_t arch, uint32_t multiarch, f_syscall_opts opts); \ No newline at end of file diff --git a/helper/seccomp/seccomp.go b/helper/seccomp/seccomp.go index a8cf8bb..fc19247 100644 --- a/helper/seccomp/seccomp.go +++ b/helper/seccomp/seccomp.go @@ -3,7 +3,7 @@ package seccomp /* #cgo linux pkg-config: --static libseccomp -#include "seccomp-export.h" +#include "seccomp-build.h" */ import "C" import ( @@ -22,6 +22,7 @@ var resErr = [...]error{ 4: errors.New("internal libseccomp failure"), 5: errors.New("seccomp_rule_add failed"), 6: errors.New("seccomp_export_bpf failed"), + 7: errors.New("seccomp_load failed"), } type SyscallOpts = C.f_syscall_opts @@ -46,7 +47,7 @@ const ( FlagBluetooth SyscallOpts = C.F_BLUETOOTH ) -func exportFilter(fd uintptr, opts SyscallOpts) error { +func buildFilter(fd int, opts SyscallOpts) error { var ( arch C.uint32_t = 0 multiarch C.uint32_t = 0 @@ -70,7 +71,7 @@ func exportFilter(fd uintptr, opts SyscallOpts) error { opts |= flagVerbose } - res, err := C.f_export_bpf(C.int(fd), arch, multiarch, opts) + res, err := C.f_build_filter(C.int(fd), arch, multiarch, opts) if re := resErr[res]; re != nil { if err == nil { return re diff --git a/test/sandbox/assert.go b/test/sandbox/assert.go index 12323a0..89df333 100644 --- a/test/sandbox/assert.go +++ b/test/sandbox/assert.go @@ -5,6 +5,7 @@ import ( "io/fs" "log" "os" + "strings" ) var ( @@ -39,8 +40,14 @@ func MustAssertMounts(name, hostMountsFile, wantFile string) { for i := range want { if want[i].Opts == "host_passthrough" { + isRunBind := want[i].FSName == "tmpfs" && strings.HasPrefix(want[i].Dir, "/run/") for _, ent := range hostMounts { if want[i].FSName == ent.FSName { + // special case for /run bind mount + if isRunBind && ent.Dir != "/run" { + continue + } + want[i].Opts = ent.Opts goto out } diff --git a/test/sandbox/mount.nix b/test/sandbox/mount.nix index 3040791..b3a310b 100644 --- a/test/sandbox/mount.nix +++ b/test/sandbox/mount.nix @@ -51,7 +51,7 @@ let (ent "tmpfs" "/etc/passwd" "tmpfs" "ro,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) (ent "tmpfs" "/etc/group" "tmpfs" "ro,nosuid,nodev,relatime,uid=1000001,gid=1000001" 0 0) (ent "/dev/disk/by-label/nixos" "/run/user/65534/wayland-0" "ext4" "ro,nosuid,nodev,relatime" 0 0) - (ent "tmpfs" "/run/user/65534/pulse/native" "tmpfs" "ro,nosuid,nodev,relatime,size=98784k,nr_inodes=24696,mode=700,uid=1000,gid=100" 0 0) + (ent "tmpfs" "/run/user/65534/pulse/native" "tmpfs" "host_passthrough" 0 0) (ent "/dev/disk/by-label/nixos" "/run/user/65534/bus" "ext4" "ro,nosuid,nodev,relatime" 0 0) (ent "tmpfs" "/var/run/nscd" "tmpfs" "rw,nosuid,nodev,relatime,size=8k,mode=755,uid=1000001,gid=1000001" 0 0) (ent "overlay" "/.fortify/sbin/fortify" "overlay" "ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on" 0 0)