do not leak file descriptors in lirc_mode2

reviewable/pr614/r7
Andrés Medina 2 years ago
parent d3e6d9066f
commit 4452e2f6e2

@ -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,11 +119,18 @@ impl Extension {
program: ProgramFd,
func_name: &str,
) -> Result<ExtensionLinkId, ProgramError> {
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)
// 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,
@ -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,

@ -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<ProgramInfo, ProgramError> {
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(())
}
}

@ -418,7 +418,7 @@ pub(crate) struct ProgramData<T: Link> {
pub(crate) fd: Option<OwnedFd>,
pub(crate) links: LinkMap<T>,
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_prog_fd: Option<RawFd>,
pub(crate) btf_fd: Option<RawFd>,
@ -468,7 +468,7 @@ impl<T: Link> ProgramData<T> {
io_error,
}
})?;
Some(fd as u32)
Some(fd)
} else {
None
};
@ -500,12 +500,10 @@ impl<T: Link> ProgramData<T> {
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);
@ -615,7 +613,7 @@ fn load_program<T: Link>(
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<RawFd, ProgramError> {
pub fn fd(&self) -> Result<OwnedFd, ProgramError> {
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,12 +971,10 @@ 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)
}),
)
}

@ -125,7 +125,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> {
pub(crate) kernel_version: u32,
pub(crate) expected_attach_type: Option<bpf_attach_type>,
pub(crate) prog_btf_fd: Option<RawFd>,
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_prog_fd: Option<RawFd>,
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<RawFd> {
pub(crate) fn bpf_prog_get_fd_by_id(prog_id: u32) -> io::Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
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<bpf_prog_info> {
pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: BorrowedFd<'_>) -> io::Result<bpf_prog_info> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
// 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::<bpf_prog_info>() as u32;
@ -530,13 +531,16 @@ pub(crate) fn bpf_link_get_info_by_fd(link_fd: BorrowedFd<'_>) -> io::Result<bpf
}
}
pub(crate) fn btf_obj_get_info_by_fd(prog_fd: RawFd, buf: &mut [u8]) -> io::Result<bpf_btf_info> {
pub(crate) fn btf_obj_get_info_by_fd(
prog_fd: BorrowedFd<'_>,
buf: &mut [u8],
) -> io::Result<bpf_btf_info> {
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.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::<bpf_btf_info>() as u32;
@ -579,12 +583,13 @@ pub(crate) fn bpf_load_btf(raw_btf: &[u8], log: &mut VerifierLog) -> Result<Owne
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> io::Result<RawFd> {
pub(crate) fn bpf_btf_get_fd_by_id(id: u32) -> io::Result<OwnedFd> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
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),
}
}

Loading…
Cancel
Save