diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-29 10:55:42 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-29 10:55:42 +0300 |
| commit | 6561d63e5a47092d8b8f2a8128ad05ca9ffd2203 (patch) | |
| tree | 81257fe07bf1cf0a343799d6c71c7bdbab33566c /internal/generate/codegen_test.go | |
| parent | a89ad0f245f15f7250ba9fe9506b2734bb49e12a (diff) | |
test(generate): lock in map_shadow_stack BPF handler field wiring
Audit of the x86 CET map_shadow_stack syscall (Linux 6.6+,
void *map_shadow_stack(unsigned long addr, unsigned long size,
unsigned int flags)) confirmed the existing tracing is correct:
KindMem / FamilyMemory classification, memFieldSpec wires
addr=args[0], length=args[1] (size), flags=args[2], length2=0, and
the return (mapped address or -errno) is captured generically as
ev->ret like every other KindMem exit. Docs and classify tests
already match.
The only gap was the lack of a codegen lock-in test for the BPF
handler field wiring, which mlock2/remap_file_pages/mprotect/brk all
have. Add TestGenerateMemHandlerMapShadowStack to guard against
future drift.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal/generate/codegen_test.go')
| -rw-r--r-- | internal/generate/codegen_test.go | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/internal/generate/codegen_test.go b/internal/generate/codegen_test.go index ae2d643..09a23a5 100644 --- a/internal/generate/codegen_test.go +++ b/internal/generate/codegen_test.go @@ -280,6 +280,24 @@ func TestGenerateMemHandlerPkeyMprotect(t *testing.T) { requireContains(t, output, "ev->flags = (__u64)ctx->args[2];") } +// TestGenerateMemHandlerMapShadowStack locks in the BPF handler wiring for the +// x86 CET map_shadow_stack syscall (Linux 6.6+): +// void *map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags). +// The hint addr and size are args[0]/args[1] and flags is args[2]; there is no +// second length, so length2 must stay zero. The return is a mapped address (or +// -errno), captured generically via ev->ret like every other KindMem exit. +func TestGenerateMemHandlerMapShadowStack(t *testing.T) { + output := GenerateTracepointsC(mustParseAll(t, syntheticPair("map_shadow_stack"))) + + requireContains(t, output, `SEC("tracepoint/syscalls/sys_enter_map_shadow_stack")`) + requireContains(t, output, "struct mem_event *ev") + requireContains(t, output, "ev->event_type = ENTER_MEM_EVENT;") + requireContains(t, output, "ev->addr = (__u64)ctx->args[0];") + requireContains(t, output, "ev->length = (__u64)ctx->args[1];") + requireContains(t, output, "ev->length2 = 0;") + requireContains(t, output, "ev->flags = (__u64)ctx->args[2];") +} + func TestGenerateMemHandlerBrk(t *testing.T) { output := GenerateTracepointsC(mustParseAll(t, syntheticPair("brk"))) |
