-
Notifications
You must be signed in to change notification settings - Fork 488
Fix race between block initialization and receiver disconnection #1084
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
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5bbfc09
to
d23c05d
Compare
d23c05d
to
b955031
Compare
taiki-e
approved these changes
Feb 26, 2024
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
bors
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Feb 26, 2024
Fix race between block initialization and receiver disconnection Port of crossbeam-rs/crossbeam#1084. Closes rust-lang#121582.
taiki-e
pushed a commit
that referenced
this pull request
Feb 28, 2024
taiki-e
pushed a commit
that referenced
this pull request
Feb 28, 2024
taiki-e
pushed a commit
that referenced
this pull request
Feb 28, 2024
petrosagg
pushed a commit
to petrosagg/crossbeam
that referenced
this pull request
Mar 20, 2025
petrosagg
added a commit
to petrosagg/crossbeam
that referenced
this pull request
Apr 8, 2025
This PR is fixing a regression introduced by crossbeam-rs#1084 that can lead to a double free when dropping the channel. The method `Channel::discard_all_messages` has the property that if it observes `head.block` pointing to a non-null pointer it will attempt to free it. The same property holds for the `Channel::drop` method and so it is critical that whenever `head.block` is freed it must also be set to a null pointer so that it is freed exactly once. Before crossbeam-rs#1084 the behavior of `discard_all_messages` ensured `head.block` was `null` after its execution due to the atomic store right before exiting [1]. After crossbeam-rs#1084 `discard_all_messages` atomically swaps the current value of `head.block` with a null pointer at the moment the value is read instead of waiting for the end of the function. The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug is similar to the one previously fixed by crossbeam-rs#972 and the double free can be reproduced by reverting the reproduction commit from that PR [2]. As with crossbeam-rs#972 it is quite difficult to trigger this bug without introducing artificial sleeps in critical points so this PR does not include a test. [1] https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-channel-0.5.11/crossbeam-channel/src/flavors/list.rs#L625 [2] crossbeam-rs@2d22628 Signed-off-by: Petros Angelatos <[email protected]>
taiki-e
pushed a commit
that referenced
this pull request
Apr 8, 2025
This PR is fixing a regression introduced by #1084 that can lead to a double free when dropping the channel. The method `Channel::discard_all_messages` has the property that if it observes `head.block` pointing to a non-null pointer it will attempt to free it. The same property holds for the `Channel::drop` method and so it is critical that whenever `head.block` is freed it must also be set to a null pointer so that it is freed exactly once. Before #1084 the behavior of `discard_all_messages` ensured `head.block` was `null` after its execution due to the atomic store right before exiting [1]. After #1084 `discard_all_messages` atomically swaps the current value of `head.block` with a null pointer at the moment the value is read instead of waiting for the end of the function. The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug is similar to the one previously fixed by #972 and the double free can be reproduced by reverting the reproduction commit from that PR [2]. As with #972 it is quite difficult to trigger this bug without introducing artificial sleeps in critical points so this PR does not include a test. [1] https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-channel-0.5.11/crossbeam-channel/src/flavors/list.rs#L625 [2] 2d22628 Signed-off-by: Petros Angelatos <[email protected]>
taiki-e
pushed a commit
that referenced
this pull request
Apr 8, 2025
This PR is fixing a regression introduced by #1084 that can lead to a double free when dropping the channel. The method `Channel::discard_all_messages` has the property that if it observes `head.block` pointing to a non-null pointer it will attempt to free it. The same property holds for the `Channel::drop` method and so it is critical that whenever `head.block` is freed it must also be set to a null pointer so that it is freed exactly once. Before #1084 the behavior of `discard_all_messages` ensured `head.block` was `null` after its execution due to the atomic store right before exiting [1]. After #1084 `discard_all_messages` atomically swaps the current value of `head.block` with a null pointer at the moment the value is read instead of waiting for the end of the function. The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug is similar to the one previously fixed by #972 and the double free can be reproduced by reverting the reproduction commit from that PR [2]. As with #972 it is quite difficult to trigger this bug without introducing artificial sleeps in critical points so this PR does not include a test. [1] https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-channel-0.5.11/crossbeam-channel/src/flavors/list.rs#L625 [2] 2d22628 Signed-off-by: Petros Angelatos <[email protected]>
taiki-e
pushed a commit
that referenced
this pull request
Apr 8, 2025
This PR is fixing a regression introduced by #1084 that can lead to a double free when dropping the channel. The method `Channel::discard_all_messages` has the property that if it observes `head.block` pointing to a non-null pointer it will attempt to free it. The same property holds for the `Channel::drop` method and so it is critical that whenever `head.block` is freed it must also be set to a null pointer so that it is freed exactly once. Before #1084 the behavior of `discard_all_messages` ensured `head.block` was `null` after its execution due to the atomic store right before exiting [1]. After #1084 `discard_all_messages` atomically swaps the current value of `head.block` with a null pointer at the moment the value is read instead of waiting for the end of the function. The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug is similar to the one previously fixed by #972 and the double free can be reproduced by reverting the reproduction commit from that PR [2]. As with #972 it is quite difficult to trigger this bug without introducing artificial sleeps in critical points so this PR does not include a test. [1] https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-channel-0.5.11/crossbeam-channel/src/flavors/list.rs#L625 [2] 2d22628 Signed-off-by: Petros Angelatos <[email protected]>
This was referenced Apr 10, 2025
Open
This was referenced Apr 11, 2025
facebook-github-bot
pushed a commit
to facebookincubator/reindeer
that referenced
this pull request
Apr 12, 2025
… Drop Package: crossbeam-channel 0.5.14 Summary: VULNERABILITY RUSTSEC-2025-0024 - 2025-04-08: crossbeam-channel: double free on Drop Package: crossbeam-channel 0.5.14 The internal `Channel` type's `Drop` method has a race which could, in some circumstances, lead to a double-free. This could result in memory corruption. Quoting from the [upstream description in merge request \#1187](crossbeam-rs/crossbeam#1187 (comment)): > The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug was introduced while fixing a memory leak, in upstream [MR \#1084](crossbeam-rs/crossbeam#1084), first published in 0.5.12. The fix is in upstream [MR \#1187](crossbeam-rs/crossbeam#1187) and has been published in 0.5.15 Reviewed By: dtolnay Differential Revision: D72915462 fbshipit-source-id: c53113f91eedf478646588a84d0fa3aa85a6d2a0
facebook-github-bot
pushed a commit
to facebook/pyrefly
that referenced
this pull request
Apr 12, 2025
… Drop Package: crossbeam-channel 0.5.14 Summary: VULNERABILITY RUSTSEC-2025-0024 - 2025-04-08: crossbeam-channel: double free on Drop Package: crossbeam-channel 0.5.14 The internal `Channel` type's `Drop` method has a race which could, in some circumstances, lead to a double-free. This could result in memory corruption. Quoting from the [upstream description in merge request \#1187](crossbeam-rs/crossbeam#1187 (comment)): > The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug was introduced while fixing a memory leak, in upstream [MR \#1084](crossbeam-rs/crossbeam#1084), first published in 0.5.12. The fix is in upstream [MR \#1187](crossbeam-rs/crossbeam#1187) and has been published in 0.5.15 Reviewed By: dtolnay Differential Revision: D72915462 fbshipit-source-id: c53113f91eedf478646588a84d0fa3aa85a6d2a0
facebook-github-bot
pushed a commit
to facebook/hhvm
that referenced
this pull request
Apr 12, 2025
… Drop Package: crossbeam-channel 0.5.14 Summary: VULNERABILITY RUSTSEC-2025-0024 - 2025-04-08: crossbeam-channel: double free on Drop Package: crossbeam-channel 0.5.14 The internal `Channel` type's `Drop` method has a race which could, in some circumstances, lead to a double-free. This could result in memory corruption. Quoting from the [upstream description in merge request \#1187](crossbeam-rs/crossbeam#1187 (comment)): > The problem lies in the fact that `dicard_all_messages` contained two paths that could lead to `head.block` being read but only one of them would swap the value. This meant that `dicard_all_messages` could end up observing a non-null block pointer (and therefore attempting to free it) without setting `head.block` to null. This would then lead to `Channel::drop` making a second attempt at dropping the same pointer. The bug was introduced while fixing a memory leak, in upstream [MR \#1084](crossbeam-rs/crossbeam#1084), first published in 0.5.12. The fix is in upstream [MR \#1187](crossbeam-rs/crossbeam#1187) and has been published in 0.5.15 Reviewed By: dtolnay Differential Revision: D72915462 fbshipit-source-id: c53113f91eedf478646588a84d0fa3aa85a6d2a0
This was referenced Apr 13, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Reported in rust-lang/rust#121582. This fixes a race that can occur if a sender installs the first block right after all receivers have disconnected and checked for any existing messages, causing a memory leak.