博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Ubuntu18.4 中 eBPF & bcc环境搭建
阅读量:3786 次
发布时间:2019-05-22

本文共 3771 字,大约阅读时间需要 12 分钟。

更多文章目录:

GitHub地址:

一、eBPF简介

eBPF是将原先的BPF发展成一个指令集更复杂、应用范围更广的“内核虚拟机”。eBPF支持在用户态将C语言编写的一小段“内核代码”注入到内核中运行,注入时要先用llvm编译得到使用BPF指令集的elf文件,然后从elf文件中解析出可以注入内核的部分,最后用bpf_load_program方法完成注入。 用户态程序和注入到内核中的程序通过共用一个位于内核中map实现通信。为了防止注入的代码导致内核崩溃,eBPF会对注入的代码进行严格检查,拒绝不合格的代码的注入。

注入程序bpf_load_program()加入了更复杂的verifier 机制,在运行注入程序之前,先进行一系列的安全检查,最大限度的保证系统的安全。具体来说,verifier机制会对注入的程序做两轮检查:

  • 首轮检查(First pass,实现于check_cfg())可以被认为是一次深度优先搜索,主要目的是对注入代码进行一次 DAG(Directed Acyclic Graph,有向无环图)检测,以保证其中没有循环存在,除此之外,一旦在代码中发现以下特征,verifier 也会拒绝注入:
  1. 代码长度超过上限;
  2. 存在可能会跳出 eBPF 代码范围的 JMP,这主要是为了防止恶意代码故意让程序跑飞;
  3. 存在永远无法运行(unreachable)的 eBPF 指令,例如位于 exit 之后的指令;
  • 次轮检查(Second pass,实现于do_check())较之于首轮则要细致很多:在本轮检测中注入代码的所有逻辑分支从头到尾都会被完全跑上一遍,所有指令的参数(寄存器)、访问的内存、调用的函数都会被仔细的捋一遍,任何的错误都会导致注入程序失败。

二、eBPF的应用(bcc的安装和使用)

目前可以用 C 来实现 BPF,但编译出来的却仍然是 ELF 文件,无法直接注入内核,bcc实现了一步到位的生成出 BPF 代码。bcc 是一个 python 库,其中有很大一部分的实现是基于 C 和 C++的,python 是实现对 bcc 应用层接口的封装。使用 BCC 进行 BPF 的开发仍然需要我们自行利用 C 来设计 BPF 程序,但编译、解析 ELF、加载 BPF 代码块以及创建 map 等可以由 bcc框架实现。

1、安装bcc

(1)检查内核配置选项

在使用bcc之前需要检查Linux系统内核配置选项,可以通过less命令查看内核配置选项

/proc/config.gz
/boot/config-<kernel-version>

less /boot/config-4.18.0-15-generic

在这里插入图片描述

BPF检查项如下:

CONFIG_BPF=yCONFIG_BPF_SYSCALL=y# [optional, for tc filters]CONFIG_NET_CLS_BPF=m# [optional, for tc actions]CONFIG_NET_ACT_BPF=mCONFIG_BPF_JIT=y# [for Linux kernel versions 4.1 through 4.6]CONFIG_HAVE_BPF_JIT=y# [for Linux kernel versions 4.7 and later]CONFIG_HAVE_EBPF_JIT=y# [optional, for kprobes]CONFIG_BPF_EVENTS=y# Need kernel headers through /sys/kernel/kheaders.tar.xzCONFIG_IKHEADERS=y

bcc 框架检查项:

CONFIG_NET_SCH_SFQ=mCONFIG_NET_ACT_POLICE=mCONFIG_NET_ACT_GACT=mCONFIG_DUMMY=mCONFIG_VXLAN=m

(2)设置内核配置选项

若检查内核配置选项与上述检查项不符,在/usr/src目录下使用 make menuconfig命令设置内核配置选项:

在这里插入图片描述
设置完成后需要编译内核。

(3)安装bcc

确认好内核配置选项没问题后,有两种方式安装bcc。

官方安装链接:https://github.com/iovisor/bcc/blob/master/INSTALL.md

方法一:安装 bcc 软件包

