From f56dd0a70b36a97036eb9447efa20f0e1c93c8d7 Mon Sep 17 00:00:00 2001 From: Thia Wyrod Date: Wed, 24 Nov 2021 21:25:46 -0800 Subject: [PATCH] aya: eliminate name duplication in maps and programs. Map and ProgramData objects had unnecessarily cloned strings for their names, despite them being just as easily available to external users via bpf.maps() and bpf.programs(). --- aya/src/bpf.rs | 85 ++++++++++++----------------- aya/src/maps/array/program_array.rs | 6 +- aya/src/maps/hash_map/hash_map.rs | 41 +++++++------- aya/src/maps/mod.rs | 65 ++++++++++------------ aya/src/maps/sock/sock_hash.rs | 2 +- aya/src/maps/sock/sock_map.rs | 2 +- aya/src/obj/mod.rs | 8 +-- aya/src/obj/relocation.rs | 14 +++-- aya/src/programs/cgroup_skb.rs | 7 +-- aya/src/programs/kprobe.rs | 7 +-- aya/src/programs/lirc_mode2.rs | 7 +-- aya/src/programs/lsm.rs | 7 +-- aya/src/programs/mod.rs | 12 +--- aya/src/programs/perf_event.rs | 2 +- aya/src/programs/raw_trace_point.rs | 7 +-- aya/src/programs/sk_msg.rs | 7 +-- aya/src/programs/sk_skb.rs | 7 +-- aya/src/programs/sock_ops.rs | 7 +-- aya/src/programs/socket_filter.rs | 2 +- aya/src/programs/tc.rs | 43 +++++++++++---- aya/src/programs/tp_btf.rs | 7 +-- aya/src/programs/trace_point.rs | 2 +- aya/src/programs/uprobe.rs | 5 -- aya/src/programs/xdp.rs | 7 +-- 24 files changed, 145 insertions(+), 214 deletions(-) diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index c580b299..0ae2bf61 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -2,6 +2,7 @@ use std::{ borrow::Cow, collections::HashMap, error::Error, + ffi::CString, fs, io, os::{raw::c_int, unix::io::RawFd}, path::{Path, PathBuf}, @@ -191,8 +192,8 @@ impl<'a> BpfLoader<'a> { obj.relocate_btf(btf)?; } - let mut maps = Vec::new(); - for (_, mut obj) in obj.maps.drain() { + let mut maps = HashMap::new(); + for (name, mut obj) in obj.maps.drain() { if obj.def.map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 && obj.def.max_entries == 0 { obj.def.max_entries = possible_cpus() @@ -214,21 +215,21 @@ impl<'a> BpfLoader<'a> { None => return Err(BpfError::NoPinPath), }; // try to open map in case it's already pinned - match map.from_pinned(path) { + match map.from_pinned(&name, path) { Ok(fd) => { map.pinned = true; fd as RawFd } Err(_) => { - let fd = map.create()?; - map.pin(path)?; + let fd = map.create(&name)?; + map.pin(&name, path)?; fd } } } - PinningType::None => map.create()?, + PinningType::None => map.create(&name)?, }; - if !map.obj.data.is_empty() && map.obj.name != ".bss" { + if !map.obj.data.is_empty() && name != ".bss" { bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data.as_mut_ptr(), 0).map_err( |(code, io_error)| MapError::SyscallError { call: "bpf_map_update_elem".to_owned(), @@ -237,27 +238,25 @@ impl<'a> BpfLoader<'a> { }, )?; } - maps.push(map); + maps.insert(name, map); } - obj.relocate_maps(maps.as_slice())?; + obj.relocate_maps(maps.iter().map(|(name, map)| (name.as_str(), map)))?; obj.relocate_calls()?; let programs = obj .programs .drain() .map(|(name, obj)| { - let section = obj.section.clone(); let data = ProgramData { obj, - name: name.clone(), fd: None, links: Vec::new(), expected_attach_type: None, attach_btf_obj_fd: None, attach_btf_id: None, }; - let program = match section { + let program = match &data.obj.section { ProgramSection::KProbe { .. } => Program::KProbe(KProbe { data, kind: ProbeKind::KProbe, @@ -290,7 +289,13 @@ impl<'a> BpfLoader<'a> { }), ProgramSection::SockOps { .. } => Program::SockOps(SockOps { data }), ProgramSection::SchedClassifier { .. } => { - Program::SchedClassifier(SchedClassifier { data }) + Program::SchedClassifier(SchedClassifier { + data, + name: unsafe { + CString::from_vec_unchecked(Vec::from(name.clone())) + .into_boxed_c_str() + }, + }) } ProgramSection::CgroupSkbIngress { .. } => Program::CgroupSkb(CgroupSkb { data, @@ -314,13 +319,11 @@ impl<'a> BpfLoader<'a> { (name, program) }) .collect(); - Ok(Bpf { - maps: maps - .drain(..) - .map(|map| (map.obj.name.clone(), MapLock::new(map))) - .collect(), - programs, - }) + let maps = maps + .drain() + .map(|(name, map)| (name, MapLock::new(map))) + .collect(); + Ok(Bpf { maps, programs }) } } @@ -468,24 +471,16 @@ impl Bpf { /// For more details on programs and their usage, see the [programs module /// documentation](crate::programs). /// - /// # Errors - /// - /// Returns [`ProgramError::NotFound`] if the program does not exist. - /// /// # Examples /// /// ```no_run /// # let bpf = aya::Bpf::load(&[])?; - /// let program = bpf.program("SSL_read")?; + /// let program = bpf.program("SSL_read").unwrap(); /// println!("program SSL_read is of type {:?}", program.prog_type()); /// # Ok::<(), aya::BpfError>(()) /// ``` - pub fn program(&self, name: &str) -> Result<&Program, ProgramError> { - self.programs - .get(name) - .ok_or_else(|| ProgramError::NotFound { - name: name.to_owned(), - }) + pub fn program(&self, name: &str) -> Option<&Program> { + self.programs.get(name) } /// Returns a mutable reference to the program with the given name. @@ -493,10 +488,6 @@ impl Bpf { /// Used to get a program before loading and attaching it. For more details on programs and /// their usage, see the [programs module documentation](crate::programs). /// - /// # Errors - /// - /// Returns [`ProgramError::NotFound`] if the program does not exist. - /// /// # Examples /// /// ```no_run @@ -504,17 +495,13 @@ impl Bpf { /// use aya::programs::UProbe; /// use std::convert::TryInto; /// - /// let program: &mut UProbe = bpf.program_mut("SSL_read")?.try_into()?; + /// let program: &mut UProbe = bpf.program_mut("SSL_read").unwrap().try_into()?; /// program.load()?; /// program.attach(Some("SSL_read"), 0, "libssl", None)?; /// # Ok::<(), aya::BpfError>(()) /// ``` - pub fn program_mut(&mut self, name: &str) -> Result<&mut Program, ProgramError> { - self.programs - .get_mut(name) - .ok_or_else(|| ProgramError::NotFound { - name: name.to_owned(), - }) + pub fn program_mut(&mut self, name: &str) -> Option<&mut Program> { + self.programs.get_mut(name) } /// An iterator over all the programs. @@ -522,17 +509,17 @@ impl Bpf { /// # Examples /// ```no_run /// # let bpf = aya::Bpf::load(&[])?; - /// for program in bpf.programs() { + /// for (name, program) in bpf.programs() { /// println!( /// "found program `{}` of type `{:?}`", - /// program.name(), + /// name, /// program.prog_type() /// ); /// } /// # Ok::<(), aya::BpfError>(()) /// ``` - pub fn programs(&self) -> impl Iterator { - self.programs.values() + pub fn programs(&self) -> impl Iterator { + self.programs.iter().map(|(s, p)| (s.as_str(), p)) } /// An iterator mutably referencing all of the programs. @@ -542,13 +529,13 @@ impl Bpf { /// # use std::path::Path; /// # let mut bpf = aya::Bpf::load(&[])?; /// # let pin_path = Path::new("/tmp/pin_path"); - /// for program in bpf.programs_mut() { + /// for (_, program) in bpf.programs_mut() { /// program.pin(pin_path)?; /// } /// # Ok::<(), aya::BpfError>(()) /// ``` - pub fn programs_mut(&mut self) -> impl Iterator { - self.programs.values_mut() + pub fn programs_mut(&mut self) -> impl Iterator { + self.programs.iter_mut().map(|(s, p)| (s.as_str(), p)) } } diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index 9b2ae51d..6f939ed4 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -32,9 +32,9 @@ use crate::{ /// use std::convert::{TryFrom, TryInto}; /// /// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?; -/// let prog_0: &CgroupSkb = bpf.program("example_prog_0")?.try_into()?; -/// let prog_1: &CgroupSkb = bpf.program("example_prog_1")?.try_into()?; -/// let prog_2: &CgroupSkb = bpf.program("example_prog_2")?.try_into()?; +/// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?; +/// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?; +/// let prog_2: &CgroupSkb = bpf.program("example_prog_2").unwrap().try_into()?; /// /// let flags = 0; /// diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index fc841f34..e38eac52 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -158,9 +158,8 @@ mod tests { use super::*; - fn new_obj_map(name: &str) -> obj::Map { + fn new_obj_map() -> obj::Map { obj::Map { - name: name.to_string(), def: bpf_map_def { map_type: BPF_MAP_TYPE_HASH as u32, key_size: 4, @@ -180,7 +179,7 @@ mod tests { #[test] fn test_wrong_key_size() { let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: None, pinned: false, }; @@ -196,7 +195,7 @@ mod tests { #[test] fn test_wrong_value_size() { let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: None, pinned: false, }; @@ -213,7 +212,6 @@ mod tests { fn test_try_from_wrong_map() { let map = Map { obj: obj::Map { - name: "TEST".to_string(), def: bpf_map_def { map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32, key_size: 4, @@ -237,7 +235,7 @@ mod tests { #[test] fn test_new_not_created() { let mut map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: None, pinned: false, }; @@ -251,7 +249,7 @@ mod tests { #[test] fn test_new_ok() { let mut map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -262,7 +260,7 @@ mod tests { #[test] fn test_try_from_ok() { let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -273,7 +271,6 @@ mod tests { fn test_try_from_ok_lru() { let map = Map { obj: obj::Map { - name: "TEST".to_string(), def: bpf_map_def { map_type: BPF_MAP_TYPE_LRU_HASH as u32, key_size: 4, @@ -296,7 +293,7 @@ mod tests { override_syscall(|_| sys_error(EFAULT)); let mut map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -319,7 +316,7 @@ mod tests { }); let mut map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -333,7 +330,7 @@ mod tests { override_syscall(|_| sys_error(EFAULT)); let mut map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -356,7 +353,7 @@ mod tests { }); let mut map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -369,7 +366,7 @@ mod tests { fn test_get_syscall_error() { override_syscall(|_| sys_error(EFAULT)); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -391,7 +388,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -430,7 +427,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -474,7 +471,7 @@ mod tests { }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -502,7 +499,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -532,7 +529,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -565,7 +562,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -599,7 +596,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; @@ -639,7 +636,7 @@ mod tests { _ => sys_error(EFAULT), }); let map = Map { - obj: new_obj_map("TEST"), + obj: new_obj_map(), fd: Some(42), pinned: false, }; diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index d99375b7..74a1c4d6 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -21,7 +21,7 @@ //! use aya::programs::SkMsg; //! //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?; -//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?; +//! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; //! prog.load()?; //! prog.attach(&intercept_egress)?; //! # Ok::<(), aya::BpfError>(()) @@ -79,8 +79,8 @@ pub enum MapError { #[error("invalid map path `{error}`")] InvalidPinPath { error: String }, - #[error("the map `{name}` has not been created")] - NotCreated { name: String }, + #[error("the map has not been created")] + NotCreated, #[error("the map `{name}` has already been created")] AlreadyCreated { name: String }, @@ -148,18 +148,16 @@ pub struct Map { } impl Map { - pub fn create(&mut self) -> Result { - let name = self.obj.name.clone(); + pub fn create(&mut self, name: &str) -> Result { if self.fd.is_some() { - return Err(MapError::AlreadyCreated { name }); + return Err(MapError::AlreadyCreated { name: name.into() }); } - let c_name = - CString::new(name.clone()).map_err(|_| MapError::InvalidName { name: name.clone() })?; + let c_name = CString::new(name).map_err(|_| MapError::InvalidName { name: name.into() })?; let fd = bpf_create_map(&c_name, &self.obj.def).map_err(|(code, io_error)| { MapError::CreateError { - name, + name: name.into(), code, io_error, } @@ -170,12 +168,15 @@ impl Map { Ok(fd) } - pub(crate) fn from_pinned>(&mut self, path: P) -> Result { - let name = self.obj.name.clone(); + pub(crate) fn from_pinned>( + &mut self, + name: &str, + path: P, + ) -> Result { if self.fd.is_some() { - return Err(MapError::AlreadyCreated { name }); + return Err(MapError::AlreadyCreated { name: name.into() }); } - let map_path = path.as_ref().join(self.name()); + let map_path = path.as_ref().join(name); let path_string = match CString::new(map_path.to_str().unwrap()) { Ok(s) => s, Err(e) => { @@ -185,7 +186,7 @@ impl Map { } }; let fd = bpf_get_object(&path_string).map_err(|(code, io_error)| MapError::PinError { - name, + name: name.into(), code, io_error, })? as RawFd; @@ -195,27 +196,19 @@ impl Map { Ok(fd) } - pub fn name(&self) -> &str { - &self.obj.name - } - pub fn map_type(&self) -> Result { bpf_map_type::try_from(self.obj.def.map_type) } pub(crate) fn fd_or_err(&self) -> Result { - self.fd.ok_or_else(|| MapError::NotCreated { - name: self.obj.name.clone(), - }) + self.fd.ok_or(MapError::NotCreated) } - pub(crate) fn pin>(&mut self, path: P) -> Result<(), MapError> { + pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), MapError> { if self.pinned { - return Err(MapError::AlreadyPinned { - name: self.name().to_string(), - }); + return Err(MapError::AlreadyPinned { name: name.into() }); } - let map_path = path.as_ref().join(self.name()); + let map_path = path.as_ref().join(name); let fd = self.fd_or_err()?; let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| { MapError::InvalidPinPath { @@ -492,9 +485,8 @@ mod tests { use super::*; - fn new_obj_map(name: &str) -> obj::Map { + fn new_obj_map() -> obj::Map { obj::Map { - name: name.to_string(), def: bpf_map_def { map_type: BPF_MAP_TYPE_HASH as u32, key_size: 4, @@ -507,9 +499,9 @@ mod tests { } } - fn new_map(name: &str) -> Map { + fn new_map() -> Map { Map { - obj: new_obj_map(name), + obj: new_obj_map(), fd: None, pinned: false, } @@ -525,18 +517,21 @@ mod tests { _ => Err((-1, io::Error::from_raw_os_error(EFAULT))), }); - let mut map = new_map("foo"); - assert!(matches!(map.create(), Ok(42))); + let mut map = new_map(); + assert!(matches!(map.create("foo"), Ok(42))); assert_eq!(map.fd, Some(42)); - assert!(matches!(map.create(), Err(MapError::AlreadyCreated { .. }))); + assert!(matches!( + map.create("foo"), + Err(MapError::AlreadyCreated { .. }) + )); } #[test] fn test_create_failed() { override_syscall(|_| Err((-42, io::Error::from_raw_os_error(EFAULT)))); - let mut map = new_map("foo"); - let ret = map.create(); + let mut map = new_map(); + let ret = map.create("foo"); assert!(matches!(ret, Err(MapError::CreateError { .. }))); if let Err(MapError::CreateError { name, diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 7e06173c..fa7914dd 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -50,7 +50,7 @@ use crate::{ /// use aya::programs::SkMsg; /// /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?; -/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?; +/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(&intercept_egress)?; /// diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index d39f449c..13a46b1e 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -35,7 +35,7 @@ use crate::{ /// use aya::programs::SkSkb; /// /// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?; -/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet")?.try_into()?; +/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(&intercept_ingress)?; /// # Ok::<(), aya::BpfError>(()) diff --git a/aya/src/obj/mod.rs b/aya/src/obj/mod.rs index 810cc83b..ec4c2da8 100644 --- a/aya/src/obj/mod.rs +++ b/aya/src/obj/mod.rs @@ -44,7 +44,6 @@ pub struct Object { #[derive(Debug, Clone)] pub struct Map { - pub(crate) name: String, pub(crate) def: bpf_map_def, pub(crate) section_index: usize, pub(crate) data: Vec, @@ -530,7 +529,6 @@ fn parse_map(section: &Section, name: &str) -> Result { Ok(Map { section_index: section.index.0, - name: name.to_string(), def, data, }) @@ -785,7 +783,6 @@ mod tests { ), Ok(Map { section_index: 0, - name, def: bpf_map_def { map_type: 1, key_size: 2, @@ -796,7 +793,7 @@ mod tests { pinning: PinningType::None, }, data - }) if name == "foo" && data.is_empty() + }) if data.is_empty() )) } @@ -813,7 +810,6 @@ mod tests { ), Ok(Map { section_index: 0, - name, def: bpf_map_def { map_type: _map_type, key_size: 4, @@ -824,7 +820,7 @@ mod tests { pinning: PinningType::None, }, data - }) if name == ".bss" && data == map_data && value_size == map_data.len() as u32 + }) if data == map_data && value_size == map_data.len() as u32 )) } diff --git a/aya/src/obj/relocation.rs b/aya/src/obj/relocation.rs index d170e868..bc70f9b6 100644 --- a/aya/src/obj/relocation.rs +++ b/aya/src/obj/relocation.rs @@ -61,10 +61,12 @@ pub(crate) struct Symbol { } impl Object { - pub fn relocate_maps(&mut self, maps: &[Map]) -> Result<(), BpfError> { + pub fn relocate_maps<'a>( + &'a mut self, + maps: impl Iterator, + ) -> Result<(), BpfError> { let maps_by_section = maps - .iter() - .map(|map| (map.obj.section_index, map)) + .map(|(name, map)| (map.obj.section_index, (name, map))) .collect::>(); let functions = self @@ -110,7 +112,7 @@ impl Object { fn relocate_maps<'a, I: Iterator>( fun: &mut Function, relocations: I, - maps_by_section: &HashMap, + maps_by_section: &HashMap, symbol_table: &HashMap, ) -> Result<(), RelocationError> { let section_offset = fun.section_offset; @@ -152,7 +154,7 @@ fn relocate_maps<'a, I: Iterator>( None => continue, }; - let map = + let (name, map) = maps_by_section .get(§ion_index.0) .ok_or(RelocationError::SectionNotFound { @@ -162,7 +164,7 @@ fn relocate_maps<'a, I: Iterator>( })?; let map_fd = map.fd.ok_or_else(|| RelocationError::MapNotCreated { - name: map.obj.name.clone(), + name: (*name).into(), section_index: section_index.0, })?; diff --git a/aya/src/programs/cgroup_skb.rs b/aya/src/programs/cgroup_skb.rs index 6b798ad1..9aff1295 100644 --- a/aya/src/programs/cgroup_skb.rs +++ b/aya/src/programs/cgroup_skb.rs @@ -43,7 +43,7 @@ use super::FdLink; /// use aya::programs::{CgroupSkb, CgroupSkbAttachType}; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter")?.try_into()?; +/// let egress: &mut CgroupSkb = bpf.program_mut("egress_filter").unwrap().try_into()?; /// egress.load()?; /// egress.attach(file, CgroupSkbAttachType::Egress)?; /// # Ok::<(), Error>(()) @@ -63,11 +63,6 @@ impl CgroupSkb { load_program(BPF_PROG_TYPE_CGROUP_SKB, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Returns the expected attach type of the program. /// /// [`CgroupSkb`] programs can specify the expected attach type in their ELF diff --git a/aya/src/programs/kprobe.rs b/aya/src/programs/kprobe.rs index 9dddf6f8..ca7cc963 100644 --- a/aya/src/programs/kprobe.rs +++ b/aya/src/programs/kprobe.rs @@ -30,7 +30,7 @@ use crate::{ /// use aya::{Bpf, programs::KProbe}; /// use std::convert::TryInto; /// -/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?; +/// let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; /// program.load()?; /// program.attach("try_to_wake_up", 0)?; /// # Ok::<(), aya::BpfError>(()) @@ -50,11 +50,6 @@ impl KProbe { load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Returns `KProbe` if the program is a `kprobe`, or `KRetProbe` if the /// program is a `kretprobe`. pub fn kind(&self) -> ProbeKind { diff --git a/aya/src/programs/lirc_mode2.rs b/aya/src/programs/lirc_mode2.rs index 06d4cd8a..25f30b53 100644 --- a/aya/src/programs/lirc_mode2.rs +++ b/aya/src/programs/lirc_mode2.rs @@ -40,7 +40,7 @@ use libc::{close, dup}; /// /// let file = File::open("/dev/lirc0")?; /// let mut bpf = aya::Bpf::load_file("imon_rsc.o")?; -/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc")?.try_into().unwrap(); +/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap(); /// decoder.load()?; /// decoder.attach(file)?; /// # Ok::<(), Error>(()) @@ -59,11 +59,6 @@ impl LircMode2 { load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given lirc device. pub fn attach(&mut self, lircdev: T) -> Result { let prog_fd = self.data.fd_or_err()?; diff --git a/aya/src/programs/lsm.rs b/aya/src/programs/lsm.rs index 5d7f4cc6..ef057d9b 100644 --- a/aya/src/programs/lsm.rs +++ b/aya/src/programs/lsm.rs @@ -43,7 +43,7 @@ use crate::{ /// use std::convert::TryInto; /// /// let btf = Btf::from_sys_fs()?; -/// let program: &mut Lsm = bpf.program_mut("lsm_prog")?.try_into()?; +/// let program: &mut Lsm = bpf.program_mut("lsm_prog").unwrap().try_into()?; /// program.load("security_bprm_exec", &btf)?; /// program.attach()?; /// # Ok::<(), LsmError>(()) @@ -83,11 +83,6 @@ impl Lsm { load_program(BPF_PROG_TYPE_LSM, &mut self.data).map_err(LsmLoadError::from) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program. pub fn attach(&mut self) -> Result { attach_btf_id(&mut self.data) diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 4964aa66..2b8f2416 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -19,7 +19,7 @@ //! //! let mut bpf = Bpf::load_file("ebpf_programs.o")?; //! // intercept_wakeups is the name of the program we want to load -//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups")?.try_into()?; +//! let program: &mut KProbe = bpf.program_mut("intercept_wakeups").unwrap().try_into()?; //! program.load()?; //! // intercept_wakeups will be called every time try_to_wake_up() is called //! // inside the kernel @@ -95,10 +95,6 @@ use crate::{ /// Error type returned when working with programs. #[derive(Debug, Error)] pub enum ProgramError { - /// The program could not be found in the object code. - #[error("program `{name}` not found")] - NotFound { name: String }, - /// The program is already loaded. #[error("the program is already loaded")] AlreadyLoaded, @@ -240,11 +236,6 @@ impl Program { } } - /// Returns the name of the program. - pub fn name(&self) -> &str { - &self.data().name - } - /// Pin the program to the provided path pub fn pin>(&mut self, path: P) -> Result<(), ProgramError> { self.data_mut().pin(path) @@ -293,7 +284,6 @@ impl Program { #[derive(Debug)] pub(crate) struct ProgramData { - pub(crate) name: String, pub(crate) obj: obj::Program, pub(crate) fd: Option, pub(crate) links: Vec>>, diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 209e2ddc..d7c0a95d 100644 --- a/aya/src/programs/perf_event.rs +++ b/aya/src/programs/perf_event.rs @@ -66,7 +66,7 @@ pub enum PerfEventScope { /// perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK, PerfEvent, PerfEventScope, PerfTypeId, SamplePolicy, /// }; /// -/// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock")?.try_into()?; +/// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?; /// prog.load()?; /// /// for cpu in online_cpus()? { diff --git a/aya/src/programs/raw_trace_point.rs b/aya/src/programs/raw_trace_point.rs index 2ca95826..81b0e393 100644 --- a/aya/src/programs/raw_trace_point.rs +++ b/aya/src/programs/raw_trace_point.rs @@ -26,7 +26,7 @@ use crate::{ /// use aya::{Bpf, programs::RawTracePoint}; /// use std::convert::TryInto; /// -/// let program: &mut RawTracePoint = bpf.program_mut("sys_enter")?.try_into()?; +/// let program: &mut RawTracePoint = bpf.program_mut("sys_enter").unwrap().try_into()?; /// program.load()?; /// program.attach("sys_enter")?; /// # Ok::<(), aya::BpfError>(()) @@ -45,11 +45,6 @@ impl RawTracePoint { load_program(BPF_PROG_TYPE_RAW_TRACEPOINT, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given tracepoint. pub fn attach(&mut self, tp_name: &str) -> Result { let prog_fd = self.data.fd_or_err()?; diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index 9298a478..fcb50926 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -38,7 +38,7 @@ use crate::{ /// use aya::programs::SkMsg; /// /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?; -/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?; +/// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(&intercept_egress)?; /// @@ -67,11 +67,6 @@ impl SkMsg { load_program(BPF_PROG_TYPE_SK_MSG, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given sockmap. pub fn attach(&mut self, map: &dyn SocketMap) -> Result { let prog_fd = self.data.fd_or_err()?; diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index 6ab8a0fb..bd07534f 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -34,7 +34,7 @@ pub enum SkSkbKind { /// use aya::programs::SkSkb; /// /// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?; -/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet")?.try_into()?; +/// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; /// prog.attach(&intercept_ingress)?; /// # Ok::<(), aya::BpfError>(()) @@ -58,11 +58,6 @@ impl SkSkb { load_program(BPF_PROG_TYPE_SK_SKB, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given socket map. pub fn attach(&mut self, map: &dyn SocketMap) -> Result { let prog_fd = self.data.fd_or_err()?; diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index 5852c4d7..579dafc3 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -36,7 +36,7 @@ use crate::{ /// use aya::programs::SockOps; /// /// let file = File::open("/sys/fs/cgroup/unified")?; -/// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets")?.try_into()?; +/// let prog: &mut SockOps = bpf.program_mut("intercept_active_sockets").unwrap().try_into()?; /// prog.load()?; /// prog.attach(file)?; /// # Ok::<(), Error>(()) @@ -54,11 +54,6 @@ impl SockOps { load_program(BPF_PROG_TYPE_SOCK_OPS, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given cgroup. pub fn attach(&mut self, cgroup: T) -> Result { let prog_fd = self.data.fd_or_err()?; diff --git a/aya/src/programs/socket_filter.rs b/aya/src/programs/socket_filter.rs index 1509b22b..883ed5d2 100644 --- a/aya/src/programs/socket_filter.rs +++ b/aya/src/programs/socket_filter.rs @@ -51,7 +51,7 @@ pub enum SocketFilterError { /// use aya::programs::SocketFilter; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; -/// let prog: &mut SocketFilter = bpf.program_mut("filter_packets")?.try_into()?; +/// let prog: &mut SocketFilter = bpf.program_mut("filter_packets").unwrap().try_into()?; /// prog.load()?; /// prog.attach(client.as_raw_fd())?; /// # Ok::<(), Error>(()) diff --git a/aya/src/programs/tc.rs b/aya/src/programs/tc.rs index 4d16e0d4..7094c04a 100644 --- a/aya/src/programs/tc.rs +++ b/aya/src/programs/tc.rs @@ -1,7 +1,11 @@ //! Network traffic control programs. use thiserror::Error; -use std::{ffi::CString, io, os::unix::io::RawFd}; +use std::{ + ffi::{CStr, CString}, + io, + os::unix::io::RawFd, +}; use crate::{ generated::{ @@ -59,7 +63,7 @@ pub enum TcAttachType { /// // attached /// tc::qdisc_add_clsact("eth0")?; /// -/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress")?.try_into()?; +/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?; /// prog.load()?; /// prog.attach("eth0", TcAttachType::Ingress)?; /// @@ -69,6 +73,7 @@ pub enum TcAttachType { #[doc(alias = "BPF_PROG_TYPE_SCHED_CLS")] pub struct SchedClassifier { pub(crate) data: ProgramData, + pub(crate) name: Box, } #[derive(Debug, Error)] @@ -108,11 +113,6 @@ impl SchedClassifier { load_program(BPF_PROG_TYPE_SCHED_CLS, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given `interface`. /// /// # Errors @@ -129,9 +129,8 @@ impl SchedClassifier { let prog_fd = self.data.fd_or_err()?; let if_index = ifindex_from_ifname(interface) .map_err(|io_error| TcError::NetlinkError { io_error })?; - let name = CString::new(self.name()).unwrap(); let priority = - unsafe { netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &name) } + unsafe { netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &self.name) } .map_err(|io_error| TcError::NetlinkError { io_error })?; Ok(self.data.link(TcLink { @@ -181,13 +180,33 @@ pub fn qdisc_detach_program( if_name: &str, attach_type: TcAttachType, name: &str, +) -> Result<(), io::Error> { + let cstr = CString::new(name)?; + qdisc_detach_program_fast(if_name, attach_type, &cstr) +} + +/// Detaches the programs with the given name as a C string. +/// Unlike qdisc_detach_program, this function does not allocate an additional +/// CString to. +/// +/// # Errors +/// +/// Returns [`io::ErrorKind::NotFound`] to indicate that no programs with the +/// given name were found, so nothing was detached. Other error kinds indicate +/// an actual failure while detaching a program. +fn qdisc_detach_program_fast( + if_name: &str, + attach_type: TcAttachType, + name: &CStr, ) -> Result<(), io::Error> { let if_index = ifindex_from_ifname(if_name)? as i32; - let c_name = CString::new(name).unwrap(); - let prios = unsafe { netlink_find_filter_with_name(if_index, attach_type, &c_name)? }; + let prios = unsafe { netlink_find_filter_with_name(if_index, attach_type, name)? }; if prios.is_empty() { - return Err(io::Error::new(io::ErrorKind::NotFound, name.to_string())); + return Err(io::Error::new( + io::ErrorKind::NotFound, + name.to_string_lossy(), + )); } for prio in prios { diff --git a/aya/src/programs/tp_btf.rs b/aya/src/programs/tp_btf.rs index 7c16db0c..966414df 100644 --- a/aya/src/programs/tp_btf.rs +++ b/aya/src/programs/tp_btf.rs @@ -40,7 +40,7 @@ use crate::{ /// use std::convert::TryInto; /// /// let btf = Btf::from_sys_fs()?; -/// let program: &mut BtfTracePoint = bpf.program_mut("sched_process_fork")?.try_into()?; +/// let program: &mut BtfTracePoint = bpf.program_mut("sched_process_fork").unwrap().try_into()?; /// program.load("sched_process_fork", &btf)?; /// program.attach()?; /// # Ok::<(), Error>(()) @@ -81,11 +81,6 @@ impl BtfTracePoint { load_program(BPF_PROG_TYPE_TRACING, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program. pub fn attach(&mut self) -> Result { let prog_fd = self.data.fd_or_err()?; diff --git a/aya/src/programs/trace_point.rs b/aya/src/programs/trace_point.rs index 844be0b9..59fa145c 100644 --- a/aya/src/programs/trace_point.rs +++ b/aya/src/programs/trace_point.rs @@ -44,7 +44,7 @@ pub enum TracePointError { /// use std::convert::TryInto; /// use aya::programs::TracePoint; /// -/// let prog: &mut TracePoint = bpf.program_mut("trace_context_switch")?.try_into()?; +/// let prog: &mut TracePoint = bpf.program_mut("trace_context_switch").unwrap().try_into()?; /// prog.load()?; /// prog.attach("sched", "sched_switch")?; /// # Ok::<(), Error>(()) diff --git a/aya/src/programs/uprobe.rs b/aya/src/programs/uprobe.rs index 2444be86..ed699f9f 100644 --- a/aya/src/programs/uprobe.rs +++ b/aya/src/programs/uprobe.rs @@ -52,11 +52,6 @@ impl UProbe { load_program(BPF_PROG_TYPE_KPROBE, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Returns `UProbe` if the program is a `uprobe`, or `URetProbe` if the /// program is a `uretprobe`. pub fn kind(&self) -> ProbeKind { diff --git a/aya/src/programs/xdp.rs b/aya/src/programs/xdp.rs index 31a595c1..3cb75856 100644 --- a/aya/src/programs/xdp.rs +++ b/aya/src/programs/xdp.rs @@ -57,7 +57,7 @@ bitflags! { /// use aya::{Bpf, programs::{Xdp, XdpFlags}}; /// use std::convert::TryInto; /// -/// let program: &mut Xdp = bpf.program_mut("intercept_packets")?.try_into()?; +/// let program: &mut Xdp = bpf.program_mut("intercept_packets").unwrap().try_into()?; /// program.attach("eth0", XdpFlags::default())?; /// # Ok::<(), aya::BpfError>(()) /// ``` @@ -75,11 +75,6 @@ impl Xdp { load_program(BPF_PROG_TYPE_XDP, &mut self.data) } - /// Returns the name of the program. - pub fn name(&self) -> String { - self.data.name.to_string() - } - /// Attaches the program to the given `interface`. /// /// # Errors