MapGuard dereferences to a dangling pointer
Qwaz opened this issue · 5 comments
Hello fellow Rustacean,
we (Rust group @sslab-gatech) are scanning Rust code on crates.io for potential memory safety and soundness bugs and found an issue in this crate which allows safe Rust code to exhibit an undefined behavior.
Issue Description
Lines 279 to 293 in b5ec44c
Lines 230 to 242 in b5ec44c
As noted in the comment, unsafe code in MapGuard
expects the underlying guard type to dereferences to the same value even when the guard object is moved. However, Map
uses Access
as a trait bound which does not guarantee this property. As a result, Map
accesses a dangling pointer when it is used with an Access
implementation that does not dereferences to the same value when moved.
Lines 295 to 322 in b5ec44c
Constant
seems to be the only type in this crate that implements Access
in this way, but there can be other user types that implements Access
on their own.
Reproduction
Below is an example program that segfaults, written only with safe APIs of arc-swap
.
Show Detail
#![forbid(unsafe_code)]
use arc_swap::access::Map;
use arc_swap::access::{Access, Constant};
static CORRECT_ADDR: &str = "I'm pointing to the correct location!";
#[derive(Clone)]
struct MemoryChecker {
// should be always CORRECT_ADDR
message: &'static str,
}
impl MemoryChecker {
pub fn new() -> Self {
MemoryChecker {
message: CORRECT_ADDR,
}
}
pub fn validate(&self) {
println!(
"Pointing to {:?}, len {}",
self.message as *const _,
self.message.len()
);
println!("Message: {}", self.message);
}
}
fn overwrite() {
let a = 123;
let b = 456;
println!("Overwriting stack content {} {}", a, b);
}
fn main() {
let constant = Constant(MemoryChecker::new());
constant.0.validate();
// Create a map with identity mapping
let map = Map::new(constant, |checker: &MemoryChecker| checker);
// After calling this, `value` pointer of `MapGuard` points to a dangling stack address
let loaded = map.load();
overwrite();
loaded.validate();
}
Output:
Pointing to 0x55dcc9269000, len 37
Message: I'm pointing to the correct location!
Overwriting stack content 123 456
Pointing to 0x55dcc9267530, len 140726361573556
Terminated with signal 11 (SIGSEGV)
Tested Environment
- Crate: arc-swap
- Version: 1.0.0
- OS: Ubuntu 20.04.1 LTS
- Rustc version: rustc 1.48.0 (7eac88abb 2020-11-16)
Hello
It's a great discovery, though disturbing this has slipped through. I'll have to think how to plug this problem in a way that doesn't disrupt users too much, but I'll have a look at it today or tomorrow.
Thank you for finding it.
Fix released as 1.1.0 (by eliminating all unsafe code in that file).
It is technically a breaking change, but the chance of actually breaking code is low and the chance people will migrate from the broken version are higher this way, and even rustc makes an exception for soundness issues in the stability guarantees. It seems less bad to release as part of the 1. version.
Added a backport, released as 0.4.8
, for all the reverse dependencies that didn't migrate to the 1.
version yet.
Thank you for the quick fix!
CVE-2020-35711 was assigned to this issue.