Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RAM init code violates pointer provenance and aliasing rules #74

Open
jonas-schievink opened this issue Nov 24, 2020 · 1 comment
Open

Comments

@jonas-schievink
Copy link
Contributor

RAM initialization currently passes pointers to these statics to r0:

extern "C" {
static mut _sbss: u32;
static mut _ebss: u32;
static mut _sdata: u32;
static mut _edata: u32;
static _sidata: u32;
}
r0::zero_bss(&mut _sbss, &mut _ebss);
r0::init_data(&mut _sdata, &mut _edata, &_sidata);

But since r0 will fill the entire memory range between the pointers, it ends up calling offset with values that create pointers well beyond the u32 the static is declared to contain. According to the docs of offset, this is UB:

Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object. Note that in Rust, every (stack-allocated) variable is considered a separate allocated object.

(every static also counts as its own "allocated object", I believe)

Moreover, the ptr::write and ptr::write_volatile calls in r0 also cause UB, because this invariant is violated:

dst must be valid for writes.

Where the validity of a pointer requires this:

For a pointer to be valid, it is necessary, but not always sufficient, that the pointer be dereferenceable: the memory range of the given size starting at the pointer must all be within the bounds of a single allocated object. Note that in Rust, every (stack-allocated) variable is considered a separate allocated object.

...but again, we are crossing between potentially many allocated objects (every static in the .data/.bss section).

Furthermore, writing to a static through a pointer not derived from that static might violate aliasing rules, but it isn't yet clear if this is the case today (I've asked the folks working on the unsafe code guidelines for clarification / guidance).

The most robust solution for this issue is to write the RAM init code in assembly instead of Rust, and run no Rust code at all until RAM is initialized.

(this issue was recently discovered to affect most -rt crates in the ecosystem; we do not believe it to cause practical issues at the moment)

@tony-iqlusion
Copy link
Member

@jonas-schievink thank you for bringing this to our attention. We will look into ASM solutions for RAM init code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants