From 1b80609cb0b96b03fec54e89fa3bb713673dd6eb Mon Sep 17 00:00:00 2001 From: Robert Allan James Date: Tue, 25 Aug 2026 14:16:12 -0400 Subject: [PATCH] FABRIC-2.md: correct glibc misattribution in 2h hot-detach writeup block_subsystem.c is shared/vendored source -- its calloc()/free() calls resolve to real glibc in the hosted build, but to this kernel's own freestanding shims (src/starkernel/vm/host/shim.c, backed by kmalloc()/ kfree() in src/starkernel/memory/kmalloc.c) in the kernel build, which is where the address-reuse bug was actually diagnosed live. The previous writeup said "glibc's allocator" -- wrong environment entirely. Verified kmalloc_aligned() is a plain first-fit walk from heap_head with no coalescing, confirming the same free-then-immediate-same-size-alloc reuse behavior originally observed, just attributed to the right allocator. Caught by the user asking directly whether this project has any glibc dependency, given .claude/CLAUDE.md's strict ANSI C99/no-GNU-extensions requirement (confirmed -std=c99 throughout both Makefiles). Documentation correction only -- no code changed. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn --- FABRIC-2.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/FABRIC-2.md b/FABRIC-2.md index fc2326c..b5d0d99 100644 --- a/FABRIC-2.md +++ b/FABRIC-2.md @@ -3883,13 +3883,25 @@ current tail — and recommended a pointer-identity check in `blk_vm_load()`'s c a minimal fix requiring no new API. That fix was implemented, then **directly falsified by its own designed-for-this test**: attach device A (blank), detach, re-attach device B (distinct content) at the identical LBN range, read that LBN — pointer comparison passed the check (i.e. -called it a hit) and served **stale content from device A** anyway. Root cause: glibc's -allocator hands `free(slot)` in `blk_subsys_detach_device()` straight back to the very next -same-size `calloc(1, sizeof(*slot))` in `blk_subsys_attach_device()`, with nothing else allocated -in between — confirmed live in this exact session, not inferred — so the "fresh" pointer and the -stale one were bitwise identical despite belonging to two different physical devices. A pointer -comparison cannot distinguish "still the same live device" from "a different device that -happened to land at the same address" when the allocator is this deterministic. +called it a hit) and served **stale content from device A** anyway. Root cause: this kernel's own +freestanding heap allocator — `block_subsystem.c` is shared/vendored source, so its `calloc()`/ +`free()` calls resolve differently per build (real glibc in the hosted build; this kernel's own +`malloc`/`free`/`calloc` shims in `src/starkernel/vm/host/shim.c`, backed by `kmalloc()`/ +`kfree()` in `src/starkernel/memory/kmalloc.c`, in the kernel build this bug was actually diagnosed +in). `kmalloc_aligned()` is a plain first-fit walk from `heap_head` on every call; `kfree()` just +marks a block's `free` flag — no coalescing, no randomization. `free(slot)` in +`blk_subsys_detach_device()` hands its block straight back to the very next same-size +`calloc(1, sizeof(*slot))` in `blk_subsys_attach_device()`, with nothing else allocated in +between — confirmed live in this exact session, not inferred — so the "fresh" pointer and the +stale one were bitwise identical despite belonging to two different physical devices. (An initial +draft of this writeup attributed the reuse to "glibc's allocator" — wrong: the live diagnosis ran +in the kernel build, nowhere near glibc; corrected after the user asked directly whether this +project has any glibc dependency, per `.claude/CLAUDE.md`'s strict ANSI C99/no-GNU-extensions +requirement, which the kernel build already honors throughout — this was a documentation +attribution error, not a code or license-compliance one.) A pointer comparison cannot distinguish +"still the same live device" from "a different device that happened to land at the same address" +when the allocator is this deterministic — true of this first-fit kmalloc just as much as it +would be of glibc's own allocator under the same free-then-immediately-realloc pattern. Fixed properly with a monotonic `blk_subsys_epoch()` counter (`block_subsystem.c`, `uint64_t g.epoch`, bumped in `blk_subsys_attach_device()`, `blk_subsys_add_raw_device()`, and