Skip to content

Commit

Permalink
Important Update: Support Modularized Uprobe
Browse files Browse the repository at this point in the history
  • Loading branch information
chenzhiy2001 committed Jul 30, 2023
1 parent 1d78f99 commit 108e81b
Show file tree
Hide file tree
Showing 33 changed files with 439 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ os/.gdb_history
os/virt.out
tools/
pushall.sh
.vscode/*.log
.vscode/*.log
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ If you don't know Rust Language and try to learn it, please visit [Rust Learnin

Official QQ group number: 735045051

## notes on ebpf version
You need to run like this: `CC=riscv64-linux-musl-gcc make run`
## news
- 23/06/2022: Version 3.6.0 is on the way! Now we directly update the code on chX branches, please periodically check if there are any updates.

Expand Down
5 changes: 5 additions & 0 deletions os/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Yifan Wu <[email protected]>"]
edition = "2021"


# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand All @@ -26,6 +27,10 @@ numeric-enum-macro = "0.2.0"
dyn-fmt = { version = "0.3.0", default-features = false }
downcast-rs = { version = "1.2", default-features = false }
ebpf2rv = { git = "https://github.com/livingshade/ebpf2rv", rev = "ecfc526" }
ruprobes = { path = "../../../ruprobes", features = ["rCore-Tutorial"] }
trap_context_riscv = { git = "https://github.com/chenzhiy2001/trap_context_riscv"}
trapframe = { git = "https://github.com/rcore-os/trapframe-rs"}
spin = "0.5"

[profile.release]
debug = true
3 changes: 3 additions & 0 deletions os/src/ebpf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ pub enum BpfObject {
Program(Arc<BpfProgram>),
}

pub use osutil::os_copy_from_user;
pub use osutil::os_copy_to_user;

impl BpfObject {
/// get the map
pub fn is_map(&self) -> Option<&SharedBpfMap> {
Expand Down
8 changes: 6 additions & 2 deletions os/src/ebpf/osutil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ pub fn os_console_write_str(s: &str) -> i64 {

/// # os_copy_from_user
/// copy `len` bytes from user space addresss `usr_addr` to `kern_buf`
pub fn os_copy_from_user(usr_addr: usize, kern_buf: *mut u8, len: usize) -> i32 {
#[inline(never)]
#[no_mangle]
pub extern "C" fn os_copy_from_user(usr_addr: usize, kern_buf: *mut u8, len: usize) -> i32 {
use crate::mm::translated_byte_buffer;
use crate::task::current_user_token;
let t = translated_byte_buffer(current_user_token(), usr_addr as *const u8, len);
Expand All @@ -93,7 +95,9 @@ pub fn os_copy_from_user(usr_addr: usize, kern_buf: *mut u8, len: usize) -> i32

/// # os_copy_to_user
/// copy `len` bytes to user space addresss `usr_addr` from `kern_buf`
pub fn os_copy_to_user(usr_addr: usize, kern_buf: *const u8, len: usize) -> i32 {
#[inline(never)]
#[no_mangle]
pub extern "C" fn os_copy_to_user(usr_addr: usize, kern_buf: *const u8, len: usize) -> i32 {
use crate::mm::translated_byte_buffer;
use crate::task::current_user_token;
let dst = translated_byte_buffer(current_user_token(), usr_addr as *const u8, len);
Expand Down
189 changes: 168 additions & 21 deletions os/src/ebpf/tracepoints.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
//! eBPF tracepoints
//!
//! attach a program to hookpoints
//!
//! currently we only support Kprobe
use alloc::{collections::BTreeMap, vec};
//!
//! currently we only support Kprobe and Uprobe_syncfunc
use crate::probe::{arch::trapframe::TrapFrame, kprobes::unregister_kprobe};
use alloc::string::{ToString, String};
use alloc::sync::Arc;
use alloc::vec::Vec;
use alloc::{collections::BTreeMap, vec};
use lazy_static::lazy_static;
use crate::probe::{arch::trapframe::TrapFrame, kprobes::unregister_kprobe};
use ruprobes::{uprobe_register, ProbePlace, ProbeType}; //todo where is unregister?
use spin::Mutex as spin_Mutex;

use lock::Mutex;
use trapframe::{TrapFrame as UprobeCrateTrapframe, UserContext,GeneralRegs};

use crate::{probe::{register_kprobe, register_kretprobe, KProbeArgs, KRetProbeArgs}};
use super::{BpfObject::*, *, retcode::BpfErrorCode::{*, self}, retcode::*};
use super::{
retcode::BpfErrorCode::{self, *},
retcode::*,
BpfObject::*,
*,
};
use crate::probe::{register_kprobe, register_kretprobe, KProbeArgs, KRetProbeArgs};

#[repr(C)]
#[derive(Clone, Copy, Debug)]
Expand All @@ -25,14 +35,20 @@ pub struct KprobeAttachAttr {

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TracepointType {
// = ProbType + ProbePlace in rCore-ebpf
KProbe,
KRetProbeEntry,
KRetProbeExit,
UProbe_Insn,
URetProbeEntry_Insn, //javascript-level long names :(
URetProbeExit_Insn,
UProbe_SyncFunc,
URetProbeEntry_SyncFunc,
URetProbeExit_SyncFunc,
}

use TracepointType::*;


#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// tracepoint abstraction, currently only for Kprobe
pub struct Tracepoint {
Expand Down Expand Up @@ -82,7 +98,29 @@ impl KProbeBPFContext {
KProbeBPFContext {
ptype: t,
paddr: probed_addr,
tf: tf.clone()
tf: tf.clone(),
}
}

pub fn as_ptr(&self) -> *const u8 {
unsafe { core::mem::transmute(self) }
}
}

#[repr(C)]
/// uProbe context are just registers, or Trapframe
struct UProbeBPFContext {
ptype: usize,//0 is syncfunc
paddr: usize,
tf: TrapFrame,
}

impl UProbeBPFContext {
pub fn new(tf: &TrapFrame, probed_addr: usize, t: usize) -> Self {
UProbeBPFContext {
ptype: t,
paddr: probed_addr,
tf: tf.clone(),
}
}

Expand All @@ -93,7 +131,7 @@ impl KProbeBPFContext {

/// the handler function that passed to register kprobe
fn kprobe_handler(tf: &mut TrapFrame, probed_addr: usize) -> isize {
let tracepoint = Tracepoint::new(KProbe, probed_addr);
let tracepoint: Tracepoint = Tracepoint::new(KProbe, probed_addr);
let ctx = KProbeBPFContext::new(tf, probed_addr, 0);
info!("run attached progs!");
run_attached_programs(&tracepoint, ctx.as_ptr());
Expand All @@ -102,6 +140,61 @@ fn kprobe_handler(tf: &mut TrapFrame, probed_addr: usize) -> isize {
0
}


fn uprobe_syncfunc_handler(tf: &mut trap_context_riscv::TrapContext, probed_addr: usize) {//tag: uprobe_handler
let tracepoint:Tracepoint=Tracepoint::new(UProbe_SyncFunc, probed_addr);
let ctx: UProbeBPFContext = UProbeBPFContext::new(&tf,probed_addr,0);
info!("run attached progs in uprobe_syncfunc_handler!");
run_attached_programs(&tracepoint, ctx.as_ptr());
info!("run attached progs in uprobe_syncfunc_handler exit!");
}


pub fn nonsense<T:Sized>(cx:&T){//cx: &mut UserContext
//println!("I'm handler! I'm useless!");
// println!{"pre_handler: spec:{:#x}", cx.sepc};
}

// /// trapframe and usercontext are basically the same,
// /// but trapframe is used in OS while usercontext is used in uprobe crate
// fn trapframe_to_usercontext (cx:&mut TrapFrame)->UserContext{
// UserContext { general:
// GeneralRegs {
// zero:cx.x[0],
// ra:cx.x[1],
// sp: cx.x[2],
// gp: cx.x[3],
// tp: cx.x[4],
// t0: cx.x[5],
// t1: cx.x[6],
// t2: cx.x[7],
// s0: cx.x[8],
// s1: cx.x[9],
// a0: cx.x[10],
// a1: cx.x[11],
// a2: cx.x[12],
// a3: cx.x[13],
// a4: cx.x[14],
// a5: cx.x[15],
// a6: cx.x[16],
// a7: cx.x[17],
// s2: cx.x[18],
// s3: cx.x[19],
// s4: cx.x[20],
// s5: cx.x[21],
// s6: cx.x[22],
// s7: cx.x[23],
// s8: cx.x[24],
// s9: cx.x[25],
// s10: cx.x[26],
// s11: cx.x[27],
// t3: cx.x[28],
// t4: cx.x[29],
// t5: cx.x[30],
// t6: cx.x[31],
// }, sstatus: cx.sstatus.bits(), sepc: cx.sepc }
// }

/// unused
fn kretprobe_entry_handler(tf: &mut TrapFrame, probed_addr: usize) -> isize {
let tracepoint = Tracepoint::new(KRetProbeEntry, probed_addr);
Expand All @@ -126,12 +219,30 @@ fn resolve_symbol(symbol: &str) -> Option<usize> {
//symbol_to_addr(symbol)
Some(crate::syscall::fs::sys_open as usize)
}

/// parse tracepoint types
fn parse_tracepoint<'a>(target: &'a str) -> Result<(TracepointType, &'a str), BpfErrorCode> {
let pos = target.find('$').ok_or(EINVAL)?;
let type_str = &target[0..pos];
let fn_name = &target[(pos + 1)..];
fn parse_tracepoint<'a>(
target: &'a str,
) -> Result<(TracepointType, String, Option<String>), BpfErrorCode> {
// in rCore-Tutorial we put name2addr outside of OS. so
// fn_name is actually just a string of address like "0x80200000"
// but in future we may consider put name2addr back to kernel, so
// we don't change fn_name variable name here.
let fn_name_not_exist_msg = "FN_NAME_NOT_EXIST_MSG".to_string();
let parts: Vec<String> = target.split("$").map(|s| s.to_string()).collect();
let how_many_parts = parts.len();
let type_str = &parts[0];
let fn_name = if how_many_parts == 2 {
&parts[1]
} else if how_many_parts == 3 {
&parts[2]
} else {
&fn_name_not_exist_msg
};
let user_program_path_not_exist_msg: String = "USER_PROGRAM_PATH_NOT_EXIST".to_string();
let user_program_path = if how_many_parts == 3 { &parts[1] } else { &user_program_path_not_exist_msg };
// let pos = target.find('$').ok_or(EINVAL)?;
// let type_str = &target[0..pos];
// let fn_name = &target[(pos + 1)..];

// determine tracepoint type
let tp_type: TracepointType;
Expand All @@ -141,16 +252,32 @@ fn parse_tracepoint<'a>(target: &'a str) -> Result<(TracepointType, &'a str), Bp
tp_type = KRetProbeEntry;
} else if type_str.eq_ignore_ascii_case("kretprobe@exit") {
tp_type = KRetProbeExit;
} else if type_str.eq_ignore_ascii_case("uprobe_insn") {
//this solution is ugly but works. maybe we can find better solutions later.
tp_type = UProbe_Insn;
} else if type_str.eq_ignore_ascii_case("uretprobe_insn@entry") {
tp_type = URetProbeEntry_Insn;
} else if type_str.eq_ignore_ascii_case("uretprobe_insn@exit") {
tp_type = URetProbeExit_Insn;
} else if type_str.eq_ignore_ascii_case("uprobe_syncfunc") {
tp_type = UProbe_SyncFunc;
} else if type_str.eq_ignore_ascii_case("uretprobe_syncfunc@entry") {
tp_type = URetProbeEntry_SyncFunc;
} else if type_str.eq_ignore_ascii_case("uretprobe_syncfunc@exit") {
tp_type = URetProbeExit_SyncFunc;
} else {
return Err(EINVAL);
}
Ok((tp_type, fn_name))
let return_ty_type = tp_type;
let return_fn_name = fn_name.clone();
let return_user_program_path = user_program_path.clone();
Ok((return_ty_type, return_fn_name, Some(return_user_program_path)))
}

/// # bpf_program_attach
/// attach a program to a hookpoint
/// # arguments
/// * target - a str the represent hookpoiint symbol
/// * target - a str that represents hookpoint symbol
/// * prog_fd - the fd of the bpf program
/// # prodecure
/// * get the bpf program object by prog_fd
Expand All @@ -163,17 +290,20 @@ pub fn bpf_program_attach(target: &str, prog_fd: u32) -> BpfResult {
// check program fd
let program = {
let objs = BPF_OBJECTS.lock();

match objs.get(&prog_fd) {
Some(bpf_obj) => {
let shared_program = bpf_obj.is_program().unwrap();
Ok(shared_program.clone())
},
}
_ => Err(ENOENT),
}
}?;
let (tp_type, fn_name) = parse_tracepoint(target)?;
let addr = resolve_symbol(fn_name).ok_or(ENOENT)?;
let (tp_type, addr_string, user_program_path) = parse_tracepoint(target)?;
//let addr = resolve_symbol(&fn_name).ok_or(ENOENT)?;
println!("addr string is {:?}", addr_string);
let addr:usize = usize::from_str_radix(&addr_string[2..], 16).unwrap();
//let addr = addr_string.parse::<usize>().unwrap();

let tracepoint = Tracepoint::new(tp_type, addr);

Expand Down Expand Up @@ -214,9 +344,26 @@ pub fn bpf_program_attach(target: &str, prog_fd: u32) -> BpfResult {
map.insert(tracepoint, vec![program]);
map.insert(dual_tp, vec![]);
}
UProbe_Insn => todo!(),
URetProbeEntry_Insn => todo!(),
URetProbeExit_Insn => todo!(),
UProbe_SyncFunc => { //tag: uprobe_handler
uprobe_register(user_program_path.unwrap().to_string(), addr, Arc::new(spin_Mutex::new(uprobe_syncfunc_handler)),None, ruprobes::ProbeType::SyncFunc);
map.insert(tracepoint, vec![program]);
}
URetProbeEntry_SyncFunc => todo!(),
URetProbeExit_SyncFunc => todo!(),
}
}
trace!("bpf prog attached! tracepoint symbol:{} addr: {:x}", fn_name, addr);
// trace!(
// "bpf prog attached! tracepoint symbol:{} addr: {:x}",
// fn_name,
// addr
// );
trace!(
"bpf prog attached! tracepoint addr: {:x}",
addr
);
Ok(0)
}

Expand Down
3 changes: 3 additions & 0 deletions os/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![feature(alloc_error_handler)]
#![feature(map_first_last)]

use crate::console::print;
//use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE, INPUT_CONDVAR};
use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE};

Expand All @@ -13,6 +14,8 @@ extern crate bitflags;
extern crate log;
#[macro_use]
extern crate alloc;
#[macro_use]
extern crate ruprobes;

#[path = "boards/qemu.rs"]
mod board;
Expand Down
Loading

0 comments on commit 108e81b

Please sign in to comment.