Phase 15 Box Separation: Fix wrapper domain check to prevent BenchMeta→CoreAlloc violation
Fix free() wrapper unconditionally routing ALL pointers to hak_free_at(),
causing Box boundary violations (BenchMeta slots[] entering CoreAlloc).
Solution: Add domain check in wrapper using 1-byte header inspection:
- Non-page-aligned: Check ptr-1 for HEADER_MAGIC (0xa0/0xb0)
- Hakmem Tiny → route to hak_free_at()
- External/BenchMeta → route to __libc_free()
- Page-aligned: Full classification (cannot safely check header)
Results:
- 99.29% BenchMeta properly freed via __libc_free() ✅
- 0.71% page-aligned fallthrough → ExternalGuard leak (acceptable)
- No crashes (100K/500K iterations stable)
- Performance: 15.3M ops/s (maintained)
Changes:
- core/box/hak_wrappers.inc.h: Domain check logic (lines 227-256)
- core/box/external_guard_box.h: Conservative leak prevention
- core/hakmem_super_registry.h: SUPER_MAX_PROBE 8→32
- PHASE15_WRAPPER_DOMAIN_CHECK_FIX.md: Comprehensive analysis
Root cause identified by user: LD_PRELOAD intercepts __libc_free(),
wrapper needs defense-in-depth to maintain Box boundaries.
This commit is contained in:
@ -118,26 +118,30 @@ static inline int external_guard_try_free(void* ptr) {
|
||||
domain_name[fg.domain], fg.class_idx);
|
||||
}
|
||||
|
||||
// Safety check: is memory mapped?
|
||||
if (!external_guard_is_mapped(ptr)) {
|
||||
if (external_guard_log_enabled()) {
|
||||
fprintf(stderr, "[ExternalGuard] ptr=%p NOT MAPPED (mincore failed)\n", ptr);
|
||||
}
|
||||
g_external_guard_stats.unknown_ptr++;
|
||||
return 0; // Can't free unmapped memory
|
||||
}
|
||||
// Phase 15 FIX: CONSERVATIVE unknown pointer handling
|
||||
// CRITICAL: If we reached ExternalGuard, ALL hakmem lookups failed:
|
||||
// - Box Tiny: TLS SLL miss
|
||||
// - Box Pool: Pool TLS miss
|
||||
// - Box Mid: Mid registry miss
|
||||
// - Box L25: L25 registry miss
|
||||
// - SuperSlab registry: lookup miss
|
||||
//
|
||||
// This pointer is UNKNOWN origin. It could be:
|
||||
// A) hakmem pointer that failed lookup (registry bug/collision)
|
||||
// B) External pointer (__libc_malloc, static data, etc.)
|
||||
//
|
||||
// SAFEST ACTION: Do NOT free it (leak vs crash tradeoff).
|
||||
// Delegating to __libc_free(A) will crash. Leaking (B) is acceptable.
|
||||
|
||||
// TODO: AllocHeader dispatch (16-byte header for Mid/Large/LD_PRELOAD)
|
||||
// For now, delegate to libc free as fallback
|
||||
g_external_guard_stats.alloc_header_dispatch++;
|
||||
g_external_guard_stats.unknown_ptr++;
|
||||
|
||||
if (external_guard_log_enabled()) {
|
||||
fprintf(stderr, "[ExternalGuard] ptr=%p delegated to __libc_free\n", ptr);
|
||||
int is_mapped = external_guard_is_mapped(ptr);
|
||||
fprintf(stderr, "[ExternalGuard] WARNING: Unknown pointer %p (mincore=%s) - IGNORED (leak prevention)\n",
|
||||
ptr, is_mapped ? "MAPPED" : "UNMAPPED");
|
||||
}
|
||||
|
||||
// CRITICAL FIX: Use __libc_free() to avoid infinite loop via hakmem wrapper
|
||||
extern void __libc_free(void*);
|
||||
__libc_free(ptr);
|
||||
// Return 1 (handled) to prevent wrapper from calling __libc_free()
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user