Skip to main content

kbpf_basic/
lib.rs

1//! Basic eBPF library providing essential functionalities for eBPF programs.
2//!! This library includes support for BPF maps, helper functions, and program
3//! loading mechanisms, making it easier to develop and run eBPF programs in a
4//! kernel-like environment.
5//!
6
7#![deny(missing_docs)]
8#![no_std]
9#![feature(c_variadic)]
10#![allow(unused)]
11extern crate alloc;
12use alloc::{string::String, vec::Vec};
13
14use lock_api::RawMutex;
15use map::UnifiedMap;
16
17use crate::preprocessor::EbpfInst;
18pub mod helper;
19pub mod linux_bpf;
20pub mod map;
21pub mod perf;
22pub mod preprocessor;
23pub mod prog;
24pub mod raw_tracepoint;
25
26/// Type alias for BPF results and errors.
27pub type BpfResult<T> = ax_errno::LinuxResult<T>;
28/// Type alias for BPF errors.
29pub type BpfError = ax_errno::LinuxError;
30
31/// PollWaiter trait for maps that support polling.
32pub trait PollWaker: Send + Sync {
33    /// Wake up any waiters on the map.
34    fn wake_up(&self);
35}
36
37/// The KernelAuxiliaryOps trait provides auxiliary operations which should
38/// be implemented by the kernel or a kernel-like environment.
39pub trait KernelAuxiliaryOps: Send + Sync + 'static {
40    /// The associated type for the map lock, which must implement RawMutex.
41    type MapLock: RawMutex + 'static;
42    /// Get a unified map from a user space pointer.
43    fn get_unified_map_from_ptr<F, R>(ptr: *const u8, func: F) -> BpfResult<R>
44    where
45        F: FnOnce(&UnifiedMap<Self::MapLock>) -> BpfResult<R>;
46    /// Get a unified map from a file descriptor.
47    fn get_unified_map_from_fd<F, R>(map_fd: u32, func: F) -> BpfResult<R>
48    where
49        F: FnOnce(&UnifiedMap<Self::MapLock>) -> BpfResult<R>;
50    /// Get a unified map pointer from a file descriptor.
51    fn get_unified_map_ptr_from_fd(map_fd: u32) -> BpfResult<*const u8>;
52    /// Translate eBPF instructions, which may involve relocating map file descriptors.
53    fn translate_instruction(instruction: Vec<u8>) -> BpfResult<Vec<impl preprocessor::EbpfInst>>;
54    /// Copy data from a user space pointer to a kernel space buffer.
55    fn copy_from_user(src: *const u8, size: usize, dst: &mut [u8]) -> BpfResult<()>;
56    /// Copy data from a kernel space buffer to a user space pointer.
57    fn copy_to_user(dest: *mut u8, size: usize, src: &[u8]) -> BpfResult<()>;
58    /// Get the current CPU ID.
59    fn current_cpu_id() -> u32;
60    /// Output some data to a perf buf
61    fn perf_event_output(
62        ctx: *mut core::ffi::c_void,
63        fd: u32,
64        flags: u32,
65        data: &[u8],
66    ) -> BpfResult<()>;
67    /// Read a string from a user space pointer.
68    fn string_from_user_cstr(ptr: *const u8) -> BpfResult<String>;
69    /// For ebpf print helper functions
70    fn ebpf_write_str(str: &str) -> BpfResult<()>;
71    /// For ebpf ktime helper functions
72    fn ebpf_time_ns() -> BpfResult<u64>;
73
74    /// Allocate pages in kernel space. Return the physical address of the allocated page.
75    fn alloc_page() -> BpfResult<usize>;
76    /// Free the allocated page in kernel space.
77    fn free_page(phys_addr: usize);
78    /// Create a virtual mapping for the given physical addresses. Return the virtual address.
79    fn vmap(phys_addrs: &[usize]) -> BpfResult<usize>;
80    /// Unmap the virtual address range corresponding to the given virtual address and number of pages.
81    fn vunmap(vaddr: usize, num_pages: usize);
82}
83
84struct DummyAuxImpl;
85
86#[derive(Clone)]
87struct DummyInst;
88impl EbpfInst for DummyInst {
89    fn opc(&self) -> u8 {
90        0
91    }
92
93    fn imm(&self) -> i32 {
94        0
95    }
96
97    fn src(&self) -> u8 {
98        0
99    }
100
101    fn set_imm(&mut self, _imm: i32) {}
102
103    fn to_array(&self) -> [u8; 8] {
104        [0; 8]
105    }
106}
107
108struct DummyMapLock;
109unsafe impl RawMutex for DummyMapLock {
110    type GuardMarker = lock_api::GuardNoSend;
111    const INIT: Self = DummyMapLock;
112    fn lock(&self) {
113        // No actual locking needed for the dummy implementation
114    }
115
116    fn try_lock(&self) -> bool {
117        true
118    }
119
120    unsafe fn unlock(&self) {
121        // No actual unlocking needed for the dummy implementation
122    }
123}
124
125impl KernelAuxiliaryOps for DummyAuxImpl {
126    type MapLock = DummyMapLock;
127    fn get_unified_map_from_ptr<F, R>(_ptr: *const u8, _func: F) -> BpfResult<R>
128    where
129        F: FnOnce(&UnifiedMap<Self::MapLock>) -> BpfResult<R>,
130    {
131        Err(BpfError::EPERM)
132    }
133
134    fn get_unified_map_from_fd<F, R>(_map_fd: u32, _func: F) -> BpfResult<R>
135    where
136        F: FnOnce(&UnifiedMap<Self::MapLock>) -> BpfResult<R>,
137    {
138        Err(BpfError::EPERM)
139    }
140
141    fn get_unified_map_ptr_from_fd(_map_fd: u32) -> BpfResult<*const u8> {
142        Err(BpfError::EPERM)
143    }
144
145    fn translate_instruction(instruction: Vec<u8>) -> BpfResult<Vec<impl preprocessor::EbpfInst>> {
146        Err::<Vec<DummyInst>, BpfError>(BpfError::EPERM)
147    }
148
149    fn copy_from_user(_src: *const u8, _size: usize, _dst: &mut [u8]) -> BpfResult<()> {
150        Err(BpfError::EPERM)
151    }
152
153    fn copy_to_user(_dest: *mut u8, _size: usize, _src: &[u8]) -> BpfResult<()> {
154        Err(BpfError::EPERM)
155    }
156
157    fn current_cpu_id() -> u32 {
158        0
159    }
160
161    fn perf_event_output(
162        _ctx: *mut core::ffi::c_void,
163        _fd: u32,
164        _flags: u32,
165        _data: &[u8],
166    ) -> BpfResult<()> {
167        Err(BpfError::EPERM)
168    }
169
170    fn string_from_user_cstr(_ptr: *const u8) -> BpfResult<String> {
171        Err(BpfError::EPERM)
172    }
173
174    fn ebpf_write_str(_str: &str) -> BpfResult<()> {
175        Err(BpfError::EPERM)
176    }
177
178    fn ebpf_time_ns() -> BpfResult<u64> {
179        Err(BpfError::EPERM)
180    }
181
182    fn alloc_page() -> BpfResult<usize> {
183        Err(BpfError::EPERM)
184    }
185
186    fn free_page(_phys_addr: usize) {}
187
188    fn vmap(_phys_addrs: &[usize]) -> BpfResult<usize> {
189        Err(BpfError::EPERM)
190    }
191
192    fn vunmap(_vaddr: usize, _num_pages: usize) {}
193}