diff options
Diffstat (limited to 'internal/generate')
| -rw-r--r-- | internal/generate/classify_test.go | 52 | ||||
| -rw-r--r-- | internal/generate/family.go | 8 | ||||
| -rw-r--r-- | internal/generate/family_test.go | 16 |
3 files changed, 76 insertions, 0 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go index 92b6e58..1d832a4 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -1259,6 +1259,58 @@ func TestClassifyE7NullNameOnlyKinds(t *testing.T) { } } +// TestClassifyIoprioNullKind locks in the argument-capture classification for +// ioprio_set/ioprio_get using their real kernel tracepoint fields. Unlike the +// name-only Misc/null syscalls above, ioprio_* are NOT in nameOnlyKindsTable: +// they classify by field fallthrough. ioprio_set(which, who, ioprio) and +// ioprio_get(which, who) carry only int-typed which/who/ioprio fields. None is +// named "fd"/"pathname"/"path"/"filename", so ClassifyFormat must return +// KindNone — in particular the "who" argument (a pid/pgid/uid selected by +// "which", never an fd) must NOT be misclassified as KindFd, and nothing must be +// captured as a path. classifyEnterForGeneration then promotes the field-bearing +// enter format to KindNull (the null_event seen in generated_tracepoints.c). +func TestClassifyIoprioNullKind(t *testing.T) { + cases := []struct { + name string + fields []Field + }{ + { + name: "sys_enter_ioprio_set", + fields: []Field{ + {Type: "int", Name: "__syscall_nr"}, + {Type: "int", Name: "which"}, + {Type: "int", Name: "who"}, + {Type: "int", Name: "ioprio"}, + }, + }, + { + name: "sys_enter_ioprio_get", + fields: []Field{ + {Type: "int", Name: "__syscall_nr"}, + {Type: "int", Name: "which"}, + {Type: "int", Name: "who"}, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + f := &Format{Name: tc.name, ExternalFields: tc.fields} + + // No field should match an fd/path/name pattern: raw classification + // is KindNone, proving "who" is not captured as an fd. + if r := ClassifyFormat(f); r.Kind != KindNone { + t.Fatalf("%s: ClassifyFormat kind = %d, want KindNone", tc.name, r.Kind) + } + + // The generator promotes the field-bearing enter format to KindNull. + if r := classifyEnterForGeneration(f); r.Kind != KindNull { + t.Fatalf("%s: classifyEnterForGeneration kind = %d, want KindNull", tc.name, r.Kind) + } + }) + } +} + func TestClassifyB7NameOnlyKinds(t *testing.T) { tests := []struct { name string diff --git a/internal/generate/family.go b/internal/generate/family.go index fb36cbd..a3c242f 100644 --- a/internal/generate/family.go +++ b/internal/generate/family.go @@ -72,6 +72,14 @@ var syscallFamilies = map[string]SyscallFamily{ "getppid": FamilyProcess, "getpriority": FamilyProcess, "getresgid": FamilyProcess, "getresuid": FamilyProcess, "getrlimit": FamilyProcess, "getrusage": FamilyProcess, "getsid": FamilyProcess, "gettid": FamilyProcess, "getuid": FamilyProcess, + // ioprio_get/ioprio_set query/set the I/O scheduling class and priority of a + // process, process group, or user (ioprio_set(which, who, ioprio)). They are + // the I/O-priority analogues of getpriority/setpriority (the CPU nice value + // for a process/group/user) and share the identical which/who selector + // signature, so they classify as Process alongside them rather than falling + // through to Misc. The who argument is a pid/pgid/uid (selected by which), + // never an fd or path, so argument capture is KindNull (null_event). + "ioprio_get": FamilyProcess, "ioprio_set": FamilyProcess, "kcmp": FamilyProcess, "personality": FamilyProcess, "pivot_root": FamilyProcess, "prctl": FamilyProcess, "prlimit64": FamilyProcess, "reboot": FamilyProcess, "restart_syscall": FamilyProcess, "set_tid_address": FamilyProcess, diff --git a/internal/generate/family_test.go b/internal/generate/family_test.go index af40e7d..47b7685 100644 --- a/internal/generate/family_test.go +++ b/internal/generate/family_test.go @@ -160,6 +160,22 @@ func TestClassifySyscallFamily(t *testing.T) { {"sys_enter_rt_sigqueueinfo", FamilySignals}, {"sys_enter_rt_tgsigqueueinfo", FamilySignals}, {"sys_enter_sigaltstack", FamilySignals}, + // ioprio_get/ioprio_set query/set the I/O scheduling class and priority of + // a process, process group, or user. They are the I/O-priority analogues of + // getpriority/setpriority (the CPU nice value) and share the identical + // which/who selector signature, so they classify as Process alongside them + // rather than falling through to Misc. Assert the ioprio pair together with + // their getpriority/setpriority siblings so a stray reclassification of any + // one of them trips this test. Note: the x86 I/O-port syscalls ioperm/iopl + // (asserted above as Misc) only share an "io" name prefix; they set + // port-access state, not process I/O priority, and stay in Misc. Keep in + // sync with the Process list in docs/syscall-tracing-plan.md. + {"sys_enter_ioprio_get", FamilyProcess}, + {"sys_exit_ioprio_get", FamilyProcess}, + {"sys_enter_ioprio_set", FamilyProcess}, + {"sys_exit_ioprio_set", FamilyProcess}, + {"sys_enter_getpriority", FamilyProcess}, + {"sys_enter_setpriority", FamilyProcess}, {"sys_enter_unlisted_future_syscall", FamilyMisc}, } |
