From ce4d19e78385083366746ba69a38462a140bbc72 Mon Sep 17 00:00:00 2001 From: Godones Date: Wed, 4 Dec 2024 20:23:43 +0800 Subject: [PATCH] feat(ebpf): support Aya framework. 1. fix the rbpf bug 2. use new Aya template 3. add kprobe related device files and attributes to sysfs --- kernel/crates/rbpf/src/interpreter.rs | 6 +- kernel/crates/rbpf/src/stack.rs | 12 +- kernel/src/arch/x86_64/mm/fault.rs | 3 +- kernel/src/bpf/helper/consts.rs | 1 + kernel/src/bpf/helper/mod.rs | 6 + kernel/src/bpf/mod.rs | 2 +- kernel/src/driver/base/device/mod.rs | 1 + .../driver/base/event_source/kprobe/device.rs | 189 ++++++++++++++++++ .../driver/base/event_source/kprobe/mod.rs | 28 +++ kernel/src/driver/base/event_source/mod.rs | 25 +++ kernel/src/driver/base/event_source/subsys.rs | 52 +++++ kernel/src/driver/base/init.rs | 3 +- kernel/src/driver/base/mod.rs | 1 + kernel/src/filesystem/procfs/mod.rs | 31 ++- kernel/src/perf/bpf.rs | 100 ++++----- kernel/src/perf/kprobe.rs | 14 +- kernel/src/syscall/mod.rs | 1 + .../{test_ebpf => }/syscall_ebpf/.gitignore | 1 + user/apps/syscall_ebpf/Cargo.toml | 40 ++++ .../apps/{test_ebpf => syscall_ebpf}/Makefile | 16 +- user/apps/syscall_ebpf/README.md | 33 +++ user/apps/syscall_ebpf/rustfmt.toml | 4 + .../syscall_ebpf-common/Cargo.toml | 2 +- .../syscall_ebpf-common/src/lib.rs | 0 .../syscall_ebpf-ebpf/.cargo/config.toml | 12 ++ .../syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml | 17 ++ .../syscall_ebpf/syscall_ebpf-ebpf/build.rs | 17 ++ .../syscall_ebpf-ebpf/rust-toolchain.toml | 3 + .../syscall_ebpf/syscall_ebpf-ebpf/src/lib.rs | 3 + .../syscall_ebpf-ebpf/src/main.rs | 50 +++++ .../apps/syscall_ebpf/syscall_ebpf/Cargo.toml | 35 ++++ user/apps/syscall_ebpf/syscall_ebpf/build.rs | 150 ++++++++++++++ .../syscall_ebpf/syscall_ebpf/src/main.rs | 74 +++++++ user/apps/test_ebpf/.gitignore | 3 - user/apps/test_ebpf/Cargo.toml | 16 -- user/apps/test_ebpf/src/main.rs | 60 ------ .../test_ebpf/syscall_ebpf/.cargo/config.toml | 2 - .../syscall_ebpf/.vscode/settings.json | 3 - user/apps/test_ebpf/syscall_ebpf/Cargo.toml | 3 - user/apps/test_ebpf/syscall_ebpf/README.md | 32 --- .../syscall_ebpf-ebpf/.cargo/config.toml | 6 - .../syscall_ebpf-ebpf/.helix/config.toml | 2 - .../syscall_ebpf-ebpf/.vim/coc-settings.json | 4 - .../syscall_ebpf-ebpf/.vscode/settings.json | 4 - .../syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml | 33 --- .../syscall_ebpf-ebpf/rust-toolchain.toml | 13 -- .../syscall_ebpf-ebpf/src/main.rs | 44 ---- .../test_ebpf/syscall_ebpf/xtask/Cargo.toml | 8 - .../test_ebpf/syscall_ebpf/xtask/src/build.rs | 42 ---- .../syscall_ebpf/xtask/src/build_ebpf.rs | 67 ------- .../test_ebpf/syscall_ebpf/xtask/src/main.rs | 36 ---- .../test_ebpf/syscall_ebpf/xtask/src/run.rs | 55 ----- ...bpf_0_1_0.toml => syscall_ebpf_0_1_0.toml} | 4 +- 53 files changed, 858 insertions(+), 511 deletions(-) create mode 100644 kernel/src/driver/base/event_source/kprobe/device.rs create mode 100644 kernel/src/driver/base/event_source/kprobe/mod.rs create mode 100644 kernel/src/driver/base/event_source/mod.rs create mode 100644 kernel/src/driver/base/event_source/subsys.rs rename user/apps/{test_ebpf => }/syscall_ebpf/.gitignore (95%) create mode 100644 user/apps/syscall_ebpf/Cargo.toml rename user/apps/{test_ebpf => syscall_ebpf}/Makefile (84%) create mode 100644 user/apps/syscall_ebpf/README.md create mode 100644 user/apps/syscall_ebpf/rustfmt.toml rename user/apps/{test_ebpf => }/syscall_ebpf/syscall_ebpf-common/Cargo.toml (56%) rename user/apps/{test_ebpf => }/syscall_ebpf/syscall_ebpf-common/src/lib.rs (100%) create mode 100644 user/apps/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml create mode 100644 user/apps/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml create mode 100644 user/apps/syscall_ebpf/syscall_ebpf-ebpf/build.rs create mode 100644 user/apps/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml create mode 100644 user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/lib.rs create mode 100644 user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs create mode 100644 user/apps/syscall_ebpf/syscall_ebpf/Cargo.toml create mode 100644 user/apps/syscall_ebpf/syscall_ebpf/build.rs create mode 100644 user/apps/syscall_ebpf/syscall_ebpf/src/main.rs delete mode 100644 user/apps/test_ebpf/.gitignore delete mode 100644 user/apps/test_ebpf/Cargo.toml delete mode 100644 user/apps/test_ebpf/src/main.rs delete mode 100644 user/apps/test_ebpf/syscall_ebpf/.cargo/config.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/.vscode/settings.json delete mode 100644 user/apps/test_ebpf/syscall_ebpf/Cargo.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/README.md delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.helix/config.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vim/coc-settings.json delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vscode/settings.json delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs delete mode 100644 user/apps/test_ebpf/syscall_ebpf/xtask/Cargo.toml delete mode 100644 user/apps/test_ebpf/syscall_ebpf/xtask/src/build.rs delete mode 100644 user/apps/test_ebpf/syscall_ebpf/xtask/src/build_ebpf.rs delete mode 100644 user/apps/test_ebpf/syscall_ebpf/xtask/src/main.rs delete mode 100644 user/apps/test_ebpf/syscall_ebpf/xtask/src/run.rs rename user/dadk/config/{test_ebpf_0_1_0.toml => syscall_ebpf_0_1_0.toml} (91%) diff --git a/kernel/crates/rbpf/src/interpreter.rs b/kernel/crates/rbpf/src/interpreter.rs index cb4bddf3c..68b9878e8 100644 --- a/kernel/crates/rbpf/src/interpreter.rs +++ b/kernel/crates/rbpf/src/interpreter.rs @@ -660,9 +660,9 @@ pub fn execute_program( // Save the callee saved registers pre_stack.save_registers(®[6..=9]); // Save the return address - pre_stack.save_return_address(insn_ptr as u16); + pre_stack.save_return_address(insn_ptr as u64); // save the stack pointer - pre_stack.save_sp(reg[10] as u16); + pre_stack.save_sp(reg[10]); let mut stack = StackFrame::new(); log::trace!("BPF TO BPF CALL: new pc: {} + {} = {}",insn_ptr ,insn.imm,insn_ptr + insn.imm as usize); reg[10] = stack.as_ptr() as u64 + stack.len() as u64; @@ -695,7 +695,7 @@ pub fn execute_program( // Restore the return address insn_ptr = stack.get_return_address() as usize; // Restore the stack pointer - reg[10] = stack.get_sp() as u64; + reg[10] = stack.get_sp(); log::trace!("EXIT: new pc: {}", insn_ptr); } } diff --git a/kernel/crates/rbpf/src/stack.rs b/kernel/crates/rbpf/src/stack.rs index be1732638..c15968566 100644 --- a/kernel/crates/rbpf/src/stack.rs +++ b/kernel/crates/rbpf/src/stack.rs @@ -1,9 +1,9 @@ use crate::{ebpf::STACK_SIZE, vec, Vec}; pub struct StackFrame { - return_address: u16, + return_address: u64, saved_registers: [u64; 4], - sp: u16, + sp: u64, frame: Vec, } @@ -54,22 +54,22 @@ impl StackFrame { } /// Save the return address - pub fn save_return_address(&mut self, address: u16) { + pub fn save_return_address(&mut self, address: u64) { self.return_address = address; } /// Get the return address - pub fn get_return_address(&self) -> u16 { + pub fn get_return_address(&self) -> u64 { self.return_address } /// Save the stack pointer - pub fn save_sp(&mut self, sp: u16) { + pub fn save_sp(&mut self, sp: u64) { self.sp = sp; } /// Get the stack pointer - pub fn get_sp(&self) -> u16 { + pub fn get_sp(&self) -> u64 { self.sp } } diff --git a/kernel/src/arch/x86_64/mm/fault.rs b/kernel/src/arch/x86_64/mm/fault.rs index e38df1f2e..e55216242 100644 --- a/kernel/src/arch/x86_64/mm/fault.rs +++ b/kernel/src/arch/x86_64/mm/fault.rs @@ -267,9 +267,10 @@ impl X86_64MMArch { }); } else { log::error!( - "No mapped vma, error_code: {:#b}, address: {:#x}", + "No mapped vma, error_code: {:#b}, address: {:#x}, flags: {:?}", error_code, address.data(), + flags ); let pid = ProcessManager::current_pid(); let mut info = diff --git a/kernel/src/bpf/helper/consts.rs b/kernel/src/bpf/helper/consts.rs index 69bce7d61..0c3685454 100644 --- a/kernel/src/bpf/helper/consts.rs +++ b/kernel/src/bpf/helper/consts.rs @@ -1,6 +1,7 @@ pub const HELPER_MAP_LOOKUP_ELEM: u32 = 1; pub const HELPER_MAP_UPDATE_ELEM: u32 = 2; pub const HELPER_MAP_DELETE_ELEM: u32 = 3; +pub const HELPER_KTIME_GET_NS: u32 = 5; pub const HELPER_MAP_FOR_EACH_ELEM: u32 = 164; pub const HELPER_MAP_LOOKUP_PERCPU_ELEM: u32 = 195; pub const HELPER_PERF_EVENT_OUTPUT: u32 = 25; diff --git a/kernel/src/bpf/helper/mod.rs b/kernel/src/bpf/helper/mod.rs index 2f951793f..2c876b25f 100644 --- a/kernel/src/bpf/helper/mod.rs +++ b/kernel/src/bpf/helper/mod.rs @@ -6,6 +6,7 @@ use crate::bpf::map::{BpfCallBackFn, BpfMap}; use crate::include::bindings::linux_bpf::BPF_F_CURRENT_CPU; use crate::libs::lazy_init::Lazy; use crate::smp::core::smp_get_processor_id; +use crate::time::Instant; use alloc::{collections::BTreeMap, sync::Arc}; use core::ffi::c_void; use system_error::SystemError; @@ -300,6 +301,10 @@ pub fn map_peek_elem(map: &Arc, value: &mut [u8]) -> Result<()> { value } +pub fn bpf_ktime_get_ns() -> u64 { + (Instant::now().total_micros() * 1000) as u64 +} + pub static BPF_HELPER_FUN_SET: Lazy> = Lazy::new(); /// Initialize the helper functions. @@ -311,6 +316,7 @@ pub fn init_helper_functions() { map.insert(HELPER_MAP_LOOKUP_ELEM, define_func!(raw_map_lookup_elem)); map.insert(HELPER_MAP_UPDATE_ELEM, define_func!(raw_map_update_elem)); map.insert(HELPER_MAP_DELETE_ELEM, define_func!(raw_map_delete_elem)); + map.insert(HELPER_KTIME_GET_NS, define_func!(bpf_ktime_get_ns)); map.insert( HELPER_MAP_FOR_EACH_ELEM, define_func!(raw_map_for_each_elem), diff --git a/kernel/src/bpf/mod.rs b/kernel/src/bpf/mod.rs index 8e84f2055..592ad7313 100644 --- a/kernel/src/bpf/mod.rs +++ b/kernel/src/bpf/mod.rs @@ -33,7 +33,7 @@ pub fn bpf(cmd: bpf_cmd, attr: &bpf_attr) -> Result { // Program related commands bpf_cmd::BPF_PROG_LOAD => prog::bpf_prog_load(attr), // Object creation commands - bpf_cmd::BPF_BTF_LOAD => { + bpf_cmd::BPF_BTF_LOAD | bpf_cmd::BPF_LINK_CREATE | bpf_cmd::BPF_OBJ_GET_INFO_BY_FD => { error!("bpf cmd {:?} not implemented", cmd); return Err(SystemError::ENOSYS); } diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index b1b76a396..bf42935ea 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -310,6 +310,7 @@ pub enum DeviceType { PlatformDev, Char, Pci, + Other, } /// @brief: 设备标识符类型 diff --git a/kernel/src/driver/base/event_source/kprobe/device.rs b/kernel/src/driver/base/event_source/kprobe/device.rs new file mode 100644 index 000000000..cb43c5f04 --- /dev/null +++ b/kernel/src/driver/base/event_source/kprobe/device.rs @@ -0,0 +1,189 @@ +use crate::driver::base::class::Class; +use crate::driver::base::device::bus::Bus; +use crate::driver::base::device::driver::Driver; +use crate::driver::base::device::{Device, DeviceCommonData, DeviceType, IdTable}; +use crate::driver::base::kobject::{ + KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState, +}; +use crate::driver::base::kset::KSet; +use crate::filesystem::kernfs::KernFSInode; +use crate::filesystem::sysfs::{Attribute, SysFSOpsSupport}; +use crate::filesystem::vfs::syscall::ModeType; +use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard}; +use crate::libs::spinlock::{SpinLock, SpinLockGuard}; +use alloc::string::{String, ToString}; +use alloc::sync::{Arc, Weak}; +use core::fmt::Debug; +use system_error::SystemError; + +#[derive(Debug)] +#[cast_to([sync] Device)] +pub struct KprobeDevice { + inner: SpinLock, + kobj_state: LockedKObjectState, + name: String, +} + +#[derive(Debug)] +struct InnerKprobeDevice { + kobject_common: KObjectCommonData, + device_common: DeviceCommonData, +} + +impl KprobeDevice { + pub fn new(parent: Option>) -> Arc { + let bus_device = Self { + inner: SpinLock::new(InnerKprobeDevice { + kobject_common: KObjectCommonData::default(), + device_common: DeviceCommonData::default(), + }), + kobj_state: LockedKObjectState::new(None), + name: "kprobe".to_string(), + }; + bus_device.set_parent(parent); + return Arc::new(bus_device); + } + + fn inner(&self) -> SpinLockGuard { + self.inner.lock() + } +} + +impl KObject for KprobeDevice { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner().kobject_common.kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner().kobject_common.kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner().kobject_common.parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner().kobject_common.parent = parent; + } + + fn kset(&self) -> Option> { + self.inner().kobject_common.kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner().kobject_common.kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner().kobject_common.kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner().kobject_common.kobj_type = ktype; + } + + fn name(&self) -> String { + self.name.clone() + } + + fn set_name(&self, _name: String) {} + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state.write() = state; + } +} + +impl Device for KprobeDevice { + #[inline] + #[allow(dead_code)] + fn dev_type(&self) -> DeviceType { + return DeviceType::Other; + } + + #[inline] + fn id_table(&self) -> IdTable { + IdTable::new("kprobe".to_string(), None) + } + + fn bus(&self) -> Option> { + self.inner().device_common.bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.inner().device_common.bus = bus; + } + + fn set_class(&self, class: Option>) { + self.inner().device_common.class = class; + } + + fn driver(&self) -> Option> { + self.inner().device_common.driver.clone()?.upgrade() + } + + fn set_driver(&self, driver: Option>) { + self.inner().device_common.driver = driver; + } + + #[inline] + fn is_dead(&self) -> bool { + false + } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn state_synced(&self) -> bool { + todo!() + } + + fn dev_parent(&self) -> Option> { + self.inner().device_common.get_parent_weak_or_clear() + } + + fn set_dev_parent(&self, dev_parent: Option>) { + self.inner().device_common.parent = dev_parent; + } +} + +#[derive(Debug)] +pub struct KprobeAttr; + +impl Attribute for KprobeAttr { + fn name(&self) -> &str { + "type" + } + + fn mode(&self) -> ModeType { + ModeType::from_bits_truncate(0o444) + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::BATTR_READ + } + fn show(&self, _kobj: Arc, buf: &mut [u8]) -> Result { + if buf.is_empty() { + return Err(SystemError::EINVAL); + } + // perf_type_id::PERF_TYPE_MAX + buf[0] = b'6'; + Ok(1) + } +} diff --git a/kernel/src/driver/base/event_source/kprobe/mod.rs b/kernel/src/driver/base/event_source/kprobe/mod.rs new file mode 100644 index 000000000..ddb1f1730 --- /dev/null +++ b/kernel/src/driver/base/event_source/kprobe/mod.rs @@ -0,0 +1,28 @@ +use crate::driver::base::device::bus::Bus; +use crate::driver::base::device::{device_manager, device_register, sys_devices_kset, Device}; +use crate::driver::base::event_source::get_event_source_bus; +use crate::driver::base::event_source::kprobe::device::{KprobeAttr, KprobeDevice}; +use crate::driver::base::kobject::KObject; +use alloc::sync::Arc; +use system_error::SystemError; + +pub mod device; +static mut KPROBE_DEVICE: Option> = None; + +pub fn kprobe_subsys_init() -> Result<(), SystemError> { + let kprobe_device = KprobeDevice::new(Some(Arc::downgrade( + &(sys_devices_kset() as Arc), + ))); + + let event_source_bus = get_event_source_bus().ok_or(SystemError::EINVAL)?; + kprobe_device.set_bus(Some(Arc::downgrade(&(event_source_bus as Arc)))); + + // 注册到/sys/devices下 + device_register(kprobe_device.clone())?; + unsafe { + KPROBE_DEVICE = Some(kprobe_device.clone()); + } + + device_manager().create_file(&(kprobe_device as Arc), &KprobeAttr)?; + Ok(()) +} diff --git a/kernel/src/driver/base/event_source/mod.rs b/kernel/src/driver/base/event_source/mod.rs new file mode 100644 index 000000000..e94a4ae33 --- /dev/null +++ b/kernel/src/driver/base/event_source/mod.rs @@ -0,0 +1,25 @@ +use crate::driver::base::device::bus::{bus_register, Bus}; +use crate::driver::base::event_source::subsys::EventSourceBus; +use alloc::sync::Arc; +use system_error::SystemError; + +mod kprobe; +mod subsys; + +static mut EVENT_SOURCE_BUS: Option> = None; + +fn get_event_source_bus() -> Option> { + unsafe { EVENT_SOURCE_BUS.clone() } +} + +pub fn init_event_source_bus() -> Result<(), SystemError> { + let event_source_bus = EventSourceBus::new(); + let r = bus_register(event_source_bus.clone() as Arc); + if r.is_err() { + unsafe { EVENT_SOURCE_BUS = None }; + return r; + } + unsafe { EVENT_SOURCE_BUS = Some(event_source_bus.clone()) }; + kprobe::kprobe_subsys_init()?; + Ok(()) +} diff --git a/kernel/src/driver/base/event_source/subsys.rs b/kernel/src/driver/base/event_source/subsys.rs new file mode 100644 index 000000000..d581f3456 --- /dev/null +++ b/kernel/src/driver/base/event_source/subsys.rs @@ -0,0 +1,52 @@ +use crate::driver::base::device::bus::Bus; +use crate::driver::base::device::Device; +use crate::driver::base::subsys::SubSysPrivate; +use alloc::string::{String, ToString}; +use alloc::sync::{Arc, Weak}; +use system_error::SystemError; + +#[derive(Debug)] +pub struct EventSourceBus { + private: SubSysPrivate, +} + +impl EventSourceBus { + pub fn new() -> Arc { + let w: Weak = Weak::new(); + let private = SubSysPrivate::new("event_source".to_string(), Some(w), None, &[]); + let bus = Arc::new(Self { private }); + bus.subsystem() + .set_bus(Some(Arc::downgrade(&(bus.clone() as Arc)))); + return bus; + } +} + +impl Bus for EventSourceBus { + fn name(&self) -> String { + "event_source".to_string() + } + + fn dev_name(&self) -> String { + self.name() + } + + fn root_device(&self) -> Option> { + None + } + + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn shutdown(&self, _device: &Arc) { + todo!() + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn subsystem(&self) -> &SubSysPrivate { + &self.private + } +} diff --git a/kernel/src/driver/base/init.rs b/kernel/src/driver/base/init.rs index 93a32d817..9abf39da1 100644 --- a/kernel/src/driver/base/init.rs +++ b/kernel/src/driver/base/init.rs @@ -5,6 +5,7 @@ use super::{ class::classes_init, cpu::CpuDeviceManager, device::{bus::buses_init, init::devices_init}, + event_source::init_event_source_bus, firmware::firmware_init, hypervisor::hypervisor_init, platform::platform_bus_init, @@ -21,7 +22,7 @@ pub fn driver_init() -> Result<(), SystemError> { platform_bus_init()?; serio_bus_init()?; CpuDeviceManager::init()?; - + init_event_source_bus()?; // 至此,已完成设备驱动模型的初始化 return Ok(()); } diff --git a/kernel/src/driver/base/mod.rs b/kernel/src/driver/base/mod.rs index 3d4df393c..2880ea885 100644 --- a/kernel/src/driver/base/mod.rs +++ b/kernel/src/driver/base/mod.rs @@ -3,6 +3,7 @@ pub mod char; pub mod class; pub mod cpu; pub mod device; +pub mod event_source; pub mod firmware; pub mod hypervisor; pub mod init; diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 0defc3e0e..f8fb1e2a5 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -394,7 +394,35 @@ impl ProcFS { } else { panic!("create ksmg error"); } - + // 这个文件是用来欺骗Aya框架识别内核版本 + /* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release, + * but Ubuntu provides /proc/version_signature file, as described at + * https://ubuntu.com/kernel, with an example contents below, which we + * can use to get a proper LINUX_VERSION_CODE. + * + * Ubuntu 5.4.0-12.15-generic 5.4.8 + * + * In the above, 5.4.8 is what kernel is actually expecting, while + * uname() call will return 5.4.0 in info.release. + */ + let binding = inode.create( + "version_signature", + FileType::File, + ModeType::from_bits_truncate(0o444), + ); + if let Ok(version_signature) = binding { + let version_signature = version_signature + .as_any_ref() + .downcast_ref::() + .unwrap(); + version_signature.0.lock().fdata.ftype = ProcFileType::Default; + version_signature.0.lock().data = "DragonOS 6.0.0-generic 6.0.0\n" + .to_string() + .as_bytes() + .to_vec(); + } else { + panic!("create version_signature error"); + } return result; } @@ -466,6 +494,7 @@ impl IndexNode for LockedProcFSInode { let file_size = match inode.fdata.ftype { ProcFileType::ProcStatus => inode.open_status(&mut private_data)?, ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?, + ProcFileType::Default => inode.data.len() as i64, _ => { todo!() } diff --git a/kernel/src/perf/bpf.rs b/kernel/src/perf/bpf.rs index b283b2e54..ee2576898 100644 --- a/kernel/src/perf/bpf.rs +++ b/kernel/src/perf/bpf.rs @@ -79,54 +79,28 @@ impl RingPage { } } + #[inline] fn can_write(&self, data_size: usize, data_tail: usize, data_head: usize) -> bool { - if (data_head + 1) % self.data_region_size == data_tail { - // The buffer is full - return false; - } - let capacity = if data_head >= data_tail { - self.data_region_size - data_head + data_tail - } else { - data_tail - data_head - }; + let capacity = self.data_region_size - data_head + data_tail; data_size <= capacity } pub fn write_event(&mut self, data: &[u8]) -> Result<()> { let data_tail = unsafe { &mut (*(self.ptr as *mut perf_event_mmap_page)).data_tail }; let data_head = unsafe { &mut (*(self.ptr as *mut perf_event_mmap_page)).data_head }; - // data_tail..data_head is the region that can be written - // check if there is enough space to write the event - let sample_size = PerfSample::calculate_size(data.len()); - let can_write_sample = - self.can_write(sample_size, *data_tail as usize, *data_head as usize); - // log::error!( - // "can_write_sample: {}, data_tail: {}, data_head: {}, data.len(): {}, region_size: {}", - // can_write_sample, - // *data_tail, - // *data_head, - // data.len(), - // self.data_region_size - // ); - if !can_write_sample { - //we need record it to the lost record - self.lost += 1; - // log::error!( - // "Lost record: {}, data_tail: {}, data_head: {}", - // self.lost, - // *data_tail, - // *data_head - // ); - Ok(()) - } else { - // we can write the sample to the page - // If the lost record is not zero, we need to write the lost record first. + // user lib will update the tail after read the data,but it will not % data_region_size + let perf_header_size = size_of::(); + let can_write_perf_header = + self.can_write(perf_header_size, *data_tail as usize, *data_head as usize); + + if can_write_perf_header { let can_write_lost_record = self.can_write( size_of::(), *data_tail as usize, *data_head as usize, ); + // if there is lost record, we need to write the lost record first if self.lost > 0 && can_write_lost_record { let new_data_head = self.write_lost(*data_head as usize)?; *data_head = new_data_head as u64; @@ -137,8 +111,21 @@ impl RingPage { // *data_head // ); self.lost = 0; - self.write_event(data) - } else { + // try to write the event again + return self.write_event(data); + } + let sample_size = PerfSample::calculate_size(data.len()); + let can_write_sample = + self.can_write(sample_size, *data_tail as usize, *data_head as usize); + // log::error!( + // "can_write_sample: {}, data_tail: {}, data_head: {}, data.len(): {}, region_size: {}", + // can_write_sample, + // *data_tail, + // *data_head, + // data.len(), + // self.data_region_size + // ); + if can_write_sample { let new_data_head = self.write_sample(data, *data_head as usize)?; *data_head = new_data_head as u64; // log::info!( @@ -146,20 +133,24 @@ impl RingPage { // *data_tail, // *data_head // ); - Ok(()) + } else { + self.lost += 1; } + } else { + self.lost += 1; } + Ok(()) } /// Write any data to the page. /// /// Return the new data_head - fn write_any(&mut self, data: &[u8], data_head: usize) -> Result { + fn write_any(&mut self, data: &[u8], data_head: usize) -> Result<()> { let data_region_len = self.data_region_size; let data_region = self.as_mut_slice()[PAGE_SIZE..].as_mut(); let data_len = data.len(); + let start = data_head % data_region_len; let end = (data_head + data_len) % data_region_len; - let start = data_head; if start < end { data_region[start..end].copy_from_slice(data); } else { @@ -167,40 +158,57 @@ impl RingPage { data_region[start..start + first_len].copy_from_slice(&data[..first_len]); data_region[0..end].copy_from_slice(&data[first_len..]); } - Ok(end) + Ok(()) + } + #[inline] + fn fill_size(&self, data_head_mod: usize) -> usize { + if self.data_region_size - data_head_mod < size_of::() { + // The remaining space is not enough to write the perf_event_header + // We need to fill the remaining space with 0 + self.data_region_size - data_head_mod + } else { + 0 + } } /// Write a sample to the page. fn write_sample(&mut self, data: &[u8], data_head: usize) -> Result { + let sample_size = PerfSample::calculate_size(data.len()); + let maybe_end = (data_head + sample_size) % self.data_region_size; + let fill_size = self.fill_size(maybe_end); let perf_sample = PerfSample { s_hdr: SampleHeader { header: perf_event_header { type_: perf_event_type::PERF_RECORD_SAMPLE as u32, misc: 0, - size: size_of::() as u16 + data.len() as u16, + size: size_of::() as u16 + data.len() as u16 + fill_size as u16, }, size: data.len() as u32, }, value: data, }; - let new_head = self.write_any(perf_sample.s_hdr.as_bytes(), data_head)?; - self.write_any(perf_sample.value, new_head) + self.write_any(perf_sample.s_hdr.as_bytes(), data_head)?; + self.write_any(perf_sample.value, data_head + size_of::())?; + Ok(data_head + sample_size + fill_size) } /// Write a lost record to the page. /// /// Return the new data_head fn write_lost(&mut self, data_head: usize) -> Result { + let maybe_end = (data_head + size_of::()) % self.data_region_size; + let fill_size = self.fill_size(maybe_end); let lost = LostSamples { header: perf_event_header { type_: perf_event_type::PERF_RECORD_LOST as u32, misc: 0, - size: size_of::() as u16, + size: size_of::() as u16 + fill_size as u16, }, id: 0, count: self.lost as u64, }; - self.write_any(lost.as_bytes(), data_head) + self.write_any(lost.as_bytes(), data_head)?; + Ok(data_head + size_of::() + fill_size) } pub fn readable(&self) -> bool { diff --git a/kernel/src/perf/kprobe.rs b/kernel/src/perf/kprobe.rs index 54ac829bc..698da7dc6 100644 --- a/kernel/src/perf/kprobe.rs +++ b/kernel/src/perf/kprobe.rs @@ -39,8 +39,10 @@ impl KprobePerfEvent { .downcast_arc::() .ok_or(SystemError::EINVAL)?; let prog_slice = file.insns(); - let mut vm = - EbpfVmRawOwned::new(Some(prog_slice.to_vec())).map_err(|_| SystemError::EINVAL)?; + let mut vm = EbpfVmRawOwned::new(Some(prog_slice.to_vec())).map_err(|e| { + log::error!("create ebpf vm failed: {:?}", e); + SystemError::EINVAL + })?; vm.register_helper_set(BPF_HELPER_FUN_SET.get()) .map_err(|_| SystemError::EINVAL)?; // create a callback to execute the ebpf prog @@ -75,10 +77,10 @@ impl CallBackFunc for KprobePerfCallBack { size_of::(), ) }; - let _res = self - .vm - .execute_program(probe_context) - .map_err(|_| SystemError::EINVAL); + let res = self.vm.execute_program(probe_context); + if res.is_err() { + log::error!("kprobe callback error: {:?}", res); + } } } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 45dd2efa6..dfb33dfd6 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -1213,6 +1213,7 @@ impl Syscall { let flags = args[4] as u32; Self::sys_perf_event_open(attr, pid, cpu, group_fd, flags) } + SYS_SETRLIMIT => Ok(0), _ => panic!("Unsupported syscall ID: {}", syscall_num), }; diff --git a/user/apps/test_ebpf/syscall_ebpf/.gitignore b/user/apps/syscall_ebpf/.gitignore similarity index 95% rename from user/apps/test_ebpf/syscall_ebpf/.gitignore rename to user/apps/syscall_ebpf/.gitignore index 9db7029fd..57e36ada9 100644 --- a/user/apps/test_ebpf/syscall_ebpf/.gitignore +++ b/user/apps/syscall_ebpf/.gitignore @@ -7,3 +7,4 @@ target/ # These are backup files generated by rustfmt **/*.rs.bk +/install/ \ No newline at end of file diff --git a/user/apps/syscall_ebpf/Cargo.toml b/user/apps/syscall_ebpf/Cargo.toml new file mode 100644 index 000000000..a8170dfc5 --- /dev/null +++ b/user/apps/syscall_ebpf/Cargo.toml @@ -0,0 +1,40 @@ +[workspace] +resolver = "2" +members = ["syscall_ebpf", "syscall_ebpf-common", "syscall_ebpf-ebpf"] +default-members = ["syscall_ebpf", "syscall_ebpf-common"] + +[workspace.dependencies] +aya = { version = "0.13.0", default-features = false } +aya-ebpf = { version = "0.1.1", default-features = false } +aya-log = { version = "0.2.1", default-features = false } +aya-log-ebpf = { version = "0.1.1", default-features = false } + + +#aya = { path = "../../../../aya/aya", default-features = false } +#aya-ebpf = { path = "../../../../aya/ebpf/aya-ebpf", default-features = false } +#aya-log = { path = "../../../../aya/aya-log", default-features = false } +#aya-log-ebpf = { path = "../../../../aya/ebpf/aya-log-ebpf", default-features = false } + + + +anyhow = { version = "1", default-features = false } +cargo_metadata = { version = "0.18.0", default-features = false } +# `std` feature is currently required to build `clap`. +# +# See https://github.com/clap-rs/clap/blob/61f5ee5/clap_builder/src/lib.rs#L15. +clap = { version = "4.5.20", default-features = false, features = ["std"] } +env_logger = { version = "0.11.5", default-features = false } +libc = { version = "0.2.159", default-features = false } +log = { version = "0.4.22", default-features = false } +tokio = { version = "1.40.0", default-features = false } +which = { version = "6.0.0", default-features = false } + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" + +[profile.release.package.syscall_ebpf-ebpf] +debug = 2 +codegen-units = 1 diff --git a/user/apps/test_ebpf/Makefile b/user/apps/syscall_ebpf/Makefile similarity index 84% rename from user/apps/test_ebpf/Makefile rename to user/apps/syscall_ebpf/Makefile index 0b5d9e43a..c8dadc36e 100644 --- a/user/apps/test_ebpf/Makefile +++ b/user/apps/syscall_ebpf/Makefile @@ -21,10 +21,10 @@ endif run: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) -build:build-ebpf +build: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) -clean:clean-ebpf +clean: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) test: @@ -42,20 +42,16 @@ fmt-check: run-release: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release -build-release:build-ebpf +build-release: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release -clean-release:clean-ebpf +clean-release: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release test-release: RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release -build-ebpf: - cd ./syscall_ebpf && RUST_LOG=debug cargo xtask build --release -clean-ebpf: - cd ./syscall_ebpf && cargo clean .PHONY: install -install:build-ebpf - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force +install: + RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path ./syscall_ebpf --no-track --root $(INSTALL_DIR) --force diff --git a/user/apps/syscall_ebpf/README.md b/user/apps/syscall_ebpf/README.md new file mode 100644 index 000000000..635b37bbd --- /dev/null +++ b/user/apps/syscall_ebpf/README.md @@ -0,0 +1,33 @@ +# syscall_ebpf + +## Prerequisites + +1. stable rust toolchains: `rustup toolchain install stable` +1. nightly rust toolchains: `rustup toolchain install nightly --component rust-src` +1. (if cross-compiling) rustup target: `rustup target add ${ARCH}-unknown-linux-musl` +1. (if cross-compiling) LLVM: (e.g.) `brew install llvm` (on macOS) +1. (if cross-compiling) C toolchain: (e.g.) [`brew install filosottile/musl-cross/musl-cross`](https://github.com/FiloSottile/homebrew-musl-cross) (on macOS) +1. bpf-linker: `cargo install bpf-linker` (`--no-default-features` on macOS) + +## Build & Run + +Use `cargo build`, `cargo check`, etc. as normal. Run your program with: + +```shell +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' +``` + +Cargo build scripts are used to automatically build the eBPF correctly and include it in the +program. + +## Cross-compiling on macOS + +Cross compilation should work on both Intel and Apple Silicon Macs. + +```shell +CC=${ARCH}-linux-musl-gcc cargo build --package syscall_ebpf --release \ + --target=${ARCH}-unknown-linux-musl \ + --config=target.${ARCH}-unknown-linux-musl.linker=\"${ARCH}-linux-musl-gcc\" +``` +The cross-compiled program `target/${ARCH}-unknown-linux-musl/release/syscall_ebpf` can be +copied to a Linux server or VM and run there. diff --git a/user/apps/syscall_ebpf/rustfmt.toml b/user/apps/syscall_ebpf/rustfmt.toml new file mode 100644 index 000000000..53f7b6d7a --- /dev/null +++ b/user/apps/syscall_ebpf/rustfmt.toml @@ -0,0 +1,4 @@ +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +reorder_imports = true +unstable_features = true diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-common/Cargo.toml b/user/apps/syscall_ebpf/syscall_ebpf-common/Cargo.toml similarity index 56% rename from user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-common/Cargo.toml rename to user/apps/syscall_ebpf/syscall_ebpf-common/Cargo.toml index 7acc25d40..b453f61b7 100644 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-common/Cargo.toml +++ b/user/apps/syscall_ebpf/syscall_ebpf-common/Cargo.toml @@ -8,7 +8,7 @@ default = [] user = ["aya"] [dependencies] -aya = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/tiny-aya.git", rev = "0689f13", optional = true } +aya = { workspace = true, optional = true } [lib] path = "src/lib.rs" diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-common/src/lib.rs b/user/apps/syscall_ebpf/syscall_ebpf-common/src/lib.rs similarity index 100% rename from user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-common/src/lib.rs rename to user/apps/syscall_ebpf/syscall_ebpf-common/src/lib.rs diff --git a/user/apps/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml new file mode 100644 index 000000000..d8d7a20cd --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml @@ -0,0 +1,12 @@ +# We have this so that one doesn't need to manually pass +# --target=bpfel-unknown-none -Z build-std=core when running cargo +# check/build/doc etc. +# +# NB: this file gets loaded only if you run cargo from this directory, it's +# ignored if you run from the workspace root. See +# https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure +[build] +target = ["bpfeb-unknown-none", "bpfel-unknown-none"] + +[unstable] +build-std = ["core"] diff --git a/user/apps/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml new file mode 100644 index 000000000..fd061ea9b --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "syscall_ebpf-ebpf" +version = "0.1.0" +edition = "2021" + +[dependencies] +syscall_ebpf-common = { path = "../syscall_ebpf-common" } + +aya-ebpf = { workspace = true } +aya-log-ebpf = { workspace = true } + +[build-dependencies] +which = { workspace = true } + +[[bin]] +name = "syscall_ebpf" +path = "src/main.rs" diff --git a/user/apps/syscall_ebpf/syscall_ebpf-ebpf/build.rs b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/build.rs new file mode 100644 index 000000000..f83c317a1 --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/build.rs @@ -0,0 +1,17 @@ +use which::which; + +/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be +/// better expressed by [artifact-dependencies][bindeps] but issues such as +/// https://github.com/rust-lang/cargo/issues/12385 make their use impractical for the time being. +/// +/// This file implements an imperfect solution: it causes cargo to rebuild the crate whenever the +/// mtime of `which bpf-linker` changes. Note that possibility that a new bpf-linker is added to +/// $PATH ahead of the one used as the cache key still exists. Solving this in the general case +/// would require rebuild-if-changed-env=PATH *and* rebuild-if-changed={every-directory-in-PATH} +/// which would likely mean far too much cache invalidation. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let bpf_linker = which("bpf-linker").unwrap(); + println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap()); +} diff --git a/user/apps/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml new file mode 100644 index 000000000..f70d22540 --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly" +components = ["rust-src"] diff --git a/user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/lib.rs b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/lib.rs new file mode 100644 index 000000000..3ac3e595b --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] + +// This file exists to enable the library target. diff --git a/user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs new file mode 100644 index 000000000..c75810172 --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs @@ -0,0 +1,50 @@ +#![no_std] +#![no_main] + +use aya_ebpf::{ + helpers::bpf_ktime_get_ns, + macros::{kprobe, map}, + maps::HashMap, + programs::ProbeContext, +}; +use aya_log_ebpf::info; + +#[kprobe] +pub fn syscall_ebpf(ctx: ProbeContext) -> u32 { + try_syscall_ebpf(ctx).unwrap_or_else(|ret| ret) +} + +fn try_syscall_ebpf(ctx: ProbeContext) -> Result { + let pt_regs = unsafe { &*ctx.regs }; + // first arg -> rdi + // second arg -> rsi + // third arg -> rdx + // four arg -> rcx + let syscall_num = pt_regs.rsi as usize; + if syscall_num != 1 { + unsafe { + if let Some(v) = SYSCALL_LIST.get(&(syscall_num as u32)) { + let new_v = *v + 1; + SYSCALL_LIST + .insert(&(syscall_num as u32), &new_v, 0) + .unwrap(); + } else { + SYSCALL_LIST.insert(&(syscall_num as u32), &1, 0).unwrap(); + } + } + let time = unsafe { bpf_ktime_get_ns() }; + info!(&ctx, "[{}] invoke syscall {}", time, syscall_num); + } + Ok(0) +} + +#[map] +static SYSCALL_LIST: HashMap = HashMap::::with_max_entries(1024, 0); + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + // we need use this because the verifier will forbid loop + unsafe { core::hint::unreachable_unchecked() } + // loop{} +} diff --git a/user/apps/syscall_ebpf/syscall_ebpf/Cargo.toml b/user/apps/syscall_ebpf/syscall_ebpf/Cargo.toml new file mode 100644 index 000000000..6191f0495 --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "syscall_ebpf" +version = "0.1.0" +edition = "2021" + +[dependencies] +syscall_ebpf-common = { path = "../syscall_ebpf-common", features = ["user"] } + +anyhow = { workspace = true, default-features = true } +aya = { workspace = true } +aya-log = { workspace = true } +env_logger = { workspace = true } +libc = { workspace = true } +log = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread", "net", "signal", "time"] } + +[build-dependencies] +cargo_metadata = { workspace = true } +# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but +# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build +# script to build this, but we want to teach cargo about the dependecy so that cache invalidation +# works properly. +# +# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added +# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in +# Cargo.toml in the workspace root. +# +# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks +# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable +# features. +syscall_ebpf-ebpf = { path = "../syscall_ebpf-ebpf" } + +[[bin]] +name = "syscall_ebpf" +path = "src/main.rs" diff --git a/user/apps/syscall_ebpf/syscall_ebpf/build.rs b/user/apps/syscall_ebpf/syscall_ebpf/build.rs new file mode 100644 index 000000000..52b2ec291 --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf/build.rs @@ -0,0 +1,150 @@ +use std::{ + env, fs, + io::{BufRead as _, BufReader}, + path::PathBuf, + process::{Child, Command, Stdio}, +}; + +use cargo_metadata::{ + Artifact, CompilerMessage, Message, Metadata, MetadataCommand, Package, Target, +}; + +/// This crate has a runtime dependency on artifacts produced by the `syscall_ebpf-ebpf` crate. +/// This would be better expressed as one or more [artifact-dependencies][bindeps] but issues such +/// as: +/// +/// * https://github.com/rust-lang/cargo/issues/12374 +/// * https://github.com/rust-lang/cargo/issues/12375 +/// * https://github.com/rust-lang/cargo/issues/12385 +/// +/// prevent their use for the time being. +/// +/// [bindeps]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html?highlight=feature#artifact-dependencies +fn main() { + let Metadata { packages, .. } = MetadataCommand::new().no_deps().exec().unwrap(); + let ebpf_package = packages + .into_iter() + .find(|Package { name, .. }| name == "syscall_ebpf-ebpf") + .unwrap(); + + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = PathBuf::from(out_dir); + + let endian = env::var_os("CARGO_CFG_TARGET_ENDIAN").unwrap(); + let target = if endian == "big" { + "bpfeb" + } else if endian == "little" { + "bpfel" + } else { + panic!("unsupported endian={:?}", endian) + }; + + // TODO(https://github.com/rust-lang/cargo/issues/4001): Make this `false` if we can determine + // we're in a check build. + let build_ebpf = true; + if build_ebpf { + let arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap(); + + let target = format!("{target}-unknown-none"); + + let Package { manifest_path, .. } = ebpf_package; + let ebpf_dir = manifest_path.parent().unwrap(); + + // We have a build-dependency on `syscall_ebpf-ebpf`, so cargo will automatically rebuild us + // if `syscall_ebpf-ebpf`'s *library* target or any of its dependencies change. Since we + // depend on `syscall_ebpf-ebpf`'s *binary* targets, that only gets us half of the way. This + // stanza ensures cargo will rebuild us on changes to the binaries too, which gets us the + // rest of the way. + println!("cargo:rerun-if-changed={}", ebpf_dir.as_str()); + + let mut cmd = Command::new("cargo"); + cmd.args([ + "build", + "-Z", + "build-std=core", + "--bins", + "--message-format=json", + "--release", + "--target", + &target, + ]); + + cmd.env("CARGO_CFG_BPF_TARGET_ARCH", arch); + + // Workaround to make sure that the rust-toolchain.toml is respected. + for key in ["RUSTUP_TOOLCHAIN", "RUSTC", "RUSTC_WORKSPACE_WRAPPER"] { + cmd.env_remove(key); + } + cmd.current_dir(ebpf_dir); + + // Workaround for https://github.com/rust-lang/cargo/issues/6412 where cargo flocks itself. + let ebpf_target_dir = out_dir.join("../syscall_ebpf-ebpf"); + cmd.arg("--target-dir").arg(&ebpf_target_dir); + + let mut child = cmd + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}")); + let Child { stdout, stderr, .. } = &mut child; + + // Trampoline stdout to cargo warnings. + let stderr = stderr.take().unwrap(); + let stderr = BufReader::new(stderr); + let stderr = std::thread::spawn(move || { + for line in stderr.lines() { + let line = line.unwrap(); + println!("cargo:warning={line}"); + } + }); + + let stdout = stdout.take().unwrap(); + let stdout = BufReader::new(stdout); + let mut executables = Vec::new(); + for message in Message::parse_stream(stdout) { + #[allow(clippy::collapsible_match)] + match message.expect("valid JSON") { + Message::CompilerArtifact(Artifact { + executable, + target: Target { name, .. }, + .. + }) => { + if let Some(executable) = executable { + executables.push((name, executable.into_std_path_buf())); + } + } + Message::CompilerMessage(CompilerMessage { message, .. }) => { + for line in message.rendered.unwrap_or_default().split('\n') { + println!("cargo:warning={line}"); + } + } + Message::TextLine(line) => { + println!("cargo:warning={line}"); + } + _ => {} + } + } + + let status = child + .wait() + .unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}")); + assert_eq!(status.code(), Some(0), "{cmd:?} failed: {status:?}"); + + stderr.join().map_err(std::panic::resume_unwind).unwrap(); + + for (name, binary) in executables { + let dst = out_dir.join(name); + let _: u64 = fs::copy(&binary, &dst) + .unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}")); + } + } else { + let Package { targets, .. } = ebpf_package; + for Target { name, kind, .. } in targets { + if *kind != ["bin"] { + continue; + } + let dst = out_dir.join(name); + fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}")); + } + } +} diff --git a/user/apps/syscall_ebpf/syscall_ebpf/src/main.rs b/user/apps/syscall_ebpf/syscall_ebpf/src/main.rs new file mode 100644 index 000000000..a65e18036 --- /dev/null +++ b/user/apps/syscall_ebpf/syscall_ebpf/src/main.rs @@ -0,0 +1,74 @@ +use aya::{maps::HashMap, programs::KProbe}; +#[rustfmt::skip] +use log::{debug, warn}; +use tokio::{signal, task::yield_now, time}; + +extern crate libc; + +#[tokio::main(flavor = "current_thread")] +async fn main() -> anyhow::Result<()> { + // env_logger::init(); + env_logger::builder() + .filter_level(log::LevelFilter::Warn) + .format_timestamp(None) + .init(); + + // Bump the memlock rlimit. This is needed for older kernels that don't use the + // new memcg based accounting, see https://lwn.net/Articles/837122/ + let rlim = libc::rlimit { + rlim_cur: libc::RLIM_INFINITY, + rlim_max: libc::RLIM_INFINITY, + }; + let ret = unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &rlim) }; + if ret != 0 { + debug!("remove limit on locked memory failed, ret is: {}", ret); + } + + // This will include your eBPF object file as raw bytes at compile-time and load it at + // runtime. This approach is recommended for most real-world use cases. If you would + // like to specify the eBPF program at runtime rather than at compile-time, you can + // reach for `Bpf::load_file` instead. + let mut ebpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!( + env!("OUT_DIR"), + "/syscall_ebpf" + )))?; + if let Err(e) = aya_log::EbpfLogger::init(&mut ebpf) { + // This can happen if you remove all log statements from your eBPF program. + warn!("failed to initialize eBPF logger: {}", e); + } + + let program: &mut KProbe = ebpf.program_mut("syscall_ebpf").unwrap().try_into()?; + program.load()?; + program.attach("dragonos_kernel::syscall::Syscall::handle", 0)?; + // println!("attacch the kprobe to dragonos_kernel::syscall::Syscall::handle"); + + // print the value of the blocklist per 5 seconds + tokio::spawn(async move { + let blocklist: HashMap<_, u32, u32> = + HashMap::try_from(ebpf.map("SYSCALL_LIST").unwrap()).unwrap(); + let mut now = time::Instant::now(); + loop { + let new_now = time::Instant::now(); + let duration = new_now.duration_since(now); + if duration.as_secs() >= 5 { + println!("------------SYSCALL_LIST----------------"); + let iter = blocklist.iter(); + for item in iter { + if let Ok((key, value)) = item { + println!("syscall: {:?}, count: {:?}", key, value); + } + } + println!("----------------------------------------"); + now = new_now; + } + yield_now().await; + } + }); + + let ctrl_c = signal::ctrl_c(); + println!("Waiting for Ctrl-C..."); + ctrl_c.await?; + println!("Exiting..."); + + Ok(()) +} diff --git a/user/apps/test_ebpf/.gitignore b/user/apps/test_ebpf/.gitignore deleted file mode 100644 index 1ac354611..000000000 --- a/user/apps/test_ebpf/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target -Cargo.lock -/install/ \ No newline at end of file diff --git a/user/apps/test_ebpf/Cargo.toml b/user/apps/test_ebpf/Cargo.toml deleted file mode 100644 index ab4a3b7f9..000000000 --- a/user/apps/test_ebpf/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "test_ebpf" -version = "0.1.0" -edition = "2021" - -[dependencies] -aya = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/tiny-aya.git", rev = "0689f13" } -aya-log = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/tiny-aya.git", rev = "0689f13" } - -log = "0.4.22" -env_logger = "0.11.5" -tokio = { version = "1.25", features = ["macros", "rt", "rt-multi-thread", "net", "signal", "time"] } - -[profile.release] -lto = true -strip = true diff --git a/user/apps/test_ebpf/src/main.rs b/user/apps/test_ebpf/src/main.rs deleted file mode 100644 index 1909aeeb9..000000000 --- a/user/apps/test_ebpf/src/main.rs +++ /dev/null @@ -1,60 +0,0 @@ -use aya::maps::HashMap; -use aya::programs::KProbe; -use aya::{include_bytes_aligned, Ebpf}; -use aya_log::EbpfLogger; -use log::{info, warn}; -use std::error::Error; -use tokio::task::yield_now; -use tokio::{signal, time}; - -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<(), Box> { - env_logger::builder() - .filter_level(log::LevelFilter::Warn) - .format_timestamp(None) - .init(); - - let mut bpf = Ebpf::load(include_bytes_aligned!( - "../syscall_ebpf/target/bpfel-unknown-none/release/syscall_ebpf" - ))?; - - // create a async task to read the log - if let Err(e) = EbpfLogger::init(&mut bpf) { - // This can happen if you remove all log statements from your eBPF program. - warn!("failed to initialize eBPF logger: {}", e); - } - - let program: &mut KProbe = bpf.program_mut("syscall_ebpf").unwrap().try_into()?; - program.load()?; - program.attach("dragonos_kernel::syscall::Syscall::handle", 0)?; - - info!("attacch the kprobe to dragonos_kernel::syscall::Syscall::handle"); - - // print the value of the blocklist per 5 seconds - tokio::spawn(async move { - let blocklist: HashMap<_, u32, u32> = - HashMap::try_from(bpf.map("SYSCALL_LIST").unwrap()).unwrap(); - let mut now = time::Instant::now(); - loop { - let new_now = time::Instant::now(); - let duration = new_now.duration_since(now); - if duration.as_secs() >= 5 { - println!("------------SYSCALL_LIST----------------"); - let iter = blocklist.iter(); - for item in iter { - if let Ok((key, value)) = item { - println!("syscall: {:?}, count: {:?}", key, value); - } - } - println!("----------------------------------------"); - now = new_now; - } - yield_now().await; - } - }); - - info!("Waiting for Ctrl-C..."); - signal::ctrl_c().await?; - info!("Exiting..."); - Ok(()) -} diff --git a/user/apps/test_ebpf/syscall_ebpf/.cargo/config.toml b/user/apps/test_ebpf/syscall_ebpf/.cargo/config.toml deleted file mode 100644 index 35049cbcb..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[alias] -xtask = "run --package xtask --" diff --git a/user/apps/test_ebpf/syscall_ebpf/.vscode/settings.json b/user/apps/test_ebpf/syscall_ebpf/.vscode/settings.json deleted file mode 100644 index 0c82ac973..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rust-analyzer.linkedProjects": ["Cargo.toml", "syscall_ebpf-ebpf/Cargo.toml"] -} diff --git a/user/apps/test_ebpf/syscall_ebpf/Cargo.toml b/user/apps/test_ebpf/syscall_ebpf/Cargo.toml deleted file mode 100644 index 6eb4e6322..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/Cargo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[workspace] -resolver = "2" -members = ["xtask", "syscall_ebpf-common"] diff --git a/user/apps/test_ebpf/syscall_ebpf/README.md b/user/apps/test_ebpf/syscall_ebpf/README.md deleted file mode 100644 index fe5ed32d3..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# syscall_ebpf - -## Prerequisites - -1. Install bpf-linker: `cargo install bpf-linker` - -## Build eBPF - -```bash -cargo xtask build-ebpf -``` - -To perform a release build you can use the `--release` flag. -You may also change the target architecture with the `--target` flag. - -## Build Userspace - -```bash -cargo build -``` - -## Build eBPF and Userspace - -```bash -cargo xtask build -``` - -## Run - -```bash -RUST_LOG=info cargo xtask run -``` diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml deleted file mode 100644 index 4302a7f16..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.cargo/config.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build] -target-dir = "../target" -target = "bpfel-unknown-none" - -[unstable] -build-std = ["core"] diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.helix/config.toml b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.helix/config.toml deleted file mode 100644 index da5424f19..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.helix/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[editor] -workspace-lsp-roots = [] diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vim/coc-settings.json b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vim/coc-settings.json deleted file mode 100644 index e2211a64f..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vim/coc-settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rust-analyzer.cargo.target": "bpfel-unknown-none", - "rust-analyzer.checkOnSave.allTargets": false -} diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vscode/settings.json b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vscode/settings.json deleted file mode 100644 index e2211a64f..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rust-analyzer.cargo.target": "bpfel-unknown-none", - "rust-analyzer.checkOnSave.allTargets": false -} diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml deleted file mode 100644 index 1911fa43c..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "syscall_ebpf-ebpf" -version = "0.1.0" -edition = "2021" - -[dependencies] -aya-ebpf = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/aya.git", rev = "3d57d35" } -aya-log-ebpf = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/aya.git", rev = "3d57d35" } - -syscall_ebpf-common = { path = "../syscall_ebpf-common" } - -[[bin]] -name = "syscall_ebpf" -path = "src/main.rs" - -[profile.dev] -opt-level = 3 -debug = false -debug-assertions = false -overflow-checks = false -lto = true -panic = "abort" -incremental = false -codegen-units = 1 -rpath = false - -[profile.release] -lto = true -panic = "abort" -codegen-units = 1 - -[workspace] -members = [] diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml deleted file mode 100644 index fda4ec82e..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/rust-toolchain.toml +++ /dev/null @@ -1,13 +0,0 @@ -[toolchain] -channel = "nightly-2024-11-05" -# The source code of rustc, provided by the rust-src component, is needed for -# building eBPF programs. -components = [ - "cargo", - "clippy", - "rust-docs", - "rust-src", - "rust-std", - "rustc", - "rustfmt", -] diff --git a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs b/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs deleted file mode 100644 index 7f9b79b65..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/syscall_ebpf-ebpf/src/main.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![no_std] -#![no_main] - -use aya_ebpf::{macros::kprobe, programs::ProbeContext}; -use aya_ebpf::macros::map; -use aya_ebpf::maps::HashMap; -use aya_log_ebpf::info; - -#[kprobe] -pub fn syscall_ebpf(ctx: ProbeContext) -> u32 { - try_syscall_ebpf(ctx).unwrap_or_else(|ret| ret) -} - -fn try_syscall_ebpf(ctx: ProbeContext) -> Result { - let pt_regs = unsafe { - &*ctx.regs - }; - // first arg -> rdi - // second arg -> rsi - // third arg -> rdx - // four arg -> rcx - let syscall_num = pt_regs.rsi as usize; - if syscall_num != 1 { - unsafe { - if let Some(v) = SYSCALL_LIST.get(&(syscall_num as u32)){ - let new_v = *v + 1; - SYSCALL_LIST.insert(&(syscall_num as u32), &new_v,0).unwrap(); - }else { - SYSCALL_LIST.insert(&(syscall_num as u32), &1,0).unwrap(); - } - } - info!(&ctx, "invoke syscall {}", syscall_num); - } - Ok(0) -} - -#[map] // -static SYSCALL_LIST: HashMap = - HashMap::::with_max_entries(1024, 0); - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - unsafe { core::hint::unreachable_unchecked() } -} diff --git a/user/apps/test_ebpf/syscall_ebpf/xtask/Cargo.toml b/user/apps/test_ebpf/syscall_ebpf/xtask/Cargo.toml deleted file mode 100644 index c4dea5d16..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/xtask/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1" -clap = { version = "4.1", features = ["derive"] } diff --git a/user/apps/test_ebpf/syscall_ebpf/xtask/src/build.rs b/user/apps/test_ebpf/syscall_ebpf/xtask/src/build.rs deleted file mode 100644 index ddeee4496..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/xtask/src/build.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::build_ebpf::{build_ebpf, Architecture, Options as BuildOptions}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, -} - -/// Build the project -fn build_project(opts: &Options) -> Result<(), anyhow::Error> { - let mut args = vec!["build"]; - if opts.release { - args.push("--release") - } - let status = Command::new("cargo") - .args(&args) - .status() - .expect("failed to build userspace"); - assert!(status.success()); - Ok(()) -} - -/// Build our ebpf program and the project -pub fn build(opts: Options) -> Result<(), anyhow::Error> { - // build our ebpf program followed by our application - build_ebpf(BuildOptions { - target: opts.bpf_target, - release: opts.release, - }) - .context("Error while building eBPF program")?; - build_project(&opts).context("Error while building userspace application")?; - Ok(()) -} \ No newline at end of file diff --git a/user/apps/test_ebpf/syscall_ebpf/xtask/src/build_ebpf.rs b/user/apps/test_ebpf/syscall_ebpf/xtask/src/build_ebpf.rs deleted file mode 100644 index 8c6e323f5..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/xtask/src/build_ebpf.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::{path::PathBuf, process::Command}; - -use clap::Parser; - -#[derive(Debug, Copy, Clone)] -pub enum Architecture { - BpfEl, - BpfEb, -} - -impl std::str::FromStr for Architecture { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(match s { - "bpfel-unknown-none" => Architecture::BpfEl, - "bpfeb-unknown-none" => Architecture::BpfEb, - _ => return Err("invalid target".to_owned()), - }) - } -} - -impl std::fmt::Display for Architecture { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Architecture::BpfEl => "bpfel-unknown-none", - Architecture::BpfEb => "bpfeb-unknown-none", - }) - } -} - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub target: Architecture, - /// Build the release target - #[clap(long)] - pub release: bool, -} - -pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { - let dir = PathBuf::from("syscall_ebpf-ebpf"); - let target = format!("--target={}", opts.target); - let mut args = vec![ - "build", - target.as_str(), - "-Z", - "build-std=core", - ]; - if opts.release { - args.push("--release") - } - - // Command::new creates a child process which inherits all env variables. This means env - // vars set by the cargo xtask command are also inherited. RUSTUP_TOOLCHAIN is removed - // so the rust-toolchain.toml file in the -ebpf folder is honored. - - let status = Command::new("cargo") - .current_dir(dir) - .env_remove("RUSTUP_TOOLCHAIN") - .args(&args) - .status() - .expect("failed to build bpf program"); - assert!(status.success()); - Ok(()) -} diff --git a/user/apps/test_ebpf/syscall_ebpf/xtask/src/main.rs b/user/apps/test_ebpf/syscall_ebpf/xtask/src/main.rs deleted file mode 100644 index 507945899..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/xtask/src/main.rs +++ /dev/null @@ -1,36 +0,0 @@ -mod build_ebpf; -mod build; -mod run; - -use std::process::exit; - -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - BuildEbpf(build_ebpf::Options), - Build(build::Options), - Run(run::Options), -} - -fn main() { - let opts = Options::parse(); - - use Command::*; - let ret = match opts.command { - BuildEbpf(opts) => build_ebpf::build_ebpf(opts), - Run(opts) => run::run(opts), - Build(opts) => build::build(opts), - }; - - if let Err(e) = ret { - eprintln!("{e:#}"); - exit(1); - } -} diff --git a/user/apps/test_ebpf/syscall_ebpf/xtask/src/run.rs b/user/apps/test_ebpf/syscall_ebpf/xtask/src/run.rs deleted file mode 100644 index 19af11c45..000000000 --- a/user/apps/test_ebpf/syscall_ebpf/xtask/src/run.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::process::Command; - -use anyhow::Context as _; -use clap::Parser; - -use crate::{build::{build, Options as BuildOptions}, build_ebpf::Architecture}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Set the endianness of the BPF target - #[clap(default_value = "bpfel-unknown-none", long)] - pub bpf_target: Architecture, - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// The command used to wrap your application - #[clap(short, long, default_value = "sudo -E")] - pub runner: String, - /// Arguments to pass to your application - #[clap(name = "args", last = true)] - pub run_args: Vec, -} - - -/// Build and run the project -pub fn run(opts: Options) -> Result<(), anyhow::Error> { - // Build our ebpf program and the project - build(BuildOptions{ - bpf_target: opts.bpf_target, - release: opts.release, - }).context("Error while building project")?; - - // profile we are building (release or debug) - let profile = if opts.release { "release" } else { "debug" }; - let bin_path = format!("target/{profile}/syscall_ebpf"); - - // arguments to pass to the application - let mut run_args: Vec<_> = opts.run_args.iter().map(String::as_str).collect(); - - // configure args - let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); - args.push(bin_path.as_str()); - args.append(&mut run_args); - - // run the command - let status = Command::new(args.first().expect("No first argument")) - .args(args.iter().skip(1)) - .status() - .expect("failed to run the command"); - - if !status.success() { - anyhow::bail!("Failed to run `{}`", args.join(" ")); - } - Ok(()) -} diff --git a/user/dadk/config/test_ebpf_0_1_0.toml b/user/dadk/config/syscall_ebpf_0_1_0.toml similarity index 91% rename from user/dadk/config/test_ebpf_0_1_0.toml rename to user/dadk/config/syscall_ebpf_0_1_0.toml index 6937a23e8..3df5f6250 100644 --- a/user/dadk/config/test_ebpf_0_1_0.toml +++ b/user/dadk/config/syscall_ebpf_0_1_0.toml @@ -1,5 +1,5 @@ # 用户程序名称 -name = "test_ebpf" +name = "test_ebpf_new" # 版本号 version = "0.1.0" # 用户程序描述信息 @@ -21,7 +21,7 @@ type = "build-from-source" # "install_from_prebuilt" 可选值:"local", "archive" source = "local" # 路径或URL -source-path = "user/apps/test_ebpf" +source-path = "user/apps/syscall_ebpf" # 构建相关信息 [build] # (可选)构建命令