znippy unpack: a generated seccomp profile for the Heimdall benchmark
Heimdall is a defensive sandbox. This is the seccomp profile of znippy unpacking archives: decompress (the whole archive) and get (one member by path, Holger's random-access read). It was measured with heimdall-probe in learning mode and approved by the owner on 2026-11-01. It will be used in the benchmark "plain youki vs youki + profile vs a full Heimdall job". It is not compiled into nordisk-heimdall-profiles: the binary and its multi-GB corpus are not in the repository, so the drift check of scripts/seccomp-tests.sh does not run it.
- Program: znippy 0.10.0 (
26ede82, glibc, built in the heim-m0 image), expected atbin/znippy(not checked in). - Profile:
profiles/znippy-unpack/x86_64-glibc.{json,oci.json,rs}(generated, never edited), evidencex86_64-glibc.probe.json. 36 rules from 41 distinct call tuples, unknown call = kill the process; 0 near-miss, 0 W|X, 0 bare allows; no socket, no exec, no mount.sha256:32dd9f2825dd2a68d7c4e0187dcd30736b988c3f35e02219a5e16be6f437a05a. - Workload:
profiles/znippy-unpack/workload.toml(11 runs, each twice). - Corpus:
make-corpus.sh(real data on oden;corpus/SHA256SUMSpins the archives): small (11 MB, 13 real packages), crates (1.1 GB, 6359 real.cratefiles, rust handler), sources (1.2 GB archive of 5.04 GB, 236089 real files), corrupt (43 bytes flipped one third in), truncated (cut at 60 %). measure.sh: probe + gen (privileged rootless podman, heim-m0; the runs' output undertmp/on /home, several GB).enforce.py: every run in a rootless podman container whose filter is the profile plus crun's ownclose_rangeandexecveafter loading the filter: 11/11 end with their expected exit, never SIGSYS, andznippy compress(outside the profile:getdents64) is killed by SIGSYS (exit 159). 12/12 on oden, kernel 7.0, 2026-11-01.
What differs between the runs: nothing is seen only on an error path. The whole-archive unpacks (and the corrupt one) add clone (worker threads), mkdir, chmod, pwrite64, madvise, exit, mmap PROT_NONE and mprotect RW; mremap is seen only in get from the 5 GB archive; the selective unpack and the two gets start no worker threads (no futex). gen merged openat to "no bit outside O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC" and clone to "no flag outside the observed union"; mmap/mprotect prot stay exact; ioctl only TCGETS.
znippy issues seen while measuring (not fixed here): a corrupt archive panics (exit 101) and leaves every member, the corrupt one too, in the output directory; a truncated archive panics with "v0.6 archives are not supported"; a missing member panics instead of a clean error.