diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index 8ef1712a..4ba1d784 100644 --- a/aya-log/src/lib.rs +++ b/aya-log/src/lib.rs @@ -57,6 +57,8 @@ use std::{ sync::Arc, }; +const MAP_NAME: &str = "AYA_LOGS"; + use aya_log_common::{Argument, DisplayHint, RecordField, LOG_BUF_CAPACITY, LOG_FIELDS}; use bytes::BytesMut; use log::{error, Level, Log, Record}; @@ -90,7 +92,10 @@ impl BpfLogger { logger: T, ) -> Result { let logger = Arc::new(logger); - let mut logs: AsyncPerfEventArray<_> = bpf.take_map("AYA_LOGS").unwrap().try_into()?; + let mut logs: AsyncPerfEventArray<_> = bpf + .take_map(MAP_NAME) + .ok_or(Error::MapNotFound)? + .try_into()?; for cpu_id in online_cpus().map_err(Error::InvalidOnlineCpu)? { let mut buf = logs.open(cpu_id, None)?; @@ -326,6 +331,9 @@ impl Log for DefaultLogger { #[derive(Error, Debug)] pub enum Error { + #[error("log event array {} doesn't exist", MAP_NAME)] + MapNotFound, + #[error("error opening log event array")] MapError(#[from] MapError), diff --git a/aya/src/programs/cgroup_device.rs b/aya/src/programs/cgroup_device.rs index be52a26e..b4a9a3c4 100644 --- a/aya/src/programs/cgroup_device.rs +++ b/aya/src/programs/cgroup_device.rs @@ -72,9 +72,9 @@ impl CgroupDevice { )? as RawFd; self.data .links - .insert(CgroupDeviceLink(CgroupDeviceLinkInner::Fd(FdLink::new( - link_fd, - )))) + .insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::Fd( + FdLink::new(link_fd), + ))) } else { bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE).map_err(|(_, io_error)| { ProgramError::SyscallError { @@ -84,7 +84,7 @@ impl CgroupDevice { })?; self.data .links - .insert(CgroupDeviceLink(CgroupDeviceLinkInner::ProgAttach( + .insert(CgroupDeviceLink::new(CgroupDeviceLinkInner::ProgAttach( ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_DEVICE), ))) } diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 17d69063..3911a3c3 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -105,7 +105,9 @@ impl CgroupSkb { )? as RawFd; self.data .links - .insert(CgroupSkbLink(CgroupSkbLinkInner::Fd(FdLink::new(link_fd)))) + .insert(CgroupSkbLink::new(CgroupSkbLinkInner::Fd(FdLink::new( + link_fd, + )))) } else { bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { ProgramError::SyscallError { @@ -116,7 +118,7 @@ impl CgroupSkb { self.data .links - .insert(CgroupSkbLink(CgroupSkbLinkInner::ProgAttach( + .insert(CgroupSkbLink::new(CgroupSkbLinkInner::ProgAttach( ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), ))) } diff --git a/aya/src/programs/cgroup_sock.rs b/aya/src/programs/cgroup_sock.rs index 17bc68ee..2a87a91d 100644 --- a/aya/src/programs/cgroup_sock.rs +++ b/aya/src/programs/cgroup_sock.rs @@ -81,7 +81,7 @@ impl CgroupSock { )? as RawFd; self.data .links - .insert(CgroupSockLink(CgroupSockLinkInner::Fd(FdLink::new( + .insert(CgroupSockLink::new(CgroupSockLinkInner::Fd(FdLink::new( link_fd, )))) } else { @@ -94,7 +94,7 @@ impl CgroupSock { self.data .links - .insert(CgroupSockLink(CgroupSockLinkInner::ProgAttach( + .insert(CgroupSockLink::new(CgroupSockLinkInner::ProgAttach( ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), ))) } diff --git a/aya/src/programs/cgroup_sock_addr.rs b/aya/src/programs/cgroup_sock_addr.rs index aa8b71fd..2f8aac7d 100644 --- a/aya/src/programs/cgroup_sock_addr.rs +++ b/aya/src/programs/cgroup_sock_addr.rs @@ -82,7 +82,7 @@ impl CgroupSockAddr { )? as RawFd; self.data .links - .insert(CgroupSockAddrLink(CgroupSockAddrLinkInner::Fd( + .insert(CgroupSockAddrLink::new(CgroupSockAddrLinkInner::Fd( FdLink::new(link_fd), ))) } else { @@ -93,11 +93,13 @@ impl CgroupSockAddr { } })?; - self.data - .links - .insert(CgroupSockAddrLink(CgroupSockAddrLinkInner::ProgAttach( - ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), - ))) + self.data.links.insert(CgroupSockAddrLink::new( + CgroupSockAddrLinkInner::ProgAttach(ProgAttachLink::new( + prog_fd, + cgroup_fd, + attach_type, + )), + )) } } diff --git a/aya/src/programs/cgroup_sockopt.rs b/aya/src/programs/cgroup_sockopt.rs index 14df5fc6..669e4f99 100644 --- a/aya/src/programs/cgroup_sockopt.rs +++ b/aya/src/programs/cgroup_sockopt.rs @@ -79,9 +79,9 @@ impl CgroupSockopt { )? as RawFd; self.data .links - .insert(CgroupSockoptLink(CgroupSockoptLinkInner::Fd(FdLink::new( - link_fd, - )))) + .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::Fd( + FdLink::new(link_fd), + ))) } else { bpf_prog_attach(prog_fd, cgroup_fd, attach_type).map_err(|(_, io_error)| { ProgramError::SyscallError { @@ -92,7 +92,7 @@ impl CgroupSockopt { self.data .links - .insert(CgroupSockoptLink(CgroupSockoptLinkInner::ProgAttach( + .insert(CgroupSockoptLink::new(CgroupSockoptLinkInner::ProgAttach( ProgAttachLink::new(prog_fd, cgroup_fd, attach_type), ))) } diff --git a/aya/src/programs/cgroup_sysctl.rs b/aya/src/programs/cgroup_sysctl.rs index f4a3f352..7c39a1e3 100644 --- a/aya/src/programs/cgroup_sysctl.rs +++ b/aya/src/programs/cgroup_sysctl.rs @@ -74,9 +74,9 @@ impl CgroupSysctl { )? as RawFd; self.data .links - .insert(CgroupSysctlLink(CgroupSysctlLinkInner::Fd(FdLink::new( - link_fd, - )))) + .insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::Fd( + FdLink::new(link_fd), + ))) } else { bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL).map_err(|(_, io_error)| { ProgramError::SyscallError { @@ -87,7 +87,7 @@ impl CgroupSysctl { self.data .links - .insert(CgroupSysctlLink(CgroupSysctlLinkInner::ProgAttach( + .insert(CgroupSysctlLink::new(CgroupSysctlLinkInner::ProgAttach( ProgAttachLink::new(prog_fd, cgroup_fd, BPF_CGROUP_SYSCTL), ))) } diff --git a/aya/src/programs/extension.rs b/aya/src/programs/extension.rs index 75296244..263b7b67 100644 --- a/aya/src/programs/extension.rs +++ b/aya/src/programs/extension.rs @@ -95,7 +95,9 @@ impl Extension { call: "bpf_link_create".to_owned(), io_error, })? as RawFd; - self.data.links.insert(ExtensionLink(FdLink::new(link_fd))) + self.data + .links + .insert(ExtensionLink::new(FdLink::new(link_fd))) } /// Attaches the extension to another program. @@ -123,7 +125,9 @@ impl Extension { call: "bpf_link_create".to_owned(), io_error, })? as RawFd; - self.data.links.insert(ExtensionLink(FdLink::new(link_fd))) + self.data + .links + .insert(ExtensionLink::new(FdLink::new(link_fd))) } /// Detaches the extension. diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index af276245..388b33b2 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -83,17 +83,17 @@ impl Drop for LinkMap { /// The identifier of an `FdLink`. #[derive(Debug, Hash, Eq, PartialEq)] -pub struct FdLinkId(pub(crate) Option); +pub struct FdLinkId(pub(crate) RawFd); /// A file descriptor link. #[derive(Debug)] pub struct FdLink { - pub(crate) fd: Option, + pub(crate) fd: RawFd, } impl FdLink { pub(crate) fn new(fd: RawFd) -> FdLink { - FdLink { fd: Some(fd) } + FdLink { fd } } /// Pins the link to a BPF file system. @@ -125,21 +125,18 @@ impl FdLink { /// let pinned_link = fd_link.pin("/sys/fs/bpf/example")?; /// # Ok::<(), Error>(()) /// ``` - pub fn pin>(mut self, path: P) -> Result { - let fd = self.fd.take().ok_or_else(|| PinError::NoFd { - name: "link".to_string(), - })?; + pub fn pin>(self, path: P) -> Result { let path_string = CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { PinError::InvalidPinPath { error: e.to_string(), } })?; - bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError { + bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError { name: "BPF_OBJ_PIN".to_string(), io_error, })?; - Ok(PinnedLink::new(PathBuf::from(path.as_ref()), fd)) + Ok(PinnedLink::new(PathBuf::from(path.as_ref()), self)) } } @@ -151,27 +148,27 @@ impl Link for FdLink { } fn detach(self) -> Result<(), ProgramError> { - // detach is a noop since it consumes self. once self is consumed, - // drop will be triggered and the link will be detached. + // detach is a noop since it consumes self. once self is consumed, drop will be triggered + // and the link will be detached. + // + // Other links don't need to do this since they use define_link_wrapper!, but FdLink is a + // bit special in that it defines a custom ::new() so it can't use the macro. Ok(()) } } -impl Drop for FdLink { - fn drop(&mut self) { - if let Some(fd) = self.fd.take() { - // Safety: libc - unsafe { close(fd) }; - } - } -} - impl From for FdLink { fn from(p: PinnedLink) -> Self { p.inner } } +impl Drop for FdLink { + fn drop(&mut self) { + unsafe { close(self.fd) }; + } +} + /// A pinned file descriptor link. /// /// This link has been pinned to the BPF filesystem. On drop, the file descriptor that backs @@ -184,11 +181,8 @@ pub struct PinnedLink { } impl PinnedLink { - fn new(path: PathBuf, fd: RawFd) -> Self { - PinnedLink { - inner: FdLink::new(fd), - path, - } + fn new(path: PathBuf, link: FdLink) -> Self { + PinnedLink { inner: link, path } } /// Creates a [`PinnedLink`] from a valid path on bpffs. @@ -200,7 +194,10 @@ impl PinnedLink { code, io_error, })? as RawFd; - Ok(PinnedLink::new(path.as_ref().to_path_buf(), fd)) + Ok(PinnedLink::new( + path.as_ref().to_path_buf(), + FdLink::new(fd), + )) } /// Removes the pinned link from the filesystem and returns an [`FdLink`]. @@ -258,29 +255,56 @@ macro_rules! define_link_wrapper { #[$doc1] #[derive(Debug)] - pub struct $wrapper($base); + pub struct $wrapper(Option<$base>); + + #[allow(dead_code)] + // allow dead code since currently XDP is the only consumer of inner and + // into_inner + impl $wrapper { + fn new(base: $base) -> $wrapper { + $wrapper(Some(base)) + } + + fn inner(&self) -> &$base { + self.0.as_ref().unwrap() + } + + fn into_inner(mut self) -> $base { + self.0.take().unwrap() + } + } + + impl Drop for $wrapper { + fn drop(&mut self) { + use crate::programs::links::Link; + + if let Some(base) = self.0.take() { + let _ = base.detach(); + } + } + } impl crate::programs::Link for $wrapper { type Id = $wrapper_id; fn id(&self) -> Self::Id { - $wrapper_id(self.0.id()) + $wrapper_id(self.0.as_ref().unwrap().id()) } - fn detach(self) -> Result<(), ProgramError> { - self.0.detach() + fn detach(mut self) -> Result<(), ProgramError> { + self.0.take().unwrap().detach() } } impl From<$base> for $wrapper { fn from(b: $base) -> $wrapper { - $wrapper(b) + $wrapper(Some(b)) } } impl From<$wrapper> for $base { - fn from(w: $wrapper) -> $base { - w.0 + fn from(mut w: $wrapper) -> $base { + w.0.take().unwrap() } } }; diff --git a/aya/src/programs/sk_lookup.rs b/aya/src/programs/sk_lookup.rs index a64e062a..8d95e9ec 100644 --- a/aya/src/programs/sk_lookup.rs +++ b/aya/src/programs/sk_lookup.rs @@ -70,7 +70,9 @@ impl SkLookup { io_error, }, )? as RawFd; - self.data.links.insert(SkLookupLink(FdLink::new(link_fd))) + self.data + .links + .insert(SkLookupLink::new(FdLink::new(link_fd))) } /// Takes ownership of the link referenced by the provided link_id. diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index 2cf4d51a..a60346d8 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -88,7 +88,7 @@ impl SkMsg { io_error, } })?; - self.data.links.insert(SkMsgLink(ProgAttachLink::new( + self.data.links.insert(SkMsgLink::new(ProgAttachLink::new( prog_fd, map_fd, BPF_SK_MSG_VERDICT, diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 79e741fd..a0470506 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -84,9 +84,11 @@ impl SkSkb { io_error, } })?; - self.data - .links - .insert(SkSkbLink(ProgAttachLink::new(prog_fd, map_fd, attach_type))) + self.data.links.insert(SkSkbLink::new(ProgAttachLink::new( + prog_fd, + map_fd, + attach_type, + ))) } /// Detaches the program. diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index c46540e4..9021b312 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -68,7 +68,7 @@ impl SockOps { io_error, } })?; - self.data.links.insert(SockOpsLink(ProgAttachLink::new( + self.data.links.insert(SockOpsLink::new(ProgAttachLink::new( prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index 0eb9a419..5cd21ab3 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -165,7 +165,7 @@ impl SchedClassifier { } .map_err(|io_error| TcError::NetlinkError { io_error })?; - self.data.links.insert(SchedClassifierLink(TcLink { + self.data.links.insert(SchedClassifierLink::new(TcLink { if_index: if_index as i32, attach_type, priority, @@ -196,7 +196,7 @@ impl SchedClassifierLink { /// Provides the linked [NetworkInterface]. pub fn interface(&self) -> NetworkInterface { NetworkInterface { - index: self.0.if_index, + index: self.inner().if_index, } } } diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 751dc77a..d201ff5c 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -1,6 +1,6 @@ //! User space probes. use libc::pid_t; -use object::{Object, ObjectSymbol}; +use object::{Object, ObjectSection, ObjectSymbol}; use std::{ error::Error, ffi::CStr, @@ -319,15 +319,41 @@ enum ResolveSymbolError { #[error("unknown symbol `{0}`")] Unknown(String), + + #[error("symbol `{0}` does not appear in section")] + NotInSection(String), + + #[error("symbol `{0}` in section `{1:?}` which has no offset")] + SectionFileRangeNone(String, Result), } fn resolve_symbol(path: &str, symbol: &str) -> Result { let data = fs::read(path)?; let obj = object::read::File::parse(&*data)?; - obj.dynamic_symbols() + let sym = obj + .dynamic_symbols() .chain(obj.symbols()) .find(|sym| sym.name().map(|name| name == symbol).unwrap_or(false)) - .map(|s| s.address()) - .ok_or_else(|| ResolveSymbolError::Unknown(symbol.to_string())) + .ok_or_else(|| ResolveSymbolError::Unknown(symbol.to_string()))?; + + let needs_addr_translation = matches!( + obj.kind(), + object::ObjectKind::Dynamic | object::ObjectKind::Executable + ); + if !needs_addr_translation { + Ok(sym.address()) + } else { + let index = sym + .section_index() + .ok_or_else(|| ResolveSymbolError::NotInSection(symbol.to_string()))?; + let section = obj.section_by_index(index)?; + let (offset, _size) = section.file_range().ok_or_else(|| { + ResolveSymbolError::SectionFileRangeNone( + symbol.to_string(), + section.name().map(str::to_owned), + ) + })?; + Ok(sym.address() - section.address() + offset) + } } diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 38188eff..41822ae1 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -117,7 +117,7 @@ impl Xdp { if_index, link: XdpLinkInnerType::FdLink(FdLink::new(link_fd)), }; - self.data.links.insert(XdpLink(inner)) + self.data.links.insert(XdpLink::new(inner)) } else { unsafe { netlink_set_xdp_fd(if_index, prog_fd, None, flags.bits) } .map_err(|io_error| XdpError::NetlinkError { io_error })?; @@ -130,7 +130,7 @@ impl Xdp { flags, }), }; - self.data.links.insert(XdpLink(inner)) + self.data.links.insert(XdpLink::new(inner)) } } @@ -154,23 +154,23 @@ impl Xdp { /// Ownership of the link will transfer to this program. pub fn attach_to_link(&mut self, link: XdpLink) -> Result { let prog_fd = self.data.fd_or_err()?; - match &link.0.link { + match &link.inner().link { XdpLinkInnerType::FdLink(fd_link) => { - let link_fd = fd_link.fd.unwrap(); + let link_fd = fd_link.fd; bpf_link_update(link_fd, prog_fd, None, 0).map_err(|(_, io_error)| { ProgramError::SyscallError { call: "bpf_link_update".to_string(), io_error, } })?; - let if_index = link.0.if_index; + let if_index = link.inner().if_index; // dispose of link and avoid detach on drop mem::forget(link); let inner = XdpLinkInner { if_index, link: XdpLinkInnerType::FdLink(FdLink::new(link_fd)), }; - self.data.links.insert(XdpLink(inner)) + self.data.links.insert(XdpLink::new(inner)) } XdpLinkInnerType::NlLink(nl_link) => { let if_index = nl_link.if_index; @@ -191,7 +191,7 @@ impl Xdp { flags, }), }; - self.data.links.insert(XdpLink(inner)) + self.data.links.insert(XdpLink::new(inner)) } } } @@ -209,7 +209,7 @@ impl XdpLink { /// Returns [None] when the link is backed by a file descriptor. pub fn interface(&self) -> NetworkInterface { NetworkInterface { - index: self.0.if_index, + index: self.inner().if_index, } } } @@ -273,7 +273,7 @@ impl TryFrom for FdLink { type Error = LinkError; fn try_from(value: XdpLink) -> Result { - if let XdpLinkInnerType::FdLink(fd) = value.0.link { + if let XdpLinkInnerType::FdLink(fd) = value.into_inner().link { Ok(fd) } else { Err(LinkError::InvalidLink) @@ -286,19 +286,14 @@ impl TryFrom for FdLink { // fn try_from(fd_link: FdLink) -> Result { // // unwrap of fd_link.fd will not panic since it's only None when being dropped. -// let info = bpf_link_get_info_by_fd(fd_link.fd.unwrap()).map_err(|io_error| { -// LinkError::SyscallError { +// let info = +// bpf_link_get_info_by_fd(fd_link.fd).map_err(|io_error| LinkError::SyscallError { // call: "BPF_OBJ_GET_INFO_BY_FD".to_string(), // code: 0, // io_error, -// } -// })?; +// })?; // if info.type_ == (bpf_link_type::BPF_LINK_TYPE_XDP as u32) { -// let inner = XdpLinkInner { -// if_index: todo!(), -// link: XdpLinkInnerType::FdLink(fd_link), -// }; -// return Ok(XdpLink(inner)); +// return Ok(XdpLink::new(XdpLinkInner::FdLink(fd_link))); // } // Err(LinkError::InvalidLink) // } diff --git a/bpf/aya-bpf/src/programs/sk_buff.rs b/bpf/aya-bpf/src/programs/sk_buff.rs index 38b0177d..3ae6cf3d 100644 --- a/bpf/aya-bpf/src/programs/sk_buff.rs +++ b/bpf/aya-bpf/src/programs/sk_buff.rs @@ -25,7 +25,7 @@ impl SkBuff { #[allow(clippy::len_without_is_empty)] #[inline] pub fn len(&self) -> u32 { - unsafe { *self.skb }.len + unsafe { (*self.skb).len } } #[inline] @@ -40,7 +40,7 @@ impl SkBuff { #[inline] pub fn set_mark(&mut self, mark: u32) { - unsafe { *self.skb }.mark = mark; + unsafe { (*self.skb).mark = mark } } #[inline] diff --git a/test/integration-ebpf/src/test.rs b/test/integration-ebpf/src/test.rs index d0ff7b32..8d40af01 100644 --- a/test/integration-ebpf/src/test.rs +++ b/test/integration-ebpf/src/test.rs @@ -1,9 +1,13 @@ #![no_std] #![no_main] -use aya_bpf::{bindings::xdp_action, macros::xdp, programs::XdpContext}; +use aya_bpf::{ + bindings::xdp_action, + macros::{kprobe, xdp}, + programs::{ProbeContext, XdpContext}, +}; -#[xdp(name = "test_unload")] +#[xdp(name = "test_unload_xdp")] pub fn pass(ctx: XdpContext) -> u32 { match unsafe { try_pass(ctx) } { Ok(ret) => ret, @@ -15,6 +19,12 @@ unsafe fn try_pass(_ctx: XdpContext) -> Result { Ok(xdp_action::XDP_PASS) } +#[kprobe] +// truncated name to match bpftool output +pub fn test_unload_kpr(_ctx: ProbeContext) -> u32 { + 0 +} + #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { unsafe { core::hint::unreachable_unchecked() } diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index f9a88ff9..e593d9b5 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -5,7 +5,7 @@ use aya::{ maps::Array, programs::{ links::{FdLink, PinnedLink}, - TracePoint, Xdp, XdpFlags, + KProbe, TracePoint, Xdp, XdpFlags, }, Bpf, }; @@ -84,28 +84,63 @@ macro_rules! assert_loaded { } #[integration_test] -fn unload() { +fn unload_xdp() { let bytes = include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/test"); let mut bpf = Bpf::load(bytes).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_unload").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf + .program_mut("test_unload_xdp") + .unwrap() + .try_into() + .unwrap(); prog.load().unwrap(); + assert_loaded!("test_unload_xdp", true); let link = prog.attach("lo", XdpFlags::default()).unwrap(); { - let _link_owned = prog.take_link(link); + let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded!("test_unload", true); + assert_loaded!("test_unload_xdp", true); }; - assert_loaded!("test_unload", false); + assert_loaded!("test_unload_xdp", false); prog.load().unwrap(); - assert_loaded!("test_unload", true); + assert_loaded!("test_unload_xdp", true); prog.attach("lo", XdpFlags::default()).unwrap(); - assert_loaded!("test_unload", true); + assert_loaded!("test_unload_xdp", true); + prog.unload().unwrap(); + + assert_loaded!("test_unload_xdp", false); +} + +#[integration_test] +fn unload_kprobe() { + let bytes = include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/test"); + let mut bpf = Bpf::load(bytes).unwrap(); + let prog: &mut KProbe = bpf + .program_mut("test_unload_kpr") + .unwrap() + .try_into() + .unwrap(); + prog.load().unwrap(); + assert_loaded!("test_unload_kpr", true); + let link = prog.attach("try_to_wake_up", 0).unwrap(); + { + let _link_owned = prog.take_link(link).unwrap(); + prog.unload().unwrap(); + assert_loaded!("test_unload_kpr", true); + }; + + assert_loaded!("test_unload_kpr", false); + prog.load().unwrap(); + + assert_loaded!("test_unload_kpr", true); + prog.attach("try_to_wake_up", 0).unwrap(); + + assert_loaded!("test_unload_kpr", true); prog.unload().unwrap(); - assert_loaded!("test_unload", false); + assert_loaded!("test_unload_kpr", false); } #[integration_test] @@ -117,26 +152,30 @@ fn pin_link() { let bytes = include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/test"); let mut bpf = Bpf::load(bytes).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_unload").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf + .program_mut("test_unload_xdp") + .unwrap() + .try_into() + .unwrap(); prog.load().unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); - assert_loaded!("test_unload", true); + assert_loaded!("test_unload_xdp", true); let fd_link: FdLink = link.try_into().unwrap(); let pinned = fd_link.pin("/sys/fs/bpf/aya-xdp-test-lo").unwrap(); // because of the pin, the program is still attached prog.unload().unwrap(); - assert_loaded!("test_unload", true); + assert_loaded!("test_unload_xdp", true); // delete the pin, but the program is still attached let new_link = pinned.unpin().unwrap(); - assert_loaded!("test_unload", true); + assert_loaded!("test_unload_xdp", true); // finally when new_link is dropped we're detached drop(new_link); - assert_loaded!("test_unload", false); + assert_loaded!("test_unload_xdp", false); } #[integration_test]