xref: /DragonOS/kernel/src/bpf/prog/util.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
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