Skip to content

Commit

Permalink
programs: ProgramFd is owned
Browse files Browse the repository at this point in the history
`ProgramData::fd` is now a `ProgramFd`. This means that `ProgramData`
now closes the file descriptor on drop. In the future we might consider
making `ProgramFd` hold a `BorrowedFd` but this requires API design work
due to overlapping borrows.

Since `ProgramFd` is no longer `Copy`, update methods to take it by
reference to allow callers to use it multiple times as they are
accustomed to doing.

`ProgramFd` is now returned by reference and implements `try_clone` to
allow callers to avoid file descriptor cloning when desired.

This is an API breaking change.

Updates #612.
  • Loading branch information
tamird committed Aug 14, 2023
1 parent 7874ad9 commit 504fd1d
Show file tree
Hide file tree
Showing 24 changed files with 251 additions and 170 deletions.
13 changes: 7 additions & 6 deletions aya/src/maps/array/program_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::{
borrow::{Borrow, BorrowMut},
os::fd::{AsRawFd, RawFd},
os::fd::{AsFd as _, AsRawFd as _, RawFd},
};

use crate::{
Expand Down Expand Up @@ -37,13 +37,13 @@ use crate::{
/// let flags = 0;
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 0) will jump to prog_0
/// prog_array.set(0, prog_0_fd, flags);
/// prog_array.set(0, &prog_0_fd, flags);
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 1) will jump to prog_1
/// prog_array.set(1, prog_1_fd, flags);
/// prog_array.set(1, &prog_1_fd, flags);
///
/// // bpf_tail_call(ctx, JUMP_TABLE, 2) will jump to prog_2
/// prog_array.set(2, prog_2_fd, flags);
/// prog_array.set(2, &prog_2_fd, flags);
/// # Ok::<(), aya::BpfError>(())
/// ```
#[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
Expand Down Expand Up @@ -73,11 +73,12 @@ impl<T: BorrowMut<MapData>> ProgramArray<T> {
///
/// When an eBPF program calls `bpf_tail_call(ctx, prog_array, index)`, control
/// flow will jump to `program`.
pub fn set(&mut self, index: u32, program: ProgramFd, flags: u64) -> Result<(), MapError> {
pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut();
check_bounds(data, index)?;
let fd = data.fd_or_err()?;
let prog_fd = program.as_raw_fd();
let prog_fd = program.as_fd();
let prog_fd = prog_fd.as_raw_fd();

bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| {
SyscallError {
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/perf/async_perf_event_array.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bytes::BytesMut;
use std::{
borrow::{Borrow, BorrowMut},
os::fd::{AsRawFd, RawFd},
os::fd::{AsRawFd as _, RawFd},
};

// See https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features.
Expand Down
6 changes: 4 additions & 2 deletions aya/src/programs/cgroup_device.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Cgroup device programs.

use crate::util::KernelVersion;
use std::os::fd::AsRawFd;
use std::os::fd::{AsFd as _, AsRawFd};

use crate::{
generated::{bpf_attach_type::BPF_CGROUP_DEVICE, bpf_prog_type::BPF_PROG_TYPE_CGROUP_DEVICE},
Expand Down Expand Up @@ -61,7 +61,9 @@ impl CgroupDevice {
///
/// The returned value can be used to detach, see [CgroupDevice::detach]
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<CgroupDeviceLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let cgroup_fd = cgroup.as_raw_fd();

if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
Expand Down
10 changes: 8 additions & 2 deletions aya/src/programs/cgroup_skb.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
//! Cgroup skb programs.

use crate::util::KernelVersion;
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use std::{
hash::Hash,
os::fd::{AsFd as _, AsRawFd},
path::Path,
};

use crate::{
generated::{
Expand Down Expand Up @@ -88,7 +92,9 @@ impl CgroupSkb {
cgroup: T,
attach_type: CgroupSkbAttachType,
) -> Result<CgroupSkbLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let cgroup_fd = cgroup.as_raw_fd();

let attach_type = match attach_type {
Expand Down
10 changes: 8 additions & 2 deletions aya/src/programs/cgroup_sock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
pub use aya_obj::programs::CgroupSockAttachType;

use crate::util::KernelVersion;
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use std::{
hash::Hash,
os::fd::{AsFd as _, AsRawFd},
path::Path,
};

use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK,
Expand Down Expand Up @@ -67,7 +71,9 @@ impl CgroupSock {
///
/// The returned value can be used to detach, see [CgroupSock::detach].
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<CgroupSockLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let cgroup_fd = cgroup.as_raw_fd();
let attach_type = self.data.expected_attach_type.unwrap();
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
Expand Down
10 changes: 8 additions & 2 deletions aya/src/programs/cgroup_sock_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
pub use aya_obj::programs::CgroupSockAddrAttachType;

use crate::util::KernelVersion;
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use std::{
hash::Hash,
os::fd::{AsFd as _, AsRawFd},
path::Path,
};

use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
Expand Down Expand Up @@ -68,7 +72,9 @@ impl CgroupSockAddr {
///
/// The returned value can be used to detach, see [CgroupSockAddr::detach].
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<CgroupSockAddrLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let cgroup_fd = cgroup.as_raw_fd();
let attach_type = self.data.expected_attach_type.unwrap();
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
Expand Down
10 changes: 8 additions & 2 deletions aya/src/programs/cgroup_sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
pub use aya_obj::programs::CgroupSockoptAttachType;

use crate::util::KernelVersion;
use std::{hash::Hash, os::fd::AsRawFd, path::Path};
use std::{
hash::Hash,
os::fd::{AsFd as _, AsRawFd},
path::Path,
};

use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_CGROUP_SOCKOPT,
Expand Down Expand Up @@ -65,7 +69,9 @@ impl CgroupSockopt {
///
/// The returned value can be used to detach, see [CgroupSockopt::detach].
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<CgroupSockoptLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let cgroup_fd = cgroup.as_raw_fd();
let attach_type = self.data.expected_attach_type.unwrap();
if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
Expand Down
9 changes: 7 additions & 2 deletions aya/src/programs/cgroup_sysctl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! Cgroup sysctl programs.

use crate::util::KernelVersion;
use std::{hash::Hash, os::fd::AsRawFd};
use std::{
hash::Hash,
os::fd::{AsFd as _, AsRawFd},
};

use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL},
Expand Down Expand Up @@ -60,7 +63,9 @@ impl CgroupSysctl {
///
/// The returned value can be used to detach, see [CgroupSysctl::detach].
pub fn attach<T: AsRawFd>(&mut self, cgroup: T) -> Result<CgroupSysctlLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let cgroup_fd = cgroup.as_raw_fd();

if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) {
Expand Down
41 changes: 26 additions & 15 deletions aya/src/programs/extension.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Extension programs.
use std::os::fd::{AsFd as _, AsRawFd as _, OwnedFd};
use std::os::fd::{AsFd as _, AsRawFd as _, BorrowedFd, OwnedFd};
use thiserror::Error;

use object::Endianness;
Expand Down Expand Up @@ -42,8 +42,9 @@ pub enum ExtensionError {
/// prog.attach("eth0", XdpFlags::default())?;
///
/// let prog_fd = prog.fd().unwrap();
/// let prog_fd = prog_fd.try_clone().unwrap();
/// let ext: &mut Extension = bpf.program_mut("extension").unwrap().try_into()?;
/// ext.load(prog_fd, "function_to_replace")?;
/// ext.load(&prog_fd, "function_to_replace")?;
/// ext.attach()?;
/// Ok::<(), aya::BpfError>(())
/// ```
Expand All @@ -68,12 +69,12 @@ impl Extension {
/// The extension code will be loaded but inactive until it's attached.
/// 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();
pub fn load(&mut self, program: &ProgramFd, func_name: &str) -> Result<(), ProgramError> {
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);
self.data.attach_prog_fd = Some(target_prog_fd);
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)
}
Expand All @@ -86,7 +87,9 @@ impl Extension {
/// The returned value can be used to detach the extension and restore the
/// original function, see [Extension::detach].
pub fn attach(&mut self) -> Result<ExtensionLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let target_fd = self.data.attach_prog_fd.ok_or(ProgramError::NotLoaded)?;
let btf_id = self.data.attach_btf_id.ok_or(ProgramError::NotLoaded)?;
// the attach type must be set as 0, which is bpf_attach_type::BPF_CGROUP_INET_INGRESS
Expand All @@ -113,18 +116,26 @@ impl Extension {
/// original function, see [Extension::detach].
pub fn attach_to_program(
&mut self,
program: ProgramFd,
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()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
// 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)
.map_err(|(_, io_error)| SyscallError {
call: "bpf_link_create",
io_error,
})?;
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)| SyscallError {
call: "bpf_link_create",
io_error,
})?;
self.data
.links
.insert(ExtensionLink::new(FdLink::new(link_fd)))
Expand All @@ -149,7 +160,7 @@ 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<(OwnedFd, u32), ProgramError> {
fn get_btf_info(prog_fd: BorrowedFd<'_>, func_name: &str) -> Result<(OwnedFd, u32), ProgramError> {
// retrieve program information
let info = sys::bpf_prog_get_info_by_fd(prog_fd, &mut [])?;

Expand Down
10 changes: 7 additions & 3 deletions aya/src/programs/lirc_mode2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Lirc programs.
use std::os::fd::{AsRawFd, IntoRawFd as _, RawFd};
use std::os::fd::{AsFd as _, AsRawFd, BorrowedFd, IntoRawFd as _, RawFd};

use crate::{
generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2},
Expand Down Expand Up @@ -61,7 +61,9 @@ impl LircMode2 {
///
/// The returned value can be used to detach, see [LircMode2::detach].
pub fn attach<T: AsRawFd>(&mut self, lircdev: T) -> Result<LircLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let prog_fd = prog_fd.as_raw_fd();
let lircdev_fd = lircdev.as_raw_fd();

bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| {
Expand Down Expand Up @@ -128,7 +130,9 @@ impl LircLink {

/// Get ProgramInfo from this link
pub fn info(&self) -> Result<ProgramInfo, ProgramError> {
ProgramInfo::new_from_fd(self.prog_fd)
// SAFETY: TODO(https://github.com/aya-rs/aya/issues/612): make this safe by not holding `RawFd`s.
let prog_fd = unsafe { BorrowedFd::borrow_raw(self.prog_fd) };
ProgramInfo::new_from_fd(prog_fd)
}
}

Expand Down
Loading

0 comments on commit 504fd1d

Please sign in to comment.