Skip to content

Kernel panic triggered by double-free in global allocator (rlsf) #327

@nuczyc

Description

@nuczyc

Describe the bug

The kernel crashes with a panic when a user application performs a "double free" operation (calling free() twice on the same pointer).

To Reproduce

  1. Compile the program and run.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

/*
 * PoC for triggering kernel panic in ArceOS memory management
 * Target: PageIter4K::new() unwrap() failure in unmap_alloc()
 * 
 * The crash occurs when PageIter4K::new() returns an error/None,
 * likely due to invalid address range or alignment issues.
 * 
 * This PoC attempts to trigger the condition by:
 * 1. Calling munmap() with invalid parameters
 * 2. Freeing corrupted pointers
 * 3. Creating misaligned memory regions
 */

int main() {
    printf("PoC: Attempting to trigger PageIter4K unwrap panic\n");
    
    // Attempt 1: munmap with invalid address range
    printf("Attempt 1: munmap with invalid range\n");
    void *invalid_addr = (void*)0x1000;
    if (munmap(invalid_addr, 0) == -1) {
        perror("munmap failed (expected)");
    }
    
    // Attempt 2: munmap with misaligned address
    printf("Attempt 2: munmap with misaligned address\n");
    void *misaligned = (void*)0x1234;
    if (munmap(misaligned, 4096) == -1) {
        perror("munmap failed (expected)");
    }
    
    // Attempt 3: munmap with size that causes overflow
    printf("Attempt 3: munmap with size causing overflow\n");
    void *addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    if (addr != MAP_FAILED) {
        // Try to unmap with size that would cause start + size to overflow
        if (munmap(addr, SIZE_MAX - (uintptr_t)addr + 1) == -1) {
            perror("munmap overflow failed (expected)");
        }
        munmap(addr, 4096); // Clean up
    }
    
    // Attempt 4: Double free to corrupt heap metadata
    printf("Attempt 4: Double free attempt\n");
    char *ptr = malloc(100);
    if (ptr) {
        free(ptr);
        // Double free - may corrupt heap metadata
        free(ptr);
    }
    
    // Attempt 5: Free with corrupted pointer
    printf("Attempt 5: Free with corrupted pointer\n");
    char *ptr2 = malloc(100);
    if (ptr2) {
        // Corrupt the pointer by offsetting it
        char *corrupted = ptr2 + 1;
        free(corrupted);
    }
    
    // Attempt 6: munmap with start > end (wraparound)
    printf("Attempt 6: munmap with wrapped address range\n");
    void *high_addr = (void*)0xFFFFF000;
    if (munmap(high_addr, 0x2000) == -1) {
        perror("munmap wraparound failed (expected)");
    }
    
    printf("PoC completed. If panic didn't trigger, the conditions may not be reachable from userspace.\n");
    printf("The PageIter4K::new() failure likely requires specific kernel-internal conditions.\n");
    
    return 0;
}

Environment

Logs

SeaBIOS (version 1.16.3-debian-1.16.3-2)


