From ef89473695784eab99cb0ca851ac5cd440b6340f Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 10 Jul 2026 15:32:31 +0300 Subject: [PATCH] amdgpu: vmalloc/vfree use mmap with guard pages vmalloc now allocates with PROT_NONE guard pages on each side, matching Linux kernel vmalloc behavior. Buffers overflow into a guard page and segfault instead of silently corrupting adjacent heap allocations. --- local/recipes/gpu/amdgpu/source/redox_stubs.c | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/local/recipes/gpu/amdgpu/source/redox_stubs.c b/local/recipes/gpu/amdgpu/source/redox_stubs.c index eb7d3a4b01..9d04a8c55c 100644 --- a/local/recipes/gpu/amdgpu/source/redox_stubs.c +++ b/local/recipes/gpu/amdgpu/source/redox_stubs.c @@ -49,13 +49,72 @@ static void redox_jiffies_advance(unsigned long delta) __sync_add_and_fetch(&jiffies, delta); } +struct redox_vmalloc_region { + void *base; + size_t total_size; + struct redox_vmalloc_region *next; +}; + +static pthread_mutex_t g_vmalloc_lock = PTHREAD_MUTEX_INITIALIZER; +static struct redox_vmalloc_region *g_vmalloc_regions; + void *vmalloc(unsigned long size) { - return malloc((size_t)size); + size_t aligned = PAGE_ALIGN((size_t)size); + size_t total = aligned + 2 * PAGE_SIZE; + void *base = mmap(NULL, total, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (base == MAP_FAILED) { + return NULL; + } + + void *usable = (char *)base + PAGE_SIZE; + if (mprotect(usable, aligned, PROT_READ | PROT_WRITE) != 0) { + munmap(base, total); + return NULL; + } + + struct redox_vmalloc_region *reg = malloc(sizeof(*reg)); + if (!reg) { + munmap(base, total); + return NULL; + } + reg->base = base; + reg->total_size = total; + + pthread_mutex_lock(&g_vmalloc_lock); + reg->next = g_vmalloc_regions; + g_vmalloc_regions = reg; + pthread_mutex_unlock(&g_vmalloc_lock); + + return usable; } void vfree(const void *addr) { + if (!addr) { + return; + } + + void *usable_base = (char *)addr - 0; + void *region_base = (char *)addr - PAGE_SIZE; + + struct redox_vmalloc_region **link; + pthread_mutex_lock(&g_vmalloc_lock); + link = &g_vmalloc_regions; + while (*link) { + if ((*link)->base == region_base) { + struct redox_vmalloc_region *reg = *link; + *link = reg->next; + pthread_mutex_unlock(&g_vmalloc_lock); + munmap(reg->base, reg->total_size); + free(reg); + return; + } + link = &(*link)->next; + } + pthread_mutex_unlock(&g_vmalloc_lock); + free((void *)addr); }