test/sandbox: check seccomp outcome
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Fpkg (push) Successful in 33s
Test / Fortify (push) Successful in 2m27s
Test / Data race detector (push) Successful in 3m15s
Test / Flake checks (push) Successful in 56s

This is as ugly as it is because it has to have CAP_SYS_ADMIN and not be in seccomp mode.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-03-28 02:24:27 +09:00
parent c13eb70d7d
commit ff3cfbb437
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
4 changed files with 71 additions and 1 deletions

View File

@ -40,6 +40,9 @@ in
# For D-Bus tests:
libnotify
mako
# For checking seccomp outcome:
testCases._testProgram
];
variables = {

View File

@ -7,10 +7,14 @@ in the public sandbox/vfs package. Files in this package are excluded by the bui
package sandbox
import (
"crypto/sha512"
"encoding/hex"
"encoding/json"
"errors"
"io/fs"
"log"
"os"
"syscall"
)
var (
@ -124,6 +128,33 @@ func (t *T) MustCheck(want *TestCase) {
}
}
func MustCheckFilter(pid int, want string) {
if err := ptraceAttach(pid); err != nil {
fatalf("cannot attach to process %d: %v", pid, err)
}
buf, err := getFilter[[8]byte](pid, 0)
if err0 := ptraceDetach(pid); err0 != nil {
printf("cannot detach from process %d: %v", pid, err0)
}
if err != nil {
if errors.Is(err, syscall.ENOENT) {
fatalf("seccomp filter not installed for process %d", pid)
}
fatalf("cannot get filter: %v", err)
}
h := sha512.New()
for _, b := range buf {
h.Write(b[:])
}
if got := hex.EncodeToString(h.Sum(nil)); got != want {
fatalf("[FAIL] %s", got)
} else {
printf("[ OK ] %s", got)
}
}
func mustDecode(wantFilePath string, v any) {
if f, err := os.Open(wantFilePath); err != nil {
fatalf("cannot open %q: %v", wantFilePath, err)

View File

@ -1,9 +1,39 @@
package main
import (
"log"
"os"
"strconv"
"strings"
"git.gensokyo.uk/security/fortify/test/sandbox"
)
func main() { (&sandbox.T{FS: os.DirFS("/")}).MustCheckFile(os.Args[1], "/tmp/sandbox-ok") }
func main() {
log.SetFlags(0)
log.SetPrefix("test: ")
if len(os.Args) < 2 {
log.Fatal("invalid argument")
}
switch os.Args[1] {
case "filter":
if len(os.Args) != 4 {
log.Fatal("invalid argument")
}
if pid, err := strconv.Atoi(strings.TrimSpace(os.Args[2])); err != nil {
log.Fatalf("%s", err)
} else if pid < 1 {
log.Fatalf("%d out of range", pid)
} else {
sandbox.MustCheckFilter(pid, os.Args[3])
return
}
default:
(&sandbox.T{FS: os.DirFS("/")}).MustCheckFile(os.Args[1], "/tmp/sandbox-ok")
return
}
}

View File

@ -99,6 +99,12 @@ print(denyOutputVerbose)
# Fail direct fsu call:
print(machine.fail("sudo -u alice -i fsu"))
# Check seccomp outcome:
swaymsg("exec fortify run cat")
pid = int(machine.wait_until_succeeds("pgrep -U 1000000 -x cat", timeout=5))
print(machine.succeed(f"fortify-test filter {pid} c698b081ff957afe17a6d94374537d37f2a63f6f9dd75da7546542407a9e32476ebda3312ba7785d7f618542bcfaf27ca27dcc2dddba852069d28bcfe8cad39a &>/dev/stdout", timeout=5))
machine.succeed(f"kill -TERM {pid}")
# Verify capabilities/securebits in user namespace:
print(machine.succeed("sudo -u alice -i fortify run capsh --print"))
print(machine.succeed("sudo -u alice -i fortify run capsh --has-no-new-privs"))