use strict provenance APIs

reviewable/pr1354/r1
Tamir Duberstein 1 month ago
parent ec3eacc1d8
commit f65c9ab641
No known key found for this signature in database

@ -39,11 +39,23 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(
clippy::all,
clippy::as_ptr_cast_mut,
//clippy::as_underscore,
clippy::cast_lossless,
//clippy::cast_possible_truncation,
//clippy::cast_possible_wrap,
clippy::cast_precision_loss,
//clippy::cast_sign_loss,
clippy::char_lit_as_u8,
clippy::fn_to_numeric_cast,
clippy::fn_to_numeric_cast_with_truncation,
clippy::mut_mut,
clippy::needless_bitwise_bool,
clippy::needless_lifetimes,
clippy::no_mangle_with_rust_abi,
clippy::ptr_as_ptr,
clippy::ptr_cast_constness,
clippy::ref_as_ptr,
clippy::unnecessary_cast,
clippy::use_self,
absolute_paths_not_starting_with_crate,

@ -300,21 +300,24 @@ mod tests {
}
fn bpf_key<T: Copy>(attr: &bpf_attr) -> Option<T> {
match unsafe { attr.__bindgen_anon_2.key } as *const T {
p if p.is_null() => None,
p => Some(unsafe { *p }),
}
let p: *const T =
std::ptr::with_exposed_provenance(unsafe { attr.__bindgen_anon_2.key } as usize);
(!p.is_null()).then(|| unsafe { *p })
}
fn set_next_key<T: Copy>(attr: &bpf_attr, next: T) -> SysResult {
let key = unsafe { attr.__bindgen_anon_2.__bindgen_anon_1.next_key } as *const T as *mut T;
unsafe { *key = next };
let p: *mut T = std::ptr::with_exposed_provenance_mut(unsafe {
attr.__bindgen_anon_2.__bindgen_anon_1.next_key
} as usize);
unsafe { *p = next };
Ok(0)
}
fn set_ret<T: Copy>(attr: &bpf_attr, ret: T) -> SysResult {
let value = unsafe { attr.__bindgen_anon_2.__bindgen_anon_1.value } as *const T as *mut T;
unsafe { *value = ret };
let p: *mut T = std::ptr::with_exposed_provenance_mut(unsafe {
attr.__bindgen_anon_2.__bindgen_anon_1.value
} as usize);
unsafe { *p = ret };
Ok(0)
}

@ -681,7 +681,7 @@ impl MapData {
pub(crate) fn finalize(&mut self) -> Result<(), MapError> {
let Self { obj, fd } = self;
if !obj.data().is_empty() {
bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0)
bpf_map_update_elem_ptr(fd.as_fd(), &0, obj.data_mut().as_mut_ptr(), 0)
.map_err(|io_error| SyscallError {
call: "bpf_map_update_elem",
io_error,
@ -1197,7 +1197,8 @@ mod tests {
);
unsafe {
let name_bytes = mem::transmute::<&[u8], &[c_char]>(TEST_NAME.as_bytes());
let map_info = attr.info.info as *mut bpf_map_info;
let map_info: *mut bpf_map_info =
std::ptr::with_exposed_provenance_mut(attr.info.info as usize);
map_info.write({
let mut map_info = map_info.read();
map_info.name[..name_bytes.len()].copy_from_slice(name_bytes);
@ -1240,7 +1241,8 @@ mod tests {
} => {
unsafe {
let info = attr.info;
let map_info = info.info as *mut bpf_map_info;
let map_info: *mut bpf_map_info =
std::ptr::with_exposed_provenance_mut(info.info as usize);
map_info.write({
let mut map_info = map_info.read();
map_info.id = info.bpf_fd - crate::MockableFd::mock_unsigned_fd();

@ -380,8 +380,9 @@ impl ProducerData {
panic!("{:?} not in {:?}", offset..offset + len, 0..data.len())
})
};
let header_ptr =
must_get_data(offset, mem::size_of::<AtomicU32>()).as_ptr() as *const AtomicU32;
let header_ptr: *const AtomicU32 = must_get_data(offset, mem::size_of::<AtomicU32>())
.as_ptr()
.cast();
// Pair the kernel's SeqCst write (implies Release) [1] with an Acquire load. This
// ensures data written by the producer will be visible.
//

@ -1,6 +1,6 @@
//! Socket filter programs.
use std::{
io, mem,
io,
os::fd::{AsFd, AsRawFd as _, RawFd},
};
@ -87,8 +87,8 @@ impl SocketFilter {
socket,
SOL_SOCKET,
SO_ATTACH_BPF as i32,
&prog_fd as *const _ as *const _,
mem::size_of::<RawFd>() as u32,
std::ptr::from_ref(&prog_fd).cast(),
std::mem::size_of_val(&prog_fd) as u32,
)
};
if ret < 0 {
@ -144,8 +144,8 @@ impl Link for SocketFilterLink {
self.socket,
SOL_SOCKET,
SO_DETACH_BPF as i32,
&self.prog_fd as *const _ as *const _,
mem::size_of::<RawFd>() as u32,
std::ptr::from_ref(&self.prog_fd).cast(),
std::mem::size_of_val(&self.prog_fd) as u32,
);
}
Ok(())

@ -1,7 +1,7 @@
//! User space probes.
use std::{
error::Error,
ffi::{CStr, OsStr, OsString, c_char},
ffi::{CStr, OsStr, OsString},
fs,
io::{self, BufRead as _, Cursor, Read as _},
mem,
@ -549,12 +549,8 @@ impl LdSoCache {
let read_str = |pos| {
use std::os::unix::ffi::OsStrExt as _;
OsStr::from_bytes(
unsafe {
CStr::from_ptr(
cursor.get_ref()[offset + pos..].as_ptr() as *const c_char
)
}
.to_bytes(),
unsafe { CStr::from_ptr(cursor.get_ref()[offset + pos..].as_ptr().cast()) }
.to_bytes(),
)
.to_owned()
};

@ -172,12 +172,12 @@ pub(crate) fn bpf_load_program(
if let Some(btf_fd) = aya_attr.prog_btf_fd {
u.prog_btf_fd = btf_fd.as_raw_fd() as u32;
if aya_attr.line_info_rec_size > 0 {
u.line_info = line_info_buf.as_ptr() as *const _ as u64;
u.line_info = line_info_buf.as_ptr().expose_provenance() as u64;
u.line_info_cnt = aya_attr.line_info.len() as u32;
u.line_info_rec_size = aya_attr.line_info_rec_size as u32;
}
if aya_attr.func_info_rec_size > 0 {
u.func_info = func_info_buf.as_ptr() as *const _ as u64;
u.func_info = func_info_buf.as_ptr().expose_provenance() as u64;
u.func_info_cnt = aya_attr.func_info.len() as u32;
u.func_info_rec_size = aya_attr.func_info_rec_size as u32;
}
@ -212,9 +212,9 @@ fn lookup<K: Pod, V: Pod>(
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
if let Some(key) = key {
u.key = key as *const _ as u64;
u.key = std::ptr::from_ref(key).expose_provenance() as u64;
}
u.__bindgen_anon_1.value = &mut value as *mut _ as u64;
u.__bindgen_anon_1.value = std::ptr::from_mut(&mut value).expose_provenance() as u64;
u.flags = flags;
match unit_sys_bpf(cmd, &mut attr) {
@ -264,7 +264,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr<K: Pod, V>(
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
if let Some(key) = key {
u.key = key as *const _ as u64;
u.key = std::ptr::from_ref(key).expose_provenance() as u64;
}
u.__bindgen_anon_1.value = value as u64;
u.flags = flags;
@ -287,9 +287,9 @@ pub(crate) fn bpf_map_update_elem<K: Pod, V: Pod>(
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
if let Some(key) = key {
u.key = key as *const _ as u64;
u.key = std::ptr::from_ref(key).expose_provenance() as u64;
}
u.__bindgen_anon_1.value = value as *const _ as u64;
u.__bindgen_anon_1.value = std::ptr::from_ref(value).expose_provenance() as u64;
u.flags = flags;
unit_sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr)
@ -304,7 +304,7 @@ pub(crate) fn bpf_map_push_elem<V: Pod>(
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
u.__bindgen_anon_1.value = value as *const _ as u64;
u.__bindgen_anon_1.value = std::ptr::from_ref(value).expose_provenance() as u64;
u.flags = flags;
unit_sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr)
@ -342,7 +342,7 @@ pub(crate) fn bpf_map_delete_elem<K: Pod>(fd: BorrowedFd<'_>, key: &K) -> io::Re
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
u.key = key as *const _ as u64;
u.key = std::ptr::from_ref(key).expose_provenance() as u64;
unit_sys_bpf(bpf_cmd::BPF_MAP_DELETE_ELEM, &mut attr)
}
@ -357,9 +357,9 @@ pub(crate) fn bpf_map_get_next_key<K: Pod>(
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
if let Some(key) = key {
u.key = key as *const _ as u64;
u.key = std::ptr::from_ref(key).expose_provenance() as u64;
}
u.__bindgen_anon_1.next_key = &mut next_key as *mut _ as u64;
u.__bindgen_anon_1.next_key = std::ptr::from_mut(&mut next_key).expose_provenance() as u64;
match unit_sys_bpf(bpf_cmd::BPF_MAP_GET_NEXT_KEY, &mut attr) {
Ok(()) => Ok(Some(unsafe { next_key.assume_init() })),
@ -573,7 +573,7 @@ fn bpf_obj_get_info_by_fd<T, F: FnOnce(&mut T)>(
init(&mut info);
attr.info.bpf_fd = fd.as_raw_fd() as u32;
attr.info.info = &info as *const _ as u64;
attr.info.info = std::ptr::from_ref(&info).expose_provenance() as u64;
attr.info.info_len = mem::size_of_val(&info) as u32;
match unit_sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &mut attr) {
@ -669,11 +669,11 @@ pub(crate) fn bpf_load_btf(
) -> io::Result<crate::MockableFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_7 };
u.btf = raw_btf.as_ptr() as *const _ as u64;
u.btf = raw_btf.as_ptr().expose_provenance() as u64;
u.btf_size = mem::size_of_val(raw_btf) as u32;
if !log_buf.is_empty() {
u.btf_log_level = verifier_log_level.bits();
u.btf_log_buf = log_buf.as_mut_ptr() as u64;
u.btf_log_buf = log_buf.as_mut_ptr().expose_provenance() as u64;
u.btf_log_size = log_buf.len() as u32;
}
// SAFETY: `BPF_BTF_LOAD` returns a newly created fd.

@ -395,7 +395,7 @@ fn probe_bpf_info<T>(fd: MockableFd, info: T) -> Result<bool, SyscallError> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.info.bpf_fd = fd.as_raw_fd() as u32;
attr.info.info_len = mem::size_of_val(&info) as u32;
attr.info.info = &info as *const _ as u64;
attr.info.info = std::ptr::from_ref(&info).expose_provenance() as u64;
let io_error = match unit_sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &mut attr) {
Ok(()) => return Ok(true),

@ -373,8 +373,8 @@ impl NetlinkSocket {
sock.as_raw_fd(),
SOL_NETLINK,
NETLINK_EXT_ACK,
&enable as *const _ as *const _,
mem::size_of::<i32>() as u32,
std::ptr::from_ref(&enable).cast(),
mem::size_of_val(&enable) as u32,
) < 0
{
return Err(NetlinkErrorInternal::IoError(io::Error::last_os_error()));
@ -385,8 +385,8 @@ impl NetlinkSocket {
sock.as_raw_fd(),
SOL_NETLINK,
NETLINK_CAP_ACK,
&enable as *const _ as *const _,
mem::size_of::<i32>() as u32,
std::ptr::from_ref(&enable).cast(),
mem::size_of_val(&enable) as u32,
) < 0
{
return Err(NetlinkErrorInternal::IoError(io::Error::last_os_error()));
@ -401,8 +401,8 @@ impl NetlinkSocket {
if unsafe {
getsockname(
sock.as_raw_fd(),
&mut addr as *mut _ as *mut _,
&mut addr_len as *mut _,
std::ptr::from_mut(&mut addr).cast(),
std::ptr::from_mut(&mut addr_len).cast(),
)
} < 0
{
@ -416,15 +416,7 @@ impl NetlinkSocket {
}
fn send(&self, msg: &[u8]) -> Result<(), NetlinkErrorInternal> {
if unsafe {
send(
self.sock.as_raw_fd(),
msg.as_ptr() as *const _,
msg.len(),
0,
)
} < 0
{
if unsafe { send(self.sock.as_raw_fd(), msg.as_ptr().cast(), msg.len(), 0) } < 0 {
return Err(NetlinkErrorInternal::IoError(io::Error::last_os_error()));
}
Ok(())
@ -437,14 +429,7 @@ impl NetlinkSocket {
'out: while multipart {
multipart = false;
// Safety: libc wrapper
let len = unsafe {
recv(
self.sock.as_raw_fd(),
buf.as_mut_ptr() as *mut _,
buf.len(),
0,
)
};
let len = unsafe { recv(self.sock.as_raw_fd(), buf.as_mut_ptr().cast(), buf.len(), 0) };
if len < 0 {
return Err(NetlinkErrorInternal::IoError(io::Error::last_os_error()));
}
@ -505,7 +490,7 @@ impl NetlinkMessage {
}
// Safety: nlmsghdr is POD so read is safe
let header = unsafe { ptr::read_unaligned(buf.as_ptr() as *const nlmsghdr) };
let header: nlmsghdr = unsafe { ptr::read_unaligned(buf.as_ptr().cast()) };
let msg_len = header.nlmsg_len as usize;
if msg_len < mem::size_of::<nlmsghdr>() || msg_len > buf.len() {
return Err(io::Error::other("invalid nlmsg_len"));
@ -525,9 +510,7 @@ impl NetlinkMessage {
(
&buf[data_offset + mem::size_of::<nlmsgerr>()..msg_len],
// Safety: nlmsgerr is POD so read is safe
Some(unsafe {
ptr::read_unaligned(buf[data_offset..].as_ptr() as *const nlmsgerr)
}),
Some(unsafe { ptr::read_unaligned(buf[data_offset..].as_ptr().cast()) }),
)
} else {
(&buf[data_offset..msg_len], None)
@ -594,8 +577,7 @@ fn write_attr<T>(
attr_type: u16,
value: T,
) -> Result<usize, io::Error> {
let value =
unsafe { slice::from_raw_parts(&value as *const _ as *const _, mem::size_of::<T>()) };
let value = bytes_of(&value);
write_attr_bytes(buf, offset, attr_type, value)
}
@ -617,9 +599,7 @@ fn write_attr_bytes(
}
fn write_attr_header(buf: &mut [u8], offset: usize, attr: nlattr) -> Result<usize, io::Error> {
let attr =
unsafe { slice::from_raw_parts(&attr as *const _ as *const _, mem::size_of::<nlattr>()) };
let attr = bytes_of(&attr);
write_bytes(buf, offset, attr)?;
Ok(NLA_HDR_LEN)
}
@ -663,7 +643,7 @@ impl<'a> Iterator for NlAttrsIterator<'a> {
}));
}
let attr = unsafe { ptr::read_unaligned(buf.as_ptr() as *const nlattr) };
let attr: nlattr = unsafe { ptr::read_unaligned(buf.as_ptr().cast()) };
let len = attr.nla_len as usize;
let align_len = align_to(len, NLA_ALIGNTO as usize);
if len < NLA_HDR_LEN {
@ -751,28 +731,32 @@ mod tests {
assert_eq!(len, nla_len);
// read IFLA_XDP
let attr = unsafe { ptr::read_unaligned(buf.as_ptr() as *const nlattr) };
let attr: nlattr = unsafe { ptr::read_unaligned(buf.as_ptr().cast()) };
assert_eq!(attr.nla_type, NLA_F_NESTED as u16 | IFLA_XDP);
assert_eq!(attr.nla_len, nla_len);
// read IFLA_XDP_FD + fd
let attr = unsafe { ptr::read_unaligned(buf[NLA_HDR_LEN..].as_ptr() as *const nlattr) };
let attr: nlattr = unsafe { ptr::read_unaligned(buf[NLA_HDR_LEN..].as_ptr().cast()) };
assert_eq!(attr.nla_type, IFLA_XDP_FD as u16);
assert_eq!(attr.nla_len, (NLA_HDR_LEN + mem::size_of::<u32>()) as u16);
let fd = unsafe { ptr::read_unaligned(buf[NLA_HDR_LEN * 2..].as_ptr() as *const u32) };
let fd: u32 = unsafe { ptr::read_unaligned(buf[NLA_HDR_LEN * 2..].as_ptr().cast()) };
assert_eq!(fd, 42);
// read IFLA_XDP_EXPECTED_FD + fd
let attr = unsafe {
let attr: nlattr = unsafe {
ptr::read_unaligned(
buf[NLA_HDR_LEN * 2 + mem::size_of::<u32>()..].as_ptr() as *const nlattr
buf[NLA_HDR_LEN * 2 + mem::size_of::<u32>()..]
.as_ptr()
.cast(),
)
};
assert_eq!(attr.nla_type, IFLA_XDP_EXPECTED_FD as u16);
assert_eq!(attr.nla_len, (NLA_HDR_LEN + mem::size_of::<u32>()) as u16);
let fd = unsafe {
let fd: u32 = unsafe {
ptr::read_unaligned(
buf[NLA_HDR_LEN * 3 + mem::size_of::<u32>()..].as_ptr() as *const u32
buf[NLA_HDR_LEN * 3 + mem::size_of::<u32>()..]
.as_ptr()
.cast(),
)
};
assert_eq!(fd, 24);

@ -417,8 +417,7 @@ pub(crate) fn page_size() -> usize {
// bytes_of converts a <T> to a byte slice
pub(crate) unsafe fn bytes_of<T: Pod>(val: &T) -> &[u8] {
let ptr: *const _ = val;
unsafe { slice::from_raw_parts(ptr.cast(), mem::size_of_val(val)) }
unsafe { slice::from_raw_parts(std::ptr::from_ref(val).cast(), mem::size_of_val(val)) }
}
pub(crate) fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
@ -436,7 +435,7 @@ pub(crate) fn bytes_of_bpf_name(bpf_name: &[core::ffi::c_char; 16]) -> &[u8] {
.rposition(|ch| *ch != 0)
.map(|pos| pos + 1)
.unwrap_or(0);
unsafe { slice::from_raw_parts(bpf_name.as_ptr() as *const _, length) }
unsafe { slice::from_raw_parts(bpf_name.as_ptr().cast(), length) }
}
// MMap corresponds to a memory-mapped region.

Loading…
Cancel
Save