diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-30 17:07:39 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-30 17:07:39 +0300 |
| commit | 07927004d6403dc88a8c24b2751d845ec1765376 (patch) | |
| tree | 2924ed25ee357f3d7ace955454e7edf5441f8dc3 | |
| parent | 231938bc6a768953cca1d0b77298f9199fb8bc61 (diff) | |
test(generate): lock in io_uring_register classification audit
Audit of io_uring_register(2) confirmed the existing tracing is correct:
KindFd with the io_uring fd captured at args[0], FamilyAIO (matching
io_uring_setup/io_uring_enter), and an UNCLASSIFIED ret_event exit. The
sys_enter_io_ KindNull prefix rule does NOT mis-catch it because
classifyNameOnly consults the exact nameOnlyKindsTable (KindFd) before the
prefix list.
Add two lock-in tests to guard these invariants:
- TestIoUringRegisterTablePrecedenceOverIoPrefix: the explicit KindFd table
entry wins over the sys_enter_io_ KindNull prefix rule (with an io_submit
sanity check that the prefix rule still yields KindNull for fd-less AIO
siblings).
- TestIoUringRegisterReturnUnclassified: the exit returns 0/small-positive,
never a byte count, so the io_uring group stays out of retClassifications.
No code, docs, or generated artifacts changed; mage generate produces no diff.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| -rw-r--r-- | internal/generate/classify_test.go | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go index b562689..7dddab7 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -2499,6 +2499,51 @@ func TestClassifyNameOnlyPrefixKinds(t *testing.T) { } } +// TestIoUringRegisterTablePrecedenceOverIoPrefix is an audit lock-in for +// io_uring_register(2): int io_uring_register(unsigned int fd, unsigned int +// opcode, void *arg, unsigned int nr_args). The io_uring fd lives at args[0], +// so the syscall MUST classify as KindFd (a single-fd fd_event) rather than +// falling through to the generic `sys_enter_io_` KindNull prefix rule shared +// with io_setup/io_destroy/io_submit/io_getevents. classifyNameOnly consults +// the exact nameOnlyKindsTable BEFORE the nameOnlyPrefixKinds list, so the +// explicit KindFd entry wins. This test would fail if that entry were removed +// (leaving the prefix rule to wrongly produce KindNull and drop the fd) or if +// table-vs-prefix lookup order were reversed. +func TestIoUringRegisterTablePrecedenceOverIoPrefix(t *testing.T) { + r, ok := classifyNameOnly("sys_enter_io_uring_register") + if !ok { + t.Fatal("classifyNameOnly(sys_enter_io_uring_register) did not match") + } + if r.Kind != KindFd { + t.Fatalf("io_uring_register kind = %d, want KindFd (fd at args[0]); the "+ + "sys_enter_io_ KindNull prefix rule must not win", r.Kind) + } + + // Sanity check the prefix rule itself still maps the io_* AIO siblings that + // have no fd argument to KindNull, so the precedence above is meaningful. + if pr, ok := classifyNameOnly("sys_enter_io_submit"); !ok || pr.Kind != KindNull { + t.Fatalf("sys_enter_io_submit kind = %d (ok=%v), want KindNull via prefix rule", pr.Kind, ok) + } +} + +// TestIoUringRegisterReturnUnclassified locks in that io_uring_register's exit +// is UNCLASSIFIED: on success it returns 0 or a small positive value (e.g. an +// fd or count specific to the opcode), never a byte-transfer count, so it must +// not appear in retClassifications as READ/WRITE/TRANSFER. Treating it as a +// byte count would corrupt throughput accounting. Its io_uring siblings +// (io_uring_setup/io_uring_enter) are likewise unclassified. +func TestIoUringRegisterReturnUnclassified(t *testing.T) { + for _, name := range []string{ + "sys_exit_io_uring_register", + "sys_exit_io_uring_enter", + "sys_exit_io_uring_setup", + } { + if got := ClassifyRet(name); got != Unclassified { + t.Errorf("ClassifyRet(%q) = %q, want %q", name, got, Unclassified) + } + } +} + func TestClassifyNameOnlyUnknown(t *testing.T) { if r, ok := classifyNameOnly("sys_enter_not_real"); ok { t.Fatalf("classifyNameOnly matched unknown syscall with kind %d", r.Kind) |
