rustsec-2023-0078
Vulnerability from osv_rustsec
The implementation of the [Instrumented::into_inner] method in affected
versions of this crate contains undefined behavior due to incorrect use of
[std::mem::forget] The function creates *const pointers to self, calls
[mem::forget(self)][std::mem::forget], and then moves values out of those
pointers using [std::ptr::read].
// To manually destructure `Instrumented` without `Drop`, we
// move it into a ManuallyDrop and use pointers to its fields
let span: *const Span = &this.span;
let inner: *const ManuallyDrop<T> = &this.inner;
mem::forget(self);
// SAFETY: Those pointers are valid for reads, because `Drop` didn't
// run, and properly aligned, because `Instrumented` isn't
// `#[repr(packed)]`.
let _span = unsafe { span.read() };
let inner = unsafe { inner.read() };
However, the [mem::forget documentation][std::mem::forget] states:
Any resources the value manages, such as heap memory or a file handle, will linger forever in an unreachable state. However, it does not guarantee that pointers to this memory will remain valid.
This means that these pointers are no longer valid. This could result in a stack
use-after-free if LLVM chooses to reuse self's stack slot for a rebinding
after the call to [std::mem::forget].
This undefined behavior has not been observed to cause miscompilation as of Rust
1.73.0. However, any use of this method with the affected versions of tracing
are unsound.
The flaw was corrected in commit 20a1762 (PR #2765) by replacing the use of
[std::mem::forget] with std::mem::ManuallyDrop, ensuring that the stack slot
is not reused and the pointers remain valid when they are read. The fix is
published in tracing v0.1.40. Affected versions have been yanked from
crates.io.
Thanks to Taylor Cramer and Manish Goregaokar for finding and correcting this issue!
{
"affected": [
{
"database_specific": {
"categories": [
"memory-corruption"
],
"cvss": null,
"informational": "unsound"
},
"ecosystem_specific": {
"affected_functions": null,
"affects": {
"arch": [],
"functions": [
"tracing::instrument::Instrumented::into_inner"
],
"os": []
}
},
"package": {
"ecosystem": "crates.io",
"name": "tracing",
"purl": "pkg:cargo/tracing"
},
"ranges": [
{
"events": [
{
"introduced": "0.1.38-0"
},
{
"fixed": "0.1.40"
}
],
"type": "SEMVER"
}
],
"versions": []
}
],
"aliases": [
"GHSA-8f24-6m29-wm2r"
],
"database_specific": {
"license": "CC0-1.0"
},
"details": "The implementation of the [`Instrumented::into_inner`] method in affected\nversions of this crate contains undefined behavior due to incorrect use of\n[`std::mem::forget`] The function creates `*const` pointers to `self`, calls\n[`mem::forget(self)`][`std::mem::forget`], and then moves values out of those\npointers using [`std::ptr::read`].\n\n```rust\n// To manually destructure `Instrumented` without `Drop`, we\n// move it into a ManuallyDrop and use pointers to its fields\nlet span: *const Span = \u0026this.span;\nlet inner: *const ManuallyDrop\u003cT\u003e = \u0026this.inner;\nmem::forget(self);\n// SAFETY: Those pointers are valid for reads, because `Drop` didn\u0027t\n// run, and properly aligned, because `Instrumented` isn\u0027t\n// `#[repr(packed)]`.\nlet _span = unsafe { span.read() };\nlet inner = unsafe { inner.read() };\n```\n\nHowever, the [`mem::forget` documentation][`std::mem::forget`] states:\n\n\u003e Any resources the value manages, such as heap memory or a file handle, will\n\u003e linger forever in an unreachable state. **However, it does not guarantee that\n\u003e pointers to this memory will remain valid.**\n\nThis means that these pointers are no longer valid. This could result in a stack\nuse-after-free if LLVM chooses to reuse `self`\u0027s stack slot for a rebinding\nafter the call to [`std::mem::forget`].\n\nThis undefined behavior has not been observed to cause miscompilation as of Rust\n1.73.0. However, any use of this method with the affected versions of `tracing`\nare unsound.\n\nThe flaw was corrected in commit [20a1762] ([PR #2765]) by replacing the use of\n[`std::mem::forget`] with `std::mem::ManuallyDrop`, ensuring that the stack slot\nis not reused and the pointers remain valid when they are read. The fix is\npublished in `tracing` [v0.1.40]. Affected versions have been yanked from\ncrates.io.\n\nThanks to [Taylor Cramer] and [Manish Goregaokar] for finding and correcting\nthis issue!\n\n[`Instrumented::into_inner`]:\n https://docs.rs/tracing/latest/tracing/instrument/struct.Instrumented.html#method.into_inner\n[`std::mem::forget`]: https://doc.rust-lang.org/std/mem/fn.forget.html\n[`std::ptr::read`]:\n https://doc.rust-lang.org/std/primitive.pointer.html#method.read-1\n[20a1762]:\n https://github.com/tokio-rs/tracing/commit/20a1762b3fd5f1fafead198fd18e469c68683721\n[PR #2765]: https://github.com/tokio-rs/tracing/pull/2765\n[v0.1.40]: https://crates.io/crates/tracing/0.1.40\n[Taylor Cramer]: https://github.com/cramertj\n[Manish Goregaokar]: https://github.com/manishearth",
"id": "RUSTSEC-2023-0078",
"modified": "2024-02-10T15:57:43Z",
"published": "2023-10-19T12:00:00Z",
"references": [
{
"type": "PACKAGE",
"url": "https://crates.io/crates/tracing"
},
{
"type": "ADVISORY",
"url": "https://rustsec.org/advisories/RUSTSEC-2023-0078.html"
},
{
"type": "WEB",
"url": "https://github.com/tokio-rs/tracing/pull/2765"
}
],
"related": [],
"severity": [],
"summary": "Potential stack use-after-free in `Instrumented::into_inner`"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.