sudo apt-get install bpfcc-tools linux-headers-$(uname -r)

在这里插入图片描述

方法二:源码安装

Ubuntu下构建依赖关系:

# Trusty (14.04 LTS) and olderVER=trustyecho "deb http://llvm.org/apt/$VER/ llvm-toolchain-$VER-3.7 maindeb-src http://llvm.org/apt/$VER/ llvm-toolchain-$VER-3.7 main" | \  sudo tee /etc/apt/sources.list.d/llvm.listwget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -sudo apt-get update# For Bionic (18.04 LTS)sudo apt-get -y install bison build-essential cmake flex git libedit-dev \  libllvm6.0 llvm-6.0-dev libclang-6.0-dev python zlib1g-dev libelf-dev libfl-dev# For Eoan (19.10) or Focal (20.04.1 LTS)sudo apt install -y bison build-essential cmake flex git libedit-dev \  libllvm7 llvm-7-dev libclang-7-dev python zlib1g-dev libelf-dev libfl-dev# For other versionssudo apt-get -y install bison build-essential cmake flex git libedit-dev \  libllvm3.7 llvm-3.7-dev libclang-3.7-dev python zlib1g-dev libelf-dev# For Lua supportsudo apt-get -y install luajit luajit-5.1-dev

安装并编译bcc

git clone https://github.com/iovisor/bcc.gitmkdir bcc/build; cd bcc/buildcmake ..makesudo make installcmake -DPYTHON_CMD=python3 .. # build python3 bindingpushd src/python/makesudo make installpopd

2、使用bcc

下面介绍一个简单的例子,代码如下:

from bcc import BPFBPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print()

可以看到,这段代码是在 python 中内嵌 C 语言程序的,请注意六点:

  1. text='...' 这里定义了一个内联的、C 语言写的 BPF 程序。
  2. kprobe__sys_clone() 这是一个通过内核探针(kprobe)进行内核动态跟踪的快捷方式。如果一个 C 函数名开头为 kprobe__ ,则后面的部分实际为设备的内核函数名,这里是 sys_clone() 。
  3. void *ctx 这里的 ctx 实际上有一些参数,不过这里我们用不到,暂时转为 void * 。
  4. bpf_trace_printk()这是一个简单的内核工具,用于 printf() 到 trace_pipe(译者注:可以理解为 BPF C 代码中的 printf())。它一般来快速调试一些东西,不过有一些限制:最多有三个参数,一个%s ,并且 trace_pipe 是全局共享的,所以会导致并发程序的输出冲突,因而 BPF_PERF_OUTPUT() 是一个更棒的方案,我们后面会提到。
  5. return 0 这是一个必须的部分。
  6. trace_print() 一个 bcc 实例会通过这个读取 trace_pipe 并打印出来。

使用如下命令运行此示例:

sudo python2 hello_world.py

切换终端输入ls做测试时,运行结果如下图:

在这里插入图片描述
可以看到有新进程被创建,程序打印出“Hello, World!”。

转载地址:http://ivutn.baihongyu.com/

你可能感兴趣的文章
php(环境搭建)
查看>>
php(变量)
查看>>
php(单双引号的区别)
查看>>
php(数据类型)
查看>>
php(运算符及流程控制)
查看>>
php(自定义函数与系统自带函数)
查看>>
php(从一个文件中调用另一个文件的变量)
查看>>
php(数组及相关操作)
查看>>
php(about error and time)
查看>>
利用php对数据库进行操作
查看>>
二叉树及其(前中后)序遍历
查看>>
2020.8.29 ssdh
查看>>
PyCharm使用技巧及常用快捷键
查看>>
ubuntu内存爆满卡住,一顿操作任务栏菜单栏消失再解决办法记录
查看>>
ubuntu下pycharm无法输入中文解决办法(记录)
查看>>
torch.cuda.is_available()返回False的解决办法
查看>>
BITVehicle_Dataset数据集转换
查看>>
将视频转存成图片小代码
查看>>
ImportError: cannot import name ‘Line 解决方法
查看>>
Ubuntu 创建/删除虚拟环境
查看>>