kernel/slab: Add checks to object_cache_alloc for 0xdeadbeef.

We should always find it if PARANOID_KERNEL_FREE is enabled
and the object size is at least 2 pointers.
This commit is contained in:
Augustin Cavalier
2025-09-03 15:43:04 -04:00
parent bc50ada648
commit 92209b9023
2 changed files with 48 additions and 43 deletions
+1
View File
@@ -159,6 +159,7 @@ ObjectCache::InitSlab(slab* slab, void* pages, size_t byteCount, uint32 flags)
return NULL; return NULL;
} }
fill_freed_block(data, object_size);
slab->free.Push(object_to_link(data, object_size)); slab->free.Push(object_to_link(data, object_size));
ADD_PARANOIA_CHECK(PARANOIA_SUSPICIOUS, slab, ADD_PARANOIA_CHECK(PARANOIA_SUSPICIOUS, slab,
+47 -43
View File
@@ -1240,59 +1240,63 @@ object_cache_set_minimum_reserve(object_cache* cache, size_t objectCount)
void* void*
object_cache_alloc(object_cache* cache, uint32 flags) object_cache_alloc(object_cache* cache, uint32 flags)
{ {
if (!(cache->flags & CACHE_NO_DEPOT)) { void* object = NULL;
void* object = object_depot_obtain(&cache->depot); if ((cache->flags & CACHE_NO_DEPOT) == 0)
if (object) { object = object_depot_obtain(&cache->depot);
add_alloc_tracing_entry(cache, flags, object);
return fill_allocated_block(object, cache->object_size);
}
}
MutexLocker locker(cache->lock); if (object == NULL) {
slab* source = NULL; MutexLocker locker(cache->lock);
slab* source = NULL;
while (true) { while (true) {
source = cache->partial.Head(); source = cache->partial.Head();
if (source != NULL) if (source != NULL)
break; break;
source = cache->empty.RemoveHead(); source = cache->empty.RemoveHead();
if (source != NULL) { if (source != NULL) {
cache->empty_count--; cache->empty_count--;
cache->partial.Add(source); cache->partial.Add(source);
break; break;
}
if (object_cache_reserve_internal(cache, 1, flags) != B_OK) {
T(Alloc(cache, flags, NULL));
return NULL;
}
cache->pressure++;
} }
if (object_cache_reserve_internal(cache, 1, flags) != B_OK) { ParanoiaChecker _2(source);
T(Alloc(cache, flags, NULL));
return NULL; slab_queue_link* link = source->free.Pop();
source->count--;
cache->used_count++;
if (cache->total_objects - cache->used_count < cache->min_object_reserve)
increase_object_reserve(cache);
REMOVE_PARANOIA_CHECK(PARANOIA_SUSPICIOUS, source, &link->next,
sizeof(void*));
TRACE_CACHE(cache, "allocate %p (%p) from %p, %lu remaining.",
link_to_object(link, cache->object_size), link, source, source->count);
if (source->count == 0) {
cache->partial.Remove(source);
cache->full.Add(source);
} }
cache->pressure++; object = link_to_object(link, cache->object_size);
locker.Unlock();
} }
ParanoiaChecker _2(source); #if PARANOID_KERNEL_FREE
if (cache->object_size >= (sizeof(void*) * 2)) {
slab_queue_link* link = source->free.Pop(); ASSERT_ALWAYS(*(uint32*)object == 0xdeadbeef);
source->count--;
cache->used_count++;
if (cache->total_objects - cache->used_count < cache->min_object_reserve)
increase_object_reserve(cache);
REMOVE_PARANOIA_CHECK(PARANOIA_SUSPICIOUS, source, &link->next,
sizeof(void*));
TRACE_CACHE(cache, "allocate %p (%p) from %p, %lu remaining.",
link_to_object(link, cache->object_size), link, source, source->count);
if (source->count == 0) {
cache->partial.Remove(source);
cache->full.Add(source);
} }
#endif
void* object = link_to_object(link, cache->object_size);
locker.Unlock();
add_alloc_tracing_entry(cache, flags, object); add_alloc_tracing_entry(cache, flags, object);
return fill_allocated_block(object, cache->object_size); return fill_allocated_block(object, cache->object_size);