Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement FdLink conversions #560

Merged
merged 5 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions aya/src/programs/kprobe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use std::{io, path::Path};
use thiserror::Error;

use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE,
generated::{bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_KPROBE},
programs::{
define_link_wrapper, load_program,
perf_attach::{PerfLinkIdInner, PerfLinkInner},
probe::{attach, ProbeKind},
ProgramData, ProgramError,
FdLink, LinkError, ProgramData, ProgramError,
},
sys::bpf_link_get_info_by_fd,
VerifierLogLevel,
};

Expand Down Expand Up @@ -119,3 +120,32 @@ pub enum KProbeError {
io_error: io::Error,
},
}

impl TryFrom<KProbeLink> for FdLink {
type Error = LinkError;

fn try_from(value: KProbeLink) -> Result<Self, Self::Error> {
if let PerfLinkInner::FdLink(fd) = value.into_inner() {
Ok(fd)
} else {
Err(LinkError::InvalidLink)
}
}
}

impl TryFrom<FdLink> for KProbeLink {
type Error = LinkError;

fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_KPROBE_MULTI as u32) {
return Ok(KProbeLink::new(PerfLinkInner::FdLink(fd_link)));
}
Err(LinkError::InvalidLink)
}
}
28 changes: 28 additions & 0 deletions aya/src/programs/links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ use crate::{
sys::{bpf_get_object, bpf_pin_object, bpf_prog_detach},
};

// for docs link
#[allow(unused)]
use crate::programs::cgroup_skb::CgroupSkb;

/// A Link.
pub trait Link: std::fmt::Debug + 'static {
/// Unique Id
Expand Down Expand Up @@ -82,6 +86,30 @@ impl<T: Link> Drop for LinkMap<T> {
pub struct FdLinkId(pub(crate) RawFd);

/// A file descriptor link.
///
/// Fd links are returned directly when attaching some program types (for
/// instance [`CgroupSkb`]), or can be obtained by converting other link
/// types (see the `TryFrom` implementations).
///
/// An important property of fd links is that they can be pinned. Pinning
/// can be used keep a link attached "in background" even after the program
/// that has created the link terminates.
///
/// # Example
///
///```no_run
/// # let mut bpf = Bpf::load_file("ebpf_programs.o")?;
/// use aya::{Bpf, programs::{links::FdLink, KProbe}};
///
/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?;
/// program.load()?;
/// let link_id = program.attach("try_to_wake_up", 0)?;
/// let link = program.take_link(link_id).unwrap();
/// let fd_link: FdLink = link.try_into().unwrap();
/// fd_link.pin("/sys/fs/bpf/intercept_wakeups_link").unwrap();
///
/// # Ok::<(), aya::BpfError>(())
/// ```
#[derive(Debug)]
pub struct FdLink {
pub(crate) fd: RawFd,
Expand Down
34 changes: 32 additions & 2 deletions aya/src/programs/perf_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use crate::generated::{

use crate::{
generated::{
bpf_link_type,
bpf_prog_type::BPF_PROG_TYPE_PERF_EVENT,
perf_type_id::{
PERF_TYPE_BREAKPOINT, PERF_TYPE_HARDWARE, PERF_TYPE_HW_CACHE, PERF_TYPE_RAW,
Expand All @@ -16,9 +17,9 @@ use crate::{
links::define_link_wrapper,
load_program, perf_attach,
perf_attach::{PerfLinkIdInner, PerfLinkInner},
ProgramData, ProgramError,
FdLink, LinkError, ProgramData, ProgramError,
},
sys::perf_event_open,
sys::{bpf_link_get_info_by_fd, perf_event_open},
};

/// The type of perf event
Expand Down Expand Up @@ -189,6 +190,35 @@ impl PerfEvent {
}
}

impl TryFrom<PerfEventLink> for FdLink {
type Error = LinkError;

fn try_from(value: PerfEventLink) -> Result<Self, Self::Error> {
if let PerfLinkInner::FdLink(fd) = value.into_inner() {
Ok(fd)
} else {
Err(LinkError::InvalidLink)
}
}
}

impl TryFrom<FdLink> for PerfEventLink {
type Error = LinkError;

fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_PERF_EVENT as u32) {
return Ok(PerfEventLink::new(PerfLinkInner::FdLink(fd_link)));
}
Err(LinkError::InvalidLink)
}
}

define_link_wrapper!(
/// The link used by [PerfEvent] programs.
PerfEventLink,
Expand Down
35 changes: 32 additions & 3 deletions aya/src/programs/trace_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use std::{fs, io, path::Path};
use thiserror::Error;

use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT,
generated::{bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_TRACEPOINT},
programs::{
define_link_wrapper, load_program,
perf_attach::{perf_attach, PerfLinkIdInner, PerfLinkInner},
utils::find_tracefs_path,
ProgramData, ProgramError,
FdLink, LinkError, ProgramData, ProgramError,
},
sys::perf_event_open_trace_point,
sys::{bpf_link_get_info_by_fd, perf_event_open_trace_point},
};

/// The type returned when attaching a [`TracePoint`] fails.
Expand Down Expand Up @@ -116,6 +116,35 @@ define_link_wrapper!(
PerfLinkIdInner
);

impl TryFrom<TracePointLink> for FdLink {
type Error = LinkError;

fn try_from(value: TracePointLink) -> Result<Self, Self::Error> {
if let PerfLinkInner::FdLink(fd) = value.into_inner() {
Ok(fd)
} else {
Err(LinkError::InvalidLink)
}
}
}

impl TryFrom<FdLink> for TracePointLink {
type Error = LinkError;

fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
return Ok(TracePointLink::new(PerfLinkInner::FdLink(fd_link)));
}
Err(LinkError::InvalidLink)
}
}

