diff --git a/ebpf/aya-ebpf/src/helpers.rs b/ebpf/aya-ebpf/src/helpers.rs index be009e90..c0fea236 100644 --- a/ebpf/aya-ebpf/src/helpers.rs +++ b/ebpf/aya-ebpf/src/helpers.rs @@ -15,7 +15,7 @@ use core::{ mem::{self, MaybeUninit}, }; -pub use aya_ebpf_bindings::helpers as generated; +pub use aya_ebpf_bindings::{bindings::path, helpers as generated}; #[doc(hidden)] pub use generated::*; @@ -842,3 +842,14 @@ pub fn bpf_strncmp(s1: &[u8; N], s2: &CStr) -> Ordering { unsafe { generated::bpf_strncmp(s1.as_ptr() as *const _, N as u32, s2.as_ptr() as *const _) } .cmp(&0) } + +#[inline] +pub unsafe fn bpf_d_path(path: *const path, dest: &mut [u8]) -> Result<&[u8], c_long> { + let len = generated::bpf_d_path( + path as *mut path, + dest.as_mut_ptr() as *mut _, + dest.len() as u32, + ); + + read_str_bytes(len, dest) +} diff --git a/test/integration-common/src/lib.rs b/test/integration-common/src/lib.rs index b9f5917b..479827ff 100644 --- a/test/integration-common/src/lib.rs +++ b/test/integration-common/src/lib.rs @@ -83,3 +83,18 @@ pub mod linear_data_structures { pub const PEEK_INDEX: u32 = 0; pub const POP_INDEX: u32 = 1; } + + +pub mod bpf_d_path { + pub const PATH_BUF_LEN: usize = 128; + + #[derive(Copy, Clone)] + #[repr(C)] + pub struct TestResult { + pub buf: [u8; PATH_BUF_LEN], + pub len: usize, + } + + #[cfg(feature = "user")] + unsafe impl aya::Pod for TestResult {} +} diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index 78c8b89e..f2da66bc 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -32,6 +32,10 @@ path = "src/bpf_probe_read.rs" name = "linear_data_structures" path = "src/linear_data_structures.rs" +[[bin]] +name = "bpf_d_path" +path = "src/bpf_d_path.rs" + [[bin]] name = "log" path = "src/log.rs" diff --git a/test/integration-ebpf/src/bpf_d_path.rs b/test/integration-ebpf/src/bpf_d_path.rs new file mode 100644 index 00000000..9a04bf9a --- /dev/null +++ b/test/integration-ebpf/src/bpf_d_path.rs @@ -0,0 +1,51 @@ +#![no_std] +#![no_main] + +use aya_ebpf::{ + bindings::path, + cty::c_long, + helpers::bpf_d_path, + macros::{fentry, map}, + maps::Array, + memcpy, + programs::FEntryContext, +}; +use integration_common::bpf_d_path::{PATH_BUF_LEN, TestResult}; +#[cfg(not(test))] +extern crate ebpf_panic; + +#[map] +static RESULT: Array = Array::with_max_entries(1, 0); + +#[fentry] +pub fn test_vfs_open(ctx: FEntryContext) -> u32 { + match try_vfs_open(ctx) { + Ok(_) => 0, + Err(_) => 1, + } +} + +fn try_vfs_open(ctx: FEntryContext) -> Result<(), c_long> { + let dest = &mut [0u8; PATH_BUF_LEN]; + let pathptr: *const path = unsafe { ctx.arg(0) }; + let data = unsafe { bpf_d_path(pathptr, dest)? }; + + let mut result = TestResult { + buf: [0u8; PATH_BUF_LEN], + len: 0, + }; + + unsafe { + memcpy( + result.buf.as_mut_ptr(), + data.as_ptr() as *mut u8, + data.len(), + ) + }; + + result.len = dest.len(); + + RESULT.set(0, &result, 0)?; + + Ok(()) +} diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 9dbb4d18..d692a962 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -38,6 +38,7 @@ bpf_file!( TEXT_64_64_RELOC => "text_64_64_reloc.o", VARIABLES_RELOC => "variables_reloc.bpf.o", + BPF_D_PATH => "bpf_d_path", BPF_PROBE_READ => "bpf_probe_read", LINEAR_DATA_STRUCTURES => "linear_data_structures", LOG => "log", diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index deaa63a5..b9533c16 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -1,3 +1,4 @@ +mod bpf_d_path; mod bpf_probe_read; mod btf_relocations; mod elf; diff --git a/test/integration-test/src/tests/bpf_d_path.rs b/test/integration-test/src/tests/bpf_d_path.rs new file mode 100644 index 00000000..3ac9f348 --- /dev/null +++ b/test/integration-test/src/tests/bpf_d_path.rs @@ -0,0 +1,42 @@ +use std::fs::File; + +use aya::{Btf, Ebpf, maps::Array, programs::FEntry}; +use integration_common::bpf_d_path::TestResult; + +#[test_log::test] +fn bpf_d_path_basic() { + let btf = Btf::from_sys_fs().unwrap(); + let mut bpf = Ebpf::load(crate::BPF_D_PATH).unwrap(); + let prog: &mut FEntry = bpf + .program_mut("test_vfs_open") + .unwrap() + .try_into() + .unwrap(); + prog.load("vfs_open", &btf).unwrap(); + prog.attach().unwrap(); + + let file = File::open("/dev/null").unwrap(); + + let result = get_result(&bpf); + + let path_len = result.len; + assert!(path_len > 0, "Path length should be greater than 0"); + assert!( + path_len <= result.buf.len(), + "Path length should not exceed buffer size" + ); + + let path_str = std::str::from_utf8(&result.buf[..path_len]).unwrap(); + assert!( + path_str.contains("/dev/null"), + "Path should contain '/dev/null', got: {}", + path_str + ); + + drop(file); +} + +fn get_result(bpf: &Ebpf) -> TestResult { + let m = Array::<_, TestResult>::try_from(bpf.map("RESULT").unwrap()).unwrap(); + m.get(&0, 0).unwrap() +} diff --git a/xtask/public-api/aya-ebpf.txt b/xtask/public-api/aya-ebpf.txt index c6299332..1debd09c 100644 --- a/xtask/public-api/aya-ebpf.txt +++ b/xtask/public-api/aya-ebpf.txt @@ -4,6 +4,7 @@ pub use aya_ebpf::cty pub use aya_ebpf::macros pub mod aya_ebpf::helpers pub use aya_ebpf::helpers::generated +pub use aya_ebpf::helpers::path pub macro aya_ebpf::helpers::bpf_printk! #[repr(transparent)] pub struct aya_ebpf::helpers::PrintkArg(_) impl aya_ebpf::helpers::PrintkArg @@ -61,6 +62,7 @@ impl core::clone::CloneToUninit for aya_ebpf::helpers::PrintkArg where T: cor pub unsafe fn aya_ebpf::helpers::PrintkArg::clone_to_uninit(&self, dest: *mut u8) impl core::convert::From for aya_ebpf::helpers::PrintkArg pub fn aya_ebpf::helpers::PrintkArg::from(t: T) -> T +pub unsafe fn aya_ebpf::helpers::bpf_d_path(path: *const aya_ebpf_bindings::x86_64::bindings::path, dest: &mut [u8]) -> core::result::Result<&[u8], aya_ebpf_cty::od::c_long> pub fn aya_ebpf::helpers::bpf_get_current_comm() -> core::result::Result<[u8; 16], aya_ebpf_cty::od::c_long> pub fn aya_ebpf::helpers::bpf_get_current_pid_tgid() -> u64 pub fn aya_ebpf::helpers::bpf_get_current_uid_gid() -> u64