rust-embedded / wg

Coordination repository of the embedded devices Working Group
1.86k stars 95 forks source link

Soundly initializing custom memory sections #771

Open ryan-summers opened 4 days ago

ryan-summers commented 4 days ago

Currently, pointer provenance appears to make it entirely impossible to correctly initialize a memory section within rust code because linkers communicate with the application by setting the address of variables. These passed-back variables then have a provenance that does not cover the entire memory region that needs to be defined. For example:

// Linker-provided symbols for a custom memory segment called `itcm`, which contain the start, end, 
// and initialization data pointers for the section, passed via variable address.
extern "C" {
    static mut __sitcm: u32;
    static mut __eitcm: u32;
    static mut __siitcm: u32;
}

unsafe {
    let sitcm = core::ptr::addr_of_mut!(__sitcm); // Provnenance of 4 bytes
    let eitcm = core::ptr::addr_of_mut!(__eitcm); // Provenance of 4 bytes
    let siitcm = core::ptr::addr_of_mut!(__siitcm); // Provenance of 4 bytes
    let len = eitcm.offset_from(sitcm) as usize;

    // This is UB because `sitcm` and `siitcm` only have provenance of 4 bytes from their respective 
    // addresses, when `len` > 4.
    core::ptr::copy_nonoverlapping(siitcm, sitcm, len);
}

Right now, it doesn't appear possible to soundly perform section initialization using data provided by the linker due to these provenance issues. I'm opening this issue to track the topic, as we were discussing this extensively in the Matrix channel earlier.

jamesmunns commented 4 days ago

https://github.com/rust-embedded/cortex-m-rt/issues/300 is the discussion where we removed this pattern from cortex-m-rt

jamesmunns commented 4 days ago

https://github.com/rust-lang/unsafe-code-guidelines/issues/259

I hadn't seen this update, it may be that statics are now more magical than I was arguing.