Skip to content

Commit

Permalink
program: add get_fd_by_pin() api
Browse files Browse the repository at this point in the history
After a eBPF program is loaded to the kernel and the loader process exited,
a user still may want to attach this program to PROG_ARRAY of another one.
Add an API to recover the file descriptor from a pinned path.

Signed-off-by: Ivan Koveshnikov <[email protected]>
  • Loading branch information
vankoven committed Aug 22, 2024
1 parent 658277e commit 07f331c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
24 changes: 24 additions & 0 deletions libbpf-rs/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,30 @@ impl<'obj> Program<'obj> {
Ok(prog_info.id)
}

/// Returns program fd by pin
pub fn get_fd_by_pin<P: AsRef<Path>>(path: P) -> Result<OwnedFd> {
let path_c = util::path_to_cstring(path)?;
let path_ptr = path_c.as_ptr();
let fd = util::parse_ret_i32(unsafe { libbpf_sys::bpf_obj_get(path_ptr) })?;

let fd = unsafe { OwnedFd::from_raw_fd(fd) };

// A pinned path may represent any kind of an object, verify that
// it represents a program before returning descriptor to the caller.
let mut info: libbpf_sys::bpf_prog_info = unsafe { mem::zeroed() };
let mut size = mem::size_of_val(&info) as u32;
// SAFETY: All pointers are derived from references and hence valid.
util::parse_ret(unsafe {
libbpf_sys::bpf_prog_get_info_by_fd(
fd.as_raw_fd(),
&mut info as *mut libbpf_sys::bpf_prog_info,
&mut size as *mut u32,
)
})?;

Ok(fd)
}

/// Returns flags that have been set for the program.
pub fn flags(&self) -> u32 {
unsafe { libbpf_sys::bpf_program__flags(self.ptr.as_ptr()) }
Expand Down
22 changes: 22 additions & 0 deletions libbpf-rs/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,28 @@ fn test_object_loading_pinned_map_from_path() {
);
}

#[tag(root)]
#[test]
fn test_object_loading_from_pin() {
bump_rlimit_mlock();

let path = "/sys/fs/bpf/myprog_test_pin_to_load_from_path";
let prog_name = "handle__sched_switch";

let mut obj = get_test_object("runqslower.bpf.o");
let mut prog = get_prog_mut(&mut obj, prog_name);
prog.pin(path).expect("pinning prog failed");
let prog_id = Program::get_id_by_fd(prog.as_fd()).expect("failed to determine prog id");

let pinned_prog_fd = Program::get_fd_by_pin(path).expect("failed to get fd of pinned prog");
let pinned_prog_id =
Program::get_id_by_fd(pinned_prog_fd.as_fd()).expect("failed to determine pinned prog id");

assert_eq!(prog_id, pinned_prog_id);

prog.unpin(path).expect("unpinning program failed");
}

#[tag(root)]
#[test]
fn test_object_loading_loaded_map_from_id() {
Expand Down

0 comments on commit 07f331c

Please sign in to comment.