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:
Moe Charm (CI)
2025-11-16 00:38:29 +09:00
parent 880ea511c8
commit 6199e9ba01
6 changed files with 576 additions and 22 deletions

View File

@ -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;
}