Skip to content

fix(agent): resolve typedef-wrapped structs in BTF preflight so fix_setuid attaches (JEF-924) - #340

Merged
thejefflarson merged 2 commits into
mainfrom
thejefflarson/jef-924-btf-preflight-fix_setuid-kuid_t-typedef
Sep 2, 2026
Merged

fix(agent): resolve typedef-wrapped structs in BTF preflight so fix_setuid attaches (JEF-924)#340
thejefflarson merged 2 commits into
mainfrom
thejefflarson/jef-924-btf-preflight-fix_setuid-kuid_t-typedef

Conversation

@thejefflarson

Copy link
Copy Markdown
Owner

Closes JEF-924

What was wrong

Every agent — arm64 (-raspi) and amd64 (-generic) alike — reported loaded=7 total=8: the fix_setuid probe (security_task_fix_setuid, the setuid→root privilege-escalation signal) was disabled fleet-wide. Privilege-escalation corroboration has been silently inert.

Root cause — a preflight false-positive

The BTF preflight logged kuid_t.val expected=0 actual=None and fail-closed the probe. actual=None means the field wasn't found, not that its offset moved. The struct lookup (preflight/btf.rs) matched only a KIND_STRUCT named kuid_t — but the kernel declares it as:

typedef struct { uid_t val; } kuid_t;   // anonymous struct; the name is on the typedef

There is no struct literally named kuid_t, so the by-name scan found nothing. The baked offset (0) is correct and the probe would work — it was being disabled by a blind spot for typedef-wrapped structs.

Fix

Add aggregate_id: resolve a struct name that is itself a typedef/see-through to its target aggregate, reusing the same resolve_to_aggregate the module already applies to anonymous members. struct_field_offset now routes through it. Adds a regression test for the exact kuid_t shape (typedef → anonymous struct { val@0 }Some(0)).

Verified

Agent workspace: fmt clean · clippy clean · 75 tests pass (incl. the new resolves_a_struct_name_that_is_itself_a_typedef). After this ships, agents should report loaded=8 total=8 and fix_setuid attaches.

How it was found

Live fleet inspection (kubectl logs across all agents) — every node showed the same single disabled probe and the same kuid_t.val mismatch, which is what pinned it to a preflight resolution bug rather than a real per-kernel offset change.

🤖 Generated with Claude Code

…d_t) so fix_setuid attaches

The BTF preflight disabled the fix_setuid probe (security_task_fix_setuid,
setuid->root escalation) on every node, arm64 and amd64 alike: agents reported
loaded=7 total=8. It logged kuid_t.val expected=0 actual=None and fail-closed.

actual=None means the field was not found, not that the offset moved. The struct
lookup matched only a KIND_STRUCT named kuid_t, but the kernel declares it as
`typedef struct { uid_t val; } kuid_t;` -- an anonymous struct whose name lives
on the typedef -- so the by-name scan found nothing. The baked offset (0) is
correct; the probe would work.

Resolve a struct name that is itself a typedef/see-through to its target
aggregate (aggregate_id), reusing the same resolve_to_aggregate the module
already applies to anonymous members. Adds a regression test for the kuid_t
shape. After deploy, agents should report loaded=8 total=8.

Closes JEF-924

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thejefflarson
thejefflarson enabled auto-merge (squash) September 2, 2026 02:25
@thejefflarson
thejefflarson merged commit 209a270 into main Sep 2, 2026
7 checks passed
@thejefflarson
thejefflarson deleted the thejefflarson/jef-924-btf-preflight-fix_setuid-kuid_t-typedef branch September 2, 2026 02:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant