1*fae6e9adSlinfeng use crate::include::bindings::linux_bpf::{bpf_attach_type, bpf_attr, bpf_prog_type}; 2*fae6e9adSlinfeng use crate::syscall::user_access::{check_and_clone_cstr, UserBufferReader}; 3*fae6e9adSlinfeng use alloc::string::{String, ToString}; 4*fae6e9adSlinfeng use alloc::vec::Vec; 5*fae6e9adSlinfeng use core::ffi::CStr; 6*fae6e9adSlinfeng use core::fmt::Debug; 7*fae6e9adSlinfeng use num_traits::FromPrimitive; 8*fae6e9adSlinfeng use system_error::SystemError; 9*fae6e9adSlinfeng 10*fae6e9adSlinfeng bitflags::bitflags! { 11*fae6e9adSlinfeng 12*fae6e9adSlinfeng pub struct VerifierLogLevel: u32 { 13*fae6e9adSlinfeng /// Sets no verifier logging. 14*fae6e9adSlinfeng const DISABLE = 0; 15*fae6e9adSlinfeng /// Enables debug verifier logging. 16*fae6e9adSlinfeng const DEBUG = 1; 17*fae6e9adSlinfeng /// Enables verbose verifier logging. 18*fae6e9adSlinfeng const VERBOSE = 2 | Self::DEBUG.bits(); 19*fae6e9adSlinfeng /// Enables verifier stats. 20*fae6e9adSlinfeng const STATS = 4; 21*fae6e9adSlinfeng } 22*fae6e9adSlinfeng } 23*fae6e9adSlinfeng 24*fae6e9adSlinfeng #[derive(Debug)] 25*fae6e9adSlinfeng pub struct BpfProgVerifierInfo { 26*fae6e9adSlinfeng /// This attribute specifies the level/detail of the log output. Valid values are. 27*fae6e9adSlinfeng pub log_level: VerifierLogLevel, 28*fae6e9adSlinfeng /// This attributes indicates the size of the memory region in bytes 29*fae6e9adSlinfeng /// indicated by `log_buf` which can safely be written to by the kernel. 30*fae6e9adSlinfeng pub _log_buf_size: u32, 31*fae6e9adSlinfeng /// This attributes can be set to a pointer to a memory region 32*fae6e9adSlinfeng /// allocated/reservedby the loader process where the verifier log will 33*fae6e9adSlinfeng /// be written to. 34*fae6e9adSlinfeng /// The detail of the log is set by log_level. The verifier log 35*fae6e9adSlinfeng /// is often the only indication in addition to the error code of 36*fae6e9adSlinfeng /// why the syscall command failed to load the program. 37*fae6e9adSlinfeng /// 38*fae6e9adSlinfeng /// The log is also written to on success. If the kernel runs out of 39*fae6e9adSlinfeng /// space in the buffer while loading, the loading process will fail 40*fae6e9adSlinfeng /// and the command will return with an error code of -ENOSPC. So it 41*fae6e9adSlinfeng /// is important to correctly size the buffer when enabling logging. 42*fae6e9adSlinfeng pub _log_buf_ptr: usize, 43*fae6e9adSlinfeng } 44*fae6e9adSlinfeng 45*fae6e9adSlinfeng impl From<&bpf_attr> for BpfProgVerifierInfo { from(attr: &bpf_attr) -> Self46*fae6e9adSlinfeng fn from(attr: &bpf_attr) -> Self { 47*fae6e9adSlinfeng unsafe { 48*fae6e9adSlinfeng let u = &attr.__bindgen_anon_3; 49*fae6e9adSlinfeng Self { 50*fae6e9adSlinfeng log_level: VerifierLogLevel::from_bits_truncate(u.log_level), 51*fae6e9adSlinfeng _log_buf_size: u.log_size, 52*fae6e9adSlinfeng _log_buf_ptr: u.log_buf as usize, 53*fae6e9adSlinfeng } 54*fae6e9adSlinfeng } 55*fae6e9adSlinfeng } 56*fae6e9adSlinfeng } 57*fae6e9adSlinfeng 58*fae6e9adSlinfeng pub struct BpfProgMeta { 59*fae6e9adSlinfeng pub prog_flags: u32, 60*fae6e9adSlinfeng pub prog_type: bpf_prog_type, 61*fae6e9adSlinfeng pub expected_attach_type: bpf_attach_type, 62*fae6e9adSlinfeng pub insns: Vec<u8>, 63*fae6e9adSlinfeng pub license: String, 64*fae6e9adSlinfeng pub kern_version: u32, 65*fae6e9adSlinfeng pub name: String, 66*fae6e9adSlinfeng } 67*fae6e9adSlinfeng 68*fae6e9adSlinfeng impl Debug for BpfProgMeta { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result69*fae6e9adSlinfeng fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 70*fae6e9adSlinfeng f.debug_struct("BpfProgMeta") 71*fae6e9adSlinfeng .field("prog_flags", &self.prog_flags) 72*fae6e9adSlinfeng .field("prog_type", &self.prog_type) 73*fae6e9adSlinfeng .field("expected_attach_type", &self.expected_attach_type) 74*fae6e9adSlinfeng .field("insns_len", &(self.insns.len() / 8)) 75*fae6e9adSlinfeng .field("license", &self.license) 76*fae6e9adSlinfeng .field("kern_version", &self.kern_version) 77*fae6e9adSlinfeng .field("name", &self.name) 78*fae6e9adSlinfeng .finish() 79*fae6e9adSlinfeng } 80*fae6e9adSlinfeng } 81*fae6e9adSlinfeng 82*fae6e9adSlinfeng impl TryFrom<&bpf_attr> for BpfProgMeta { 83*fae6e9adSlinfeng type Error = SystemError; try_from(attr: &bpf_attr) -> Result<Self, Self::Error>84*fae6e9adSlinfeng fn try_from(attr: &bpf_attr) -> Result<Self, Self::Error> { 85*fae6e9adSlinfeng let u = unsafe { &attr.__bindgen_anon_3 }; 86*fae6e9adSlinfeng let prog_type = bpf_prog_type::from_u32(u.prog_type).ok_or(SystemError::EINVAL)?; 87*fae6e9adSlinfeng let expected_attach_type = 88*fae6e9adSlinfeng bpf_attach_type::from_u32(u.expected_attach_type).ok_or(SystemError::EINVAL)?; 89*fae6e9adSlinfeng unsafe { 90*fae6e9adSlinfeng let insns_buf = 91*fae6e9adSlinfeng UserBufferReader::new(u.insns as *mut u8, u.insn_cnt as usize * 8, true)?; 92*fae6e9adSlinfeng let insns = insns_buf.read_from_user::<u8>(0)?.to_vec(); 93*fae6e9adSlinfeng let name_slice = 94*fae6e9adSlinfeng core::slice::from_raw_parts(u.prog_name.as_ptr() as *const u8, u.prog_name.len()); 95*fae6e9adSlinfeng let prog_name = CStr::from_bytes_until_nul(name_slice) 96*fae6e9adSlinfeng .map_err(|_| SystemError::EINVAL)? 97*fae6e9adSlinfeng .to_str() 98*fae6e9adSlinfeng .map_err(|_| SystemError::EINVAL)? 99*fae6e9adSlinfeng .to_string(); 100*fae6e9adSlinfeng let license = check_and_clone_cstr(u.license as *const u8, None)?; 101*fae6e9adSlinfeng Ok(Self { 102*fae6e9adSlinfeng prog_flags: u.prog_flags, 103*fae6e9adSlinfeng prog_type, 104*fae6e9adSlinfeng expected_attach_type, 105*fae6e9adSlinfeng insns, 106*fae6e9adSlinfeng license: license.into_string().map_err(|_| SystemError::EINVAL)?, 107*fae6e9adSlinfeng kern_version: u.kern_version, 108*fae6e9adSlinfeng name: prog_name, 109*fae6e9adSlinfeng }) 110*fae6e9adSlinfeng } 111*fae6e9adSlinfeng } 112*fae6e9adSlinfeng } 113