Skip to content

Alignment issue in GlobalAlloc::{alloc, dealloc} #974

@fbq

Description

@fbq

This was brought up at: #815 (comment)

  • kmalloc() only guarantees “aligned to size” for size is a power of 2
  • otherwise the alignment is SLAB_MINALIGN (usually is size_of::<usize>() )
  • right now, our allocator is just
    • bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL)

And the result of this is that in theory, if a struct has alignment > SLAB_MINALIGN, and its size is not a power of two, we may get a mis-aligned memory object from Rust allocation APIs (Box, Arc, etc.).

For fixes, based on previous and recent discussions:

  • For long term, we want slab APIs (mostly krealloc()) to provide a way for users to tell the allocator the desired alignment, which benefits both C and Rust.
  • For short term, a quick fix would be do an internal "extend the size to the closest power of 2" trick in side GlobalAlloc::alloc, for example:
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
    let layout = layout.pad_to_align(); // Handles customized layout.
    let mut size = layout.size();
    
    if layout.align() > SLAB_MINALIGN {
        // `align()` exceeds the kernel allocator alignment guarantee, round up to next 2^n if the size is not a power of two.
        size = size.next_power_of_two(); 
    }
    bindings::krealloc(ptr::null(), size, bindings::GFP_KERNEL)
}

Metadata

Metadata

Assignees

Labels

unsoundThe possibility of UB in safe code.• bugRelated to runtime bugs, panics, warnings...

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions