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