summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-29 11:37:38 +0300
committerPaul Buetow <paul@buetow.org>2026-05-29 11:37:38 +0300
commit0e835414ad424e2061f5c0203e4ba797dd5a9281 (patch)
tree0a740bac2120c0e644ce79ba004ebb724ea773cd /internal
parentc78920d55d58ff54ab4a6adbd425072963b7e8f9 (diff)
test(generate): lock in setdomainname KindNull classification
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>
Diffstat (limited to 'internal')
-rw-r--r--internal/generate/classify_test.go46
1 files changed, 46 insertions, 0 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
index 904a7ff..c9ac8eb 100644
--- a/internal/generate/classify_test.go
+++ b/internal/generate/classify_test.go
@@ -1200,6 +1200,52 @@ func TestClassifyAcctPathname(t *testing.T) {
}
}
+// TestClassifySetdomainnameNotPath locks in the audit finding for the
+// setdomainname(2) syscall (`int setdomainname(const char *name, size_t len)`).
+// 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 table therefore pins it to
+// KindNull so the field-based path heuristic (which would otherwise treat a
+// `const char *name` arg as KindPathname) never fires. The sibling sethostname
+// must classify identically, and both must share a family, so the two stay
+// consistent.
+func TestClassifySetdomainnameNotPath(t *testing.T) {
+ // Realistic format including the const char *name arg that the path
+ // heuristic would latch onto if the name-only table did not win first.
+ setdomainname := ClassifyFormat(&Format{
+ Name: "sys_enter_setdomainname",
+ ExternalFields: []Field{
+ {Type: "long", Name: "__syscall_nr"},
+ {Type: "const char *", Name: "name"},
+ {Type: "size_t", Name: "len"},
+ },
+ })
+ if setdomainname.Kind != KindNull {
+ t.Fatalf("setdomainname: got kind %d, want KindNull (domain name is not a path)", setdomainname.Kind)
+ }
+ if setdomainname.PathnameField != "" {
+ t.Fatalf("setdomainname: PathnameField=%q, want empty (must not be captured as a path)", setdomainname.PathnameField)
+ }
+
+ sethostname := ClassifyFormat(&Format{
+ Name: "sys_enter_sethostname",
+ ExternalFields: []Field{
+ {Type: "long", Name: "__syscall_nr"},
+ {Type: "const char *", Name: "name"},
+ {Type: "size_t", Name: "len"},
+ },
+ })
+ if sethostname.Kind != setdomainname.Kind {
+ t.Fatalf("sethostname kind %d != setdomainname kind %d: siblings must agree", sethostname.Kind, setdomainname.Kind)
+ }
+
+ if got := ClassifySyscallFamily("sys_enter_setdomainname"); got != FamilyMisc {
+ t.Fatalf("setdomainname: family=%q, want %q", got, FamilyMisc)
+ }
+ if got, want := ClassifySyscallFamily("sys_enter_setdomainname"), ClassifySyscallFamily("sys_enter_sethostname"); got != want {
+ t.Fatalf("setdomainname family %q != sethostname family %q: siblings must agree", got, want)
+ }
+}
+
func TestClassifyMount(t *testing.T) {
r := classifyFromData(t, FormatMount)
if r.Kind != KindPathname {