programs: Plug attach_btf_obj_fd leak

`ProgramData::attach_btf_obj_fd` is now owned.  This means that
`ProgramData` now closes the file descriptor on drop.

Updates #612.
pull/748/head
Tamir Duberstein 1 year ago
parent c0a08276a6
commit d88ca62aaa
No known key found for this signature in database

@ -1,5 +1,5 @@
//! Extension programs. //! Extension programs.
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsFd as _, AsRawFd as _, OwnedFd};
use thiserror::Error; use thiserror::Error;
use object::Endianness; use object::Endianness;
@ -72,7 +72,7 @@ impl Extension {
let target_prog_fd = program.as_raw_fd(); let target_prog_fd = program.as_raw_fd();
let (btf_fd, btf_id) = get_btf_info(target_prog_fd, func_name)?; 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_btf_obj_fd = Some(btf_fd);
self.data.attach_prog_fd = Some(target_prog_fd); self.data.attach_prog_fd = Some(target_prog_fd);
self.data.attach_btf_id = Some(btf_id); self.data.attach_btf_id = Some(btf_id);
load_program(BPF_PROG_TYPE_EXT, &mut self.data) load_program(BPF_PROG_TYPE_EXT, &mut self.data)
@ -149,7 +149,7 @@ impl Extension {
/// Retrieves the FD of the BTF object for the provided `prog_fd` and the BTF ID of the function /// 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. /// 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: i32, func_name: &str) -> Result<(OwnedFd, u32), ProgramError> {
// retrieve program information // retrieve program information
let info = sys::bpf_prog_get_info_by_fd(prog_fd, &mut [])?; let info = sys::bpf_prog_get_info_by_fd(prog_fd, &mut [])?;
@ -165,7 +165,7 @@ fn get_btf_info(prog_fd: i32, func_name: &str) -> Result<(RawFd, u32), ProgramEr
// assume 4kb. if this is too small we can resize based on the size obtained in the response. // 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 mut buf = vec![0u8; 4096];
loop { loop {
let info = sys::btf_obj_get_info_by_fd(btf_fd, &mut buf)?; let info = sys::btf_obj_get_info_by_fd(btf_fd.as_fd(), &mut buf)?;
let btf_size = info.btf_size as usize; let btf_size = info.btf_size as usize;
if btf_size > buf.len() { if btf_size > buf.len() {
buf.resize(btf_size, 0u8); buf.resize(btf_size, 0u8);

@ -406,7 +406,7 @@ pub(crate) struct ProgramData<T: Link> {
pub(crate) fd: Option<RawFd>, pub(crate) fd: Option<RawFd>,
pub(crate) links: LinkMap<T>, pub(crate) links: LinkMap<T>,
pub(crate) expected_attach_type: Option<bpf_attach_type>, pub(crate) expected_attach_type: Option<bpf_attach_type>,
pub(crate) attach_btf_obj_fd: Option<u32>, pub(crate) attach_btf_obj_fd: Option<OwnedFd>,
pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>, pub(crate) attach_prog_fd: Option<RawFd>,
pub(crate) btf_fd: Option<Arc<OwnedFd>>, pub(crate) btf_fd: Option<Arc<OwnedFd>>,
@ -450,16 +450,9 @@ impl<T: Link> ProgramData<T> {
} else { } else {
None None
}; };
let attach_btf_obj_fd = if info.attach_btf_obj_id > 0 { let attach_btf_obj_fd = (info.attach_btf_obj_id != 0)
let fd = .then(|| bpf_btf_get_fd_by_id(info.attach_btf_obj_id))
bpf_btf_get_fd_by_id(info.attach_btf_obj_id).map_err(|io_error| SyscallError { .transpose()?;
call: "bpf_btf_get_fd_by_id",
io_error,
})?;
Some(fd as u32)
} else {
None
};
Ok(ProgramData { Ok(ProgramData {
name, name,
@ -604,7 +597,7 @@ fn load_program<T: Link>(
kernel_version: target_kernel_version, kernel_version: target_kernel_version,
expected_attach_type: *expected_attach_type, expected_attach_type: *expected_attach_type,
prog_btf_fd: btf_fd.as_ref().map(|f| f.as_fd()), prog_btf_fd: btf_fd.as_ref().map(|f| f.as_fd()),
attach_btf_obj_fd: *attach_btf_obj_fd, attach_btf_obj_fd: attach_btf_obj_fd.as_ref().map(|fd| fd.as_fd()),
attach_btf_id: *attach_btf_id, attach_btf_id: *attach_btf_id,
attach_prog_fd: *attach_prog_fd, attach_prog_fd: *attach_prog_fd,
func_info_rec_size: *func_info_rec_size, func_info_rec_size: *func_info_rec_size,

@ -118,7 +118,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> {
pub(crate) kernel_version: u32, pub(crate) kernel_version: u32,
pub(crate) expected_attach_type: Option<bpf_attach_type>, pub(crate) expected_attach_type: Option<bpf_attach_type>,
pub(crate) prog_btf_fd: Option<BorrowedFd<'a>>, pub(crate) prog_btf_fd: Option<BorrowedFd<'a>>,
pub(crate) attach_btf_obj_fd: Option<u32>, pub(crate) attach_btf_obj_fd: Option<BorrowedFd<'a>>,
pub(crate) attach_btf_id: Option<u32>, pub(crate) attach_btf_id: Option<u32>,
pub(crate) attach_prog_fd: Option<RawFd>, pub(crate) attach_prog_fd: Option<RawFd>,
pub(crate) func_info_rec_size: usize, pub(crate) func_info_rec_size: usize,
@ -181,7 +181,7 @@ pub(crate) fn bpf_load_program(
u.log_size = log_buf.len() as u32; u.log_size = log_buf.len() as u32;
} }
if let Some(v) = aya_attr.attach_btf_obj_fd { 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 _;
} }
if let Some(v) = aya_attr.attach_prog_fd { if let Some(v) = aya_attr.attach_prog_fd {
u.__bindgen_anon_1.attach_prog_fd = v as u32; u.__bindgen_anon_1.attach_prog_fd = v as u32;
@ -539,10 +539,9 @@ pub(crate) fn bpf_link_get_info_by_fd(fd: BorrowedFd<'_>) -> Result<bpf_link_inf
} }
pub(crate) fn btf_obj_get_info_by_fd( pub(crate) fn btf_obj_get_info_by_fd(
fd: RawFd, fd: BorrowedFd<'_>,
buf: &mut [u8], buf: &mut [u8],
) -> Result<bpf_btf_info, SyscallError> { ) -> Result<bpf_btf_info, SyscallError> {
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
bpf_obj_get_info_by_fd(fd, |info: &mut bpf_btf_info| { bpf_obj_get_info_by_fd(fd, |info: &mut bpf_btf_info| {
info.btf = buf.as_mut_ptr() as _; info.btf = buf.as_mut_ptr() as _;
info.btf_size = buf.len() as _; info.btf_size = buf.len() as _;
@ -595,14 +594,18 @@ unsafe fn fd_sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<OwnedFd> {
Ok(OwnedFd::from_raw_fd(fd)) Ok(OwnedFd::from_raw_fd(fd))
} }
pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<RawFd, io::Error> { pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> Result<OwnedFd, SyscallError> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() }; let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
attr.__bindgen_anon_6.__bindgen_anon_1.btf_id = id; attr.__bindgen_anon_6.__bindgen_anon_1.btf_id = id;
match sys_bpf(bpf_cmd::BPF_BTF_GET_FD_BY_ID, &mut attr) { // SAFETY: BPF_BTF_GET_FD_BY_ID returns a new file descriptor.
Ok(v) => Ok(v as RawFd), unsafe { fd_sys_bpf(bpf_cmd::BPF_BTF_GET_FD_BY_ID, &mut attr) }.map_err(|(code, io_error)| {
Err((_, err)) => Err(err), assert_eq!(code, -1);
SyscallError {
call: "bpf_btf_get_fd_by_id",
io_error,
} }
})
} }
pub(crate) fn is_prog_name_supported() -> bool { pub(crate) fn is_prog_name_supported() -> bool {

Loading…
Cancel
Save