Skip to content

Commit

Permalink
add windows crash_dump support & sys split (#713)
Browse files Browse the repository at this point in the history
* add windows crash_dump support & sys split

* fix: replace WRITE_PIPE_FD with HIGH_PRIORIT_FD in unix get_high_writer
  • Loading branch information
kulukami authored Nov 28, 2024
1 parent 49c5a1a commit 88aa15a
Show file tree
Hide file tree
Showing 6 changed files with 273 additions and 92 deletions.
3 changes: 3 additions & 0 deletions plugins/lib/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.vscode/
dev.sh
target/
21 changes: 18 additions & 3 deletions plugins/lib/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "plugins"
version = "0.1.0"
authors = ["zhanglei.sec <[email protected]>"]
edition = "2018"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
Expand All @@ -23,9 +23,24 @@ serde_json = "1"
protobuf-codegen-pure = "2.3"

[dependencies.windows]
version = "0.48.0"
version = "0.58.0"
features = [
"Win32_System_Diagnostics_ToolHelp",
"Win32_Foundation",
"Win32_Security",
"Win32_Storage_FileSystem",
"Win32_System_Console",
"Win32_System_Services",
"Win32_System_Kernel",
"Win32_System_JobObjects",
"Win32_System_Memory",
"Win32_System_Threading",
"Win32_System_Diagnostics",
"Win32_System_Diagnostics_ToolHelp",
"Win32_System_Diagnostics_Debug_Extensions",
]


# Library dependencies (Windows)
[target.'cfg(target_os = "windows")'.dependencies]
anyhow = "1.0"
zip = "2.2"
114 changes: 25 additions & 89 deletions plugins/lib/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
pub mod bridge;
pub mod logger;

pub use bridge::*;
use crossbeam::channel::{select, tick};
use log::{debug, info};
use parking_lot::Mutex;
use protobuf::Message;
use signal_hook::consts::SIGTERM;
use std::{
env,
fs::File,
Expand All @@ -16,15 +7,17 @@ use std::{
time::Duration,
};

#[cfg(target_family = "unix")]
use signal_hook::{consts::SIGUSR1, iterator::Signals};
#[cfg(target_family = "unix")]
use std::os::unix::prelude::FromRawFd;
use crossbeam::channel::{select, tick};
use log::debug;
use parking_lot::Mutex;
use protobuf::Message;

pub mod logger;

#[cfg(target_family = "windows")]
use std::os::windows::prelude::{FromRawHandle, RawHandle};
#[cfg(target_family = "windows")]
use windows::Win32::System::Console::{GetStdHandle, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
pub mod bridge;
pub use bridge::*;

pub mod sys;

#[derive(Clone)]
pub enum EncodeType {
Expand All @@ -37,62 +30,26 @@ pub struct Client {
writer: Arc<Mutex<BufWriter<File>>>,
reader: Arc<Mutex<BufReader<File>>>,
}
#[cfg(feature = "debug")]
const READ_PIPE_FD: i32 = 0;
#[cfg(not(feature = "debug"))]
const READ_PIPE_FD: i32 = 3;
#[cfg(feature = "debug")]
const WRITE_PIPE_FD: i32 = 1;
#[cfg(not(feature = "debug"))]
const WRITE_PIPE_FD: i32 = 4;
const HIGH_PRIORIT_FD: i32 = 5;

impl Client {

pub fn can_use_high() -> bool {
match env::var("ELKEID_PLUGIN_HIGH_PRIORITY_PIPE") {
Ok(value) => {
if !value.is_empty() {
return true;
}

}
Err(_) => {
return false;
}

}
false
}
pub fn new(ignore_terminate: bool) -> Self {

let writer = Arc::new(Mutex::new(BufWriter::with_capacity(512 * 1024, unsafe {
#[cfg(target_family = "unix")]
{
File::from_raw_fd(WRITE_PIPE_FD)
}

#[cfg(target_family = "windows")]
{
let raw_handle = GetStdHandle(STD_OUTPUT_HANDLE).unwrap();
File::from_raw_handle(raw_handle.0 as _)
}
})));
let writer = sys::get_writer();
let mut high_writer = writer.clone();
if Self::can_use_high() {
high_writer = Arc::new(Mutex::new(BufWriter::with_capacity(512 * 1024, unsafe {
#[cfg(target_family = "unix")]
{
File::from_raw_fd(HIGH_PRIORIT_FD)
}

#[cfg(target_family = "windows")]
{
let raw_handle = GetStdHandle(STD_OUTPUT_HANDLE).unwrap();
File::from_raw_handle(raw_handle.0 as _)
}
})));

if Self::can_use_high() {
high_writer = sys::get_high_writer();
let high_writer_c = high_writer.clone();
thread::spawn(move || {
let ticker = tick(Duration::from_millis(200));
Expand All @@ -109,19 +66,8 @@ impl Client {
});
}

let reader = Arc::new(Mutex::new(BufReader::new(unsafe {
#[cfg(target_family = "unix")]
{
File::from_raw_fd(READ_PIPE_FD)
}
let reader = sys::get_reader();

#[cfg(target_family = "windows")]
{
let raw_handle = GetStdHandle(STD_INPUT_HANDLE).unwrap();
File::from_raw_handle(raw_handle.0 as _)
}
})));

let writer_c = writer.clone();
thread::spawn(move || {
let ticker = tick(Duration::from_millis(200));
Expand All @@ -136,26 +82,18 @@ impl Client {
}
}
});
#[cfg(target_family = "unix")]

sys::regist_exception_handler();

if ignore_terminate {
let mut signals = Signals::new(&[SIGTERM, SIGUSR1]).unwrap();
thread::spawn(move || {
for sig in signals.forever() {
if sig == SIGTERM {
info!("received signal: {:?}, wait 3 secs to exit", sig);
thread::sleep(Duration::from_secs(3));
unsafe {
if Self::can_use_high() {
libc::close(HIGH_PRIORIT_FD);
}
libc::close(WRITE_PIPE_FD);
libc::close(READ_PIPE_FD);
}
}
}
});
sys::ignore_terminate()
}

Self {
high_writer,
writer,
reader,
}
Self { high_writer, writer, reader }
}
pub fn send_record(&mut self, rec: &Record) -> Result<(), Error> {
let mut w = self.writer.lock();
Expand All @@ -176,7 +114,6 @@ impl Client {
}
}
pub fn send_record_high_priority(&mut self, rec: &Record) -> Result<(), Error> {

let mut w = self.high_writer.lock();
#[cfg(not(feature = "debug"))]
{
Expand Down Expand Up @@ -209,7 +146,6 @@ impl Client {
}
#[cfg(feature = "debug")]
{

for rec in recs.iter() {
w.write_all(b"{\"data_type\":")?;
w.write_all(rec.data_type.to_string().as_bytes())?;
Expand All @@ -220,7 +156,7 @@ impl Client {
w.write_all(b"}\n")?
}
Ok(())
}
}
}

pub fn send_records(&mut self, recs: &Vec<Record>) -> Result<(), Error> {
Expand Down
9 changes: 9 additions & 0 deletions plugins/lib/rust/src/sys/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[cfg(target_family = "windows")]
pub mod windows;
#[cfg(target_family = "windows")]
pub use windows::*;

#[cfg(target_family = "unix")]
pub mod unix;
#[cfg(target_family = "unix")]
pub use unix::*;
61 changes: 61 additions & 0 deletions plugins/lib/rust/src/sys/unix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::os::unix::prelude::FromRawFd;

#[cfg(feature = "debug")]
const READ_PIPE_FD: i32 = 0;
#[cfg(not(feature = "debug"))]
const READ_PIPE_FD: i32 = 3;
#[cfg(feature = "debug")]
const WRITE_PIPE_FD: i32 = 1;
#[cfg(not(feature = "debug"))]
const WRITE_PIPE_FD: i32 = 4;
const HIGH_PRIORIT_FD: i32 = 5;

use std::{
fs::File,
io::{BufReader, BufWriter},
sync::Arc,
};

use parking_lot::Mutex;

pub fn get_writer() -> Arc<Mutex<BufWriter<File>>> {
Arc::new(Mutex::new(BufWriter::with_capacity(512 * 1024, unsafe {
File::from_raw_fd(WRITE_PIPE_FD)
})))
}

pub fn get_high_writer() -> Arc<Mutex<BufWriter<File>>> {
Arc::new(Mutex::new(BufWriter::with_capacity(512 * 1024, unsafe {
File::from_raw_fd(HIGH_PRIORIT_FD)
})))
}

pub fn get_reader() -> Arc<Mutex<BufReader<File>>> {
Arc::new(Mutex::new(BufReader::with_capacity(512 * 1024, unsafe {
File::from_raw_fd(READ_PIPE_FD)
})))
}

extern "C" fn signal_handler(signal: i32) {
eprintln!("catched signal {:?}, wait 3 seconds and exit", signal);
unsafe {
libc::sleep(3);
libc::close(WRITE_PIPE_FD);
libc::close(READ_PIPE_FD);
if libc::fcntl(HIGH_PRIORIT_FD, libc::F_GETFD) != -1
|| std::io::Error::last_os_error().kind() != std::io::ErrorKind::InvalidInput
{
libc::close(READ_PIPE_FD);
}
}
}

pub fn ignore_terminate() {
unsafe {
libc::signal(libc::SIGINT, libc::SIG_IGN);
libc::signal(libc::SIGUSR1, libc::SIG_IGN);
libc::signal(libc::SIGTERM, signal_handler as _);
}
}

pub fn regist_exception_handler() {}
Loading

0 comments on commit 88aa15a

Please sign in to comment.