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-config
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 13
rm -f ./llvm.sh
//检验是否安装成功,输出版本号表示安装成功
llvm-config-13 --version | grep 13
(三)安装 cargo-bpf脚手架
cargo install cargo-bpf --no-default-features --features=llvm13
(四)应用示例
#1、创建用户空间代码目录
cargo new bpfdemo
cd bpfdemo
#2、创建bpf代码目录
cargo bpf new probes
ls
>>Cargo.lock Cargo.toml probes src
#3、编写一个openmonitor bpf程序 输出系统打开的文件
cd probes
cargo bpf add openmonitor
cd src
ls
>>lib.rs openmonitor
cd openmonitor
nano 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=../target
ls ../target/bpf/programs/openmonitor/openmonitor.elf
#5.在用户空间代码中使用bpf程序,获取系统打开文件
cd ../src
nano 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 build
cargo 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
完毕!
Rust如何开发eBPF应用(一)?的更多相关文章
- Rust Aya 编写 eBPF 程序
本文地址:https://www.ebpf.top/post/ebpf_rust_aya 1. 前言 Linux 内核 6.1 版本中有一个非常引人注意的变化:引入了对 Rust 编程语言的支持.Ru ...
- Rust语言开发
Rust开发 第一个程序 fn main() { println!("Hello, world!"); // 带!号的都是宏 并不是函数 } fn main() { let nam ...
- 专访Rust——由Mozilla开发的系统编程语言(目标人群就是那些纠结的C++程序员,甚至也是他们自己)
Rust是由Mozilla开发的专门用来编写高性能应用程序的系统编程语言.以下是对Rust的创始人——Graydon Hoare的采访. Graydon Hoare,自称为职业编程语言工程师,从200 ...
- Rust语言
Rust语言 https://doc.rust-lang.org/stable/book/ http://www.phperz.com/article/15/0717/141560.html Rust ...
- InfoQ中文站特供稿件:Rust编程语言的核心部件
本文为InfoQ中文站特供稿件.首发地址为: http://www.infoq.com/cn/articles/rust-core-components .如需转载.请与InfoQ中文站联系. 原文发 ...
- Rust语言——无虚拟机、无垃圾收集器、无运行时、无空指针/野指针/内存越界/缓冲区溢出/段错误、无数据竞争
2006年,编程语言工程师Graydon Hoare利用业余时间启动了Rust语言项目.该项目充分借鉴了C/C++/Java/Python等语言的经验,试图在保持良好性能的同时,克服以往编程语言所存在 ...
- 我持续推动Rust语言支持Windows XP系统
前言 Rust好像长期以来不支持Windows XP系统.有不少用户发帖提议官方支持XP,基本上都被Rust官方开发人员明白的拒绝了.他们的对话大致上是以这种形式開始和结束的(当中乙方代表官方及其拥趸 ...
- SQLite为何要用C语言来开发?
SQLite 选择 C 语言的理由是?为什么不选择 Go 或者 Rust? C 语言是最好的 SQLite 在 2000 年 5 月 29 日发布,并一直使用 C 语言实现.C 语言一直是实现 SQL ...
- eBPF Tracing 入门教程与实例
原文链接 Learn eBPF Tracing: Tutorial and Examples译者 弃余 在 LPC'18(Linux Plumber's conference) 会议上,至少有24个关 ...
随机推荐
- 后门及持久化访问4----Com组件劫持
代码及原理介绍 COM是Component Object Model(组件对象模型)的缩写,COM组件由DLL和EXE形式发布的可执行代码所组成.每个COM组件都有一个CLSID,这个CLSID是注册 ...
- 『现学现忘』Docker基础 — 31、实现MySQL同步数据
目录 1.搜索镜像 2.拉取镜像 3.查看镜像 4.启动镜像 5.操作容器 (1)在MySQL中创建数据库 (2)外部连接Dokcer容器中的MySQL服务 (3)查看挂载情况 (4)测试MySQL服 ...
- springboot实现热部署的几种方式
原理:使用了两个ClassLoader,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,这样在 ...
- 用maven建立一个工程3
在文件夹里面创建一个新文件夹把工程建立在里面
- [Errno 14] curl#6 - "Could not resolve host: mirrors.cloud.aliyuncs.com; Name or service not known"
修改/etc/resolv.conf文件 [root@lihui ~]# vi /etc/resolv.conf nameserver 8.8.8.8 nameserver 114.114.114.1 ...
- 如何解决用response输出字符流数据时的乱码问题
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOE ...
- 二十二、导入DXF文件
x
- 技术架构:IT生存之道
Technical architecture: What IT does for a living (cio.com) Technical architecture: What IT does for ...
- 基于vue-cli搭了一个多页面应用的空脚手架
vue2.* (多页面跳转) @[vue2.3.3|webpack2.6.1|less|axios] 之前看过有相关朋友share了空的多页面脚手架. 不过down了几个都是webpack1.0或者v ...
- js压缩图片到2m以下
用的canvas.这个问题测试妹子反馈了好几次bug,解决了好多次,虽然用了比较僵硬的办法,但总算最终解决了. 因为php的同事说,页面上的图片要直接调用七牛的接口上传到七牛,所以后端那边不能处理,必 ...