Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ebpf/aya-ebpf/src/btf_maps/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
pub mod array;
pub mod ring_buf;
pub mod sk_storage;
pub mod task_storage;

pub use array::Array;
pub use ring_buf::RingBuf;
pub use sk_storage::SkStorage;
pub use task_storage::TaskStorage;

/// Defines a BTF-compatible map struct with flat `#[repr(C)]` layout.
///
Expand Down
74 changes: 74 additions & 0 deletions ebpf/aya-ebpf/src/btf_maps/task_storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use core::ptr;

use aya_ebpf_bindings::bindings::{BPF_F_NO_PREALLOC, BPF_LOCAL_STORAGE_GET_F_CREATE, task_struct};

use crate::{
btf_maps::btf_map_def,
helpers::{bpf_get_current_task_btf, bpf_task_storage_delete, bpf_task_storage_get},
};

btf_map_def!(
/// A BTF-compatible BPF task storage map.
///
/// Task storage maps require `BPF_F_NO_PREALLOC` flag and `max_entries: 0`.
pub struct TaskStorage<T>,
map_type: BPF_MAP_TYPE_TASK_STORAGE,
max_entries: 0,
map_flags: BPF_F_NO_PREALLOC as usize,
key_type: i32,
value_type: T,
);

impl<T> TaskStorage<T> {
#[inline(always)]
fn get_ptr(&self, task: Option<*mut task_struct>, value: *mut T, flags: u64) -> *mut T {
let task = task.unwrap_or_else(|| unsafe { bpf_get_current_task_btf() });
unsafe { bpf_task_storage_get(self.as_ptr(), task.cast(), value.cast(), flags) }.cast()
}

/// Gets a mutable reference to the value associated with `task`.
///
/// If `task` is `None`, the current task is used.
///
/// # Safety
///
/// This function may dereference the pointer `task`.
#[inline(always)]
pub unsafe fn get_ptr_mut(&self, task: Option<*mut task_struct>) -> *mut T {
self.get_ptr(task, ptr::null_mut(), 0)
}

/// Gets a mutable reference to the value associated with `task`.
///
/// If no value is associated with `task`, `value` will be inserted. If
/// `task` is `None`, the current task is used.
///
/// # Safety
///
/// This function may dereference the pointer `task`.
#[inline(always)]
pub unsafe fn get_or_insert_ptr_mut(
&self,
task: Option<*mut task_struct>,
value: Option<&mut T>,
) -> *mut T {
self.get_ptr(
task,
value.map_or(ptr::null_mut(), ptr::from_mut),
BPF_LOCAL_STORAGE_GET_F_CREATE.into(),
)
}

/// Deletes the value associated with `task`. If `task` is `None`, the
/// current task is used.
///
/// # Safety
///
/// This function may dereference the pointer `task`.
#[inline(always)]
pub unsafe fn delete(&self, task: Option<*mut task_struct>) -> Result<(), i32> {
let task = task.unwrap_or_else(|| unsafe { bpf_get_current_task_btf() });
let ret = unsafe { bpf_task_storage_delete(self.as_ptr(), task.cast()) };
if ret == 0 { Ok(()) } else { Err(ret as i32) }
}
}
4 changes: 4 additions & 0 deletions test/integration-ebpf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ path = "src/simple_prog.rs"
name = "strncmp"
path = "src/strncmp.rs"

[[bin]]
name = "task_storage"
path = "src/task_storage.rs"

[[bin]]
name = "tcx"
path = "src/tcx.rs"
Expand Down
59 changes: 59 additions & 0 deletions test/integration-ebpf/src/task_storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#![no_std]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ignore this program for now, will modify it in due time.

#![no_main]
#![expect(unused_crate_dependencies, reason = "used in other bins")]

use aya_ebpf::{
btf_maps::TaskStorage,
helpers::bpf_get_current_task_btf,
macros::{btf_map, kprobe},
programs::ProbeContext,
};

#[cfg(not(test))]
extern crate ebpf_panic;

#[btf_map]
static TASK_STORAGE: TaskStorage<u64> = TaskStorage::new();

