mirror of
https://github.com/ParrotXray/Mantis.git
synced 2026-08-24 19:00:27 +09:00
Compare commits
2 Commits
77c427c298
...
71eb4f2429
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71eb4f2429 | ||
|
|
ed31e34925 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -21,3 +21,5 @@ node_modules/
|
||||
*.db
|
||||
lib/ebpf/mantis-ingress
|
||||
lib/ebpf/mantis-egress
|
||||
lib/ebpf/mantis-process
|
||||
.claude/worktrees/
|
||||
|
||||
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2172,6 +2172,16 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "process-ebpf"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aya-ebpf",
|
||||
"aya-log-ebpf",
|
||||
"common",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.11.9"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["mantis", "common", "macros", "ingress-ebpf", "egress-ebpf"]
|
||||
members = ["mantis", "common", "macros", "ingress-ebpf", "egress-ebpf", "process-ebpf"]
|
||||
default-members = ["mantis", "common"]
|
||||
|
||||
[workspace.dependencies]
|
||||
@ -36,3 +36,7 @@ codegen-units = 1
|
||||
[profile.release.package.egress-ebpf]
|
||||
debug = 2
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release.package.process-ebpf]
|
||||
debug = 2
|
||||
codegen-units = 1
|
||||
|
||||
@ -4,4 +4,5 @@ pub mod http_method;
|
||||
pub mod ip_address;
|
||||
pub mod packet;
|
||||
pub mod placeholder;
|
||||
pub mod process_event;
|
||||
pub mod pseudo_header;
|
||||
|
||||
15
common/src/model/process_event.rs
Normal file
15
common/src/model/process_event.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#[cfg(feature = "user")]
|
||||
use serde::Serialize;
|
||||
|
||||
pub const PROCESS_EVENT_EXEC: u32 = 0;
|
||||
pub const PROCESS_EVENT_EXIT: u32 = 1;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "user", derive(Serialize))]
|
||||
pub struct ProcessEvent {
|
||||
pub event_type: u32,
|
||||
pub pid: u32,
|
||||
pub uid: u32,
|
||||
pub comm: [u8; 16],
|
||||
}
|
||||
@ -13,7 +13,7 @@ compact_str = { workspace = true }
|
||||
axum = { version = "0.8", features = ["ws", "macros"] }
|
||||
tower = { version = "0.5", features = ["util"] }
|
||||
tower-http = { version = "0.6", features = ["cors"] }
|
||||
aya = { workspace = true }
|
||||
aya = { workspace = true, features = ["async_tokio"] }
|
||||
aya-log = { workspace = true }
|
||||
network-types = { workspace = true }
|
||||
crossbeam = "0.8.4"
|
||||
|
||||
110
mantis/build.rs
110
mantis/build.rs
@ -20,6 +20,7 @@ fn main() {
|
||||
let onnxruntime_dir = lib_dir.join("onnxruntime").join("libonnxruntime.so");
|
||||
let ingress_edpf_dir = lib_dir.join("ebpf").join("mantis-ingress");
|
||||
let egress_edpf_dir = lib_dir.join("ebpf").join("mantis-egress");
|
||||
let process_ebpf_dir = lib_dir.join("ebpf").join("mantis-process");
|
||||
|
||||
let static_web = manifest_dir.join("static").join("web");
|
||||
let project_name = manifest_dir.file_name().unwrap().to_string_lossy().into_owned();
|
||||
@ -33,6 +34,7 @@ fn main() {
|
||||
println!("cargo:rustc-env=ONNXRUNTIME_PATH={}", onnxruntime_dir.display());
|
||||
println!("cargo:rustc-env=INGRESS_PATH={}", ingress_edpf_dir.display());
|
||||
println!("cargo:rustc-env=EGRESS_PATH={}", egress_edpf_dir.display());
|
||||
println!("cargo:rustc-env=PROCESS_PATH={}", process_ebpf_dir.display());
|
||||
println!("cargo:rustc-env=RULE_PATH={}", rule_dir.display());
|
||||
println!("cargo:rustc-env=DB_PATH={}", db_dir.display());
|
||||
println!("cargo:rustc-env=RULE_EVE_PATH={}", suricata_eve_socket.display());
|
||||
@ -42,6 +44,7 @@ fn main() {
|
||||
// git clean, fresh clone, or manual deletion.
|
||||
println!("cargo:rerun-if-changed={}", ingress_edpf_dir.display());
|
||||
println!("cargo:rerun-if-changed={}", egress_edpf_dir.display());
|
||||
println!("cargo:rerun-if-changed={}", process_ebpf_dir.display());
|
||||
|
||||
for item in &[
|
||||
"src",
|
||||
@ -57,7 +60,7 @@ fn main() {
|
||||
}
|
||||
|
||||
if env::var_os("SKIP_EBPF_BUILD").is_some() {
|
||||
for path in &[&ingress_edpf_dir, &egress_edpf_dir] {
|
||||
for path in &[&ingress_edpf_dir, &egress_edpf_dir, &process_ebpf_dir] {
|
||||
if !path.exists() {
|
||||
fs::write(path, []).unwrap_or_else(|e| panic!("cannot write stub {path:?}: {e}"));
|
||||
}
|
||||
@ -66,6 +69,7 @@ fn main() {
|
||||
}
|
||||
build_ingress_ebpf(&ingress_edpf_dir);
|
||||
build_egress_ebpf(&egress_edpf_dir);
|
||||
build_process_ebpf(&process_ebpf_dir);
|
||||
build_frontend(&frontend_dir, &static_web);
|
||||
}
|
||||
|
||||
@ -278,6 +282,110 @@ fn build_egress_ebpf(dst: &PathBuf) {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_process_ebpf(dst: &PathBuf) {
|
||||
let Metadata { packages, .. } = MetadataCommand::new().no_deps().exec().unwrap();
|
||||
let ebpf_package = packages
|
||||
.into_iter()
|
||||
.find(|Package { name, .. }| **name == "process-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)
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
for key in ["RUSTUP_TOOLCHAIN", "RUSTC", "RUSTC_WORKSPACE_WRAPPER"] {
|
||||
cmd.env_remove(key);
|
||||
}
|
||||
cmd.current_dir(ebpf_dir);
|
||||
|
||||
let ebpf_target_dir = out_dir.join("../process-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;
|
||||
|
||||
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!("{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!("{line}");
|
||||
}
|
||||
}
|
||||
Message::TextLine(line) => {
|
||||
println!("{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 _: u64 = fs::copy(&binary, dst).unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}"));
|
||||
}
|
||||
}
|
||||
|
||||
fn build_frontend(frontend_dir: &PathBuf, static_dir: &PathBuf) {
|
||||
if !frontend_dir.exists() {
|
||||
panic!("Frontend directory {:?} does not exist", frontend_dir);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
pub mod access_control;
|
||||
pub mod process_tracker;
|
||||
pub mod statistics;
|
||||
pub mod xsk_manager;
|
||||
|
||||
@ -10,6 +11,7 @@ use macros::log;
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
use crate::core::ebpf::access_control::AccessControl;
|
||||
use crate::core::ebpf::process_tracker::ProcessTracker;
|
||||
use crate::core::ebpf::statistics::Statistics;
|
||||
use crate::core::ebpf::xsk_manager::XskManager;
|
||||
use crate::core::infrastructure::app_config::AppConfig;
|
||||
@ -22,18 +24,26 @@ pub struct EbpfServices {
|
||||
pub xsk_manager: Arc<XskManager>,
|
||||
pub access_control: Arc<AccessControl>,
|
||||
pub statistics: Arc<Statistics>,
|
||||
pub process_tracker: Arc<ProcessTracker>,
|
||||
pub shutdowns: SegQueue<oneshot::Sender<()>>,
|
||||
}
|
||||
|
||||
impl EbpfServices {
|
||||
pub fn new(app_config: Arc<AppConfig>, ingress_ebpf: &mut Ebpf, egress_ebpf: &mut Ebpf) -> Result<Self, Error> {
|
||||
pub fn new(
|
||||
app_config: Arc<AppConfig>,
|
||||
ingress_ebpf: &mut Ebpf,
|
||||
egress_ebpf: &mut Ebpf,
|
||||
process_ebpf: &mut Ebpf,
|
||||
) -> Result<Self, Error> {
|
||||
let xsk_manager = XskManager::new(app_config.clone(), ingress_ebpf, egress_ebpf)?;
|
||||
let access_control = AccessControl::new(ingress_ebpf, egress_ebpf)?;
|
||||
let statistics = Statistics::new(app_config.clone(), ingress_ebpf, egress_ebpf)?;
|
||||
let process_tracker = ProcessTracker::new(process_ebpf)?;
|
||||
let ebpf_services = Self {
|
||||
xsk_manager: Arc::new(xsk_manager),
|
||||
access_control: Arc::new(access_control),
|
||||
statistics: Arc::new(statistics),
|
||||
process_tracker: Arc::new(process_tracker),
|
||||
shutdowns: SegQueue::new(),
|
||||
};
|
||||
Ok(ebpf_services)
|
||||
|
||||
99
mantis/src/core/ebpf/process_tracker.rs
Normal file
99
mantis/src/core/ebpf/process_tracker.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use aya::maps::perf::AsyncPerfEventArray;
|
||||
use aya::maps::MapData;
|
||||
use aya::util::online_cpus;
|
||||
use aya::Ebpf;
|
||||
use bytes::BytesMut;
|
||||
use common::model::process_event::{ProcessEvent, PROCESS_EVENT_EXEC, PROCESS_EVENT_EXIT};
|
||||
use macros::log;
|
||||
use std::sync::Mutex;
|
||||
use tokio::task;
|
||||
|
||||
use crate::model::error::ebpf::EbpfError;
|
||||
use crate::model::error::Error;
|
||||
use crate::model::log::ebpf::EbpfLog;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ProcessInfo {
|
||||
pub comm: String,
|
||||
pub uid: u32,
|
||||
}
|
||||
|
||||
pub struct ProcessTracker {
|
||||
pub table: Arc<Mutex<HashMap<u32, ProcessInfo>>>,
|
||||
}
|
||||
|
||||
impl ProcessTracker {
|
||||
pub fn new(process_ebpf: &mut Ebpf) -> Result<Self, Error> {
|
||||
let map = process_ebpf.take_map("PROCESS_EVENTS").ok_or(EbpfError::MapNotFound)?;
|
||||
let perf_array: AsyncPerfEventArray<MapData> =
|
||||
AsyncPerfEventArray::try_from(map).map_err(EbpfError::MapOperationError)?;
|
||||
|
||||
let table: Arc<Mutex<HashMap<u32, ProcessInfo>>> = Arc::new(Mutex::new(HashMap::new()));
|
||||
let table_clone = table.clone();
|
||||
|
||||
task::spawn(async move {
|
||||
if let Err(e) = run_perf_reader(perf_array, table_clone).await {
|
||||
log!(EbpfLog::ProcessTrackerError { error: format!("{e:?}") });
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self { table })
|
||||
}
|
||||
|
||||
pub fn lookup(&self, pid: u32) -> Option<ProcessInfo> {
|
||||
self.table.lock().ok()?.get(&pid).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_perf_reader(
|
||||
mut perf_array: AsyncPerfEventArray<MapData>,
|
||||
table: Arc<Mutex<HashMap<u32, ProcessInfo>>>,
|
||||
) -> Result<(), EbpfError> {
|
||||
let cpus = online_cpus().map_err(|_| EbpfError::UnknownError)?;
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
for cpu_id in cpus {
|
||||
let mut buf = perf_array.open(cpu_id, None).map_err(EbpfError::MapOperationError)?;
|
||||
let table = table.clone();
|
||||
|
||||
tasks.push(task::spawn(async move {
|
||||
let mut buffers: Vec<BytesMut> = (0..10).map(|_| BytesMut::with_capacity(256)).collect();
|
||||
loop {
|
||||
let events = match buf.read_events(&mut buffers).await {
|
||||
Ok(e) => e,
|
||||
Err(_) => break,
|
||||
};
|
||||
for buf in buffers.iter().take(events.read) {
|
||||
if buf.len() < core::mem::size_of::<ProcessEvent>() {
|
||||
continue;
|
||||
}
|
||||
let event = unsafe { &*(buf.as_ptr() as *const ProcessEvent) };
|
||||
let comm = String::from_utf8_lossy(
|
||||
event.comm.iter().take_while(|&&b| b != 0).cloned().collect::<Vec<_>>().as_slice(),
|
||||
)
|
||||
.into_owned();
|
||||
|
||||
if let Ok(mut t) = table.lock() {
|
||||
match event.event_type {
|
||||
PROCESS_EVENT_EXEC => {
|
||||
t.insert(event.pid, ProcessInfo { comm, uid: event.uid });
|
||||
}
|
||||
PROCESS_EVENT_EXIT => {
|
||||
t.remove(&event.pid);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for t in tasks {
|
||||
let _ = t.await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use axum::Router;
|
||||
use aya::Ebpf;
|
||||
use aya::maps::{MapData, ProgramArray};
|
||||
use aya::programs::{Xdp, XdpFlags};
|
||||
use aya::programs::{TracePoint, Xdp, XdpFlags};
|
||||
use aya_log::EbpfLogger;
|
||||
use common::define::program_array::*;
|
||||
use macros::log;
|
||||
@ -33,6 +33,7 @@ pub struct System {
|
||||
pub app_services: Arc<AppServices>,
|
||||
pub ingress_ebpf: Ebpf,
|
||||
pub egress_ebpf: Ebpf,
|
||||
pub process_ebpf: Ebpf,
|
||||
#[allow(dead_code)]
|
||||
ingress_program_array: ProgramArray<MapData>,
|
||||
#[allow(dead_code)]
|
||||
@ -48,6 +49,7 @@ impl System {
|
||||
|
||||
let (mut ingress_ebpf, ingress_program_array) = System::get_ingress_ebpf()?;
|
||||
let (mut egress_ebpf, egress_program_array) = System::get_egress_ebpf()?;
|
||||
let mut process_ebpf = System::get_process_ebpf()?;
|
||||
let app_config = Arc::new(AppConfig::new()?);
|
||||
|
||||
let inference_config = Arc::new(InferenceConfig::load_file(
|
||||
@ -59,6 +61,7 @@ impl System {
|
||||
app_config.clone(),
|
||||
&mut ingress_ebpf,
|
||||
&mut egress_ebpf,
|
||||
&mut process_ebpf,
|
||||
)?);
|
||||
|
||||
let app_services = Arc::new(AppServices::new(
|
||||
@ -74,6 +77,7 @@ impl System {
|
||||
app_services,
|
||||
ingress_ebpf,
|
||||
egress_ebpf,
|
||||
process_ebpf,
|
||||
ingress_program_array,
|
||||
egress_program_array,
|
||||
};
|
||||
@ -94,6 +98,7 @@ impl System {
|
||||
|
||||
self.aya_log_init()?;
|
||||
self.attach_ebpf()?;
|
||||
self.attach_process_ebpf()?;
|
||||
|
||||
ebpf_services
|
||||
.run(app_services.ml_engine.clone(), app_services.suricata_engine.clone())
|
||||
@ -120,6 +125,7 @@ impl System {
|
||||
fn aya_log_init(&mut self) -> Result<(), Error> {
|
||||
EbpfLogger::init(&mut self.ingress_ebpf).map_err(EbpfError::LoggerInitFailed)?;
|
||||
EbpfLogger::init(&mut self.egress_ebpf).map_err(EbpfError::LoggerInitFailed)?;
|
||||
EbpfLogger::init(&mut self.process_ebpf).map_err(EbpfError::LoggerInitFailed)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -191,6 +197,25 @@ impl System {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_process_ebpf() -> Result<Ebpf, Error> {
|
||||
let ebpf = Ebpf::load(aya::include_bytes_aligned!(env!("PROCESS_PATH"))).map_err(EbpfError::EbpfNotFound)?;
|
||||
Ok(ebpf)
|
||||
}
|
||||
|
||||
fn attach_process_ebpf(&mut self) -> Result<(), Error> {
|
||||
for name in &["sched_process_exec", "sched_process_exit"] {
|
||||
let program: &mut TracePoint = self
|
||||
.process_ebpf
|
||||
.program_mut(name)
|
||||
.ok_or(EbpfError::ProgramNotFound)?
|
||||
.try_into()
|
||||
.map_err(EbpfError::GetProgramFailed)?;
|
||||
program.load().map_err(EbpfError::LoadProgramFailed)?;
|
||||
program.attach("sched", name).map_err(EbpfError::AttachProgramFailed)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_ingress_ebpf() -> Result<(Ebpf, ProgramArray<MapData>), Error> {
|
||||
let mut ingress_ebpf =
|
||||
Ebpf::load(aya::include_bytes_aligned!(env!("INGRESS_PATH"))).map_err(EbpfError::EbpfNotFound)?;
|
||||
|
||||
@ -59,5 +59,8 @@ loggable! {
|
||||
|
||||
#[error("SO_PREFER_BUSY_POLL not supported on this kernel/driver (queue {queue_id}, errno {errno})")]
|
||||
BusyPollUnavailable { queue_id: u32, errno: i32 } => tracing::Level::WARN,
|
||||
|
||||
#[error("Process tracker error: {error}")]
|
||||
ProcessTrackerError { error: String } => tracing::Level::ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
19
process-ebpf/Cargo.toml
Normal file
19
process-ebpf/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "process-ebpf"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../common", features = ["kernel"] }
|
||||
aya-ebpf = { workspace = true }
|
||||
aya-log-ebpf = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
which = "8.0.0"
|
||||
|
||||
[[bin]]
|
||||
name = "mantis-process"
|
||||
path = "src/main.rs"
|
||||
test = false
|
||||
doctest = false
|
||||
bench = false
|
||||
6
process-ebpf/build.rs
Normal file
6
process-ebpf/build.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use which::which;
|
||||
|
||||
fn main() {
|
||||
let bpf_linker = which("bpf-linker").unwrap();
|
||||
println!("cargo:rerun-if-changed={}", bpf_linker.to_str().unwrap());
|
||||
}
|
||||
43
process-ebpf/src/main.rs
Normal file
43
process-ebpf/src/main.rs
Normal file
@ -0,0 +1,43 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aya_ebpf::helpers::{bpf_get_current_comm, bpf_get_current_pid_tgid, bpf_get_current_uid_gid};
|
||||
use aya_ebpf::macros::{map, tracepoint};
|
||||
use aya_ebpf::maps::PerfEventArray;
|
||||
use aya_ebpf::programs::TracePointContext;
|
||||
use common::model::process_event::{ProcessEvent, PROCESS_EVENT_EXEC, PROCESS_EVENT_EXIT};
|
||||
|
||||
#[map]
|
||||
static PROCESS_EVENTS: PerfEventArray<ProcessEvent> = PerfEventArray::new(0);
|
||||
|
||||
#[tracepoint]
|
||||
pub fn sched_process_exec(ctx: TracePointContext) -> u32 {
|
||||
emit_event(&ctx, PROCESS_EVENT_EXEC)
|
||||
}
|
||||
|
||||
#[tracepoint]
|
||||
pub fn sched_process_exit(ctx: TracePointContext) -> u32 {
|
||||
emit_event(&ctx, PROCESS_EVENT_EXIT)
|
||||
}
|
||||
|
||||
fn emit_event(ctx: &TracePointContext, event_type: u32) -> u32 {
|
||||
let pid_tgid = unsafe { bpf_get_current_pid_tgid() };
|
||||
let uid_gid = unsafe { bpf_get_current_uid_gid() };
|
||||
let mut comm = [0u8; 16];
|
||||
let _ = unsafe { bpf_get_current_comm(&mut comm) };
|
||||
|
||||
let event = ProcessEvent {
|
||||
event_type,
|
||||
pid: (pid_tgid >> 32) as u32,
|
||||
uid: uid_gid as u32,
|
||||
comm,
|
||||
};
|
||||
unsafe { PROCESS_EVENTS.output(ctx, &event, 0) };
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
unsafe { core::hint::unreachable_unchecked() }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user