-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Overflow in Arc
#108706
Comments
I've opened a pull request here |
@rustbot assign @noamtashma |
This comment was marked as outdated.
This comment was marked as outdated.
I must stress that our 16-bit targets do not support "atomics" |
This comment was marked as outdated.
This comment was marked as outdated.
(I changed the title because this issue is about an overflow - I don't think there's an underflow issue as well) |
There was some discussion about whether |
I wanted to add I-unsound, since I think an RCE during that time window can still be a serious vulnerability. Especially since rust doesn't have much control over the system's IMO the main thing stopping this from being severe is that, to be vulnerable your code must leak a lot of values, without leaking actual heap space. Or that the attacker wouldn't be able to have a lot of close calls to |
From the security perspective, I just want to emphasize that "adversarial" should be considered non-literal -- source code is generally considered within the trust boundary, and if that's ever not the case then you need an entire sandboxing solution for both compilation and execution. |
I do think it's accurate to classify this as an unsoundness bug, even though it's very low risk. Let's mark it as I-unsound with P-low for now. |
…u-se Prevent overflow through Arc::downgrade Fixes rust-lang#108706
I discovered a memory safety vulnerability in the standard library's
Arc
.Before the rest of the issue, I just want to say thanks in advance to everyone involved for helping to keep rust safe 🦀 :)
Description of the vulnerability:
In
Weak::clone
, the weak count is incremented usingfetch_add
, and then it's checked whether the result passedMAX_REFCOUNT
. As is documented inArc::clone
's code, this is because if the counter gets too close to overflowing, the overflow might happen before the call toabort
completes, breaking Arc's invariants and probably causing UB. Checking if the counter passedMAX_REFCOUNT
means that at least 2^15 (in 16-bit platforms) increments to the counter beforeabort
completes are needed for an overflow.However, in
Arc::downgrade
, the code increments the weak count, without checking that the counter doesn't passMAX_REFCOUNT
. This allows the counter to get all the way up tousize::MAX - 1
. Then, usingWeak::clone
, we can get a much more favorable race than intended.Therefore, the attack is as follows:
We use
Arc::downgrade
to increment the weak count all the way tousize::MAX - 1
, then runWeak::clone
three times in parallel.The first two will call
abort
, but the third will result in a weak count of 1, indicating that there are no remainingWeak
s (while there actually are).Then we can abuse this broken invariant to cause UB, for example through
Arc::get_mut
, as long as we manage to do so before either of the twoabort
calls complete.Demonstration of the vulnerability:
Note than to run this exploit yourself, if you're running a 64-bit architecture, the exploit won't run in a reasonable length of time. So
Arc
has to be modified to lower the counter to 32-bits, to demonstrate the vulnerability.The exploit in code
Running on 64-bit architectures
This is how I tested the exploit myself. I modified the `std` so that the counter would only be a `u32`, and ran the exploit as a "test", with this command:
This is also present here.
Fixing:
The fix is very simple. In the
Arc::downgrade
compare-exchange loop, add a check that ifcur > MAX_REFCOUNT
, and it's notusize::MAX
, panic.Add a comment explaining that not straying too much above
MAX_REFCOUNT
is a global invariant, and must be enforced in all increment operations.Severity:
I'm not sure how severe it is, since it depends on a race with
abort
, and I don't know how to assess winning this race in real code on different platforms.It should also be noted that in order for this to be exploited, a large amount of
Weak
s need to be leaked (depending onusize
size), without also leaking heap memory (otherwise the program would run out of memory first).The text was updated successfully, but these errors were encountered: