bpf_api/platform/linux/
prog.rs

1use crate::error::Error;
2use crate::platform::linux::bpf::{AttachType, CallBpf, Command};
3use crate::platform::linux::syscalls::close;
4
5use std::io::Write;
6
7#[derive(Default)]
8#[repr(C, align(8))]
9#[derive(Copy, Clone)]
10struct BpfProgramAttr {
11    pub prog_type: u32,
12    pub insn_cnt: u32,
13    pub insns: u64,
14    pub license: u64,
15    pub log_level: u32,
16    pub log_size: u32,
17    pub log_buf: u64,
18    pub kern_version: u32,
19    pub prog_flags: u32,
20    pub prog_name: [u8; 16],
21    pub prog_ifindex: u32,
22    pub expected_attach_type: u32,
23    pub prog_btf_fd: u32,
24    pub func_info_rec_size: u32,
25    pub func_info: u64,
26    pub func_info_count: u32,
27    pub line_info_rec_size: u32,
28    pub line_info: u64,
29    pub line_info_count: u32,
30    pub attach_btf_id: u32,
31}
32
33impl CallBpf for BpfProgramAttr {}
34
35#[derive(Copy, Clone)]
36pub enum ProgramType {
37    Unspec = 0,
38    SocketFilter,
39    KProbe,
40    SchedCls,
41    SchedAct,
42    Tracepoint,
43    Xdp,
44    PerfEvent,
45    CgroupSkb,
46    CgroupSock,
47    LwtIn,
48    LwtOut,
49    LwtXmit,
50    SockOps,
51    SkSkb,
52    CgroupDevice,
53    SkMsg,
54    RawTracepoint,
55    CgroupSockAddr,
56    LwtSeg6local,
57    LircMode2,
58    SkReuseport,
59    FlowDissector,
60    CgroupSysctl,
61    RawTracepointWritable,
62    CgroupSockopt,
63    Tracing,
64    StructOps,
65    Ext,
66    Lsm,
67    SkLookup,
68    Syscall,
69}
70
71#[derive(Clone)]
72pub struct ProgramAttr {
73    /// An optional name for the program.
74    pub prog_name: Option<String>,
75
76    /// The type of program. Only certain program types can be attached to certain names/btf ids,
77    /// so this field and the `attach_*` fields need to be coordinated properly.
78    pub prog_type: ProgramType,
79
80    /// The type of attachment.
81    pub expected_attach_type: Option<AttachType>,
82
83    /// If the probe is being attached to a function using the BTF id, specify it here.
84    pub attach_btf_id: Option<u32>,
85}
86
87pub struct Program {
88    attr: ProgramAttr,
89    fd: u32,
90}
91
92impl Program {
93    const LICENSE: &'static str = "GPL\0";
94
95    /// Creates a program with the given attributes and instructions. Optionally,
96    /// an object implementing the Write trait can be passed in that receives the
97    /// kernel eBPF logging output.
98    ///
99    /// # Arguments
100    ///
101    /// * `attr` - The program attributes.
102    /// * `instructions` - The raw eBPF instructions describing the program.
103    /// * `log_out` - The logger object.
104    pub fn create(
105        attr: &ProgramAttr,
106        instructions: &[u64],
107        log_out: Option<&mut dyn Write>,
108    ) -> Result<Self, Error> {
109        let mut buf = vec![0; 1 << 20];
110
111        let expected_attach_type = if let Some(t) = attr.expected_attach_type {
112            t as u32
113        } else {
114            0
115        };
116
117        let attach_btf_id = if let Some(id) = attr.attach_btf_id {
118            id
119        } else {
120            0
121        };
122
123        let mut prog_name: [u8; 16] = [0; 16];
124        if let Some(name) = &attr.prog_name {
125            for (i, c) in name.chars().enumerate() {
126                if i == 16 {
127                    break;
128                }
129                prog_name[i] = c as u8;
130            }
131        }
132
133        let bpf_attr = BpfProgramAttr {
134            prog_type: attr.prog_type as u32,
135            insns: instructions.as_ptr() as u64,
136            insn_cnt: instructions.len() as u32,
137            license: Self::LICENSE.as_ptr() as u64,
138            log_level: 1,
139            log_size: 1 << 20,
140            log_buf: buf.as_mut_ptr() as u64,
141            kern_version: 0,
142            prog_flags: 0,
143            prog_name,
144            prog_ifindex: 0,
145            expected_attach_type,
146            prog_btf_fd: 0,
147            func_info_rec_size: 0,
148            func_info: 0,
149            func_info_count: 0,
150            line_info_rec_size: 0,
151            line_info: 0,
152            line_info_count: 0,
153            attach_btf_id,
154        };
155
156        let r = bpf_attr.call_bpf(Command::ProgLoad);
157
158        if let (Ok(s), Some(log_out)) = (std::str::from_utf8(&buf), log_out) {
159            let _ = write!(log_out, "{}", s);
160        }
161
162        match r {
163            Err(e) => Err(e),
164            Ok(r) => Ok(Self {
165                fd: r,
166                attr: attr.clone(),
167            }),
168        }
169    }
170
171    /// Retrieves the attributes for the program.
172    pub fn get_attr(&self) -> &ProgramAttr {
173        &self.attr
174    }
175
176    /// Retrieves the underlying fd for the program.
177    pub fn get_fd(&self) -> u32 {
178        self.fd
179    }
180}
181
182impl Drop for Program {
183    fn drop(&mut self) {
184        close(self.fd);
185    }
186}