diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-30 10:44:55 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-30 10:44:55 +0300 |
| commit | 5e334d33b3ddc3e308455262577c461835939bc7 (patch) | |
| tree | 924eaf62dd5e993c327c06a3b2d6f7686d1d038e | |
| parent | 1491f883fc6feee512e92bde9af884852502dd0b (diff) | |
test(clock_nanosleep): lock in exit handler UNCLASSIFIED ret + args[2] request ptr
Audit of clock_nanosleep tracing confirmed the classification is correct:
KindSleep + FamilyTime (matching the nanosleep sibling), the enter handler
captures the request timespec at ctx->args[2] (not args[0]/clockid), and the
exit handler emits a plain ret_event with ret_type UNCLASSIFIED, which is
correct since clock_nanosleep returns 0 or a positive errno, never an fd or
byte count.
Strengthen the existing enter-handler test with the requested_ns -1 sentinel
and add TestClockNanosleepExitHandlerIsUnclassifiedRet to pin the exit-side
behavior. No classification, docs, or generated-code changes were needed
(mage generate produces no diff).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| -rw-r--r-- | internal/generate/codegen_test.go | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/internal/generate/codegen_test.go b/internal/generate/codegen_test.go index bb06418..9bd391e 100644 --- a/internal/generate/codegen_test.go +++ b/internal/generate/codegen_test.go @@ -1378,10 +1378,30 @@ func TestGenerateClockNanosleepHandlerCapturesRequestedTimespec(t *testing.T) { requireContains(t, output, "struct sleep_event *ev") requireContains(t, output, "ev->event_type = ENTER_SLEEP_EVENT;") + // clock_nanosleep(clockid_t, int flags, const struct timespec *request, + // struct timespec *remain): the request pointer is args[2], not args[0] + // (which is the clockid). The sentinel -1 marks a missing/unreadable ptr. + requireContains(t, output, "ev->requested_ns = -1;") requireContains(t, output, "if (ctx->args[2] != 0) {") requireContains(t, output, "ev->requested_ns = ts.tv_sec * 1000000000LL + ts.tv_nsec;") } +// TestClockNanosleepExitHandlerIsUnclassifiedRet locks in that the exit side of +// clock_nanosleep records a plain ret_event with ret_type UNCLASSIFIED. The +// syscall returns 0 on success or a positive errno (and -1 only when invoked +// via the libc wrapper on error), never an fd or byte count, so UNCLASSIFIED is +// the correct return classification — same as its nanosleep sibling. +func TestClockNanosleepExitHandlerIsUnclassifiedRet(t *testing.T) { + output := generateFromPair(t, FormatClockNanosleep, FormatExitClockNanosleep) + + requireContains(t, output, "handle_sys_exit_clock_nanosleep") + requireContains(t, output, "ev->event_type = EXIT_RET_EVENT;") + requireContains(t, output, "ev->ret = ctx->ret;") + requireContains(t, output, "ev->ret_type = UNCLASSIFIED;") + // The exit handler must not try to read a timespec or treat ret as an fd. + requireNotContains(t, output, "handle_sys_exit_clock_nanosleep(struct syscall_trace_exit *ctx) {\n __u32 pid, tid;\n if (filter(&pid, &tid))\n return 0;\n\n if (!ior_on_syscall_exit(tid, SYS_ENTER_CLOCK_NANOSLEEP, ctx->ret))\n return 0;\n\n struct sleep_event") +} + func TestGenerateKeyctlHandler(t *testing.T) { output := GenerateTracepointsC(mustParseAll(t, syntheticPair("keyctl"))) |
