From 0cfdd29db2f9cae372617ef01ed4aecc2f6fa93d Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Tue, 2 Jun 2026 10:10:45 +0300 Subject: test(xattr): add removexattrat end-to-end integration coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit removexattrat(2) (Linux 6.13+) was the one xattr *at-variant lacking integration coverage: xattr_test.go exercised getxattrat/listxattrat (READ-classified byte counts) and the path-based setxattr, but never the REMOVE *at variant. Unlike its getxattrat/listxattrat siblings, removexattrat returns a 0/-1 status (not a byte count), so its exit must be UNCLASSIFIED — matching removexattr/lremovexattr/fremovexattr. Add an ioworkload scenario (xattr-removexattrat) that setxattr's a user.* attribute via a real path then removes it via raw removexattrat(AT_FDCWD, path, 0, name), plus TestXattrRemovexattrat asserting the path (args[1], after the dirfd) is captured (never the xattr name at args[3]) and that accounted bytes are exactly zero (guarding against wrongly READ-classifying it like getxattrat/ listxattrat). Distinct from the fd-based fremovexattr gap (task 8i0). Classification verified by inspection: FamilyFS (xattr marker), KindPathname at the pathname field (ctx->args[1]), and absent from the ret-classification table => UNCLASSIFIED. No generator change needed. Co-Authored-By: Claude Opus 4.8 --- integrationtests/xattr_test.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'integrationtests') diff --git a/integrationtests/xattr_test.go b/integrationtests/xattr_test.go index 16efb4a..f99629d 100644 --- a/integrationtests/xattr_test.go +++ b/integrationtests/xattr_test.go @@ -10,6 +10,10 @@ var xattrTraceArgs = []string{"-trace-syscalls", "getxattrat,setxattr,openat"} // test is not perturbed by unrelated xattr/open traffic. var xattrListTraceArgs = []string{"-trace-syscalls", "listxattrat,setxattr,openat"} +// xattrRemoveTraceArgs restricts tracing to the removexattrat tracepoints so +// the test is not perturbed by unrelated xattr/open traffic. +var xattrRemoveTraceArgs = []string{"-trace-syscalls", "removexattrat,setxattr,openat"} + // TestXattrGetxattrat verifies ior traces getxattrat(2) (Linux 6.13+) // end-to-end. getxattrat takes a dirfd plus a real filesystem path at args[1] // (NOT args[0]=dfd) and an xattr NAME at args[3]; only the path must be @@ -100,3 +104,36 @@ func TestXattrListxattrat(t *testing.T) { assertEventBytesAtLeast(t, result, exp, uint64(len("user.ior")+1)) assertEventDurationPositive(t, result, exp) } + +// TestXattrRemovexattrat verifies ior traces removexattrat(2) (Linux 6.13+) +// end-to-end. removexattrat takes a dirfd plus a real filesystem path at +// args[1] (NOT args[0]=dfd); the xattr name is at args[3] and must NOT be +// captured. The path is read on syscall entry, so enter_removexattrat must +// carry the file path "xattrfile.txt", never the name "user.ior". +func TestXattrRemovexattrat(t *testing.T) { + result, _ := runScenarioResultWithIorArgs(t, "xattr-removexattrat", []ExpectedEvent{ + { + PathContains: "xattrfile.txt", + Tracepoint: "enter_removexattrat", + Comm: "ioworkload", + MinCount: 1, + }, + }, xattrRemoveTraceArgs) + + // The captured path must be the filesystem path, never the xattr name. + for _, rec := range result.Records { + if rec.TraceID.String() == "enter_removexattrat" && rec.Path == "user.ior" { + t.Errorf("removexattrat captured xattr name %q as path instead of file path", rec.Path) + } + } + + // removexattrat is UNCLASSIFIED: it REMOVES an attribute and returns a 0/-1 + // status, never a byte count (contrast getxattrat/listxattrat, which return + // value/name-list sizes). The accounted bytes must therefore be exactly + // zero — matching removexattr/lremovexattr/fremovexattr, and guarding + // against wrongly READ-classifying it like its getxattrat/listxattrat + // siblings. + exp := ExpectedEvent{Tracepoint: "enter_removexattrat", Comm: "ioworkload"} + assertEventBytesEqual(t, result, exp, 0) + assertEventDurationPositive(t, result, exp) +} -- cgit v1.2.3