Browse Source

aya: use RAII to close FDs

Tamir Duberstein 1 year ago
parent
commit
3d68fa32cb
1 changed files with 23 additions and 46 deletions
  1. 23 46
      aya/src/sys/bpf.rs

+ 23 - 46
aya/src/sys/bpf.rs

@@ -3,12 +3,12 @@ use std::{
     ffi::{CStr, CString},
     io, iter,
     mem::{self, MaybeUninit},
-    os::fd::{AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
+    os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
     slice,
 };
 
 use crate::util::KernelVersion;
-use libc::{c_char, c_long, close, ENOENT, ENOSPC};
+use libc::{c_char, c_long, ENOENT, ENOSPC};
 use obj::{
     btf::{BtfEnum64, Enum64},
     maps::{bpf_map_def, LegacyMap},
@@ -190,8 +190,7 @@ pub(crate) fn bpf_load_program(
     if let Some(v) = aya_attr.attach_btf_id {
         u.attach_btf_id = v;
     }
-    // SAFETY: BPF_PROG_LOAD returns a new file descriptor.
-    unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) }
+    bpf_prog_load(&mut attr)
 }
 
 fn lookup<K: Pod, V: Pod>(
@@ -633,14 +632,7 @@ pub(crate) fn is_prog_name_supported() -> bool {
     u.insns = insns.as_ptr() as u64;
     u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
 
-    match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
-        Ok(v) => {
-            let fd = v as RawFd;
-            unsafe { close(fd) };
-            true
-        }
-        Err(_) => false,
-    }
+    bpf_prog_load(&mut attr).is_ok()
 }
 
 pub(crate) fn is_probe_read_kernel_supported() -> bool {
@@ -664,14 +656,7 @@ pub(crate) fn is_probe_read_kernel_supported() -> bool {
     u.insns = insns.as_ptr() as u64;
     u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
 
-    match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
-        Ok(v) => {
-            let fd = v as RawFd;
-            unsafe { close(fd) };
-            true
-        }
-        Err(_) => false,
-    }
+    bpf_prog_load(&mut attr).is_ok()
 }
 
 pub(crate) fn is_perf_link_supported() -> bool {
@@ -691,18 +676,18 @@ pub(crate) fn is_perf_link_supported() -> bool {
     u.insns = insns.as_ptr() as u64;
     u.prog_type = bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT as u32;
 
-    if let Ok(fd) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
-        if let Err((_, e)) =
+    if let Ok(fd) = bpf_prog_load(&mut attr) {
+        let fd = fd.as_fd();
+        let fd = fd.as_raw_fd();
+        matches!(
             // Uses an invalid target FD so we get EBADF if supported.
-            bpf_link_create(fd as i32, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0)
-        {
+            bpf_link_create(fd, -1, bpf_attach_type::BPF_PERF_EVENT, None, 0),
             // Returns EINVAL if unsupported. EBADF if supported.
-            let res = e.raw_os_error() == Some(libc::EBADF);
-            unsafe { libc::close(fd as i32) };
-            return res;
-        }
+            Err((_, e)) if e.raw_os_error() == Some(libc::EBADF),
+        )
+    } else {
+        false
     }
-    false
 }
 
 pub(crate) fn is_bpf_global_data_supported() -> bool {
@@ -746,16 +731,10 @@ pub(crate) fn is_bpf_global_data_supported() -> bool {
         u.insns = insns.as_ptr() as u64;
         u.prog_type = bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER as u32;
 
-        if let Ok(v) = sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
-            let fd = v as RawFd;
-
-            unsafe { close(fd) };
-
-            return true;
-        }
+        bpf_prog_load(&mut attr).is_ok()
+    } else {
+        false
     }
-
-    false
 }
 
 pub(crate) fn is_bpf_cookie_supported() -> bool {
@@ -775,14 +754,7 @@ pub(crate) fn is_bpf_cookie_supported() -> bool {
     u.insns = insns.as_ptr() as u64;
     u.prog_type = bpf_prog_type::BPF_PROG_TYPE_KPROBE as u32;
 
-    match sys_bpf(bpf_cmd::BPF_PROG_LOAD, &mut attr) {
-        Ok(v) => {
-            let fd = v as RawFd;
-            unsafe { close(fd) };
-            true
-        }
-        Err(_) => false,
-    }
+    bpf_prog_load(&mut attr).is_ok()
 }
 
 pub(crate) fn is_btf_supported() -> bool {
@@ -941,6 +913,11 @@ pub(crate) fn is_btf_type_tag_supported() -> bool {
     bpf_load_btf(btf_bytes.as_slice(), &mut [], Default::default()).is_ok()
 }
 
+fn bpf_prog_load(attr: &mut bpf_attr) -> SysResult<OwnedFd> {
+    // SAFETY: BPF_PROG_LOAD returns a new file descriptor.
+    unsafe { fd_sys_bpf(bpf_cmd::BPF_PROG_LOAD, attr) }
+}
+
 fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> {
     syscall(Syscall::Bpf { cmd, attr })
 }