pub(crate) fn read_sys_fs_trace_point_id(
tracefs: &Path,
category: &str,
Expand Down
34 changes: 32 additions & 2 deletions aya/src/programs/uprobe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ use std::{
use thiserror::Error;

use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_KPROBE,
generated::{bpf_link_type, bpf_prog_type::BPF_PROG_TYPE_KPROBE},
programs::{
define_link_wrapper, load_program,
perf_attach::{PerfLinkIdInner, PerfLinkInner},
probe::{attach, ProbeKind},
ProgramData, ProgramError,
FdLink, LinkError, ProgramData, ProgramError,
},
sys::bpf_link_get_info_by_fd,
VerifierLogLevel,
};

Expand Down Expand Up @@ -160,6 +161,35 @@ define_link_wrapper!(
PerfLinkIdInner
);

impl TryFrom<UProbeLink> for FdLink {
type Error = LinkError;

fn try_from(value: UProbeLink) -> Result<Self, Self::Error> {
if let PerfLinkInner::FdLink(fd) = value.into_inner() {
Ok(fd)
} else {
Err(LinkError::InvalidLink)
}
}
}

impl TryFrom<FdLink> for UProbeLink {
type Error = LinkError;

fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
let info =
bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError {
call: "BPF_OBJ_GET_INFO_BY_FD",
code: 0,
io_error,
})?;
if info.type_ == (bpf_link_type::BPF_LINK_TYPE_TRACING as u32) {
return Ok(UProbeLink::new(PerfLinkInner::FdLink(fd_link)));
}
Err(LinkError::InvalidLink)
}
}

/// The type returned when attaching an [`UProbe`] fails.
#[derive(Debug, Error)]
pub enum UProbeError {
Expand Down
19 changes: 14 additions & 5 deletions test/integration-ebpf/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

use aya_bpf::{
bindings::xdp_action,
macros::{kprobe, xdp},
programs::{ProbeContext, XdpContext},
macros::{kprobe, tracepoint, uprobe, xdp},
programs::{ProbeContext, TracePointContext, XdpContext},
};

#[xdp(name = "test_unload_xdp")]
#[xdp(name = "test_xdp")]
pub fn pass(ctx: XdpContext) -> u32 {
match unsafe { try_pass(ctx) } {
Ok(ret) => ret,
Expand All @@ -20,8 +20,17 @@ unsafe fn try_pass(_ctx: XdpContext) -> Result<u32, u32> {
}

#[kprobe]
// truncated name to match bpftool output
pub fn test_unload_kpr(_ctx: ProbeContext) -> u32 {
pub fn test_kprobe(_ctx: ProbeContext) -> u32 {
0
}

#[tracepoint]
pub fn test_tracepoint(_ctx: TracePointContext) -> u32 {
0
}

#[uprobe]
pub fn test_uprobe(_ctx: ProbeContext) -> u32 {
0
}

Expand Down
Loading