xref: /DragonOS/kernel/src/bpf/prog/mod.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 mod util;
2 mod verifier;
3 
4 use super::Result;
5 use crate::bpf::map::BpfMap;
6 use crate::bpf::prog::util::{BpfProgMeta, BpfProgVerifierInfo};
7 use crate::bpf::prog::verifier::BpfProgVerifier;
8 use crate::filesystem::vfs::file::{File, FileMode};
9 use crate::filesystem::vfs::syscall::ModeType;
10 use crate::filesystem::vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata};
11 use crate::include::bindings::linux_bpf::bpf_attr;
12 use crate::libs::spinlock::SpinLockGuard;
13 use crate::process::ProcessManager;
14 use alloc::string::String;
15 use alloc::sync::Arc;
16 use alloc::vec::Vec;
17 use core::any::Any;
18 use system_error::SystemError;
19 
20 #[derive(Debug)]
21 pub struct BpfProg {
22     meta: BpfProgMeta,
23     raw_file_ptr: Vec<usize>,
24 }
25 
26 impl BpfProg {
27     pub fn new(meta: BpfProgMeta) -> Self {
28         Self {
29             meta,
30             raw_file_ptr: Vec::new(),
31         }
32     }
33 
34     pub fn insns(&self) -> &[u8] {
35         &self.meta.insns
36     }
37 
38     pub fn insns_mut(&mut self) -> &mut [u8] {
39         &mut self.meta.insns
40     }
41 
42     pub fn insert_map(&mut self, map_ptr: usize) {
43         self.raw_file_ptr.push(map_ptr);
44     }
45 }
46 
47 impl IndexNode for BpfProg {
48     fn open(&self, _data: SpinLockGuard<FilePrivateData>, _mode: &FileMode) -> Result<()> {
49         Ok(())
50     }
51     fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<()> {
52         Ok(())
53     }
54     fn read_at(
55         &self,
56         _offset: usize,
57         _len: usize,
58         _buf: &mut [u8],
59         _data: SpinLockGuard<FilePrivateData>,
60     ) -> Result<usize> {
61         Err(SystemError::ENOSYS)
62     }
63 
64     fn write_at(
65         &self,
66         _offset: usize,
67         _len: usize,
68         _buf: &[u8],
69         _data: SpinLockGuard<FilePrivateData>,
70     ) -> Result<usize> {
71         Err(SystemError::ENOSYS)
72     }
73 
74     fn metadata(&self) -> Result<Metadata> {
75         let meta = Metadata {
76             mode: ModeType::from_bits_truncate(0o755),
77             file_type: FileType::File,
78             ..Default::default()
79         };
80         Ok(meta)
81     }
82 
83     fn resize(&self, _len: usize) -> Result<()> {
84         Ok(())
85     }
86 
87     fn fs(&self) -> Arc<dyn FileSystem> {
88         panic!("BpfProg does not have a filesystem")
89     }
90 
91     fn as_any_ref(&self) -> &dyn Any {
92         self
93     }
94 
95     fn list(&self) -> Result<Vec<String>> {
96         Err(SystemError::ENOSYS)
97     }
98 }
99 
100 impl Drop for BpfProg {
101     fn drop(&mut self) {
102         unsafe {
103             for ptr in self.raw_file_ptr.iter() {
104                 let file = Arc::from_raw(*ptr as *const u8 as *const BpfMap);
105                 drop(file)
106             }
107         }
108     }
109 }
110 /// Load a BPF program into the kernel.
111 ///
112 /// See https://ebpf-docs.dylanreimerink.nl/linux/syscall/BPF_PROG_LOAD/
113 pub fn bpf_prog_load(attr: &bpf_attr) -> Result<usize> {
114     let args = BpfProgMeta::try_from(attr)?;
115     // info!("bpf_prog_load: {:#?}", args);
116     let log_info = BpfProgVerifierInfo::from(attr);
117     let prog = BpfProg::new(args);
118     let fd_table = ProcessManager::current_pcb().fd_table();
119     let prog = BpfProgVerifier::new(prog, log_info.log_level, &mut []).verify(&fd_table)?;
120     let file = File::new(Arc::new(prog), FileMode::O_RDWR)?;
121     let fd = fd_table.write().alloc_fd(file, None).map(|x| x as usize)?;
122     Ok(fd)
123 }
124