#[kprobe]
fn task_storage_test(_ctx: ProbeContext) -> i64 {
let task = unsafe { bpf_get_current_task_btf() };

let mut initial_val: u64 = 42;
let ptr = unsafe { TASK_STORAGE.get_or_insert_ptr_mut(Some(task), Some(&mut initial_val)) };
if ptr.is_null() {
return 0;
}

let val = unsafe { *ptr };
if val != 42 {
return 0;
}

unsafe {
*ptr = 1337;
}
let ptr = unsafe { TASK_STORAGE.get_ptr_mut(Some(task)) };
if ptr.is_null() {
return 0;
}

let val = unsafe { *ptr };
if val != 1337 {
return 0;
}

let ret = unsafe {
TASK_STORAGE.delete(None /* uses current task */)
};
if ret.is_err() {
return 0;
}

let ptr = unsafe { TASK_STORAGE.get_ptr_mut(Some(task)) };
if !ptr.is_null() {
return 0;
}

0
}
3 changes: 3 additions & 0 deletions test/integration-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ bpf_file!(
SIMPLE_PROG => "simple_prog",
SK_STORAGE => "sk_storage",
STRNCMP => "strncmp",
// TODO(sblaisdo) - add integration test after userspace support is completed
// https://github.com/aya-rs/aya/pull/1161
// TASK_STORAGE => "task_storage",
TCX => "tcx",
TEST => "test",
TWO_PROGS => "two_progs",
Expand Down
65 changes: 65 additions & 0 deletions xtask/public-api/aya-ebpf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,39 @@ impl<T> core::borrow::BorrowMut<T> for aya_ebpf::btf_maps::sk_storage::SkStorage
pub fn aya_ebpf::btf_maps::sk_storage::SkStorage<T>::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya_ebpf::btf_maps::sk_storage::SkStorage<T>
pub fn aya_ebpf::btf_maps::sk_storage::SkStorage<T>::from(t: T) -> T
pub mod aya_ebpf::btf_maps::task_storage
#[repr(C)] pub struct aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub unsafe fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::delete(&self, task: core::option::Option<*mut aya_ebpf_bindings::x86_64::bindings::task_struct>) -> core::result::Result<(), i32>
pub unsafe fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::get_or_insert_ptr_mut(&self, task: core::option::Option<*mut aya_ebpf_bindings::x86_64::bindings::task_struct>, value: core::option::Option<&mut T>) -> *mut T
pub unsafe fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::get_ptr_mut(&self, task: core::option::Option<*mut aya_ebpf_bindings::x86_64::bindings::task_struct>) -> *mut T
impl<T> aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub const fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::new() -> Self
impl<T> core::default::Default for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::default() -> Self
impl<T> core::marker::Sync for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::marker::Freeze for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> !core::marker::Send for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::marker::Unpin for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::marker::UnsafeUnpin for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: core::panic::unwind_safe::RefUnwindSafe
impl<T> core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: core::panic::unwind_safe::RefUnwindSafe
impl<T, U> core::convert::Into<U> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where U: core::convert::From<T>
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::into(self) -> U
impl<T, U> core::convert::TryFrom<U> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where U: core::convert::Into<T>
pub type aya_ebpf::btf_maps::task_storage::TaskStorage<T>::Error = core::convert::Infallible
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
impl<T, U> core::convert::TryInto<U> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where U: core::convert::TryFrom<T>
pub type aya_ebpf::btf_maps::task_storage::TaskStorage<T>::Error = <U as core::convert::TryFrom<T>>::Error
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
impl<T> core::any::Any for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: 'static + ?core::marker::Sized
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::type_id(&self) -> core::any::TypeId
impl<T> core::borrow::Borrow<T> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: ?core::marker::Sized
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::borrow(&self) -> &T
impl<T> core::borrow::BorrowMut<T> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: ?core::marker::Sized
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::from(t: T) -> T
#[repr(C)] pub struct aya_ebpf::btf_maps::Array<T, const MAX_ENTRIES: usize, const FLAGS: usize>
impl<T, const MAX_ENTRIES: usize, const FLAGS: usize> aya_ebpf::btf_maps::array::Array<T, MAX_ENTRIES, FLAGS>
pub fn aya_ebpf::btf_maps::array::Array<T, MAX_ENTRIES, FLAGS>::get(&self, index: u32) -> core::option::Option<&T>
Expand Down Expand Up @@ -206,6 +239,38 @@ impl<T> core::borrow::BorrowMut<T> for aya_ebpf::btf_maps::sk_storage::SkStorage
pub fn aya_ebpf::btf_maps::sk_storage::SkStorage<T>::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya_ebpf::btf_maps::sk_storage::SkStorage<T>
pub fn aya_ebpf::btf_maps::sk_storage::SkStorage<T>::from(t: T) -> T
#[repr(C)] pub struct aya_ebpf::btf_maps::TaskStorage<T>
impl<T> aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub unsafe fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::delete(&self, task: core::option::Option<*mut aya_ebpf_bindings::x86_64::bindings::task_struct>) -> core::result::Result<(), i32>
pub unsafe fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::get_or_insert_ptr_mut(&self, task: core::option::Option<*mut aya_ebpf_bindings::x86_64::bindings::task_struct>, value: core::option::Option<&mut T>) -> *mut T
pub unsafe fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::get_ptr_mut(&self, task: core::option::Option<*mut aya_ebpf_bindings::x86_64::bindings::task_struct>) -> *mut T
impl<T> aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub const fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::new() -> Self
impl<T> core::default::Default for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::default() -> Self
impl<T> core::marker::Sync for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::marker::Freeze for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> !core::marker::Send for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::marker::Unpin for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::marker::UnsafeUnpin for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
impl<T> core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: core::panic::unwind_safe::RefUnwindSafe
impl<T> core::panic::unwind_safe::UnwindSafe for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: core::panic::unwind_safe::RefUnwindSafe
impl<T, U> core::convert::Into<U> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where U: core::convert::From<T>
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::into(self) -> U
impl<T, U> core::convert::TryFrom<U> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where U: core::convert::Into<T>
pub type aya_ebpf::btf_maps::task_storage::TaskStorage<T>::Error = core::convert::Infallible
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
impl<T, U> core::convert::TryInto<U> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where U: core::convert::TryFrom<T>
pub type aya_ebpf::btf_maps::task_storage::TaskStorage<T>::Error = <U as core::convert::TryFrom<T>>::Error
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
impl<T> core::any::Any for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: 'static + ?core::marker::Sized
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::type_id(&self) -> core::any::TypeId
impl<T> core::borrow::Borrow<T> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: ?core::marker::Sized
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::borrow(&self) -> &T
impl<T> core::borrow::BorrowMut<T> for aya_ebpf::btf_maps::task_storage::TaskStorage<T> where T: ?core::marker::Sized
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya_ebpf::btf_maps::task_storage::TaskStorage<T>
pub fn aya_ebpf::btf_maps::task_storage::TaskStorage<T>::from(t: T) -> T
pub mod aya_ebpf::helpers
pub use aya_ebpf::helpers::generated
pub macro aya_ebpf::helpers::bpf_printk!
Expand Down