@ -68,9 +68,11 @@ use libc::ENOSPC;
use std ::{
use std ::{
ffi ::CString ,
ffi ::CString ,
io ,
io ,
num ::NonZeroU32 ,
os ::fd ::{ AsFd , AsRawFd , IntoRawFd as _ , OwnedFd , RawFd } ,
os ::fd ::{ AsFd , AsRawFd , IntoRawFd as _ , OwnedFd , RawFd } ,
path ::{ Path , PathBuf } ,
path ::{ Path , PathBuf } ,
sync ::Arc ,
sync ::Arc ,
time ::{ Duration , SystemTime } ,
} ;
} ;
use thiserror ::Error ;
use thiserror ::Error ;
@ -108,6 +110,7 @@ use crate::{
maps ::MapError ,
maps ::MapError ,
obj ::{ self , btf ::BtfError , Function , VerifierLog } ,
obj ::{ self , btf ::BtfError , Function , VerifierLog } ,
pin ::PinError ,
pin ::PinError ,
programs ::utils ::{ boot_time , get_fdinfo } ,
sys ::{
sys ::{
bpf_btf_get_fd_by_id , bpf_get_object , bpf_link_get_fd_by_id , bpf_link_get_info_by_fd ,
bpf_btf_get_fd_by_id , bpf_get_object , bpf_link_get_fd_by_id , bpf_link_get_info_by_fd ,
bpf_load_program , bpf_pin_object , bpf_prog_get_fd_by_id , bpf_prog_get_info_by_fd ,
bpf_load_program , bpf_pin_object , bpf_prog_get_fd_by_id , bpf_prog_get_info_by_fd ,
@ -476,14 +479,15 @@ impl<T: Link> ProgramData<T> {
) -> Result < ProgramData < T > , ProgramError > {
) -> Result < ProgramData < T > , ProgramError > {
let path_string =
let path_string =
CString ::new ( path . as_ref ( ) . as_os_str ( ) . to_string_lossy ( ) . as_bytes ( ) ) . unwrap ( ) ;
CString ::new ( path . as_ref ( ) . as_os_str ( ) . to_string_lossy ( ) . as_bytes ( ) ) . unwrap ( ) ;
let fd = bpf_get_object ( & path_string ) . map_err ( | ( _ , io_error ) | SyscallError {
let fd = bpf_get_object ( & path_string ) . map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_obj_get" ,
call : "bpf_obj_get" ,
io_error ,
io_error ,
} ) ? ;
} ) ? ;
let info = bpf_prog_get_info_by _fd( fd . as_raw_fd ( ) , & mut [ ] ) ? ;
let info = ProgramInfo::new_from _fd( fd . as_raw_fd ( ) ) ? ;
let name = ProgramInfo( info) . name_as_str ( ) . map ( | s | s . to_string ( ) ) ;
let name = info. name_as_str ( ) . map ( | s | s . to_string ( ) ) ;
ProgramData ::from_bpf_prog_info ( name , fd , path . as_ref ( ) , info , verifier_log_level )
ProgramData ::from_bpf_prog_info ( name , fd , path . as_ref ( ) , info .0 , verifier_log_level )
}
}
}
}
@ -901,11 +905,65 @@ impl_try_from_program!(
CgroupDevice ,
CgroupDevice ,
) ;
) ;
/// Returns information about a loaded program with the [`ProgramInfo`] structure.
///
/// This information is populated at load time by the kernel and can be used
/// to correlate a given [`Program`] to it's corresponding [`ProgramInfo`]
/// metadata.
macro_rules! impl_program_info {
( $( $struct_name :ident ) , + $(, ) ? ) = > {
$(
impl $struct_name {
/// Returns the file descriptor of this Program.
pub fn program_info ( & self ) -> Result < ProgramInfo , ProgramError > {
let fd = self . fd ( ) . ok_or ( ProgramError ::NotLoaded ) ? ;
ProgramInfo ::new_from_fd ( fd . as_raw_fd ( ) )
}
}
) +
}
}
impl_program_info ! (
KProbe ,
UProbe ,
TracePoint ,
SocketFilter ,
Xdp ,
SkMsg ,
SkSkb ,
SchedClassifier ,
CgroupSkb ,
CgroupSysctl ,
CgroupSockopt ,
LircMode2 ,
PerfEvent ,
Lsm ,
RawTracePoint ,
BtfTracePoint ,
FEntry ,
FExit ,
Extension ,
CgroupSockAddr ,
SkLookup ,
SockOps ,
CgroupSock ,
CgroupDevice ,
) ;
/// Provides information about a loaded program, like name, id and statistics
/// Provides information about a loaded program, like name, id and statistics
#[ derive(Debug) ]
#[ derive(Debug) ]
pub struct ProgramInfo ( bpf_prog_info ) ;
pub struct ProgramInfo ( bpf_prog_info ) ;
impl ProgramInfo {
impl ProgramInfo {
fn new_from_fd ( fd : RawFd ) -> Result < Self , ProgramError > {
Ok ( ProgramInfo ( bpf_prog_get_info_by_fd (
fd . as_raw_fd ( ) ,
& mut [ ] ,
) ? ) )
}
/// The name of the program as was provided when it was load. This is limited to 16 bytes
/// The name of the program as was provided when it was load. This is limited to 16 bytes
pub fn name ( & self ) -> & [ u8 ] {
pub fn name ( & self ) -> & [ u8 ] {
let length = self
let length = self
@ -921,23 +979,88 @@ impl ProgramInfo {
unsafe { std ::slice ::from_raw_parts ( self . 0. name . as_ptr ( ) as * const _ , length ) }
unsafe { std ::slice ::from_raw_parts ( self . 0. name . as_ptr ( ) as * const _ , length ) }
}
}
/// The name of the program as a &str. If the name was not valid unicode, None is returned
/// The name of the program as a &str. If the name was not valid unicode, None is returned .
pub fn name_as_str ( & self ) -> Option < & str > {
pub fn name_as_str ( & self ) -> Option < & str > {
std ::str ::from_utf8 ( self . name ( ) ) . ok ( )
std ::str ::from_utf8 ( self . name ( ) ) . ok ( )
}
}
/// The program id for this program. Each program has a unique id.
/// The id for this program. Each program has a unique id.
pub fn id ( & self ) -> u32 {
pub fn id ( & self ) -> u32 {
self . 0. id
self . 0. id
}
}
/// Returns the fd associated with the program.
/// The program tag.
///
/// The program tag is a SHA sum of the program's instructions which be used as an alternative to
/// [`Self::id()`]". A program's id can vary every time it's loaded or unloaded, but the tag
/// will remain the same.
pub fn tag ( & self ) -> u64 {
u64 ::from_be_bytes ( self . 0. tag )
}
/// The program type as defined by the linux kernel enum
/// [`bpf_prog_type`](https://elixir.bootlin.com/linux/v6.4.4/source/include/uapi/linux/bpf.h#L948).
pub fn program_type ( & self ) -> u32 {
self . 0. type_
}
/// Returns true if the program is defined with a GPL-compatible license.
pub fn gpl_compatible ( & self ) -> bool {
self . 0. gpl_compatible ( ) ! = 0
}
/// The ids of the maps used by the program.
pub fn map_ids ( & self ) -> Result < Vec < u32 > , ProgramError > {
let fd = self . fd ( ) ? ;
let mut map_ids = vec! [ 0 u32 ; self . 0. nr_map_ids as usize ] ;
bpf_prog_get_info_by_fd ( fd . as_raw_fd ( ) , & mut map_ids ) ? ;
Ok ( map_ids )
}
/// The btf id for the program.
pub fn btf_id ( & self ) -> Option < NonZeroU32 > {
NonZeroU32 ::new ( self . 0. btf_id )
}
/// The size in bytes of the program's translated eBPF bytecode, which is the bytecode after it has been
/// passed though the verifier where it was possibly modified by the kernel.
pub fn size_translated ( & self ) -> u32 {
self . 0. xlated_prog_len
}
/// The size in bytes of the program's JIT-compiled machine code.
pub fn size_jitted ( & self ) -> u32 {
self . 0. jited_prog_len
}
/// How much memory in bytes has been allocated and locked for the program.
pub fn memory_locked ( & self ) -> Result < u32 , ProgramError > {
get_fdinfo ( self . fd ( ) ? . as_fd ( ) , "memlock" )
}
/// The number of verified instructions in the program.
///
/// This may be less than the total number of instructions in the compiled
/// program due to dead code elimination in the verifier.
pub fn verified_instruction_count ( & self ) -> u32 {
self . 0. verified_insns
}
/// The time the program was loaded.
pub fn loaded_at ( & self ) -> SystemTime {
boot_time ( ) + Duration ::from_nanos ( self . 0. load_time )
}
/// Returns a file descriptor referencing the program.
///
///
/// The returned fd must be closed when no longer needed.
/// The returned file descriptor can be closed at any time and doing so does not
pub fn fd ( & self ) -> Result < RawFd , ProgramError > {
/// influence the life cycle of the program.
pub fn fd ( & self ) -> Result < OwnedFd , ProgramError > {
let Self ( info ) = self ;
let Self ( info ) = self ;
let fd = bpf_prog_get_fd_by_id ( info . id ) ? ;
let fd = bpf_prog_get_fd_by_id ( info . id ) ? ;
Ok ( fd . into_raw_fd ( ) )
Ok ( fd )
}
}
/// Loads a program from a pinned path in bpffs.
/// Loads a program from a pinned path in bpffs.