Bug
In library/std/src/sys/net/connection/socket/unix.rs (lines 524-532), the acceptfilter() method returns a &CStr that references stack-local memory:
pub fn acceptfilter(&self) -> io::Result<&CStr> {
let arg: libc::accept_filter_arg =
unsafe { getsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER)? };
let s: &[u8] =
unsafe { core::slice::from_raw_parts(arg.af_name.as_ptr() as *const u8, 16) };
let name = CStr::from_bytes_with_nul(s).unwrap();
Ok(name)
}
arg is a stack-local accept_filter_arg. The from_raw_parts creates a slice borrowing arg.af_name on the stack. The returned &CStr has its lifetime tied to &self, but the data it points to is dropped when the function returns. This is a use-after-free.
Impact
Any program calling .acceptfilter() on a TcpListener on FreeBSD/NetBSD reads freed stack memory, producing garbage or crashing. Behind unstable feature gate acceptfilter (issue rust-lang#121891).
Fix
Return an owned CString instead of &CStr:
pub fn acceptfilter(&self) -> io::Result<CString> {
let arg: libc::accept_filter_arg =
unsafe { getsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER)? };
let s: &[u8] =
unsafe { core::slice::from_raw_parts(arg.af_name.as_ptr() as *const u8, 16) };
let name = CStr::from_bytes_with_nul(s).unwrap();
Ok(name.to_owned())
}
Bug
In
library/std/src/sys/net/connection/socket/unix.rs(lines 524-532), theacceptfilter()method returns a&CStrthat references stack-local memory:argis a stack-localaccept_filter_arg. Thefrom_raw_partscreates a slice borrowingarg.af_nameon the stack. The returned&CStrhas its lifetime tied to&self, but the data it points to is dropped when the function returns. This is a use-after-free.Impact
Any program calling
.acceptfilter()on aTcpListeneron FreeBSD/NetBSD reads freed stack memory, producing garbage or crashing. Behind unstable feature gateacceptfilter(issue rust-lang#121891).Fix
Return an owned
CStringinstead of&CStr: