-
Notifications
You must be signed in to change notification settings - Fork 32
Closed
Description
A heap-buffer-overflow vulnerability exists in the Rust wrapper for libnftnl, triggered via the nftnl::Batch::with_page_size constructor. When a small or malformed page size is provided, the underlying C code allocates an insufficient buffer, leading to out-of-bounds writes during batch initialization.
Crash Information
Error Type: Heap-buffer-overflow (AddressSanitizer)
Input: 4 bytes, e.g.:
data = [255, 254, 240, 12]
data len = 4
ASan report
==2172050==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7b42c86e0040 at pc 0x563922b4b176 bp 0x7ffc4dac0090 sp 0x7ffc4dabf850
WRITE of size 4 at 0x7b42c86e0040 thread T0
#0 0x563922b4b175 in memset /Rust-Lib-Testing/src/rust/src/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:87:3
#1 0x7f22c93813d2 in mnl_nlmsg_put_extra_header (/lib/x86_64-linux-gnu/libmnl.so.0+0x23d2) (BuildId: 802cd79dcbdf324a4e373dfabcb6eaede0813d9a)
#2 0x7f22c991774b in nftnl_batch_begin (/lib/x86_64-linux-gnu/libnftnl.so.11+0xb74b) (BuildId: 8751267ba57814422c1ce67b70d1392640e2fffb)
#3 0x563922b8a5fe in nftnl::batch::Batch::write_begin_msg::hc994c1a26a827f39 /Rust-Lib-Testing/tests2/nftnl-rs/nftnl/src/batch.rs:107:18
#4 0x563922b8a5fe in nftnl::batch::Batch::with_page_size::h05a4e8017eba0d90 /Rust-Lib-Testing/tests2/nftnl-rs/nftnl/src/batch.rs:61:9
#5 0x563922b83325 in replay_nftnl0::test_function0::h9aa3123b4a034745 /Rust-Lib-Testing/tests2/nftnl-rs/fuzz_target/nftnl_wubfs_generic_fuzz/multipleTargets/replay_nftnl0/src/main.rs:40:23
#6 0x563922b83325 in replay_nftnl0::main::h680382695cc4a2a9 /Rust-Lib-Testing/tests2/nftnl-rs/fuzz_target/nftnl_wubfs_generic_fuzz/multipleTargets/replay_nftnl0/src/main.rs:75:5
#7 0x563922b7f8d2 in core::ops::function::FnOnce::call_once::h4f174a2df974819d /Rust-Lib-Testing/src/rust/library/core/src/ops/function.rs:250:5
#8 0x563922b7f8d2 in std::sys::backtrace::__rust_begin_short_backtrace::h4d958b27e2608b20 /Rust-Lib-Testing/src/rust/library/std/src/sys/backtrace.rs:152:18
#9 0x563922b7f8b8 in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hf29da7ae1471a052 /Rust-Lib-Testing/src/rust/library/std/src/rt.rs:199:18
#10 0x563922bb1f14 in std::rt::lang_start_internal::h0cf56da6010e8a06 (/Rust-Lib-Testing/tests2/nftnl-rs/fuzz_target/nftnl_wubfs_generic_fuzz/multipleTargets/target/debug/replay_nftnl0+0x18bf14) (BuildId: ae369495f5b0e5b16d87bff14ba3361e81352396)
#11 0x563922b844c3 in main (/Rust-Lib-Testing/tests2/nftnl-rs/fuzz_target/nftnl_wubfs_generic_fuzz/multipleTargets/target/debug/replay_nftnl0+0x15e4c3) (BuildId: ae369495f5b0e5b16d87bff14ba3361e81352396)
#12 0x7f22c95ab082 in __libc_start_main /build/glibc-B3wQXB/glibc-2.31/csu/../csu/libc-start.c:308:16
#13 0x563922a7e06d in _start (/Rust-Lib-Testing/tests2/nftnl-rs/fuzz_target/nftnl_wubfs_generic_fuzz/multipleTargets/target/debug/replay_nftnl0+0x5806d) (BuildId: ae369495f5b0e5b16d87bff14ba3361e81352396)
replay file
extern crate nftnl;
use std::ffi::{CString, CStr, OsString, OsStr};
use std::path::{PathBuf, Path};
use std::os::raw::{
c_char, c_int, c_uint, c_long, c_ulong, c_short, c_ushort,
c_longlong, c_ulonglong, c_float, c_double, c_void,
};
use std::str;
fn _to_u8(data:&[u8], index:usize)->u8 {
if index >= data.len() {
use std::process;
process::exit(0);
}
data[index]
}
fn _to_u32(data:&[u8], index:usize)->u32 {
if index + 3 >= data.len() {
use std::process;
process::exit(0);
}
let data0 = _to_u16(data, index) as u32;
let data1 = _to_u16(data, index+2) as u32;
data0 << 16 | data1
}
fn _to_u16(data:&[u8], index:usize)->u16 {
if index + 1 >= data.len() {
use std::process;
process::exit(0);
}
let data0 = _to_u8(data, index) as u16;
let data1 = _to_u8(data, index + 1) as u16;
data0 << 8 | data1
}
fn test_function0(_param0: u32) {
unsafe {
let _local0 = nftnl::Batch::with_page_size(_param0);
nftnl::Batch::as_raw_batch(&(_local0));
let _local2 = nftnl::Batch::finalize(_local0);
nftnl::FinalizedBatch::iter(&(_local2));
}
}
fn _read_data()-> Vec<u8> {
use std::env;
use std::process::exit;
let args:Vec<String> = env::args().collect();
if args.len() < 2 {
println!("No crash filename provided");
exit(-1);
}
use std::path::PathBuf;
let crash_file_name = &args[1];
let crash_path = PathBuf::from(crash_file_name);
if !crash_path.is_file() {
println!("Not a valid crash file");
exit(-1);
}
use std::fs;
let data = fs::read(crash_path).unwrap();
data
}
fn main() {
let _content = _read_data();
let data = &_content;
println!("data = {:?}", data);
println!("data len = {:?}", data.len());
//actual body emit
if data.len() != 4 {return;}
let _param0 = _to_u32(data, 0);
test_function0(_param0);
}Metadata
Metadata
Assignees
Labels
No labels