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 {
new(meta: BpfProgMeta) -> Self27 pub fn new(meta: BpfProgMeta) -> Self {
28 Self {
29 meta,
30 raw_file_ptr: Vec::new(),
31 }
32 }
33
insns(&self) -> &[u8]34 pub fn insns(&self) -> &[u8] {
35 &self.meta.insns
36 }
37
insns_mut(&mut self) -> &mut [u8]38 pub fn insns_mut(&mut self) -> &mut [u8] {
39 &mut self.meta.insns
40 }
41
insert_map(&mut self, map_ptr: usize)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 {
open(&self, _data: SpinLockGuard<FilePrivateData>, _mode: &FileMode) -> Result<()>48 fn open(&self, _data: SpinLockGuard<FilePrivateData>, _mode: &FileMode) -> Result<()> {
49 Ok(())
50 }
close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<()>51 fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<()> {
52 Ok(())
53 }
read_at( &self, _offset: usize, _len: usize, _buf: &mut [u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize>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
write_at( &self, _offset: usize, _len: usize, _buf: &[u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize>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
metadata(&self) -> Result<Metadata>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
resize(&self, _len: usize) -> Result<()>83 fn resize(&self, _len: usize) -> Result<()> {
84 Ok(())
85 }
86
fs(&self) -> Arc<dyn FileSystem>87 fn fs(&self) -> Arc<dyn FileSystem> {
88 panic!("BpfProg does not have a filesystem")
89 }
90
as_any_ref(&self) -> &dyn Any91 fn as_any_ref(&self) -> &dyn Any {
92 self
93 }
94
list(&self) -> Result<Vec<String>>95 fn list(&self) -> Result<Vec<String>> {
96 Err(SystemError::ENOSYS)
97 }
98 }
99
100 impl Drop for BpfProg {
drop(&mut self)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/
bpf_prog_load(attr: &bpf_attr) -> Result<usize>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