Callback handling contains UB and may lead to use-after-free
Opened this issue · 1 comments
jasonyu1996 commented
ConfigBuilder::with_callback receives an owned cb the address of which is assigned to cfg.decode.context.
libipt-rs/src/config/config.rs
Line 230 in b312bc7
The callback is later invoked in decode_callback.
libipt-rs/src/config/config.rs
Line 201 in b312bc7
However, cb only lives until the end of with_callback. This can lead to use-after-free, as demonstrated by this test case below:
#[test]
fn test_bad_callback() {
let mut data = [18; 3];
let c = {
let counter = [1, 2, 3, 4, 5, 6, 7, 8];
ConfigBuilder::with_callback(
&mut data,
move |c, p| {
assert_eq!(counter, [1, 2, 3, 4, 5, 6, 7, 8]); // counter points to freed memory
(Unknown::new(c.0.cpu.model + p[0]), 1) })
}.unwrap().finish();
unsafe {
let mut ukn: pt_packet_unknown = std::mem::zeroed();
let _ = c.0.decode.callback.unwrap()(&mut ukn,
c.0.as_ref(), c.0.begin,
c.0.decode.context);
}
}
Marcondiro commented
Thanks for the report!
The decoder callback functionality will be removed from the next version, which more broadly aims to make this crate safer.
If anyone is willing to fix this, PRs are welcome!