更多文章目录:点击这里
GitHub地址:https://github.com/ljrcore

一、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=y
CONFIG_BPF_SYSCALL=y
# [optional, for tc filters]
CONFIG_NET_CLS_BPF=m
# [optional, for tc actions]
CONFIG_NET_ACT_BPF=m
CONFIG_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.xz
CONFIG_IKHEADERS=y

bcc 框架检查项:

CONFIG_NET_SCH_SFQ=m
CONFIG_NET_ACT_POLICE=m
CONFIG_NET_ACT_GACT=m
CONFIG_DUMMY=m
CONFIG_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 older
VER=trusty
echo "deb http://llvm.org/apt/$VER/ llvm-toolchain-$VER-3.7 main
deb-src http://llvm.org/apt/$VER/ llvm-toolchain-$VER-3.7 main" | \sudo tee /etc/apt/sources.list.d/llvm.list
wget -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 versions
sudo 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 support
sudo apt-get -y install luajit luajit-5.1-dev

安装并编译bcc

git clone https://github.com/iovisor/bcc.git
mkdir bcc/build; cd bcc/build
cmake ..
make
sudo make install
cmake -DPYTHON_CMD=python3 .. # build python3 binding
pushd src/python/
make
sudo make install
popd

2、使用bcc

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

from bcc import BPF
BPF(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!”。

Ubuntu18.4 中 eBPF bcc环境搭建相关推荐

  1. 基于30系显卡以及Ubuntu18.04系统的YOLOv3环境搭建和训练模型以及测试

    基于30系显卡以及Ubuntu18.04系统的YOLOv3环境搭建和训练模型以及测试 安装环境 下面是官网对N卡框架以及驱动和cuda版本的部分对应关系 驱动 (可以跳过这段安装,你可以在安装CUDA ...

  2. win7中Android开发环境搭建超详细(百度)

    Android系统如火如荼,Android软件开发也相当流行,这里介绍如何一步步完成Android软件开发环境的搭建. 工具/原料 能联网的计算机 Java环境搭建 1 Android软建开发用的是J ...

  3. 用Python在Minecraft(我的世界)中编程——开发环境搭建

    为了教十岁的儿子Python编程,我研究了下Minecraft中的编程,搭建环境是第一步,可惜网上的资料不是很多,特此记录下,以供有同样需求的家长们参考: 准备工作 安装Python,要2.7版本的, ...

  4. ubuntu18.04系统下px4avoidance环境搭建问题

    按照csdn中一文进行环境搭建时候出现tf坐标报错问题,使用offboard模式时候如图3

  5. windows中freeRTOS模拟器环境搭建

    windows中的freeRTOS使用   FreeRTOS参考手册中的模拟程序都是基于windows版本的模拟器.因此为了学习FreeRTOS,需要在Windows中搭建一下模拟器的运行环境.网络上 ...

  6. 虚拟机屏幕显示不全(界面大小更改 )虚拟机Ubuntu18.04 的超详细环境搭建教程/步骤 SDN软件定义网络实验

    打开虚拟机后,我们可能发现,桌面周围有大量黑边,且有些界面无法完整显示,影响我们的感受和操作!!!  解决方法: (1)点击箭头所指,进入目录 (2)点击箭头所指的齿轮,进入"setting ...

  7. PyCharm中的pyqt-designer环境搭建和汉化

    pyqt-designer环境搭建: 1.安装pyqt5.pyqt-tools依赖包 2.打开pycharm,菜单栏File->Settings... 3.在打开的Settings窗口中,Too ...

  8. java中easyUI开发环境搭建

    最近在用easyui,感觉是比较好用的,java程序员基本上可以通过使用easyui自己来开发出一些项目,下面简单介绍一下java中easyui环境的搭建. 1.首先从官网下载easyui开发包,下载 ...

  9. 金融分析师 python_金融分析中的Python环境搭建

    首先安装Anaconda,Anaconda下载地址如下:Download Anaconda now! 我的环境时OS X python2.7环境,直接找到匹配的版本下载链接: 按照安装说明,通过com ...

最新文章

  1. 2018-3-4 nginx和Tengine 以及高并发的概念
  2. 关于全连接层梯度的链式法则
  3. 解决Subquery returns more than 1 rowsql查询错误
  4. 《游戏编程模式》读书笔记之一
  5. C语言基于GTK+Libvlc实现的简易视频播放器(二)
  6. linux cacti安装教程,Linux下cacti的安装与配置
  7. iOS 7开源项目干货集合
  8. [AHOI2009]飞行棋 BZOJ1800
  9. 利用Helm简化Kubernetes应用部署(2)
  10. 「LibreOJ Round #11」Misaka Network 与测试 (网络流跑二分图匹配)
  11. php sdk 调用示例,开放服务-SDK调用示例
  12. XHTML + CSS使用技巧
  13. 关于oracle存储微信表情emoji问题 “[[%F0%9F%A4%AA]]“
  14. java setcharat,Java StringBuilder setCharAt()方法
  15. oracle里的字符串类型,Oracle中的字符串類型及相關函數詳解
  16. 面向组学大数据的生物信息学研究
  17. 通达OA迈向开放协同,定制成功
  18. Java进制转换问题(详解)
  19. 【滤波器】7. 带通滤波器
  20. 最全最新cpu显卡天梯图_CPU天梯图2020年-2020年最新CPU天梯图(高清大图) - 系统家园...

热门文章

  1. 运维自动化之Cobbler安装配置
  2. ExecuteNonQuery()返回受影响行数不适用select语句
  3. [转]Linux下pppoe配合Drcom插件上网方法介绍......
  4. 强生进军医疗机器人、Deepmind利用深度学习算法检查乳腺癌X光,AI医疗的风口已到来?...
  5. 如何从PostgreSQL json中提取数组
  6. 程序员面试题100题第17题——字符串转化为整数
  7. WinCE设置DataGrid行高
  8. js 显示当前时间(年月日时分秒)——getYear()与getFullYear()
  9. [教程]JS从糊涂到明白:一步一步编写计算器2 – 简化代码
  10. mybatis configuration的内容必须匹配问题