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

Multiple soundness issues with ImmutAfterInitCell #591

Open
msft-jlange opened this issue Jan 9, 2025 · 0 comments
Open

Multiple soundness issues with ImmutAfterInitCell #591

msft-jlange opened this issue Jan 9, 2025 · 0 comments
Assignees

Comments

@msft-jlange
Copy link
Collaborator

ImmutAfterInitCell both implements Deref and has a method called reinit, which permits reinitialization of the contents of the cell. In combination, this means it is possible for reinit to be called in one context while another context holds a shared (immutable) reference to the cell. This violates borrowing safety rules. At a minimum, reinit must be declared as unsafe because it is not safe, but it would be better to prohibit reinitialization altogether.

The one-time initialization checks for ImmutAfterInitCell are limited to debug builds, which means that non-debug builds are unsound because there are no initialization checks. If there is a code path which can be invoked in non-debug builds which can attempt to reference an uninitialized cell or to reinitialize an initialized cell, then no checking is performed, leading to unsound behavior.

Sync guarantees around initialization depend on a point in time where multiple CPUs are started, under the assumption that cross-thread safety is maintained as long as only one CPU can execute. However, the ability to invoke exception handlers (like the #VC handler) means that the exception handler can attempt to interact an ImmutAfterInitCell which is also being modified by the code that was interrupted, and that means that Sync rules need to apply even before multiple processors have started.

We need to fix ImmutAfterInitCell so that

  • it is truly immutable after initialization (no reinitialize method)
  • initialization checks are always performed
  • it is Sync in all cases

This is similar to the requirements of std::OnceLock, except that is not available in nostd so we need a custom implementation.

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

1 participant