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

Root<T>: Data race allowed on T #995

Closed
wants to merge 1 commit into from
Closed

Root<T>: Data race allowed on T #995

wants to merge 1 commit into from

Conversation

kuzeyardabulut
Copy link

Hi,
I found a memory-safety/soundness issue in this crate while scanning Rust code for potential vulnerabilities. This PR contains a fix for the issue.

Issue Description

Root<T> unconditionally implements Sync. This allows users to create data races on T: !Sync. Such data races can lead to undefined behavior.

unsafe impl<T> Send for Root<T> {}
unsafe impl<T> Sync for Root<T> {}

@kjvalencik
Copy link
Member

kjvalencik commented Aug 3, 2023

Can you give an example of such a data race? The only thing that Root can ever hold is a napi_ref, which can be sent across threads.

Root can't hold any T, it's specifically a wrapper to allow safely holding references to JS values across threads. They can only ever be dereferenced on the JS main thread.

@kuzeyardabulut
Copy link
Author

I agree with what you said. This may not cause a direct data race. But making the above changes is useful if it doesn't break the flow of the code.

@kjvalencik
Copy link
Member

kjvalencik commented Aug 3, 2023

But making the above changes is useful if it doesn't break the flow of the code.

It does because T is the type that will be pulled from the Root on the main thread and that type is explicitly not Sync.

If you take a look at CI, there are a bunch of use cases no longer compiling (the most common one is dropping a Root in a global).

@kjvalencik
Copy link
Member

Closing the loop on this, after discussing and examining with a few folks:

  • This is sound as Root may only be constructed with T: Object and does not contain any references to T
  • Requiring T: Send and T: Sync is not possible because the intent of this type is a safe Send/Sync wrapper around normally !Send + !Sync references to JS values on the V8 heap.
  • We could add a bound on struct Root to require T: Value, but this does not increase external safety (already protected by private fields) and would propagate T bounds unnecessarily.

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

Successfully merging this pull request may close these issues.

2 participants