Skip to main content

aya_ebpf/maps/
program_array.rs

1use crate::{
2    EbpfContext,
3    bindings::bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY,
4    helpers::bpf_tail_call,
5    maps::{MapDef, PinningType},
6};
7
8/// A BPF map that stores an array of program indices for tail calling.
9///
10/// # Examples
11///
12/// ```no_run
13/// use aya_ebpf::{macros::map, maps::ProgramArray};
14/// # use aya_ebpf::{programs::LsmContext};
15///
16/// #[map]
17/// static JUMP_TABLE: ProgramArray = ProgramArray::with_max_entries(16, 0);
18///
19/// # unsafe fn try_test(ctx: &LsmContext) {
20/// let index: u32 = 13;
21///
22/// unsafe {
23///     JUMP_TABLE.tail_call(ctx, index);
24/// }
25/// # }
26/// ```
27#[repr(transparent)]
28pub struct ProgramArray {
29    def: MapDef,
30}
31
32impl ProgramArray {
33    map_constructors!(u32, u32, BPF_MAP_TYPE_PROG_ARRAY);
34
35    /// Performs a tail call into a program indexed by this map.
36    ///
37    /// # Safety
38    ///
39    /// This function is inherently unsafe, since it causes control flow to
40    /// jump into another eBPF program. This can have side effects, such as
41    /// drop methods not being called. Note that tail calling into an eBPF
42    /// program is not the same thing as a function call -- control flow
43    /// never returns to the caller.
44    ///
45    /// # Return Value
46    ///
47    /// On success, this function does not return into the original program.
48    /// On failure, control returns to the caller. The kernel's
49    /// `bpf_tail_call` helper is declared with `ret_type = RET_VOID` and
50    /// does not write `R0` on failure, so callers cannot distinguish
51    /// between the three failure modes (out-of-bounds index, empty slot,
52    /// or `MAX_TAIL_CALL_CNT` exceeded).
53    pub unsafe fn tail_call<C: EbpfContext>(&self, ctx: &C, index: u32) {
54        // SAFETY: `ctx` and `self.def` are valid pointers managed by aya.
55        unsafe {
56            bpf_tail_call(ctx.as_ptr(), self.def.as_ptr().cast(), index);
57        }
58    }
59}