aya_ebpf/
lib.rs

1//! [![](https://aya-rs.dev/assets/images/aya_logo_docs.svg)](https://aya-rs.dev)
2//!
3//! A library to write eBPF programs.
4//!
5//! Aya-bpf is an eBPF library built with a focus on operability and developer experience.
6//! It is the kernel-space counterpart of [Aya](https://docs.rs/aya)
7#![doc(
8    html_logo_url = "https://aya-rs.dev/assets/images/crabby.svg",
9    html_favicon_url = "https://aya-rs.dev/assets/images/crabby.svg"
10)]
11#![cfg_attr(
12    feature = "const_assert",
13    allow(incomplete_features),
14    feature(generic_const_exprs)
15)]
16#![cfg_attr(unstable, feature(never_type))]
17#![cfg_attr(target_arch = "bpf", feature(asm_experimental_arch))]
18#![allow(clippy::missing_safety_doc)]
19#![deny(warnings)]
20#![warn(clippy::cast_lossless, clippy::cast_sign_loss)]
21#![no_std]
22
23pub use aya_ebpf_bindings::bindings;
24
25mod args;
26pub use args::PtRegs;
27pub mod helpers;
28pub mod maps;
29pub mod programs;
30
31use core::ffi::c_void;
32
33pub use aya_ebpf_cty as cty;
34pub use aya_ebpf_macros as macros;
35use cty::{c_int, c_long};
36use helpers::{bpf_get_current_comm, bpf_get_current_pid_tgid, bpf_get_current_uid_gid};
37
38pub const TASK_COMM_LEN: usize = 16;
39
40pub trait EbpfContext {
41    fn as_ptr(&self) -> *mut c_void;
42
43    #[inline]
44    fn command(&self) -> Result<[u8; TASK_COMM_LEN], c_long> {
45        bpf_get_current_comm()
46    }
47
48    fn pid(&self) -> u32 {
49        bpf_get_current_pid_tgid() as u32
50    }
51
52    fn tgid(&self) -> u32 {
53        (bpf_get_current_pid_tgid() >> 32) as u32
54    }
55
56    fn uid(&self) -> u32 {
57        bpf_get_current_uid_gid() as u32
58    }
59
60    fn gid(&self) -> u32 {
61        (bpf_get_current_uid_gid() >> 32) as u32
62    }
63}
64
65#[no_mangle]
66pub unsafe extern "C" fn memset(s: *mut u8, c: c_int, n: usize) {
67    #[allow(clippy::cast_sign_loss)]
68    let b = c as u8;
69    for i in 0..n {
70        *s.add(i) = b;
71    }
72}
73
74#[no_mangle]
75pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *mut u8, n: usize) {
76    copy_forward(dest, src, n);
77}
78
79#[no_mangle]
80pub unsafe extern "C" fn memmove(dest: *mut u8, src: *mut u8, n: usize) {
81    let delta = (dest as usize).wrapping_sub(src as usize);
82    if delta >= n {
83        // We can copy forwards because either dest is far enough ahead of src,
84        // or src is ahead of dest (and delta overflowed).
85        copy_forward(dest, src, n);
86    } else {
87        copy_backward(dest, src, n);
88    }
89}
90
91#[inline(always)]
92unsafe fn copy_forward(dest: *mut u8, src: *mut u8, n: usize) {
93    for i in 0..n {
94        *dest.add(i) = *src.add(i);
95    }
96}
97
98#[inline(always)]
99unsafe fn copy_backward(dest: *mut u8, src: *mut u8, n: usize) {
100    for i in (0..n).rev() {
101        *dest.add(i) = *src.add(i);
102    }
103}
104
105/// Check if a value is within a range, using conditional forms compatible with
106/// the verifier.
107#[inline(always)]
108pub fn check_bounds_signed(value: i64, lower: i64, upper: i64) -> bool {
109    #[cfg(target_arch = "bpf")]
110    unsafe {
111        let mut in_bounds = 0u64;
112        core::arch::asm!(
113            "if {value} s< {lower} goto +2",
114            "if {value} s> {upper} goto +1",
115            "{i} = 1",
116            i = inout(reg) in_bounds,
117            lower = in(reg) lower,
118            upper = in(reg) upper,
119            value = in(reg) value,
120        );
121        in_bounds == 1
122    }
123    // We only need this for doc tests which are compiled for the host target
124    #[cfg(not(target_arch = "bpf"))]
125    {
126        let _ = value;
127        let _ = lower;
128        let _ = upper;
129        unimplemented!()
130    }
131}