diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index 32a51042..ad28767e 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -1,8 +1,8 @@ //! Extension programs. -use std::os::fd::{AsRawFd, RawFd}; -use thiserror::Error; +use std::os::fd::{AsFd, AsRawFd, OwnedFd}; use object::Endianness; +use thiserror::Error; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_INET_INGRESS, bpf_prog_type::BPF_PROG_TYPE_EXT}, @@ -71,11 +71,12 @@ impl Extension { /// There are no restrictions on what functions may be replaced, so you could replace /// the main entry point of your program with an extension. pub fn load(&mut self, program: ProgramFd, func_name: &str) -> Result<(), ProgramError> { - let target_prog_fd = program.as_raw_fd(); + let target_prog_fd = program.as_fd(); let (btf_fd, btf_id) = get_btf_info(target_prog_fd, func_name)?; - self.data.attach_btf_obj_fd = Some(btf_fd as u32); - self.data.attach_prog_fd = Some(target_prog_fd); + self.data.attach_btf_obj_fd = Some(btf_fd); + // TODO (AM) + self.data.attach_prog_fd = Some(target_prog_fd.as_raw_fd()); self.data.attach_btf_id = Some(btf_id); load_program(BPF_PROG_TYPE_EXT, &mut self.data) } @@ -118,15 +119,22 @@ impl Extension { program: ProgramFd, func_name: &str, ) -> Result { - let target_fd = program.as_raw_fd(); + let target_fd = program.as_fd(); let (_, btf_id) = get_btf_info(target_fd, func_name)?; let prog_fd = self.data.fd_or_err()?; // the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS - let link_fd = bpf_link_create(prog_fd, target_fd, BPF_CGROUP_INET_INGRESS, Some(btf_id), 0) - .map_err(|(_, io_error)| ProgramError::SyscallError { - call: "bpf_link_create".to_owned(), - io_error, - })?; + // TODO (AM) + let link_fd = bpf_link_create( + prog_fd, + target_fd.as_raw_fd(), + BPF_CGROUP_INET_INGRESS, + Some(btf_id), + 0, + ) + .map_err(|(_, io_error)| ProgramError::SyscallError { + call: "bpf_link_create".to_owned(), + io_error, + })?; self.data .links .insert(ExtensionLink::new(FdLink::new(link_fd))) @@ -151,7 +159,10 @@ impl Extension { /// Retrieves the FD of the BTF object for the provided `prog_fd` and the BTF ID of the function /// with the name `func_name` within that BTF object. -fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramError> { +fn get_btf_info( + prog_fd: std::os::fd::BorrowedFd<'_>, + func_name: &str, +) -> Result<(OwnedFd, u32), ProgramError> { // retrieve program information let info = sys::bpf_prog_get_info_by_fd(prog_fd).map_err(|io_error| ProgramError::SyscallError { @@ -174,12 +185,12 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr // we need to read the btf bytes into a buffer but we don't know the size ahead of time. // assume 4kb. if this is too small we can resize based on the size obtained in the response. let mut buf = vec![0u8; 4096]; - let btf_info = match sys::btf_obj_get_info_by_fd(btf_fd, &mut buf) { + let btf_info = match sys::btf_obj_get_info_by_fd(btf_fd.as_fd(), &mut buf) { Ok(info) => { if info.btf_size > buf.len() as u32 { buf.resize(info.btf_size as usize, 0u8); let btf_info = - sys::btf_obj_get_info_by_fd(btf_fd, &mut buf).map_err(|io_error| { + sys::btf_obj_get_info_by_fd(btf_fd.as_fd(), &mut buf).map_err(|io_error| { ProgramError::SyscallError { call: "bpf_prog_get_info_by_fd".to_owned(), io_error, diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 0eff664c..b0d704b5 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -71,7 +71,7 @@ impl LircMode2 { // TODO (AM) self.data.links.insert(LircLink::new( - prog_fd.as_raw_fd(), + prog_fd.try_clone_to_owned()?, lircdev_fd.try_clone_to_owned()?, )) } @@ -104,7 +104,7 @@ impl LircMode2 { io_error, })?; - prog_fds.push(fd as RawFd); + prog_fds.push(fd); } prog_fds @@ -121,18 +121,18 @@ pub struct LircLinkId(RawFd, RawFd); #[derive(Debug)] /// An LircMode2 Link pub struct LircLink { - prog_fd: RawFd, + prog_fd: OwnedFd, target_fd: OwnedFd, } impl LircLink { - pub(crate) fn new(prog_fd: RawFd, target_fd: OwnedFd) -> LircLink { + pub(crate) fn new(prog_fd: OwnedFd, target_fd: OwnedFd) -> LircLink { LircLink { prog_fd, target_fd } } /// Get ProgramInfo from this link pub fn info(&self) -> Result { - match bpf_prog_get_info_by_fd(self.prog_fd) { + match bpf_prog_get_info_by_fd(self.prog_fd.as_fd()) { Ok(info) => Ok(ProgramInfo(info)), Err(io_error) => Err(ProgramError::SyscallError { call: "bpf_prog_get_info_by_fd".to_owned(), @@ -147,12 +147,16 @@ impl Link for LircLink { fn id(&self) -> Self::Id { // TODO (AM) - LircLinkId(self.prog_fd, self.target_fd.as_raw_fd()) + LircLinkId(self.prog_fd.as_raw_fd(), self.target_fd.as_raw_fd()) } fn detach(self) -> Result<(), ProgramError> { // TODO (AM) - let _ = bpf_prog_detach(self.prog_fd, self.target_fd.as_raw_fd(), BPF_LIRC_MODE2); + let _ = bpf_prog_detach( + self.prog_fd.as_raw_fd(), + self.target_fd.as_raw_fd(), + BPF_LIRC_MODE2, + ); Ok(()) } } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index eb6bfbc2..c0b60311 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -418,7 +418,7 @@ pub(crate) struct ProgramData { pub(crate) fd: Option, pub(crate) links: LinkMap, pub(crate) expected_attach_type: Option, - pub(crate) attach_btf_obj_fd: Option, + pub(crate) attach_btf_obj_fd: Option, pub(crate) attach_btf_id: Option, pub(crate) attach_prog_fd: Option, pub(crate) btf_fd: Option, @@ -468,7 +468,7 @@ impl ProgramData { io_error, } })?; - Some(fd as u32) + Some(fd) } else { None }; @@ -500,13 +500,11 @@ impl ProgramData { io_error, })?; - // TODO: AM - let info = bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| { - ProgramError::SyscallError { + let info = + bpf_prog_get_info_by_fd(fd.as_fd()).map_err(|io_error| ProgramError::SyscallError { call: "bpf_prog_get_info_by_fd".to_owned(), io_error, - } - })?; + })?; let info = ProgramInfo(info); let name = info.name_as_str().map(|s| s.to_string()); @@ -615,7 +613,7 @@ fn load_program( kernel_version: target_kernel_version, expected_attach_type: data.expected_attach_type, prog_btf_fd: data.btf_fd, - attach_btf_obj_fd: data.attach_btf_obj_fd, + attach_btf_obj_fd: data.attach_btf_obj_fd.as_ref().map(|f| f.as_fd()), attach_btf_id: data.attach_btf_id, attach_prog_fd: data.attach_prog_fd, func_info_rec_size: *func_info_rec_size, @@ -955,15 +953,13 @@ impl ProgramInfo { } /// Returns the fd associated with the program. - /// - /// The returned fd must be closed when no longer needed. - pub fn fd(&self) -> Result { + pub fn fd(&self) -> Result { let fd = bpf_prog_get_fd_by_id(self.0.id).map_err(|io_error| ProgramError::SyscallError { call: "bpf_prog_get_fd_by_id".to_owned(), io_error, })?; - Ok(fd as RawFd) + Ok(fd) } /// Loads a program from a pinned path in bpffs. @@ -975,13 +971,11 @@ impl ProgramInfo { io_error, })?; - // TODO (AM) - let info = bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| { - ProgramError::SyscallError { + let info = + bpf_prog_get_info_by_fd(fd.as_fd()).map_err(|io_error| ProgramError::SyscallError { call: "bpf_prog_get_info_by_fd".to_owned(), io_error, - } - })?; + })?; Ok(ProgramInfo(info)) } @@ -1012,14 +1006,12 @@ impl Iterator for ProgramsIter { io_error, }) .and_then(|fd| { - let info = bpf_prog_get_info_by_fd(fd) + bpf_prog_get_info_by_fd(fd.as_fd()) .map_err(|io_error| ProgramError::SyscallError { call: "bpf_prog_get_info_by_fd".to_owned(), io_error, }) - .map(ProgramInfo); - unsafe { libc::close(fd) }; - info + .map(ProgramInfo) }), ) } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 0bba20d3..bceb7b17 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -125,7 +125,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> { pub(crate) kernel_version: u32, pub(crate) expected_attach_type: Option, pub(crate) prog_btf_fd: Option, - pub(crate) attach_btf_obj_fd: Option, + pub(crate) attach_btf_obj_fd: Option>, pub(crate) attach_btf_id: Option, pub(crate) attach_prog_fd: Option, pub(crate) func_info_rec_size: usize, @@ -189,7 +189,7 @@ pub(crate) fn bpf_load_program( u.log_size = log_buf.capacity() as u32; } if let Some(v) = aya_attr.attach_btf_obj_fd { - u.__bindgen_anon_1.attach_btf_obj_fd = v; + u.__bindgen_anon_1.attach_btf_obj_fd = v.as_raw_fd() as u32; } if let Some(v) = aya_attr.attach_prog_fd { u.__bindgen_anon_1.attach_prog_fd = v as u32; @@ -474,23 +474,24 @@ pub(crate) fn bpf_prog_query( ret } -pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> io::Result { +pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> io::Result { let mut attr = unsafe { mem::zeroed::() }; attr.__bindgen_anon_6.__bindgen_anon_1.prog_id = prog_id; match sys_bpf(bpf_cmd::BPF_PROG_GET_FD_BY_ID, &attr) { - Ok(v) => Ok(v as RawFd), + // SAFETY: BPF_PROG_GET_FD_BY_ID returns new fd + Ok(v) => Ok(unsafe { OwnedFd::from_raw_fd(v as RawFd) }), Err((_, err)) => Err(err), } } -pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> io::Result { +pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: BorrowedFd<'_>) -> io::Result { let mut attr = unsafe { mem::zeroed::() }; // info gets entirely populated by the kernel let info = MaybeUninit::zeroed(); - attr.info.bpf_fd = prog_fd as u32; + attr.info.bpf_fd = prog_fd.as_raw_fd() as u32; attr.info.info = &info as *const _ as u64; attr.info.info_len = mem::size_of::() as u32; @@ -530,13 +531,16 @@ pub(crate) fn bpf_link_get_info_by_fd(link_fd: BorrowedFd<'_>) -> io::Result io::Result { +pub(crate) fn btf_obj_get_info_by_fd( + prog_fd: BorrowedFd<'_>, + buf: &mut [u8], +) -> io::Result { let mut attr = unsafe { mem::zeroed::() }; let mut info = unsafe { mem::zeroed::() }; let buf_size = buf.len() as u32; info.btf = buf.as_ptr() as u64; info.btf_size = buf_size; - attr.info.bpf_fd = prog_fd as u32; + attr.info.bpf_fd = prog_fd.as_raw_fd() as u32; attr.info.info = &info as *const bpf_btf_info as u64; attr.info.info_len = mem::size_of::() as u32; @@ -579,12 +583,13 @@ pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> Result io::Result { +pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> io::Result { let mut attr = unsafe { mem::zeroed::() }; attr.__bindgen_anon_6.__bindgen_anon_1.btf_id = id; match sys_bpf(bpf_cmd::BPF_BTF_GET_FD_BY_ID, &attr) { - Ok(v) => Ok(v as RawFd), + // SAFETY: BPF_BTF_GET_FD_BY_ID returns new fd + Ok(v) => Ok(unsafe { OwnedFd::from_raw_fd(v as RawFd) }), Err((_, err)) => Err(err), } } diff --git a/test/integration-ebpf/src/bpf_probe_read.rs b/test/integration-ebpf/src/bpf_probe_read.rs index 1ee8878c..7e8e6c89 100644 --- a/test/integration-ebpf/src/bpf_probe_read.rs +++ b/test/integration-ebpf/src/bpf_probe_read.rs @@ -14,8 +14,8 @@ macro_rules! read_str_bytes { ($fun:ident, $ptr:expr, $len:expr $(,)?) => { let r = unsafe { let Some(ptr) = RESULT.get_ptr_mut(0) else { - return; - }; + return; + }; &mut *ptr };