Skip to content

Commit

Permalink
implemented a way to test kernel compatibility
Browse files Browse the repository at this point in the history
Signed-off-by: Quentin JEROME <qjerome@users.noreply.github.com>
  • Loading branch information
qjerome committed Sep 28, 2023
1 parent ed8b6d3 commit d7d5004
Show file tree
Hide file tree
Showing 11 changed files with 398 additions and 146 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ private
**/*.rs.bk
target/
.vim
cache
6 changes: 5 additions & 1 deletion kunai/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ clap = { version = "4.3.4", features = ["derive"] }

[[bin]]
name = "kunai"
path = "src/main.rs"
path = "src/bin/main.rs"

[[bin]]
name = "tests"
path = "src/tests/kernel.rs"
138 changes: 13 additions & 125 deletions kunai/src/main.rs → kunai/src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
mod cache;
mod compat;
/*mod cache;
mod config;
mod info;
mod util;
mod util;*/

use aya::maps::MapData;
use bytes::BytesMut;
use clap::Parser;
use env_logger::Builder;
use info::{AdditionalFields, StdEventInfo};
use json::{object, JsonValue};
use kunai::info::{AdditionalFields, CorrInfo, ProcFsInfo, ProcFsTaskInfo, StdEventInfo};
use kunai::{cache, configure_probes, util};
use kunai_common::cgroup::Cgroup;
use kunai_common::config::{BpfConfig, Filter};

Expand All @@ -24,9 +24,9 @@ use std::path::PathBuf;
use std::sync::mpsc::{channel, Receiver, SendError, Sender};
use std::sync::Arc;

use kunai::util::*;
use std::thread;
use users::get_current_uid;
use util::*;

use aya::{
include_bytes_aligned,
Expand All @@ -41,20 +41,18 @@ use aya_log::BpfLogger;
use kunai_common::{
events::{self, EncodedEvent, Event, *},
inspect_err,
uuid::TaskUuid,
};

use log::{debug, error, info, warn};

//use tokio::sync::{Barrier, Mutex};
use tokio::sync::{Barrier, Mutex};
use tokio::{signal, task, time};

use cache::*;
use kunai::cache::*;

use crate::compat::{KernelVersion, Programs};
use crate::config::Config;
use crate::util::namespaces::unshare;
use kunai::compat::{KernelVersion, Programs};
use kunai::config::Config;
use kunai::util::namespaces::unshare;

const PAGE_SIZE: usize = 4096;

Expand All @@ -64,74 +62,6 @@ macro_rules! format_ptr {
};
}

#[derive(Debug, Clone, Copy)]
struct ProcFsTaskInfo {
pid: i32,
uuid: TaskUuid,
}

impl ProcFsTaskInfo {
fn new(start_time_clk_tck: u64, random: u32, pid: i32) -> Self {
// starttime in procfs is measured in tick count so we need to convert it
let clk_tck = get_clk_tck() as u64;

Self {
pid,
uuid: TaskUuid::new(
// convert time to the same scale as starttime in task_struct
start_time_clk_tck * 1_000_000_000 / clk_tck,
random,
pid as u32,
),
}
}
}

#[derive(Debug, Clone, Copy)]
struct ProcFsInfo {
task: ProcFsTaskInfo,
parent: Option<ProcFsTaskInfo>,
}

#[derive(Debug, Clone)]
enum CorrInfo {
ProcFs(ProcFsInfo),
Event(StdEventInfo),
}

impl CorrInfo {
fn corr_key(tuuid: TaskUuid) -> u128 {
// in task_struct start_time has a higher resolution so we need to scale it
// down in order to have a comparable value with the procfs one
let start_time_sec = tuuid.start_time_ns / 1_000_000_000;
TaskUuid::new(start_time_sec, tuuid.random, tuuid.pid).into()
}

#[inline]
fn pid(&self) -> i32 {
match self {
Self::ProcFs(pi) => pi.task.pid,
Self::Event(si) => si.info.process.tgid,
}
}

#[inline]
fn correlation_key(&self) -> u128 {
match self {
Self::ProcFs(pi) => Self::corr_key(pi.task.uuid),
Self::Event(si) => Self::corr_key(si.info.process.tg_uuid),
}
}

#[inline]
fn parent_correlation_key(&self) -> Option<u128> {
match self {
Self::ProcFs(pi) => Some(Self::corr_key(pi.parent?.uuid)),
Self::Event(si) => Some(Self::corr_key(si.info.parent.tg_uuid)),
}
}
}

#[derive(Debug, Clone)]
struct CorrelationData {
image: PathBuf,
Expand Down Expand Up @@ -266,10 +196,7 @@ impl EventProcessor {
));
}

let ci = CorrInfo::ProcFs(ProcFsInfo {
task: pi,
parent: ppi,
});
let ci = CorrInfo::from(ProcFsInfo::new(pi, ppi));

let ck = ci.correlation_key();

Expand Down Expand Up @@ -1378,15 +1305,15 @@ async fn main() -> Result<(), anyhow::Error> {
BpfLoader::new()
.verifier_log_level(verifier_level)
.load(include_bytes_aligned!(
"../../target/bpfel-unknown-none/debug/kunai-ebpf"
"../../../target/bpfel-unknown-none/debug/kunai-ebpf"
))?;

#[cfg(not(debug_assertions))]
let mut bpf =
BpfLoader::new()
.verifier_log_level(verifier_level)
.load(include_bytes_aligned!(
"../../target/bpfel-unknown-none/release/kunai-ebpf"
"../../../target/bpfel-unknown-none/release/kunai-ebpf"
))?;

if let Err(e) = BpfLogger::init(&mut bpf) {
Expand Down Expand Up @@ -1418,46 +1345,7 @@ async fn main() -> Result<(), anyhow::Error> {

let mut programs = Programs::from_bpf(&mut bpf);

programs.expect_mut("execve.security_bprm_check").prio = 0;

programs.expect_mut("execve.exit.bprm_execve").prio = 20;
programs
.expect_mut("execve.exit.bprm_execve")
.min_kernel(kernel!(5, 9));

programs.expect_mut("syscalls.sys_exit_execve").prio = 20;
programs
.expect_mut("syscalls.sys_exit_execve")
.max_kernel(kernel!(5, 9));

programs
.expect_mut("syscalls.sys_exit_execveat")
.max_kernel(kernel!(5, 9));

// bpf probes
programs.expect_mut("entry.security_bpf_prog").prio = 90;
programs.expect_mut("exit.bpf_prog_load").prio = 100;

// fd_install
programs.expect_mut("fd.fd_install").prio = 0;
programs.expect_mut("fd.entry.__fdget").prio = 0;
programs.expect_mut("fd.exit.__fdget").prio = 10;

// kernel function name changed above 5.9
if current_kernel < kernel!(5, 9) {
// kernel_clone -> _do_fork
programs
.expect_mut("kprobe.enter.kernel_clone")
.rename("kprobe.enter._do_fork");

// path_mount -> do_mount
programs
.expect_mut("fs.exit.path_mount")
.rename("fs.exit.do_mount")
}

// mmap probe
programs.expect_mut("syscalls.sys_enter_mmap").prio = 90;
configure_probes(&mut programs, current_kernel);

// generic program loader
for (_, mut p) in programs.into_vec_sorted_by_prio() {
Expand Down
6 changes: 6 additions & 0 deletions kunai/src/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ impl<'a> Program<'a> {
self.name = new.as_ref().to_string();
}

pub fn rename_if<T: AsRef<str>>(&mut self, cond: bool, new: T) {
if cond {
self.rename(new)
}
}

pub fn enable(&mut self) {
self.enable = true
}
Expand Down
10 changes: 5 additions & 5 deletions kunai/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ pub struct Event {
}

impl Event {
pub(crate) fn name(&self) -> &str {
pub fn name(&self) -> &str {
&self.name
}

pub(crate) fn disable(&mut self) {
pub fn disable(&mut self) {
self.enable = false
}

pub(crate) fn enable(&mut self) {
pub fn enable(&mut self) {
self.enable = true
}
}
Expand Down Expand Up @@ -87,11 +87,11 @@ impl Config {
Ok(())
}

pub(crate) fn enable_all(&mut self) {
pub fn enable_all(&mut self) {
self.events.iter_mut().for_each(|e| e.enable())
}

pub(crate) fn disable_all(&mut self) {
pub fn disable_all(&mut self) {
self.events.iter_mut().for_each(|e| e.disable())
}
}
Expand Down
87 changes: 85 additions & 2 deletions kunai/src/info.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,91 @@
use chrono::{DateTime, SecondsFormat, Utc};
use json::{object, JsonValue};
use kunai_common::events::{self, EventInfo};
use kunai_common::{
events::{self, EventInfo},
uuid::TaskUuid,
};

use crate::CorrInfo;
use crate::util::get_clk_tck;

#[derive(Debug, Clone, Copy)]
pub struct ProcFsTaskInfo {
pid: i32,
uuid: TaskUuid,
}

impl ProcFsTaskInfo {
pub fn new(start_time_clk_tck: u64, random: u32, pid: i32) -> Self {
// starttime in procfs is measured in tick count so we need to convert it
let clk_tck = get_clk_tck() as u64;

Self {
pid,
uuid: TaskUuid::new(
// convert time to the same scale as starttime in task_struct
start_time_clk_tck * 1_000_000_000 / clk_tck,
random,
pid as u32,
),
}
}
}

#[derive(Debug, Clone, Copy)]
pub struct ProcFsInfo {
task: ProcFsTaskInfo,
parent: Option<ProcFsTaskInfo>,
}

impl ProcFsInfo {
pub fn new(task: ProcFsTaskInfo, parent: Option<ProcFsTaskInfo>) -> Self {
ProcFsInfo { task, parent }
}
}

#[derive(Debug, Clone)]
pub enum CorrInfo {
ProcFs(ProcFsInfo),
Event(StdEventInfo),
}

impl From<ProcFsInfo> for CorrInfo {
fn from(value: ProcFsInfo) -> Self {
Self::ProcFs(value)
}
}

impl CorrInfo {
fn corr_key(tuuid: TaskUuid) -> u128 {
// in task_struct start_time has a higher resolution so we need to scale it
// down in order to have a comparable value with the procfs one
let start_time_sec = tuuid.start_time_ns / 1_000_000_000;
TaskUuid::new(start_time_sec, tuuid.random, tuuid.pid).into()
}

#[inline]
pub fn pid(&self) -> i32 {
match self {
Self::ProcFs(pi) => pi.task.pid,
Self::Event(si) => si.info.process.tgid,
}
}

#[inline]
pub fn correlation_key(&self) -> u128 {
match self {
Self::ProcFs(pi) => Self::corr_key(pi.task.uuid),
Self::Event(si) => Self::corr_key(si.info.process.tg_uuid),
}
}

#[inline]
pub fn parent_correlation_key(&self) -> Option<u128> {
match self {
Self::ProcFs(pi) => Some(Self::corr_key(pi.parent?.uuid)),
Self::Event(si) => Some(Self::corr_key(si.info.parent.tg_uuid)),
}
}
}

#[derive(Default, Debug, Clone)]
pub struct AdditionalFields {
Expand Down
Loading

0 comments on commit d7d5004

Please sign in to comment.