1use alloc::{
3 string::{String, ToString},
4 vec,
5 vec::Vec,
6};
7use core::{ffi::CStr, fmt::Debug};
8
9use crate::{
10 BpfError, KernelAuxiliaryOps, Result,
11 linux_bpf::{bpf_attach_type, bpf_attr, bpf_prog_type},
12};
13
14pub struct BpfProgMeta {
16 pub prog_flags: u32,
18 pub prog_type: bpf_prog_type,
20 pub expected_attach_type: bpf_attach_type,
22 pub insns: Option<Vec<u8>>,
24 pub license: String,
26 pub kern_version: u32,
28 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 pub fn take_insns(&mut self) -> Option<Vec<u8>> {
54 self.insns.take()
55 }
56
57 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 #[derive(Debug, Clone, Copy)]
105 pub struct VerifierLogLevel: u32 {
106 const DISABLE = 0;
108 const DEBUG = 1;
110 const VERBOSE = 2 | Self::DEBUG.bits();
112 const STATS = 4;
114 }
115}
116
117#[derive(Debug)]
119pub struct BpfProgVerifierInfo {
120 pub log_level: VerifierLogLevel,
122 pub _log_buf_size: u32,
125 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}