iPXE (https://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+06FCAA40+06F0AA40 CA00
                                                                               


Booting from ROM..TSC frequency: 4000 MHz

       d8888                            .d88888b.   .d8888b.
      d88888                           d88P" "Y88b d88P  Y88b
     d88P888                           888     888 Y88b.
    d88P 888 888d888  .d8888b  .d88b.  888     888  "Y888b.
   d88P  888 888P"   d88P"    d8P  Y8b 888     888     "Y88b.
  d88P   888 888     888      88888888 888     888       "888
 d8888888888 888     Y88b.    Y8b.     Y88b. .d88P Y88b  d88P
d88P     888 888      "Y8888P  "Y8888   "Y88888P"   "Y8888P"

arch = x86_64
platform = x86-pc
target = x86_64-unknown-none
build_mode = debug
log_level = info
smp = 1

[  0.004535 0 axruntime:136] Logging is enabled.
[  0.005021 0 axruntime:137] Primary CPU 0 started, arg = 0x9500.
[  0.005895 0 axruntime:140] Found physcial memory regions:
[  0.006453 0 axruntime:142]   [PA:0x0, PA:0x100000) reserved (READ | WRITE | RESERVED)
[  0.007236 0 axruntime:142]   [PA:0x100000, PA:0x200000) free memory (READ | WRITE | FREE)
[  0.008033 0 axruntime:142]   [PA:0x200000, PA:0x323000) .text (READ | EXECUTE | RESERVED)
[  0.008835 0 axruntime:142]   [PA:0x323000, PA:0x34b000) .rodata (READ | RESERVED)
[  0.009575 0 axruntime:142]   [PA:0x34b000, PA:0x36c000) .data .tdata .tbss .percpu (READ | WRITE | RESERVED)
[  0.010517 0 axruntime:142]   [PA:0x36c000, PA:0x3ac000) boot stack (READ | WRITE | RESERVED)
[  0.011345 0 axruntime:142]   [PA:0x3ac000, PA:0x3b5000) .bss (READ | WRITE | RESERVED)
[  0.012129 0 axruntime:142]   [PA:0x3b5000, PA:0x7fdc000) free memory (READ | WRITE | FREE)
[  0.012937 0 axruntime:142]   [PA:0xb0000000, PA:0xc0000000) mmio (READ | WRITE | DEVICE | RESERVED)
[  0.013813 0 axruntime:142]   [PA:0xfe000000, PA:0xfec00000) mmio (READ | WRITE | DEVICE | RESERVED)
[  0.014711 0 axruntime:142]   [PA:0xfec00000, PA:0xfec01000) mmio (READ | WRITE | DEVICE | RESERVED)
[  0.015598 0 axruntime:142]   [PA:0xfed00000, PA:0xfed01000) mmio (READ | WRITE | DEVICE | RESERVED)
[  0.016492 0 axruntime:142]   [PA:0xfee00000, PA:0xfee01000) mmio (READ | WRITE | DEVICE | RESERVED)
[  0.017368 0 axruntime:217] Initialize global memory allocator...
[  0.017985 0 axruntime:218]   use TLSF allocator.
[  0.018628 0 axmm:103] Initialize virtual memory management...
[  0.062412 0 axruntime:157] Initialize platform devices...
[  0.062769 0 axplat_x86_pc::apic:65] Initialize Local APIC...
[  0.063138 0 axplat_x86_pc::apic:80] Using x2APIC.
[  0.063480 0 axplat_x86_pc::apic:95] Initialize IO APIC...
[  0.063846 0 axtask::api:73] Initialize scheduling...
[  0.064199 0 axtask::api:79]   use FIFO scheduler.
[  0.064532 0 axdriver:152] Initialize device drivers...
[  0.064870 0 axdriver:153]   device model: static
[  0.072478 0 virtio_drivers::device::blk:59] config: 0xffff8000fe002000
[  0.072909 0 virtio_drivers::device::blk:64] found a block device of size 65536KB
[  0.073468 0 axdriver::bus::pci:104] registered a new Block device at 00:02.0: "virtio-blk"
[  0.078548 0 virtio_drivers::device::net::dev_raw:30] negotiated_features Features(MAC | STATUS | RING_INDIRECT_DESC | RING_EVENT_IDX)
[  0.080381 0 axdriver::bus::pci:104] registered a new Net device at 00:03.0: "virtio-net"
[  0.187469 0 axfs:41] Initialize filesystems...
[  0.187774 0 axfs:44]   use block device 0: "virtio-blk"
[  0.190992 0 fatfs::dir:145] Is a directory
[  0.194836 0 fatfs::dir:145] Is a directory
[  0.201864 0 fatfs::dir:145] Is a directory
[  0.211629 0 fatfs::dir:145] Is a directory
[  0.215816 0 axnet:42] Initialize network subsystem...
[  0.216159 0 axnet:45]   use NIC 0: "virtio-net"
[  0.217872 0 axnet::smoltcp_impl:333] created net interface "eth0":
[  0.218275 0 axnet::smoltcp_impl:334]   ether:    52-54-00-12-34-56
[  0.218672 0 axnet::smoltcp_impl:335]   ip:       10.0.2.15/24
[  0.219041 0 axnet::smoltcp_impl:336]   gateway:  10.0.2.2
[  0.219388 0 axruntime:183] Initialize interrupt handlers...
[  0.219755 0 axcpu::x86_64::trap:46] No registered handler for trap IRQ
[  0.220280 0 axruntime:195] Primary CPU 0 init OK.
PoC: Attempting to trigger PageIter4K unwrap panic
Attempt 1: munmap with invalid range
WARN: no ax_call implementation for munmap: 
Attempt 2: munmap with misaligned address
WARN: no ax_call implementation for munmap: 
Attempt 3: munmap with size causing overflow
WARN: no ax_call implementation for mmap: 
Attempt 4: Double free attempt
[  0.222320 0:2 axruntime::lang_items:5] panicked at /home/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rlsf-0.2.1/src/tlsf.rs:1034:9:
assertion failed: (block.as_ref().size & SIZE_USED) != 0
[  0.223347 0:2 axplat_x86_pc::power:25] Shutting down...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions