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

static mut transform is unsound on multi-core systems #411

Open
Disasm opened this issue Feb 23, 2021 · 8 comments
Open

static mut transform is unsound on multi-core systems #411

Disasm opened this issue Feb 23, 2021 · 8 comments
Labels
I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness

Comments

@Disasm
Copy link
Member

Disasm commented Feb 23, 2021

RP2040 starts execution on both cores. If entry function contains a "special" definition of static mut variable, each core takes a mutable reference to it, which is illegal from the Rust point of view.

Here is the relevant piece of #[entry] code:
https://github.com/rust-embedded/cortex-m-rt/blob/ca4790f40738bcc770285c8080955a2077682078/macros/src/lib.rs#L87-L88

@jonas-schievink
Copy link
Contributor

cortex-m-rt only supports single-core systems

@Disasm
Copy link
Member Author

Disasm commented Feb 23, 2021

Is it stated anywhere apart from this comment?

@adamgreig
Copy link
Member

Do the static mut transforms in the macros provide much value? I can't remember but I think we discussed removing them at some point, maybe involving #407/#250. Cortex-m's Mutex is definitely only single-core aware too, though, and I'm not sure what else would need changing in c-m-rt to make it safe on multi-core systems (at least, when they both execute the same code).

Doesn't the RP2040 ROM send the second core to sleep, so it only starts execution after being signalled once user code is running?

@adamgreig adamgreig transferred this issue from rust-embedded/cortex-m-rt Jan 23, 2022
@jamesmunns
Copy link
Member

Chiming in that this also applies to #[interrupt] macro, if the two cores share the same vector table/ISR functions.

@thejpster thejpster changed the title statics defined in #[entry] are not safe on multi-core systems static mut transform is unsound on multi-core systems Feb 5, 2024
@thejpster
Copy link
Contributor

It's unsound where the interrupt function can be re-entered. The NVIC usually prohibits this but on a multi-core system you need something at the HAL level to ensure this. You can imagine a mechanism that moves ownership of system interrupts from one core to another, hiding the regular NVIC API from the user. Then it would still be sound.

@newAM newAM added the I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness label Jun 30, 2024
@9names
Copy link
Contributor

9names commented Sep 14, 2024

The NVIC usually prohibits this but on a multi-core system you need something at the HAL level to ensure this.

You can also re-enable interrupts inside an interrupt and get the same problem.

In spite of rp2040 being around for several years we haven't had a single report of anyone having issues with this.

Rather than trying to make this safe, I think we should just document that you should not do anything that allows concurrent/recurrent execution of interrupt handlers and leave it at that, since the actual real-world usages of this behaviour are exceptionally rare, and even in the absence of the static mut transform are likely to be unsafe.

@jannic
Copy link
Member

jannic commented Sep 14, 2024

In spite of rp2040 being around for several years we haven't had a single report of anyone having issues with this.

I'm not sure if this is a strong argument. Having two instances of &mut references to the same underlying static is instant UB, but that doesn't guarantee that something bad happens. And even if it somehow breaks the software, it may happen very occasional, basically impossible to reproduce, and with non-obvious symptoms. So it may be dismissed as a flaky device and never be traced back to the underlying cause.

IMHO if we know that there are conditions that the user must hold up to avoid UB, there should be at least one unsafe function with a useful safety comment, so the user has a fair chance of knowing about these requirements, and a point to start looking for UB in case the software doesn't work as expected.

@thejpster
Copy link
Contributor

It should go behind a flag, like the cs impl. Maybe even the same flag.

jannic added a commit to jannic/cortex-m that referenced this issue Oct 12, 2024
On nightly, the static_mut_refs lint defaults to warn. With some of our
examples using `#[deny(warnings)]`, this leads to the following error:

```
error: creating a mutable reference to mutable static is discouraged
  --> cortex-m-rt/examples/entry-static.rs:15:16
   |
15 |     static mut COUNT: u32 = 0;
   |                ^^^^^ mutable reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
```

With edition 2024, the lint will probably default to deny.
(https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html)

To avoid that, set #[allow(static_mut_refs)] locally in the macro
expansion.

This only silences the warning and doesn't answer the underlying
question if we want to do that transform at all. See eg.
rust-embedded#411 for discussion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
Projects
None yet
Development

No branches or pull requests

8 participants