Browse Source

Merge pull request #747 from aya-rs/helpers

sys: add map_ids to bpf_prog_get_info_by_fd
Tamir Duberstein 1 year ago
parent
commit
5bc922af23
4 changed files with 42 additions and 53 deletions
  1. 12 25
      aya/src/programs/extension.rs
  2. 1 1
      aya/src/programs/lirc_mode2.rs
  3. 3 3
      aya/src/programs/mod.rs
  4. 26 24
      aya/src/sys/bpf.rs

+ 12 - 25
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)

+ 1 - 1
aya/src/programs/lirc_mode2.rs

@@ -131,7 +131,7 @@ impl LircLink {
 
     /// Get ProgramInfo from this link
     pub fn info(&self) -> Result<ProgramInfo, ProgramError> {
-        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)
     }

+ 3 - 3
aya/src/programs/mod.rs

@@ -488,7 +488,7 @@ impl<T: Link> ProgramData<T> {
             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<Item = Result<ProgramInfo, ProgramErro
         })
         .map(|fd| {
             let fd = fd?;
-            bpf_prog_get_info_by_fd(fd.as_raw_fd())
+            bpf_prog_get_info_by_fd(fd.as_raw_fd(), &mut [])
         })
         .map(|result| result.map(ProgramInfo).map_err(Into::into))
 }

+ 26 - 24
aya/src/sys/bpf.rs

@@ -477,10 +477,14 @@ pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> Result<OwnedFd, SyscallErro
     })
 }
 
-fn bpf_obj_get_info_by_fd<T>(fd: BorrowedFd<'_>) -> Result<T, SyscallError> {
+fn bpf_obj_get_info_by_fd<T, F: FnOnce(&mut T)>(
+    fd: BorrowedFd<'_>,
+    init: F,
+) -> Result<T, SyscallError> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
-    // 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<T>(fd: BorrowedFd<'_>) -> Result<T, SyscallError> {
     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<T>(fd: BorrowedFd<'_>) -> Result<T, SyscallError> {
     }
 }
 
-pub(crate) fn bpf_prog_get_info_by_fd(fd: RawFd) -> Result<bpf_prog_info, SyscallError> {
+pub(crate) fn bpf_prog_get_info_by_fd(
+    fd: RawFd,
+    map_ids: &mut [u32],
+) -> Result<bpf_prog_info, SyscallError> {
     let fd = unsafe { BorrowedFd::borrow_raw(fd) };
-    bpf_obj_get_info_by_fd::<bpf_prog_info>(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_map_info, SyscallError> {
-    bpf_obj_get_info_by_fd::<bpf_map_info>(fd)
+    bpf_obj_get_info_by_fd(fd, |_| {})
 }
 
 pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result<OwnedFd, SyscallError> {
@@ -525,26 +535,18 @@ pub(crate) fn bpf_link_get_fd_by_id(link_id: u32) -> Result<OwnedFd, SyscallErro
 }
 
 pub(crate) fn bpf_link_get_info_by_fd(fd: BorrowedFd<'_>) -> Result<bpf_link_info, SyscallError> {
-    bpf_obj_get_info_by_fd::<bpf_link_info>(fd)
+    bpf_obj_get_info_by_fd(fd, |_| {})
 }
 
 pub(crate) fn btf_obj_get_info_by_fd(
-    prog_fd: RawFd,
-    buf: &[u8],
-) -> Result<bpf_btf_info, io::Error> {
-    let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
-    let mut info = unsafe { mem::zeroed::<bpf_btf_info>() };
-    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::<bpf_btf_info>() 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<bpf_btf_info, SyscallError> {
+    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<OwnedFd> {