From 64f8a434d2a337578bde86c1983f46a3282e7f53 Mon Sep 17 00:00:00 2001 From: Dave Tucker Date: Thu, 7 Jul 2022 23:51:32 +0100 Subject: [PATCH] aya: Implement FdLink::pin() This allows for FdLinks to also be pinned to BpfFs. In order for it to be called, the user would first call `take_link` to get the underlying link. This can then be destructured to an FdLink where FdLink::pin() may be called. Signed-off-by: Dave Tucker --- aya/src/programs/links.rs | 46 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index b3ee0e06..157bb164 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -1,14 +1,40 @@ //! Program links. use libc::{close, dup}; +use thiserror::Error; use std::{ borrow::Borrow, collections::{hash_map::Entry, HashMap}, + ffi::CString, + io, ops::Deref, os::unix::prelude::RawFd, + path::Path, }; -use crate::{generated::bpf_attach_type, programs::ProgramError, sys::bpf_prog_detach}; +use crate::{ + generated::bpf_attach_type, + programs::ProgramError, + sys::{bpf_pin_object, bpf_prog_detach}, +}; + +/// An error ocurred working with a Link. +#[derive(Error, Debug)] +pub enum LinkError { + /// Invalid Pin Path. + #[error("invalid pin path `{error}`")] + InvalidPinPath { + /// The error message. + error: String, + }, + /// Pinning error. + #[error("BPF_OBJ_PIN failed")] + PinError { + /// The [`io::Error`] returned by the syscall. + #[source] + io_error: io::Error, + }, +} /// A Link. pub trait Link: std::fmt::Debug + 'static { @@ -111,6 +137,24 @@ impl FdLink { pub(crate) fn new(fd: RawFd) -> FdLink { FdLink { fd } } + + /// Pins the FdLink to a BPF filesystem. + /// + /// When a BPF object is pinned to a BPF filesystem it will remain attached after + /// Aya has detached the link. + /// To remove the attachment, the file on the BPF filesystem must be remove. + /// Any directories in the the path provided should have been created by the caller. + pub fn pin>(&self, path: P) -> Result<(), LinkError> { + let path_string = + CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| { + LinkError::InvalidPinPath { + error: e.to_string(), + } + })?; + bpf_pin_object(self.fd, &path_string) + .map_err(|(_code, io_error)| LinkError::PinError { io_error })?; + Ok(()) + } } impl Link for FdLink {