add unload api for programs

pull/264/head
Davide Bertola 3 years ago
parent 6b1f47323b
commit 08d5697948

@ -10,8 +10,8 @@ use crate::{
bpf_prog_type::BPF_PROG_TYPE_CGROUP_SKB,
},
programs::{
define_link_wrapper, load_program, FdLink, Link, OwnedLink, ProgAttachLink, ProgramData,
ProgramError,
define_link_wrapper, load_program, unload_program, FdLink, Link, OwnedLink, ProgAttachLink,
ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach, kernel_version},
};
@ -72,6 +72,14 @@ impl CgroupSkb {
load_program(BPF_PROG_TYPE_CGROUP_SKB, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Returns the expected attach type of the program.
///
/// [`CgroupSkb`] programs can specify the expected attach type in their ELF

@ -7,8 +7,8 @@ use std::{
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SYSCTL, bpf_prog_type::BPF_PROG_TYPE_CGROUP_SYSCTL},
programs::{
define_link_wrapper, load_program, FdLink, Link, OwnedLink, ProgAttachLink, ProgramData,
ProgramError,
define_link_wrapper, load_program, unload_program, FdLink, Link, OwnedLink, ProgAttachLink,
ProgramData, ProgramError,
},
sys::{bpf_link_create, bpf_prog_attach, kernel_version},
};
@ -59,6 +59,14 @@ impl CgroupSysctl {
load_program(BPF_PROG_TYPE_CGROUP_SYSCTL, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given cgroup.
///
/// The returned value can be used to detach, see [CgroupSysctl::detach].

@ -4,8 +4,8 @@ use crate::{
generated::{bpf_attach_type::BPF_TRACE_FENTRY, bpf_prog_type::BPF_PROG_TYPE_TRACING},
obj::btf::{Btf, BtfKind},
programs::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
OwnedLink, ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, utils::attach_raw_tracepoint, FdLink,
FdLinkId, OwnedLink, ProgramData, ProgramError,
},
};
@ -62,6 +62,14 @@ impl FEntry {
load_program(BPF_PROG_TYPE_TRACING, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program.
///
/// The returned value can be used to detach, see [FEntry::detach].

@ -4,8 +4,8 @@ use crate::{
generated::{bpf_attach_type::BPF_TRACE_FEXIT, bpf_prog_type::BPF_PROG_TYPE_TRACING},
obj::btf::{Btf, BtfKind},
programs::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
OwnedLink, ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, utils::attach_raw_tracepoint, FdLink,
FdLinkId, OwnedLink, ProgramData, ProgramError,
},
};
@ -62,6 +62,14 @@ impl FExit {
load_program(BPF_PROG_TYPE_TRACING, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program.
///
/// The returned value can be used to detach, see [FExit::detach].

@ -12,6 +12,8 @@ use crate::{
},
};
use super::unload_program;
/// A kernel probe.
///
/// Kernel probes are eBPF programs that can be attached to almost any function inside
@ -49,6 +51,14 @@ impl KProbe {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the
/// program is a `kretprobe`.
pub fn kind(&self) -> ProbeKind {

@ -79,6 +79,13 @@ impl<T: Link> LinkMap<T> {
.detach()
}
pub(crate) fn remove_all(&mut self) -> Result<(), ProgramError> {
for (_, link) in self.links.drain() {
link.detach()?;
}
Ok(())
}
pub(crate) fn forget(&mut self, link_id: T::Id) -> Result<T, ProgramError> {
self.links.remove(&link_id).ok_or(ProgramError::NotAttached)
}
@ -86,9 +93,7 @@ impl<T: Link> LinkMap<T> {
impl<T: Link> Drop for LinkMap<T> {
fn drop(&mut self) {
for (_, link) in self.links.drain() {
let _ = link.detach();
}
let _ = self.remove_all();
}
}

@ -3,7 +3,10 @@ use std::os::unix::prelude::{AsRawFd, RawFd};
use crate::{
generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2},
programs::{load_program, query, Link, OwnedLink, ProgramData, ProgramError, ProgramInfo},
programs::{
load_program, query, unload_program, Link, OwnedLink, ProgramData, ProgramError,
ProgramInfo,
},
sys::{bpf_obj_get_info_by_fd, bpf_prog_attach, bpf_prog_detach, bpf_prog_get_fd_by_id},
};
@ -58,6 +61,14 @@ impl LircMode2 {
load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given lirc device.
///
/// The returned value can be used to detach, see [LircMode2::detach].

@ -3,8 +3,8 @@ use crate::{
generated::{bpf_attach_type::BPF_LSM_MAC, bpf_prog_type::BPF_PROG_TYPE_LSM},
obj::btf::{Btf, BtfKind},
programs::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
OwnedLink, ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, utils::attach_raw_tracepoint, FdLink,
FdLinkId, OwnedLink, ProgramData, ProgramError,
},
};
@ -67,6 +67,14 @@ impl Lsm {
load_program(BPF_PROG_TYPE_LSM, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program.
///
/// The returned value can be used to detach, see [Lsm::detach].

@ -386,6 +386,18 @@ impl<T: Link> ProgramData<T> {
}
}
fn unload_program<T: Link>(data: &mut ProgramData<T>, detach: bool) -> Result<(), ProgramError> {
if detach {
data.links.remove_all()?;
}
let fd = data.fd_or_err()?;
unsafe {
libc::close(fd);
}
data.fd = None;
Ok(())
}
fn load_program<T: Link>(
prog_type: bpf_prog_type,
data: &mut ProgramData<T>,

@ -14,7 +14,7 @@ use crate::{
programs::{
load_program, perf_attach,
perf_attach::{PerfLink, PerfLinkId},
OwnedLink, ProgramData, ProgramError,
unload_program, OwnedLink, ProgramData, ProgramError,
},
sys::perf_event_open,
};
@ -128,6 +128,14 @@ impl PerfEvent {
load_program(BPF_PROG_TYPE_PERF_EVENT, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches to the given perf event.
///
/// The possible values and encoding of the `config` argument depends on the

@ -4,8 +4,8 @@ use std::ffi::CString;
use crate::{
generated::bpf_prog_type::BPF_PROG_TYPE_RAW_TRACEPOINT,
programs::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
OwnedLink, ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, utils::attach_raw_tracepoint, FdLink,
FdLinkId, OwnedLink, ProgramData, ProgramError,
},
};
@ -45,6 +45,14 @@ impl RawTracePoint {
load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given tracepoint.
///
/// The returned value can be used to detach, see [RawTracePoint::detach].

@ -3,8 +3,8 @@ use crate::{
generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG},
maps::sock::SocketMap,
programs::{
define_link_wrapper, load_program, OwnedLink, ProgAttachLink, ProgAttachLinkId,
ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, OwnedLink, ProgAttachLink,
ProgAttachLinkId, ProgramData, ProgramError,
},
sys::bpf_prog_attach,
};
@ -69,6 +69,14 @@ impl SkMsg {
load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given sockmap.
///
/// The returned value can be used to detach, see [SkMsg::detach].

@ -6,8 +6,8 @@ use crate::{
},
maps::sock::SocketMap,
programs::{
define_link_wrapper, load_program, OwnedLink, ProgAttachLink, ProgAttachLinkId,
ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, OwnedLink, ProgAttachLink,
ProgAttachLinkId, ProgramData, ProgramError,
},
sys::bpf_prog_attach,
};
@ -62,6 +62,14 @@ impl SkSkb {
load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given socket map.
///
/// The returned value can be used to detach, see [SkSkb::detach].

@ -4,8 +4,8 @@ use std::os::unix::io::AsRawFd;
use crate::{
generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS},
programs::{
define_link_wrapper, load_program, OwnedLink, ProgAttachLink, ProgAttachLinkId,
ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, OwnedLink, ProgAttachLink,
ProgAttachLinkId, ProgramData, ProgramError,
},
sys::bpf_prog_attach,
};
@ -56,6 +56,14 @@ impl SockOps {
load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given cgroup.
///
/// The returned value can be used to detach, see [SockOps::detach].

@ -8,7 +8,7 @@ use thiserror::Error;
use crate::{
generated::{bpf_prog_type::BPF_PROG_TYPE_SOCKET_FILTER, SO_ATTACH_BPF, SO_DETACH_BPF},
programs::{load_program, Link, OwnedLink, ProgramData, ProgramError},
programs::{load_program, unload_program, Link, OwnedLink, ProgramData, ProgramError},
};
/// The type returned when attaching a [`SocketFilter`] fails.
@ -70,6 +70,14 @@ impl SocketFilter {
load_program(BPF_PROG_TYPE_SOCKET_FILTER, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the filter on the given socket.
///
/// The returned value can be used to detach from the socket, see [SocketFilter::detach].

@ -10,7 +10,10 @@ use crate::{
generated::{
bpf_prog_type::BPF_PROG_TYPE_SCHED_CLS, TC_H_CLSACT, TC_H_MIN_EGRESS, TC_H_MIN_INGRESS,
},
programs::{define_link_wrapper, load_program, Link, OwnedLink, ProgramData, ProgramError},
programs::{
define_link_wrapper, load_program, unload_program, Link, OwnedLink, ProgramData,
ProgramError,
},
sys::{
netlink_find_filter_with_name, netlink_qdisc_add_clsact, netlink_qdisc_attach,
netlink_qdisc_detach,
@ -106,6 +109,14 @@ impl SchedClassifier {
load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given `interface`.
///
/// The returned value can be used to detach, see [SchedClassifier::detach].

@ -3,8 +3,8 @@ use crate::{
generated::{bpf_attach_type::BPF_TRACE_RAW_TP, bpf_prog_type::BPF_PROG_TYPE_TRACING},
obj::btf::{Btf, BtfKind},
programs::{
define_link_wrapper, load_program, utils::attach_raw_tracepoint, FdLink, FdLinkId,
OwnedLink, ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, utils::attach_raw_tracepoint, FdLink,
FdLinkId, OwnedLink, ProgramData, ProgramError,
},
};
@ -65,6 +65,14 @@ impl BtfTracePoint {
load_program(BPF_PROG_TYPE_TRACING, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program.
///
/// The returned value can be used to detach, see [BtfTracePoint::detach].

@ -12,6 +12,8 @@ use crate::{
sys::perf_event_open_trace_point,
};
use super::unload_program;
/// The type returned when attaching a [`TracePoint`] fails.
#[derive(Debug, Error)]
pub enum TracePointError {
@ -71,6 +73,14 @@ impl TracePoint {
load_program(BPF_PROG_TYPE_TRACEPOINT, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches to a given trace point.
///
/// For a list of the available event categories and names, see

@ -19,7 +19,7 @@ use crate::{
define_link_wrapper, load_program,
perf_attach::{PerfLink, PerfLinkId},
probe::{attach, ProbeKind},
OwnedLink, ProgramData, ProgramError,
unload_program, OwnedLink, ProgramData, ProgramError,
},
};
@ -51,6 +51,14 @@ impl UProbe {
load_program(BPF_PROG_TYPE_KPROBE, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the
/// program is a `uretprobe`.
pub fn kind(&self) -> ProbeKind {

@ -12,7 +12,8 @@ use crate::{
XDP_FLAGS_UPDATE_IF_NOEXIST,
},
programs::{
define_link_wrapper, load_program, FdLink, Link, OwnedLink, ProgramData, ProgramError,
define_link_wrapper, load_program, unload_program, FdLink, Link, OwnedLink, ProgramData,
ProgramError,
},
sys::{bpf_link_create, kernel_version, netlink_set_xdp_fd},
};
@ -81,6 +82,14 @@ impl Xdp {
load_program(BPF_PROG_TYPE_XDP, &mut self.data)
}
/// Unloads the program from the kernel.
///
/// If `detach` is true, links will be detached before unloading the program.
/// Note that OwnedLinks you obtained using [KProbe::forget_link] will not be detached.
pub fn unload(&mut self, detach: bool) -> Result<(), ProgramError> {
unload_program(&mut self.data, detach)
}
/// Attaches the program to the given `interface`.
///
/// The returned value can be used to detach, see [Xdp::detach].

@ -0,0 +1,30 @@
//! ```cargo
//! [dependencies]
//! aya-bpf = { path = "../../../../bpf/aya-bpf" }
//! ```
#![no_std]
#![no_main]
use aya_bpf::{
bindings::xdp_action,
macros::xdp,
programs::XdpContext,
};
#[xdp(name="ihaveaverylongname")]
pub fn pass(ctx: XdpContext) -> u32 {
match unsafe { try_pass(ctx) } {
Ok(ret) => ret,
Err(_) => xdp_action::XDP_ABORTED,
}
}
unsafe fn try_pass(_ctx: XdpContext) -> Result<u32, u32> {
Ok(xdp_action::XDP_PASS)
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() }
}

@ -0,0 +1,59 @@
//! ```cargo
//! [dependencies]
//! aya = { path = "../../../../aya" }
//! ```
use aya::{
programs::{Xdp, XdpFlags},
Bpf,
};
use std::convert::TryInto;
use std::process::Command;
fn is_loaded() -> bool {
let output = Command::new("bpftool").args(&["prog"]).output().unwrap();
let stdout = String::from_utf8(output.stdout).unwrap();
stdout.contains("xdp name ihaveaverylongn tag")
}
fn assert_loaded(loaded: bool) {
let state = is_loaded();
if state == loaded {
return;
}
panic!("Expected loaded: {} but was loaded: {}", loaded, state);
}
fn main() {
println!("Loading XDP program");
let mut bpf = Bpf::load_file("test.o").unwrap();
let dispatcher: &mut Xdp = bpf
.program_mut("ihaveaverylongname")
.unwrap()
.try_into()
.unwrap();
dispatcher.load().unwrap();
let link = dispatcher.attach("eth0", XdpFlags::default()).unwrap();
dispatcher.unload(false).unwrap();
assert_loaded(true);
dispatcher.detach(link).unwrap();
assert_loaded(false);
dispatcher.load().unwrap();
assert_loaded(true);
dispatcher.attach("eth0", XdpFlags::default()).unwrap();
assert_loaded(true);
dispatcher.unload(true).unwrap();
assert_loaded(false);
}

@ -0,0 +1,27 @@
#!/bin/sh
# SUMMARY: Check that long names are properly truncated
# LABELS:
set -ex
# Source libraries. Uncomment if needed/defined
#. "${RT_LIB}"
. "${RT_PROJECT_ROOT}/_lib/lib.sh"
NAME=test
clean_up() {
rm -rf ebpf user ${NAME}.o ${NAME}
exec_vm rm ${NAME} ${NAME}.o
}
trap clean_up EXIT
# Test code goes here
compile_ebpf ${NAME}.ebpf.rs
compile_user ${NAME}.rs
scp_vm ${NAME}.o
scp_vm ${NAME}
exec_vm sudo ./${NAME}
Loading…
Cancel
Save