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

HeaderMap::Drain can cause data race #355

Closed
Qwaz opened this issue Nov 16, 2019 · 1 comment · Fixed by #362
Closed

HeaderMap::Drain can cause data race #355

Qwaz opened this issue Nov 16, 2019 · 1 comment · Fixed by #362
Labels
A-headers Area: HTTP headers E-hard Effort: hard. S-bug Severity: bug. Something is wrong!

Comments

@Qwaz
Copy link

Qwaz commented Nov 16, 2019

http/src/header/map.rs

Lines 2099 to 2102 in 9c05e39

impl<'a, T> Iterator for Drain<'a, T> {
type Item = (HeaderName, ValueDrain<'a, T>);
fn next(&mut self) -> Option<Self::Item> {

HeaderMap::Drain implements Iterator trait with Item = (HeaderName, ValueDrain<'a, T>). This definition makes it possible to create multiple mutable references to the underlying HeaderMap by creating multiple ValueDrain, because there is no relation between the lifetime of &mut self and the returned ValueDrain.

This bug may invalidate ValueDrain iterators or make them return incorrect results. In multi-threaded scenario, the bug allows multiple threads to mutate underlying Vec at the same time, which I believe exploitable. However, I expect no code is sending ValueDrain to the other thread in practice.

Demonstration

@seanmonstar
Copy link
Member

seanmonstar commented Nov 25, 2019

Yea, the call to extra_values.swap_remove isn't synchronized, so that's a problem. I think the solutions both have downsides, but I'll list them out:

  • Remove the impl Send for ValueDrain, but this is an API breaking change. I suspect this should be incredibly uncommon. Perhaps the only sort of way someone would be affected is if using rayon::par_iter or similar with this.
  • Put a Mutex into the ValueDrain. This negatively affects everyone for such a rare occurrence.
  • Re-write the internals of HeaderMap to not store all extra values in a single Vec. This seems like the worst option, as it will take longer to do, and also negatively impacts memory usage and fragmentation.

@seanmonstar seanmonstar added A-headers Area: HTTP headers E-hard Effort: hard. S-bug Severity: bug. Something is wrong! labels Nov 25, 2019
roy-work added a commit to roy-work/advisory-db that referenced this issue Jan 9, 2020
…0.1.20

I believe these two vulnerabilities were patched at 0.1.20.

For RUSTSEC-2019-0033:

The advisory links to the bug: hyperium/http#352
In that bug, the fixing PR was hyperium/http#360
That PR merged the commit 81ceb61 to fix the bug; that commit, according to
GitHub, was first picked up by tag v0.1.20 ([commit][1]).

[1]: hyperium/http@81ceb61

For RUSTSEC-2019-0034:

This advisory is two separate GitHub issues against `HeaderMap::drain`,
http rustsec#354 and http rustsec#355.

For the first: the issue: hyperium/http#354
In that bug, the fixing PR was hyperium/http#357
That PR merged the commit 82d53db to fix the bug; that commit, according to
GitHub, was first picked up by tag v0.1.20 ([commit][2]).

[2]: hyperium/http@82d53db

For the second: the issue: hyperium/http#355
In that bug, the fixing PR was hyperium/http#362
That PR merged the commit 8ffe094 to fix the bug; that commit, according to
GitHub, was first picked up by tag v0.1.20 ([commit][3]).

[3]: hyperium/http@8ffe094
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-headers Area: HTTP headers E-hard Effort: hard. S-bug Severity: bug. Something is wrong!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants