diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-31 19:09:16 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-31 19:09:16 +0300 |
| commit | 8a1bf6236f6a525881c647fd881093b393436411 (patch) | |
| tree | 0fb537b847b6e5c72d2d3d98d7ce8fbc15330102 /internal | |
| parent | c3177bd82c16429c1bb246d19af76012479f0c01 (diff) | |
listxattrat: READ-classify return for xattr-list family consistency
listxattrat(2) (Linux 6.13+) returns the size in bytes of the list of
extended attribute names, exactly like listxattr/llistxattr/flistxattr,
but its exit was classified UNCLASSIFIED, so its read bytes were dropped
from I/O totals. Classify it as ReadClassified and regenerate the BPF
handler (ret_type now READ_CLASSIFIED). This mirrors the getxattrat fix
(task ku, commit c3177bd) and completes xattr-family consistency:
get-family and list-family are READ_CLASSIFIED while set-family and
remove-family stay UNCLASSIFIED (they return 0/-1).
Update the docs ReadClassified list and the retclassify expectation, and
add an ioworkload scenario plus integration test: the workload sets a
user xattr then lists names via the raw listxattrat(2) syscall with
AT_FDCWD, and the test asserts enter_listxattrat captures the file path
and accounts the returned name-list size as read bytes.
Task: r20
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/c/generated_tracepoints.c | 4 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints_result.txt | 2 | ||||
| -rw-r--r-- | internal/generate/classify.go | 4 | ||||
| -rw-r--r-- | internal/generate/retclassify_test.go | 6 |
4 files changed, 12 insertions, 4 deletions
diff --git a/internal/c/generated_tracepoints.c b/internal/c/generated_tracepoints.c index 8c76e7a..64d40db 100644 --- a/internal/c/generated_tracepoints.c +++ b/internal/c/generated_tracepoints.c @@ -6579,7 +6579,7 @@ int handle_sys_enter_listxattrat(struct syscall_trace_enter *ctx) { return 0; } -/// sys_exit_listxattrat is a struct ret_event (UNCLASSIFIED) (kind=ret) +/// sys_exit_listxattrat is a struct ret_event (READ_CLASSIFIED) (kind=ret) SEC("tracepoint/syscalls/sys_exit_listxattrat") int handle_sys_exit_listxattrat(struct syscall_trace_exit *ctx) { __u32 pid, tid; @@ -6599,7 +6599,7 @@ int handle_sys_exit_listxattrat(struct syscall_trace_exit *ctx) { ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); ev->ret = ctx->ret; - ev->ret_type = UNCLASSIFIED; + ev->ret_type = READ_CLASSIFIED; bpf_ringbuf_submit(ev, 0); return 0; diff --git a/internal/c/generated_tracepoints_result.txt b/internal/c/generated_tracepoints_result.txt index 0842bda..e6cb4d3 100644 --- a/internal/c/generated_tracepoints_result.txt +++ b/internal/c/generated_tracepoints_result.txt @@ -510,7 +510,7 @@ sys_exit_listen is a struct ret_event (UNCLASSIFIED) (kind=ret) sys_exit_listmount is a struct ret_event (UNCLASSIFIED) (kind=ret) sys_exit_listns is a struct ret_event (UNCLASSIFIED) (kind=ret) sys_exit_listxattr is a struct ret_event (READ_CLASSIFIED) (kind=ret) -sys_exit_listxattrat is a struct ret_event (UNCLASSIFIED) (kind=ret) +sys_exit_listxattrat is a struct ret_event (READ_CLASSIFIED) (kind=ret) sys_exit_llistxattr is a struct ret_event (READ_CLASSIFIED) (kind=ret) sys_exit_lremovexattr is a struct ret_event (UNCLASSIFIED) (kind=ret) sys_exit_lseek is a struct ret_event (UNCLASSIFIED) (kind=ret) diff --git a/internal/generate/classify.go b/internal/generate/classify.go index 3746bd9..0735291 100644 --- a/internal/generate/classify.go +++ b/internal/generate/classify.go @@ -593,6 +593,10 @@ var retClassifications = map[string]RetClassification{ "getxattrat": ReadClassified, "lgetxattr": ReadClassified, "listxattr": ReadClassified, + // listxattrat (Linux 6.13+) returns the size in bytes of the list of + // extended attribute names, exactly like listxattr/llistxattr/flistxattr, + // so it is a read byte-count. + "listxattrat": ReadClassified, "llistxattr": ReadClassified, "pread64": ReadClassified, "preadv": ReadClassified, diff --git a/internal/generate/retclassify_test.go b/internal/generate/retclassify_test.go index acd019b..4fc7501 100644 --- a/internal/generate/retclassify_test.go +++ b/internal/generate/retclassify_test.go @@ -8,7 +8,11 @@ func TestClassifyRetRead(t *testing.T) { // getxattrat (Linux 6.13+) returns the xattr value size in bytes, the // same read byte-count as getxattr/lgetxattr/fgetxattr. "getxattrat", - "lgetxattr", "listxattr", "llistxattr", "pread64", "preadv", + "lgetxattr", "listxattr", + // listxattrat (Linux 6.13+) returns the size in bytes of the xattr + // name list, the same read byte-count as listxattr/llistxattr/flistxattr. + "listxattrat", + "llistxattr", "pread64", "preadv", "preadv2", "process_vm_readv", "read", "readlink", "readlinkat", "readv", "recvmsg", "recvfrom", "syslog", "mq_timedreceive", "getrandom", "msgrcv", } |
