diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index 143c909f..3c389791 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -151,7 +151,7 @@ impl Extension { /// with the name `func_name` within that BTF object. fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramError> { // retrieve program information - let info = sys::bpf_prog_get_info_by_fd(prog_fd)?; + let info = sys::bpf_prog_get_info_by_fd(prog_fd, &mut [])?; // btf_id refers to the ID of the program btf that was loaded with bpf(BPF_BTF_LOAD) if info.btf_id == 0 { @@ -159,36 +159,23 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr } // the bpf fd of the BTF object - let btf_fd = sys::bpf_btf_get_fd_by_id(info.btf_id).map_err(|io_error| SyscallError { - call: "bpf_btf_get_fd_by_id", - io_error, - })?; + let btf_fd = sys::bpf_btf_get_fd_by_id(info.btf_id)?; // 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, &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, &buf).map_err(|io_error| SyscallError { - call: "bpf_prog_get_info_by_fd", - io_error, - })?; - Ok(btf_info) - } else { - Ok(info) - } + loop { + let info = sys::btf_obj_get_info_by_fd(btf_fd, &mut buf)?; + let btf_size = info.btf_size as usize; + if btf_size > buf.len() { + buf.resize(btf_size, 0u8); + continue; } - Err(io_error) => Err(SyscallError { - call: "bpf_prog_get_info_by_fd", - io_error, - }), - }?; + buf.truncate(btf_size); + break; + } - let btf = Btf::parse(&buf[0..btf_info.btf_size as usize], Endianness::default()) - .map_err(ProgramError::Btf)?; + let btf = Btf::parse(&buf, Endianness::default()).map_err(ProgramError::Btf)?; let btf_id = btf .id_by_type_name_kind(func_name, BtfKind::Func) diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index e39bbf1a..39e1d820 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -131,7 +131,7 @@ impl LircLink { /// Get ProgramInfo from this link pub fn info(&self) -> Result { - bpf_prog_get_info_by_fd(self.prog_fd) + bpf_prog_get_info_by_fd(self.prog_fd, &mut []) .map(ProgramInfo) .map_err(Into::into) } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index eab30abe..ff643fa5 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -488,7 +488,7 @@ impl ProgramData { io_error, })?; - let info = bpf_prog_get_info_by_fd(fd.as_raw_fd())?; + let info = bpf_prog_get_info_by_fd(fd.as_raw_fd(), &mut [])?; let name = ProgramInfo(info).name_as_str().map(|s| s.to_string()); ProgramData::from_bpf_prog_info(name, fd, path.as_ref(), info, verifier_log_level) } @@ -955,7 +955,7 @@ impl ProgramInfo { io_error, })?; - let info = bpf_prog_get_info_by_fd(fd.as_raw_fd())?; + let info = bpf_prog_get_info_by_fd(fd.as_raw_fd(), &mut [])?; Ok(ProgramInfo(info)) } } @@ -991,7 +991,7 @@ pub fn loaded_programs() -> impl Iterator Result(fd: BorrowedFd<'_>) -> Result { +fn bpf_obj_get_info_by_fd( + fd: BorrowedFd<'_>, + init: F, +) -> Result { let mut attr = unsafe { mem::zeroed::() }; - // info gets entirely populated by the kernel - let info = MaybeUninit::zeroed(); + let mut info = unsafe { mem::zeroed() }; + + init(&mut info); attr.info.bpf_fd = fd.as_raw_fd() as u32; attr.info.info = &info as *const _ as u64; @@ -489,7 +493,7 @@ fn bpf_obj_get_info_by_fd(fd: BorrowedFd<'_>) -> Result { match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &mut attr) { Ok(code) => { assert_eq!(code, 0); - Ok(unsafe { info.assume_init() }) + Ok(info) } Err((code, io_error)) => { assert_eq!(code, -1); @@ -501,13 +505,19 @@ fn bpf_obj_get_info_by_fd(fd: BorrowedFd<'_>) -> Result { } } -pub(crate) fn bpf_prog_get_info_by_fd(fd: RawFd) -> Result { +pub(crate) fn bpf_prog_get_info_by_fd( + fd: RawFd, + map_ids: &mut [u32], +) -> Result { let fd = unsafe { BorrowedFd::borrow_raw(fd) }; - bpf_obj_get_info_by_fd::(fd) + bpf_obj_get_info_by_fd(fd, |info: &mut bpf_prog_info| { + info.nr_map_ids = map_ids.len() as _; + info.map_ids = map_ids.as_mut_ptr() as _; + }) } pub(crate) fn bpf_map_get_info_by_fd(fd: BorrowedFd<'_>) -> Result { - bpf_obj_get_info_by_fd::(fd) + bpf_obj_get_info_by_fd(fd, |_| {}) } pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result { @@ -525,26 +535,18 @@ pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result) -> Result { - bpf_obj_get_info_by_fd::(fd) + bpf_obj_get_info_by_fd(fd, |_| {}) } pub(crate) fn btf_obj_get_info_by_fd( - prog_fd: RawFd, - buf: &[u8], -) -> 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.info = &info as *const bpf_btf_info as u64; - attr.info.info_len = mem::size_of::() as u32; - - match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &mut attr) { - Ok(_) => Ok(info), - Err((_, err)) => Err(err), - } + fd: RawFd, + buf: &mut [u8], +) -> Result { + let fd = unsafe { BorrowedFd::borrow_raw(fd) }; + bpf_obj_get_info_by_fd(fd, |info: &mut bpf_btf_info| { + info.btf = buf.as_mut_ptr() as _; + info.btf_size = buf.len() as _; + }) } pub(crate) fn bpf_raw_tracepoint_open(name: Option<&CStr>, prog_fd: RawFd) -> SysResult {