Rust如何开发eBPF应用?(一)

博客 分享
0 209
张三
张三 2022-04-17 11:58:05
悬赏:0 积分 收藏

Rust如何开发eBPF应用?(一)

前言

eBPF是一项革命性的技术,可以在Linux内核中运行沙盒程序,而无需重新编译内核或加载内核模块。它能够在许多内核 hook 点安全地执行字节码,主要应用在云原生网络、安全、跟踪监控等方面。

eBPF 基金会 (https://ebpf.io) 是一个为 eBPF 技术而创建的非盈利性组织,隶属于 Linux 基金会,其意在推动 eBPF 更好地发展,使其得到更加广泛的运用。

下面我将介绍如何在Rust中开发基于eBPF技术的应用示例。(该示例教程主要面向具备Rust开发基础的同学)

 

(一)环境准备

一台VM或Linux系统主机

推荐系统:Ubuntu20.04

内存:4G以上

Rust开发工具链:v1.56~

 

(二)安装llvm13(编译bpf字节码需要)

apt-get update apt-get -y install wget build-essential software-properties-common lsb-release libelf-dev linux-headers-generic pkg-configwget https://apt.llvm.org/llvm.shchmod +x llvm.sh./llvm.sh 13rm -f ./llvm.sh
//检验是否安装成功,输出版本号表示安装成功llvm-config-13 --version | grep 13

 

(三)安装 cargo-bpf脚手架

cargo install cargo-bpf --no-default-features --features=llvm13

 

(四)应用示例

#1、创建用户空间代码目录cargo new bpfdemocd bpfdemo#2、创建bpf代码目录cargo bpf new probesls>>Cargo.lock  Cargo.toml  probes  src#3、编写一个openmonitor bpf程序 输出系统打开的文件cd probescargo bpf add openmonitorcd src ls>>lib.rs  openmonitorcd openmonitornano main.rs

完整openmonitor/main.rs代码如下:

#![no_std]#![no_main]use probes::openmonitor::*;use redbpf_probes::kprobe::prelude::*;program!(0xFFFFFFFE, "GPL");#[map]static mut OPEN_PATHS: PerfMap<OpenPath> = PerfMap::with_max_entries(1024);#[kprobe]fn do_sys_open(regs: Registers) {    let mut path = OpenPath::default();    unsafe {        let filename = regs.parm2() as *const u8;        if bpf_probe_read_user_str(            path.filename.as_mut_ptr() as *mut _,            path.filename.len() as u32,            filename as *const _,        ) <= 0        {            bpf_trace_printk(b"error on bpf_probe_read_user_str\0");            return;        }        OPEN_PATHS.insert(regs.ctx, &path);    }}

完整openmonitor/mod.rs代码如下

pub const PATHLEN: usize = 256;#[repr(C)]#[derive(Debug, Clone)]pub struct OpenPath {    pub filename: [u8; PATHLEN],}impl Default for OpenPath {    fn default() -> OpenPath {        OpenPath {            filename: [0; PATHLEN],        }    }}
#4.在probes目录下编译bpf程序,生成openmonitor.elf文件cargo bpf build --target-dir=../targetls ../target/bpf/programs/openmonitor/openmonitor.elf#5.在用户空间代码中使用bpf程序,获取系统打开文件cd ../srcnano main.rs

完整bpfdemo/src/main.rs代码如下

use futures::stream::StreamExt;use std::{ffi::CStr, ptr};use tracing::Level;use tracing_subscriber::FmtSubscriber;use redbpf::load::Loader;use probes::openmonitor::OpenPath;fn probe_code() -> &'static [u8] {    include_bytes!(concat!(        env!("CARGO_MANIFEST_DIR"),        "/target/bpf/programs/openmonitor/openmonitor.elf"    ))}#[tokio::main(flavor = "current_thread")]async fn main() {    let subscriber = FmtSubscriber::builder()        .with_max_level(Level::WARN)        .finish();    tracing::subscriber::set_global_default(subscriber).unwrap();    let mut loaded = Loader::load(probe_code()).expect("error on Loader::load");    let probe = loaded        .kprobe_mut("do_sys_open")        .expect("error on Loaded::kprobe_mut");    probe        .attach_kprobe("do_sys_open", 0)        .expect("error on KProbe::attach_kprobe");    probe        .attach_kprobe("do_sys_openat2", 0)        .expect("error on KProbe::attach_kprobe");    while let Some((map_name, events)) = loaded.events.next().await {        if map_name == "OPEN_PATHS" {            for event in events {                let open_path = unsafe { ptr::read(event.as_ptr() as *const OpenPath) };                unsafe {                    let cfilename = CStr::from_ptr(open_path.filename.as_ptr() as *const _);                    println!("{}", cfilename.to_string_lossy());                };            }        }    }}
#6.在bpfdemo目录下编译运行cargo buildcargo run#将会输出系统实时打开的文件>>/proc/driver/nvidia/params/dev/nvidia0/proc/driver/nvidia/params/dev/nvidia0/proc/driver/nvidia/params/dev/nvidia0/etc/localtime/lib/x86_64-linux-gnu/libcuda.so.1/lib/x86_64-linux-gnu/libm.so.6/etc/netconfig/sys/fs/cgroup/unified/system.slice/systemd-udevd.service/cgroup.procs/sys/fs/cgroup/unified/system.slice/systemd-udevd.service/cgroup.threads/proc/3084/cmdline/proc/3729/cmdline/proc/3994/cmdline/proc/8823/cmdline/proc/2231364/cmdline/proc/2431788/cmdline/proc/2560949/cmdline/sys/class/hwmon/sys/class/hwmon/hwmon6/sys/class/hwmon/hwmon4/sys/class/hwmon/hwmon2/sys/class/hwmon/hwmon0/sys/class/hwmon/hwmon7/sys/class/hwmon/hwmon5

完毕!

posted @ 2022-04-17 11:18 Jaciot 阅读(10) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员