| Age | Commit message (Collapse) | Author |
|
After p10 suppressed the sys_exit_exit/sys_exit_exit_group handlers, the
enter handlers for exit/exit_group still called ior_on_syscall_enter,
which writes a per-tid entry into syscall_enter_state_map. With the exit
handler gone, nothing ever bpf_map_delete_elem'd that entry, so stale
per-tid state accumulated in the bounded (32768) map on hosts churning
many distinct tids and could starve legitimate inserts.
Add ior_on_noreturn_syscall_enter in internal/c/filter.c: it only makes
the sampling decision (ior_should_emit_trace) and deliberately does NOT
record enter-state. The code generator now emits this hook for noreturn
enter handlers (detected via isNoreturnSyscall(syscallName(name))) so the
enter null_event is still emitted while the dead, unreclaimable map write
is skipped. Regenerated generated_tracepoints.c accordingly.
Extend TestGenerateExitNoreturnHandlers with a negative assertion (no
ior_on_syscall_enter for noreturn) and add
TestGenerateReturningSyscallEnterRecordsState as a positive contrast.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
classify.go has KindNull entries for sys_enter_seteuid/sys_enter_setegid,
but family.go's FamilyProcess credential cluster omitted them, so
ClassifySyscallFamily returned Misc — inconsistent with their siblings
setuid/setgid/setresuid/setreuid/setfsuid. Add seteuid/setegid to the
FamilyProcess group with a comment noting they are latent: current kernels
expose no dedicated seteuid/setegid tracepoints (glibc wraps them over
setreuid/setresuid), so they never reach the generated tracepoint map or
docs/syscall-tracing-plan.md. mage generate confirmed idempotent with no
diff, so docs/drift test are untouched. Lock-in unit tests assert Process
for seteuid/setegid (enter+exit) by name directly, since no tracepoint exists.
Refs task 620.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
get_mempolicy(2) retrieves the NUMA memory policy for a thread or
address range and is logically a Memory-family syscall, sharing
FamilyMemory with its NUMA siblings set_mempolicy, set_mempolicy_home_node,
mbind, migrate_pages, and move_pages. It was misclassified FamilySecurity
(a copy/paste/alphabetical-ordering slip alongside the security modules).
Move it to the Memory group in internal/generate/family.go, update the
Memory and Security lists in docs/syscall-tracing-plan.md (keeps the
docs_drift_test green), and regenerate artifacts (traceId2Family 735/734
and syscallFamilies[get_mempolicy] flip Security->Memory; C unchanged,
mage generate idempotent). Add enter+exit family lock-in assertions for
get_mempolicy and set_mempolicy alongside the NUMA siblings so the whole
cluster is pinned.
Task 120.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
TestCleanupLeakedWorkloadTempDirCaughtByAssertion was order/concurrency
dependent: passed in isolation but its detection scanned the shared system
temp root (os.TempDir) for ANY "ioworkload-" directory via a before/after
diff. Real ioworkload scenario workloads legitimately create
ioworkload-<scenario>-* dirs in that same root while they run (in parallel
under `mage integrationTest`), so this test both falsely attributed them as
leaks and, worse, RemoveAll'd them out from under the still-running tests.
Fix: scope both detection and cleanup to a prefix unique to this single test
invocation (PID + sanitized t.Name()) via listWorkloadTempDirsWithPrefix and
newLeakedDirs. Other tests' temp dirs can no longer be observed or deleted.
Also fixed a latent detection bug: the intentional-leak workload script
hard-coded /tmp instead of os.TempDir(), so detection silently failed whenever
$TMPDIR differed from /tmp. The mktemp template now uses os.TempDir().
Removed the dead assertNoNewWorkloadTempDirs helper (defined, never called).
Verified: mage build OK; mage test green across repeated runs; mage generate
produces no diff; gofmt clean. A stress run with decoy ioworkload-<scenario>-*
dirs confirms they survive untouched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of times(2) (clock_t times(struct tms *buf)) confirmed its
classification is correct and consistent with its time/clock siblings:
- sys_enter_times: KindNull (single userspace output struct tms *buf;
no fd or pathname argument).
- sys_exit_times: ret_event UNCLASSIFIED — times() returns a clock_t
tick count (or (clock_t)-1 on error), which is a tick tally, not a
transferred byte count.
- family: FamilyTime, alongside gettimeofday/clock_gettime, and NOT
FamilyProcess where getrusage lives.
No misclassification was found; docs/syscall-tracing-plan.md already
lists times under the Time family and the null kind. Add lock-in tests
so any stray reclassification trips a unit test:
- family_test.go: assert sys_enter/exit_times == FamilyTime.
- retclassify_test.go: assert sys_exit_times stays UNCLASSIFIED.
KindNull is already covered by TestClassifyM7NameOnlyKinds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of setuid(2) confirmed correct tracing classification:
- KindNull (single uid_t arg, never an fd or path)
- FamilyProcess (credential-setting, consistent with siblings)
- Unclassified exit ret (int 0/-1 status, not a byte count)
Add lock-in tests asserting the setuid enter (KindNull, no pathname
capture) and exit (KindRet, UNCLASSIFIED) classification, plus a
family assertion covering the credential-setting cluster
(setuid/setresuid/setreuid/setfsuid, the gid analogues, and the
getuid/geteuid/... readers).
Discovered out of scope: family.go omits seteuid/setegid from the
FamilyProcess list (they fall through to Misc), unlike their siblings.
These have no dedicated kernel tracepoints today, so it is latent;
tracked as follow-up task 620.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of mknod(2) found the tracing implementation already correct:
sys_enter_mknod captures the real pathname from args[0] (no dirfd),
while the sibling sys_enter_mknodat captures it from args[1] (after
dirfd). Both are FamilyFS path_events; both exits are ret_event
UNCLASSIFIED (int 0/-1). No code or doc changes were needed.
Add lock-in tests guarding this behavior against regressions:
- TestGenerateMknodMknodatHandlers asserts the generated BPF C reads
the path from args[0] for mknod and args[1] for mknodat.
- FormatMknodat/FormatExitMknodat testdata mirroring the real
tracepoint layout (dfd pushes filename to args[1]).
- mknodat rows added to the classify kind (KindPathname) and family
(FamilyFS) test tables, matching the existing mknod coverage.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of migrate_pages(2) confirmed its tracing classification matches
the man page and its NUMA siblings:
- KindNull (null_event): args are pid (a pid, NOT an fd), maxnode, and
two userspace bitmask pointers; the BPF handler emits a null_event and
never reads args[0] as an fd.
- FamilyMemory: consistent with set_mempolicy/mbind/move_pages/
set_mempolicy_home_node (the lone get_mempolicy->Security inconsistency
is tracked separately and out of scope here).
- exit UNCLASSIFIED (ret_event): the return is the count of pages that
could NOT be moved (>=0) or -1, a page tally rather than a transferred
byte count.
Add explicit lock-in assertions for migrate_pages and its sibling
move_pages to TestClassifyRetUnclassified so a future stray
read/write/transfer reclassification trips the test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of keyctl(2), add_key(2), request_key(2) confirmed the existing
tracing is correct: all three are KindKeyctl (operation + generic numeric
args captured via keyctl_event, no fd/path probe), live in FamilySecurity
alongside their *_key/landlock_*/lsm_*/seccomp siblings, and return an
operation-dependent value or -1 that is not a byte transfer (UNCLASSIFIED).
Add TestClassifyKeyctlAudit as a lock-in regression test, mirroring prior
audits: it asserts the Security family on both enter and exit names, the
UNCLASSIFIED return classification, and that add_key's const char *
type/description arguments are key metadata that must not trip the generic
pathname/open heuristics (PathnameField stays empty, kind stays KindKeyctl).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of dup2(2) found the tracing implementation already correct and
consistent with its dup/dup3 siblings: dup2 is KindFd (a plain fd_event),
the enter handler captures ev->fd from args[0] (oldfd) per the KindFd
convention, it is in the FS family, and its exit returns the new fd
(newfd/-1) as a plain UNCLASSIFIED ret_event (never a byte-count
transfer). Unlike dup3 it carries no flags and clears O_CLOEXEC on the
duplicate, which the eventloop registerDup path already honors.
No discrepancies were found, so add a lock-in test (matching prior
audits) that asserts the generated BPF C for dup2 captures fd from
args[0] (not args[1]/newfd), emits an fd_event (not a dup3_event), wires
no flags, and classifies the exit UNCLASSIFIED. Adds FormatExitDup2
testdata to drive the exit handler assertions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of get_robust_list(2)/set_robust_list(2) found the existing
classification already correct and consistent across classify.go,
family.go, the generated C handlers, and docs/syscall-tracing-plan.md:
- enter is KindNull: args[0] of get_robust_list is a PID, not an fd,
and head_ptr/len_ptr are userspace output pointers (no fd/path), so
the pid must not be picked up as a file descriptor.
- exit is ret_event UNCLASSIFIED: both return 0/-1 with no byte count.
- family is Misc, grouped with the per-thread sibling rseq rather than
promoted to IPC like the futex_* shared-memory primitives.
Add TestClassifyGetRobustListPidNotFd pinning these invariants (Kind,
Family, Ret) plus a futex_* IPC contrast case, mirroring the prior
sched_getattr/recvmsg audit lock-in tests. No behavior change.
The IPC-vs-Misc family question for the robust-list pair is tracked as
a separate follow-up task, not changed here (no clear correctness case).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of access(2) found the tracing implementation already correct:
FS family, KindPathname capturing the real path, and an UNCLASSIFIED
int 0/-1 ret_event on exit. access(2) captures its path from args[0]
(no dirfd), while siblings faccessat(2)/faccessat2(2) capture from
args[1] (dfd precedes the path). mage generate produces no diff and the
docs/integration coverage already match.
Add unit lock-in tests mirroring prior syscall audits:
- FormatAccess/FormatFaccessat tracepoint fixtures (real kernel formats).
- classify tests asserting both classify as KindPathname/"filename".
- family_test cluster asserting access/faccessat/faccessat2 stay FamilyFS.
- codegen test proving access reads ctx->args[0] while faccessat reads
ctx->args[1], guarding against a wrong-arg or dropped-path regression.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of bare sync(2) per man 2 sync: void sync(void) takes no args and
returns no value. Confirmed it is correctly classified KindNull in
FamilyFS, its ret is UNCLASSIFIED, and — unlike noreturn exit/exit_group —
its exit handler IS emitted because sync does return (void != noreturn).
Docs and generated maps already match; no code or doc changes needed.
Add lock-in tests:
- TestGenerateSyncHandler: enter null_event with no arg capture (sync has
no args at all), live exit handler emitted, ret recorded UNCLASSIFIED.
- TestClassifyRetSyncUnclassified: meaningless void ret stays UNCLASSIFIED.
- TestSyncIsNotNoreturn: guards sync from the noreturn suppression list.
- Add sync (FamilyFS) to the family/exit-handler table test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of wait4(2): pid_t wait4(pid_t pid, int *wstatus, int options,
struct rusage *rusage) waits for a child process to change state and
optionally retrieves its resource usage. None of the arguments is an fd
or a filesystem path: args[0] (pid) is a process/group selector -- a pid,
NOT a file descriptor; args[1] (wstatus) and args[3] (rusage) are
userspace output pointers; args[2] (options) is an int flag set. The
return value is a pid_t (child pid, 0 for WNOHANG, or -1) -- never a byte
count. The existing classification (KindProc -> null_event, FamilyProcess,
ret UNCLASSIFIED) and the generated null_event enter handler (captures no
args) are correct, matching siblings waitid/clone/fork/vfork, and
docs/syscall-tracing-plan.md plus the drift tests are in sync.
Add a dedicated lock-in test, modeled on the clone3 audit, that asserts
the wait* siblings classify as KindProc, the family is Process, the
generated enter handler emits a null_event capturing none of the args
(so the pid at args[0] is never misclassified as an fd), and the
pid/0/-1 return stays UNCLASSIFIED rather than a byte-count transfer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
recvmsg(2) returns the number of bytes received, so its exit must be
READ_CLASSIFIED (bytes counted as read), matching recvfrom/recv/read/readv.
Audit confirmed the implementation is already correct: enter=KindFd off
the first 'fd' field (sockfd at args[0]), family=Network, exit=
READ_CLASSIFIED. Add a dedicated lock-in test mirroring the prior sendmsg
audit, with contrast cases guarding the easy mistakes: sendmsg is the
write-side sibling (WRITE_CLASSIFIED) and recvmmsg is the batch variant
whose scalar return is a message count, deferred to UNCLASSIFIED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of remap_file_pages(2): int remap_file_pages(void *addr,
size_t size, int prot, size_t pgoff, int flags). The implementation
was already correct (KindMem, FamilyMemory, addr=args[0],
length=args[1], length2=pgoff=args[3], flags=args[4]), but the
lock-in test was thinner than its madvise/mincore/munlock siblings.
Strengthen TestGenerateMemHandlerRemapFilePages to:
- negative-assert flags is never read from args[2] (prot, always 0)
or args[0] (addr), guarding the prot/flags index hazard
- verify the exit handler captures the int 0/-1 status generically as
UNCLASSIFIED, like every other KindMem exit
- document the wiring and the prot-vs-flags pitfall in the comment
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of munlock(2): int munlock(const void addr[.size], size_t size).
Verified the existing implementation is correct and consistent with its
mlock/mlock2 siblings:
- KindMem (classify.go) with addr=args[0], length=args[1]
- length2=0 and flags=0 (munlock has no flags, unlike mlock2's
MLOCK_ONFAULT at args[2]; distinct from munlockall which is KindNull)
- FamilyMemory (family.go)
- exit UNCLASSIFIED (returns int 0/-1, not a byte count)
- docs/syscall-tracing-plan.md already lists munlock under Memory + mem
No code or doc changes were needed; mage generate produces no diff.
Added a dedicated TestGenerateMemHandlerMunlock lock-in test mirroring
the madvise/mincore guards, asserting the correct arg mapping and the
absence of any flags/length2 wiring so a future copy of the mlock2
handler cannot silently surface a nonexistent args[2] as flags.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of the ppoll syscall confirmed the tracing implementation is
correct: ppoll(struct pollfd *fds, nfds_t nfds,
const struct timespec *tmo_p, const sigset_t *sigmask) is classified as
KindPoll (poll_event, sibling of poll/select/pselect6) in FamilyPolling,
with an UNCLASSIFIED ret_event exit. The enter handler captures nfds from
args[1] and the timeout from the args[2] timespec, and correctly never
reads args[0] (a pointer to an ARRAY of pollfd structs) as a file
descriptor.
Add a dedicated codegen lock-in test mirroring the poll/pselect6 tests,
including negative assertions that args[0] is not captured as an fd and
that no byte-transfer field is emitted (the return value is a ready-count
>=0 or -1, not a byte count). Introduce a requireNotContains helper for
these negative checks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of rt_tgsigqueueinfo(2): int rt_tgsigqueueinfo(pid_t tgid, pid_t
tid, int sig, siginfo_t *info) queues a signal plus data to a thread in
a thread group. Args are pids (tgid/tid), a signal number, and a
userspace siginfo_t pointer -- no fds or filesystem paths. The existing
classification (KindNull, FamilySignals, ret UNCLASSIFIED) and the
generated null_event enter handler (captures no args) are correct, and
docs/syscall-tracing-plan.md plus the drift tests are in sync.
Add dedicated lock-in tests, modeled on the rt_sigpending audit, that
assert the generated handler emits a null_event capturing none of the
args (so tgid/tid are never misclassified as fds) and that the int
0/-1 return stays UNCLASSIFIED rather than a byte-count transfer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of ioprio_set found a family inconsistency. ioprio_set(which, who,
ioprio) and ioprio_get(which, who) query/set the I/O scheduling class and
priority of a process, process group, or user. They are the direct
I/O-priority analogues of getpriority/setpriority (the CPU nice value) and
share the identical which/who selector signature, yet were falling through to
FamilyMisc while getpriority/setpriority are FamilyProcess.
Reclassify both ioprio syscalls to FamilyProcess for consistency with their
priority siblings, update docs/syscall-tracing-plan.md, and regenerate the
tracepoint/type artifacts (mage generate is idempotent).
Argument capture is unchanged and confirmed correct: the args are all ints
(which/who/ioprio), none named fd/path, so ClassifyFormat returns KindNone and
the generator promotes the enter format to KindNull (null_event). In
particular the 'who' argument (a pid/pgid/uid, never an fd) is not
misclassified as KindFd. The exit is a ret_event (UNCLASSIFIED, int 0/-1).
Add lock-in tests:
- TestClassifyIoprioNullKind asserts KindNone/KindNull using the real kernel
tracepoint fields, proving 'who' is not captured as an fd.
- Family assertions for the ioprio pair alongside getpriority/setpriority so a
stray reclassification of any of them trips the test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of clone3(2): long clone3(struct clone_args *cl_args, size_t size).
Neither arg is an fd or filesystem path (cl_args is a userspace control
block, size is its byte length), and the return value is a pid_t (child
PID in the parent, 0 in the child, -1 on error) — not a byte count.
clone3 was already correctly classified as KindProc in FamilyProcess with
an UNCLASSIFIED exit, identical to its clone/fork/vfork siblings; the
generated BPF handlers emit a null_event on enter (no arg capture) and a
ret_event tagged UNCLASSIFIED on exit. No code, classification, or doc
changes were needed.
Add TestGenerateClone3Handler to pin this down against future drift:
the name-only table maps all four siblings to KindProc even when fed the
real (struct clone_args *, size_t) args, the family is Process, the ret
is UNCLASSIFIED, the enter handler captures no ctx->args[], and the exit
handler reports ret_type=UNCLASSIFIED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of fallocate(2) found the tracing correct and consistent with its
fd-based siblings, so add lock-in tests rather than fixing anything:
- fallocate(int fd, int mode, off_t offset, off_t len) returns int 0/-1
(a status code, NOT a transferred byte count). Its exit must stay a
plain ret_event with ret_type UNCLASSIFIED so it is never mistaken for
a READ/WRITE/TRANSFER byte count.
- The enter tracepoint carries a leading fd field (args[0]); only fd is
captured into a fd_event (KindFd), matching fadvise64/ftruncate/
sync_file_range which likewise drop their trailing offset/len/advice
args.
- fallocate belongs to FamilyFS alongside fadvise64/ftruncate/
sync_file_range.
TestClassifyFallocateEnterFd and TestClassifyExitFallocateUnclassifiedRet
assert the per-syscall behavior; TestClassifySyscallFamily now also
covers fallocate/fadvise64/ftruncate so a stray reclassification trips a
test. No classification logic or generated artifacts changed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of sigaltstack(2) confirmed the existing tracing is correct:
both args are userspace stack_t pointers (new + old alternate signal
stack), neither an fd nor a path, and it returns 0/-1. It is already
classified KindNull in FamilySignals across classify.go, family.go,
docs/syscall-tracing-plan.md, and the generated C/Go artifacts, matching
the rt_sig*/kill/pause sibling group. No discrepancies were found.
Add lock-in tests mirroring the prior rt_sigpending audit:
- TestGenerateSigaltstackHandler asserts the enter handler emits a
null_event capturing no args and the exit handler reports ctx->ret
as UNCLASSIFIED.
- TestClassifyRetSigaltstackUnclassified asserts the 0/-1 status is
never tagged as a byte count.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
setsid(2) takes no arguments and returns the new session ID (a pid_t)
on success or (pid_t)-1 on error. Audit confirms it is correctly
classified as KindNull (null_event enter handler, captures nothing),
FamilyProcess (alongside its session/process-group siblings
getsid/setpgid/getpgid/getpgrp and the pid-returning getpid/getppid),
and its exit ret_type stays UNCLASSIFIED so the session-id return is
never mistaken for a transferred byte count.
No codegen or doc changes were required (mage generate yields no diff).
Add lock-in assertions so a stray reclassification trips a test:
- family_test.go: setsid + session/pgrp/pid siblings -> FamilyProcess
- retclassify_test.go: setsid + pid-returning siblings -> Unclassified
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of pwritev2(2) confirmed its tracing is already correct: enter is
KindFd (fd at args[0]), return is WRITE_CLASSIFIED so the byte count is
counted as written like its pwritev/writev/write/pwrite64 siblings, and
family is FS. Add a dedicated lock-in test pinning kind, family, and the
WRITE return classification, with the read-side preadv2 as a contrast and
the whole p/readv/writev family asserted together to guard against a
stray off-by-one reclassification.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of init_module (man 2 init_module) confirmed the implementation is
correct: init_module(void *module_image, unsigned long len, const char
*param_values) is classified KindModule (null_event), capturing neither
an fd nor a path — param_values is a module-parameter string, not a
filesystem path. finit_module(int fd, ...) is classified KindFd via
field-based matching and captures fd = args[0]. Both syscalls live in the
Security family and match docs/syscall-tracing-plan.md.
No explicit finit_module test or init_module-vs-finit_module distinction
test existed, so add lock-in coverage:
- testdata.go: real-layout Format constants for (f)init_module enter/exit.
- classify_test.go: assert init_module=KindModule with no PathnameField
and finit_module=KindFd.
- codegen_test.go: assert generated BPF C for init_module captures no fd
and no filename/path, while finit_module captures fd = args[0].
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of syncfs(2) confirmed the existing tracing is correct: single fd
arg (fd=args[0], KindFd), FamilyFS like its fsync/fdatasync/
sync_file_range siblings, and an int 0/-1 return that stays Unclassified
(plain ret_event). No code or generated artifacts changed.
Add lock-in tests so a stray reclassification trips CI:
- TestClassifySyncFamilyFdSyscallsByName: enter -> KindFd for the
fsync/fdatasync/syncfs/sync_file_range group.
- TestClassifyExitSyncfs: exit -> KindRet.
- sync-family FamilyFS assertions in TestClassifySyncallFamily.
- syncfs added to the ret-UNCLASSIFIED list.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of sysinfo(2): int sysinfo(struct sysinfo *info) returns overall
system statistics into a single userspace output pointer (not an fd or
path) and returns 0/-1. The existing classification was already correct
(KindNull, FamilyMisc, UNCLASSIFIED return) and docs/generated artifacts
are consistent; no behavior change was needed.
Add dedicated lock-in regression tests mirroring the rt_sigpending audit:
- TestGenerateSysinfoHandler: enter emits a null_event and captures no
args; exit emits a ret_event with ctx->ret tagged UNCLASSIFIED.
- TestClassifyRetSysinfoUnclassified: the 0/-1 status is never a byte
count.
- family_test.go: assert sysinfo/newuname/sysfs stay in FamilyMisc, with
a note that ustat is FamilyFS (matched by the 'stat' name marker) and
is intentionally not grouped here.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
utime(2) and utimes(2) change a file's access/modification times by a real
filesystem path (filename at args[0]). The path was already captured
(KindPathname), but both syscalls fell through to FamilyMisc instead of
joining their siblings utimensat/futimesat in FamilyFS. Add them to
fsSyscalls and regenerate; the only generated change is trace IDs
1034-1037 flipping FamilyMisc -> FamilyFS.
Lock-in coverage:
- family_test.go asserts utime/utimes/utimensat/futimesat are all FamilyFS.
- classify_test.go + FormatUtime fixture assert utime is KindPathname with
PathnameField "filename" (path captured even though it is a char* string,
unlike domain/host name args).
- New ioworkload scenarios utime-basic/utimes/enoent and integration tests
TestUtimeBasic/Utimes/Enoent verify the path is captured at runtime,
including on the ENOENT error path.
Docs updated: moved utime/utimes from Misc to FS in
docs/syscall-tracing-plan.md to keep the drift tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of rt_sigpending(2) confirmed the existing classification is correct
and added lock-in coverage:
- KindNull: int rt_sigpending(sigset_t *set, size_t sigsetsize). args[0] is
a userspace output pointer to a sigset_t (a signal mask, not a traced I/O
resource) and args[1] is the byte size; neither is an fd or path. The enter
handler emits a null_event and must not capture either arg. Added
TestGenerateRtSigpendingHandler with a negative assertion guarding against
any ctx->args[] capture in the enter handler.
- Exit ret_type=UNCLASSIFIED: rt_sigpending returns 0/-1, a status code, not
a byte count, so it must never be tagged READ/WRITE/TRANSFER. Added an exit
handler assertion plus TestClassifyRetRtSigpendingUnclassified.
- FamilySignals: shares the family with the whole rt_sig* group plus
kill/pause/sigaltstack/tkill/tgkill. Added lock-in family cases asserting
every rt_sig* sibling alongside rt_sigpending in TestClassifySyscallFamily.
No classification/codegen/doc changes were required; mage generate produces
no diff. Full ./internal/... passes (only the known pre-existing flake
TestCleanupLeakedWorkloadTempDirCaughtByAssertion fails, unrelated).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of sendmsg(2) found the tracing implementation already correct:
enter is an fd_event with fd=args[0] (the kernel tracepoint first field
is 'int fd'), family is Network, and the exit is WRITE_CLASSIFIED so the
bytes-sent return value is counted as written, consistent with the
send/sendto/write siblings and distinct from recvmsg (read side) and the
deferred sendmmsg batch variant.
Add TestClassifySendmsgWriteByteCount as a lock-in regression test
pinning KindFd + FamilyNetwork + WRITE_CLASSIFIED, with recvmsg and
sendmmsg contrast cases to guard against read/write and batch
misclassification.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of sched_getattr confirmed it is correctly classified as
FamilySched + KindNull, consistent with its siblings (sched_setattr,
sched_getparam, sched_getscheduler). The syscall's first argument is a
pid_t (a process/thread id), not a file descriptor, and the kernel
tracepoint field is named "pid" rather than "fd", so the fd heuristic
never applies; the name-only classification table also short-circuits
before any field inspection.
Add TestClassifySchedGetattrPidNotFd as a regression guard that pins
KindNull and FamilySched using the real kernel field layout, explicitly
asserting the pid arg is never treated as an fd, plus sibling
consistency. No behavior or generated-artifact changes (mage generate
produces no diff).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of the set_mempolicy_home_node(2) NUMA syscall (task mz) confirmed
it is correctly classified: KindNull (name-only, ior does not capture the
addr/len range), FamilyMemory (matching its siblings set_mempolicy, mbind,
migrate_pages, move_pages and docs/syscall-tracing-plan.md), and an
Unclassified return (0/-1 with no byte count).
Add lock-in tests so the classification cannot silently drift:
- family_test.go asserts FamilyMemory for set_mempolicy_home_node and its
NUMA siblings, with a note that get_mempolicy is the lone sibling still
on FamilySecurity (tracked separately, out of scope here).
- retclassify_test.go asserts the exit stays UNCLASSIFIED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
The Linux Security Module introspection syscalls lsm_list_modules,
lsm_get_self_attr and lsm_set_self_attr (Linux 6.8+) were classified as
FamilyMisc while every sibling LSM/security syscall (landlock_*, keyctl,
add_key, request_key, seccomp) is FamilySecurity. This audited
inconsistency is fixed by adding the three lsm_* entries to the
syscallFamilies map; their kind stays KindNull (args are userspace
pointers + flags, no fd/path) and the exit remains a ret_event.
Docs (syscall-tracing-plan.md) updated accordingly, generated artifacts
regenerated via mage generate, and lock-in family assertions added to
TestClassifySyscallPairEmitsAllFamilies.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of process_madvise(2) confirmed the existing classification is correct
and added lock-in coverage:
- KindFd with fd=args[0]: the first arg is a pidfd (a PID file descriptor
selecting the target process), not an address, so it must NOT be treated
like madvise(2) (KindMem, addr=args[0]). Extended the enter-handler test
with a negative assertion guarding against the KindMem addr wiring.
- Exit ret_type=UNCLASSIFIED: process_madvise returns the number of bytes
advised, but that is advisory accounting, not real I/O data movement, so it
stays UNCLASSIFIED like madvise(2). Added an exit-handler assertion plus
TestClassifyRetProcessMadviseUnclassified.
- FamilyMemory: shares the family with madvise/process_mrelease/process_vm_*
siblings rather than FamilyIPC (pidfd_* lifecycle). Added family lock-in
cases in family_test.go.
No classification/codegen changes were required; mage generate produces no
diff. Full ./internal/... passes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of sync_file_range(2) confirmed the existing tracing is correct:
classified as KindFd (FS family) with fd from args[0] per the kernel
tracepoint format, and an UNCLASSIFIED ret (int 0/-1, no userspace
bytes transferred) - identical to siblings fsync/fdatasync/fadvise64/
readahead. The byte range/offset/flags are intentionally not captured
for fd-kind syscalls.
Add SyncFileRangeFailureTest to lock in the EBADF path: the enter
fd_event still pairs with the exit ret_event carrying ret=-9, and the
eventloop synthesizes a placeholder FdFile (unknown name, O_NONE flags)
for the never-opened bogus fd rather than dropping file metadata.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of setdomainname(2): its first arg is a const char *name, but that
name is the NIS/YP domain-name string, not a filesystem path. The name-only
classification table pins it to KindNull, which short-circuits before the
field-based path heuristic that would otherwise treat a const char *name arg
as KindPathname. Classification, family (Misc), docs, and existing tests all
already matched; this adds a dedicated lock-in test asserting KindNull, an
empty PathnameField, and kind+family parity with the sibling sethostname.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of the rseq(2) syscall confirmed the existing classification is
correct and consistent with its siblings:
- KindNull: the rseq argument is a userspace struct pointer (not an fd or
filesystem path), and args[2] flags are intentionally not captured, in
line with the KindNull convention shared with set_robust_list and
membarrier. (Already covered by classify_test.go.)
- FamilyMisc: rseq is not in the explicit family table and falls through
to Misc, grouped with its closest per-thread sibling
set_robust_list/get_robust_list (also Misc).
- Return value is int 0/-1 with no byte count, so its exit stays
UNCLASSIFIED.
Add lock-in tests for the family and return-value classification (kind
was already covered) so a future drift in either is caught.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of sched_get_priority_min(2): the syscall takes a single int policy
scheduling-policy enum (not an fd or path) and returns the minimum static
priority for that policy, or -1 on error. ior classifies it as KindNull in
FamilySched, consistent with every sibling sched_* syscall and the man page.
Add TestGenerateSchedGetPriorityMinHandler (covering the identical sibling
sched_get_priority_max too) to lock in that the enter handler emits a
null_event without capturing the int policy arg, that the family is
FamilySched, and that a live exit handler emitting EXIT_RET_EVENT is
generated since this syscall returns (unlike the noreturn exit syscalls).
No classification change was required, so generated artifacts are unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of mincore(2) confirmed the existing tracing is correct: KindMem +
FamilyMemory, with addr=args[0], length=args[1], and both flags and length2
held at zero. args[2] is the userspace 'vec' output pointer, not a flags
value, so it is correctly NOT wired into ev->flags.
Add TestGenerateMemHandlerMincore to lock in this wiring and explicitly guard
against the historical mistake of mapping args[2] onto ev->flags the way
flags-bearing siblings (madvise/mlock2/mseal) do.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of madvise(2) (int madvise(void *addr, size_t length, int advice))
confirmed the existing classification and BPF wiring are correct: KindMem /
FamilyMemory, addr=args[0], length=args[1], advice (flags-like) at args[2],
length2=0, and the int return captured generically as UNCLASSIFIED. This is
correctly distinct from process_madvise(2) (KindFd, pidfd at args[0]).
Unlike its KindMem siblings (mprotect, mlock2, brk, map_shadow_stack), madvise
lacked a dedicated handler-field lock-in test. Add TestGenerateMemHandlerMadvise
with positive field assertions plus negative guards: advice must come from
args[2] (not args[0]/addr), length2 must stay zero (no second region), and the
exit must return ctx->ret as UNCLASSIFIED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of the x86 CET map_shadow_stack syscall (Linux 6.6+,
void *map_shadow_stack(unsigned long addr, unsigned long size,
unsigned int flags)) confirmed the existing tracing is correct:
KindMem / FamilyMemory classification, memFieldSpec wires
addr=args[0], length=args[1] (size), flags=args[2], length2=0, and
the return (mapped address or -errno) is captured generically as
ev->ret like every other KindMem exit. Docs and classify tests
already match.
The only gap was the lack of a codegen lock-in test for the BPF
handler field wiring, which mlock2/remap_file_pages/mprotect/brk all
have. Add TestGenerateMemHandlerMapShadowStack to guard against
future drift.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Commit 49b1641 reclassified the futex syscalls (futex, futex_requeue,
futex_wait, futex_waitv, futex_wake) from FamilyMisc to FamilyIPC in the
generated family map but left docs/syscall-tracing-plan.md listing them
under Misc. This drift broke
TestSyscallTracingPlanFamiliesStayInSyncWithGeneratedMap.
Move the 5 futex syscalls into the documented IPC list (alphabetical
order) and drop the stale Misc entries so the documented family
membership matches the generated map again. The IPC rationale is already
recorded in internal/generate/family.go (futexes are shared-memory
synchronization/IPC primitives alongside the System V semaphores).
Fixes regression tracked by task t10.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
exit and exit_group never return to userspace, so their sys_exit
tracepoints can never fire. The generator previously emitted matching
EXIT_RET_EVENT handlers anyway, producing dead code in the generated BPF
program. classifySyscall now skips exit-handler emission for noreturn
syscalls via isNoreturnSyscall, and the regenerated artifacts drop the
sys_exit_exit / sys_exit_exit_group handlers (enter handlers are kept).
Tests updated to match the new reality:
- TestGenerateExitNoreturnHandlers asserts no exit handler is emitted.
- TestClassifySyscallPairEmitsAllFamilies exempts noreturn syscalls from
the exit-handler-required assertion while staying strict for all others.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of gettimeofday(2) confirmed the existing implementation is
correct: it is classified KindNull (userspace timeval/timezone pointer
args, not fd/path) and FamilyTime alongside its clock_gettime/
settimeofday/time siblings; its exit emits a plain ret_event carrying
the int 0/-1 return as UNCLASSIFIED. mage generate produces no diff.
Add lock-in tests mirroring prior syscall audits:
- family_test.go asserts sys_enter/exit_gettimeofday => FamilyTime
- retclassify_test.go asserts gettimeofday exit stays UNCLASSIFIED
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of futex_wake found that the futex family syscalls (futex,
futex_wait, futex_wake, futex_requeue, futex_waitv) were absent from the
syscallFamilies map and fell through to FamilyMisc. Per futex(2) ("fast
user-space locking"), these are shared-memory synchronization/IPC
primitives, conceptually identical to the System V semaphores
(semop/semget) already tagged FamilyIPC. Group them under IPC so
per-family aggregation/reporting bins them with the other synchronization
primitives.
Argument and return-value handling were already correct: futex_wake's
first arg (uaddr) is a userspace pointer, captured via KindFutex
(null_event), and the exit ret_event records the woken-waiter count
(>=0) or -1 on error.
Add lock-in unit tests in family_test.go and regenerate the C/Go
artifacts (generated_tracepoints.go, generated_types.go).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of the getpeername(2) syscall confirmed the tracing pipeline already
matches the man page: FamilyNetwork + KindFd (sockfd at args[0]) on enter, and
a plain ret_event (int 0/-1) on exit. The enter classification was already
covered by TestClassifySocketFdSyscallsByName, but the exit path (resolved via
the generic 'ret' field matcher) had no dedicated assertion. Add
TestClassifyExitGetpeername to pin sys_exit_getpeername -> KindRet so future
classifier changes cannot silently regress it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
exit(2) and exit_group(2) take a single int status arg and never return.
ior classifies both as KindNull (FamilyProcess): the enter handler emits a
null_event without capturing the status arg, and the kernel-exposed
sys_exit_{exit,exit_group} EXIT_RET_EVENT handlers are emitted but never
fire at runtime. Audit confirmed the implementation already matches the
man page; this adds a lock-in test documenting the noreturn behavior.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audited epoll_create/epoll_create1 against man 2 epoll_create.
Implementation already correct: both classify as KindEventfd (fd-creating),
epoll_create(size) hardcodes flags=0 (no flags arg), epoll_create1(flags)
reads ctx->args[0], and exit captures the returned fd via ev->ret.
Add FormatEpollCreate1/FormatExitEpollCreate1 fixtures and
TestGenerateEpollCreate1HandlerUsesArg0Flags as the positive counterpart to
the existing TestGenerateEpollCreateHandlerUsesZeroFlags negative test,
asserting the enter handler captures args[0] as flags rather than 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Audit of ioperm(2) confirmed the syscall is traced correctly: classified
as KindNull (name-only enter, no arg decoding) with the exit handler
capturing the raw int return value, matching the man-page semantics
(int ioperm(unsigned long from, unsigned long num, int turn_on) -> 0/-1).
ioperm and its x86 port/CPU-state siblings (iopl, modify_ldt) are not in
the explicit family table and intentionally fall through to Misc. Add
explicit family-classification assertions so a future regression that
accidentally remaps them is caught. No implementation change was needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|