Skip to main content

kbpf_basic/prog/
mod.rs

1//! Metadata and verifier info for BPF programs.
2use alloc::{
3    string::{String, ToString},
4    vec,
5    vec::Vec,
6};
7use core::{ffi::CStr, fmt::Debug};
8
9use crate::{
10    BpfError, BpfResult as Result, KernelAuxiliaryOps,
11    linux_bpf::{bpf_attach_type, bpf_attr, bpf_prog_type},
12};
13
14/// Metadata for a BPF program.
15pub struct BpfProgMeta {
16    /// Program flags.
17    pub prog_flags: u32,
18    /// Program type.
19    pub prog_type: bpf_prog_type,
20    /// Expected attach type.
21    pub expected_attach_type: bpf_attach_type,
22    /// eBPF instructions.
23    pub insns: Option<Vec<u8>>,
24    /// License string.
25    pub license: String,
26    /// Kernel version.
27    pub kern_version: u32,
28    /// Program name.
29    pub name: String,
30}
31
32impl Debug for BpfProgMeta {
33    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
34        let insn_len = if let Some(insns) = &self.insns {
35            insns.len() / 8
36        } else {
37            0
38        };
39        f.debug_struct("BpfProgMeta")
40            .field("prog_flags", &self.prog_flags)
41            .field("prog_type", &self.prog_type)
42            .field("expected_attach_type", &self.expected_attach_type)
43            .field("insns_len", &insn_len)
44            .field("license", &self.license)
45            .field("kern_version", &self.kern_version)
46            .field("name", &self.name)
47            .finish()
48    }
49}
50
51impl BpfProgMeta {
52    /// Take the instructions out of the metadata.
53    pub fn take_insns(&mut self) -> Option<Vec<u8>> {
54        self.insns.take()
55    }
56
57    /// Try to create a `BpfProgMeta` from a `bpf_attr` structure.
58    pub fn try_from_bpf_attr<F: KernelAuxiliaryOps>(attr: &bpf_attr) -> Result<Self> {
59        let u = unsafe { &attr.__bindgen_anon_3 };
60        let prog_type = bpf_prog_type::try_from(u.prog_type).map_err(|_| BpfError::EINVAL)?;
61        let expected_attach_type =
62            bpf_attach_type::try_from(u.expected_attach_type).map_err(|_| BpfError::EINVAL)?;
63        let name_slice = unsafe {
64            core::slice::from_raw_parts(u.prog_name.as_ptr() as *const u8, u.prog_name.len())
65        };
66        let prog_name = CStr::from_bytes_until_nul(name_slice)
67            .map_err(|_| BpfError::EINVAL)?
68            .to_str()
69            .map_err(|_| BpfError::EINVAL)?
70            .to_string();
71        let license = if u.license != 0 {
72            F::string_from_user_cstr(u.license as *const u8)?
73        } else {
74            String::new()
75        };
76
77        let insns_buf = if u.insns == 0 {
78            assert_eq!(u.insn_cnt, 0);
79            Vec::new()
80        } else {
81            let mut insns_buf = vec![0u8; u.insn_cnt as usize * 8];
82            F::copy_from_user(
83                u.insns as *const u8,
84                u.insn_cnt as usize * 8,
85                &mut insns_buf,
86            )?;
87            insns_buf
88        };
89        Ok(Self {
90            prog_flags: u.prog_flags,
91            prog_type,
92            expected_attach_type,
93            insns: Some(insns_buf),
94            license,
95            kern_version: u.kern_version,
96            name: prog_name,
97        })
98    }
99}
100
101bitflags::bitflags! {
102
103    /// The log level for BPF program verifier.
104    #[derive(Debug, Clone, Copy)]
105    pub struct VerifierLogLevel: u32 {
106        /// Sets no verifier logging.
107        const DISABLE = 0;
108        /// Enables debug verifier logging.
109        const DEBUG = 1;
110        /// Enables verbose verifier logging.
111        const VERBOSE = 2 | Self::DEBUG.bits();
112        /// Enables verifier stats.
113        const STATS = 4;
114    }
115}
116
117/// BPF program verifier information.
118#[derive(Debug)]
119pub struct BpfProgVerifierInfo {
120    /// This attribute specifies the level/detail of the log output. Valid values are.
121    pub log_level: VerifierLogLevel,
122    /// This attributes indicates the size of the memory region in bytes
123    /// indicated by `log_buf` which can safely be written to by the kernel.
124    pub _log_buf_size: u32,
125    /// This attributes can be set to a pointer to a memory region
126    /// allocated/reservedby the loader process where the verifier log will
127    /// be written to.
128    /// The detail of the log is set by log_level. The verifier log
129    /// is often the only indication in addition to the error code of
130    /// why the syscall command failed to load the program.
131    ///
132    /// The log is also written to on success. If the kernel runs out of
133    /// space in the buffer while loading, the loading process will fail
134    /// and the command will return with an error code of -ENOSPC. So it
135    /// is important to correctly size the buffer when enabling logging.
136    pub _log_buf_ptr: usize,
137}
138
139impl From<&bpf_attr> for BpfProgVerifierInfo {
140    fn from(attr: &bpf_attr) -> Self {
141        unsafe {
142            let u = &attr.__bindgen_anon_3;
143            Self {
144                log_level: VerifierLogLevel::from_bits_truncate(u.log_level),
145                _log_buf_size: u.log_size,
146                _log_buf_ptr: u.log_buf as usize,
147            }
148        }
149    }
150}