bpf.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. use std::{
  2. cell::{Ref, RefCell, RefMut},
  3. collections::HashMap,
  4. convert::TryFrom,
  5. };
  6. use thiserror::Error;
  7. use crate::{
  8. generated::bpf_insn,
  9. maps::{Map, MapError},
  10. obj::{relocate, Object, ParseError, RelocationError},
  11. programs::{KProbe, Program, ProgramData, ProgramError, SocketFilter, TracePoint, UProbe, Xdp},
  12. syscalls::bpf_map_update_elem_ptr,
  13. };
  14. unsafe impl object::Pod for bpf_insn {}
  15. pub(crate) const BPF_OBJ_NAME_LEN: usize = 16;
  16. /* FIXME: these are arch dependent */
  17. pub(crate) const PERF_EVENT_IOC_ENABLE: libc::c_ulong = 9216;
  18. pub(crate) const PERF_EVENT_IOC_DISABLE: libc::c_ulong = 9217;
  19. pub(crate) const PERF_EVENT_IOC_SET_BPF: libc::c_ulong = 1074013192;
  20. pub unsafe trait Pod: Copy + 'static {}
  21. macro_rules! unsafe_impl_pod {
  22. ($($struct_name:ident),+ $(,)?) => {
  23. $(
  24. unsafe impl Pod for $struct_name { }
  25. )+
  26. }
  27. }
  28. unsafe_impl_pod!(i8, u8, i16, u16, i32, u32, i64, u64);
  29. #[repr(C)]
  30. #[derive(Copy, Clone, Debug)]
  31. pub(crate) struct bpf_map_def {
  32. pub(crate) map_type: u32,
  33. pub(crate) key_size: u32,
  34. pub(crate) value_size: u32,
  35. pub(crate) max_entries: u32,
  36. pub(crate) map_flags: u32,
  37. }
  38. unsafe impl object::Pod for bpf_map_def {}
  39. #[derive(Debug)]
  40. pub struct Bpf {
  41. maps: HashMap<String, RefCell<Map>>,
  42. programs: HashMap<String, Program>,
  43. }
  44. impl Bpf {
  45. pub fn load(data: &[u8]) -> Result<Bpf, BpfError> {
  46. let mut obj = Object::parse(data)?;
  47. let mut maps = Vec::new();
  48. for (_, obj) in obj.maps.drain() {
  49. let mut map = Map { obj, fd: None };
  50. let fd = map.create()?;
  51. if !map.obj.data.is_empty() && map.obj.name != ".bss" {
  52. bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data.as_ptr(), 0)
  53. .map_err(|(code, io_error)| MapError::UpdateElementFailed { code, io_error })?;
  54. }
  55. maps.push(map);
  56. }
  57. relocate(&mut obj, maps.as_slice())?;
  58. let programs = obj
  59. .programs
  60. .drain()
  61. .map(|(name, obj)| {
  62. let kind = obj.kind;
  63. let data = ProgramData {
  64. obj,
  65. name: name.clone(),
  66. fd: None,
  67. links: Vec::new(),
  68. };
  69. let program = match kind {
  70. crate::obj::ProgramKind::KProbe => Program::KProbe(KProbe { data }),
  71. crate::obj::ProgramKind::UProbe => Program::UProbe(UProbe { data }),
  72. crate::obj::ProgramKind::TracePoint => Program::TracePoint(TracePoint { data }),
  73. crate::obj::ProgramKind::Xdp => Program::Xdp(Xdp { data }),
  74. };
  75. (name, program)
  76. })
  77. .collect();
  78. Ok(Bpf {
  79. maps: maps
  80. .drain(..)
  81. .map(|map| (map.obj.name.clone(), RefCell::new(map)))
  82. .collect(),
  83. programs,
  84. })
  85. }
  86. pub fn map<'a, 'slf: 'a, T: TryFrom<Ref<'a, Map>>>(
  87. &'slf self,
  88. name: &str,
  89. ) -> Result<Option<T>, <T as TryFrom<Ref<'a, Map>>>::Error> {
  90. self.maps
  91. .get(name)
  92. .map(|cell| T::try_from(cell.borrow()))
  93. .transpose()
  94. }
  95. pub fn map_mut<'a, 'slf: 'a, T: TryFrom<RefMut<'a, Map>>>(
  96. &'slf self,
  97. name: &str,
  98. ) -> Result<Option<T>, <T as TryFrom<RefMut<'a, Map>>>::Error> {
  99. self.maps
  100. .get(name)
  101. .map(|cell| T::try_from(cell.borrow_mut()))
  102. .transpose()
  103. }
  104. pub fn program(&self, name: &str) -> Option<&Program> {
  105. self.programs.get(name)
  106. }
  107. pub fn program_mut(&mut self, name: &str) -> Option<&mut Program> {
  108. self.programs.get_mut(name)
  109. }
  110. pub fn kprobe(&self, name: &str) -> Option<&KProbe> {
  111. match self.programs.get(name) {
  112. Some(Program::KProbe(kprobe)) => Some(kprobe),
  113. _ => None,
  114. }
  115. }
  116. pub fn kprobe_mut(&mut self, name: &str) -> Option<&mut KProbe> {
  117. match self.programs.get_mut(name) {
  118. Some(Program::KProbe(kprobe)) => Some(kprobe),
  119. _ => None,
  120. }
  121. }
  122. pub fn uprobe(&self, name: &str) -> Option<&UProbe> {
  123. match self.programs.get(name) {
  124. Some(Program::UProbe(uprobe)) => Some(uprobe),
  125. _ => None,
  126. }
  127. }
  128. pub fn uprobe_mut(&mut self, name: &str) -> Option<&mut UProbe> {
  129. match self.programs.get_mut(name) {
  130. Some(Program::UProbe(uprobe)) => Some(uprobe),
  131. _ => None,
  132. }
  133. }
  134. pub fn trace_point(&self, name: &str) -> Option<&TracePoint> {
  135. match self.programs.get(name) {
  136. Some(Program::TracePoint(trace_point)) => Some(trace_point),
  137. _ => None,
  138. }
  139. }
  140. pub fn trace_point_mut(&mut self, name: &str) -> Option<&mut TracePoint> {
  141. match self.programs.get_mut(name) {
  142. Some(Program::TracePoint(trace_point)) => Some(trace_point),
  143. _ => None,
  144. }
  145. }
  146. pub fn socket_filter(&self, name: &str) -> Option<&SocketFilter> {
  147. match self.programs.get(name) {
  148. Some(Program::SocketFilter(socket_filter)) => Some(socket_filter),
  149. _ => None,
  150. }
  151. }
  152. pub fn socket_filter_mut(&mut self, name: &str) -> Option<&mut SocketFilter> {
  153. match self.programs.get_mut(name) {
  154. Some(Program::SocketFilter(socket_filter)) => Some(socket_filter),
  155. _ => None,
  156. }
  157. }
  158. pub fn xdp(&self, name: &str) -> Option<&Xdp> {
  159. match self.programs.get(name) {
  160. Some(Program::Xdp(xdp)) => Some(xdp),
  161. _ => None,
  162. }
  163. }
  164. pub fn xdp_mut(&mut self, name: &str) -> Option<&mut Xdp> {
  165. match self.programs.get_mut(name) {
  166. Some(Program::Xdp(xdp)) => Some(xdp),
  167. _ => None,
  168. }
  169. }
  170. }
  171. #[derive(Debug, Error)]
  172. pub enum BpfError {
  173. #[error("error parsing BPF object: {0}")]
  174. ParseError(#[from] ParseError),
  175. #[error("error relocating BPF object: {0}")]
  176. RelocationError(#[from] RelocationError),
  177. #[error("map error: {0}")]
  178. MapError(#[from] MapError),
  179. #[error("program error: {0}")]
  180. ProgramError(#[from] ProgramError),
  181. }