gem5(2)——利用gem5模拟Spectre攻击
iamywang

引言

背景

从去年开始,一直在学习Meltdown攻击和Spectre攻击,包括攻击原理的学习、攻击的复现(在x86和ARM两种架构下复现)、利用符号执行(基于LLVM的KLEE)进行检测等。

Meltdown攻击是通过绕过CPU的权限检查机制,将内核态的数据读取到用户态,从而实现数据泄露。Spectre攻击是通过利用CPU的分支预测机制,让CPU错误预测执行,从而实现数据泄露。

这两种攻击都是通过利用CPU的特性来实现的,而gem5是一个CPU模拟器,并且提供了这两种攻击所利用到的乱序执行、分支预测特性以及Cache,因此理论上可以利用gem5来模拟这两种攻击。

主要工作

在查阅相关资料时,发现2021年的一篇文章[1],利用gem5模拟了Spectre攻击,因此决定在学习gem5的过程中对这篇论文进行复现。

主要工作:

  1. 复现论文”Reproducing Spectre Attack with gem5: How To Do It Right?”,尽管经过了一番努力,仍然没有配置成功;
  2. 利用gem5推荐的系统镜像运行并进行Spectre攻击的复现,这次系统引导成功,程序也可以运行,但是没有得到与论文中一样的结果;
  3. 还要继续研究…

论文环境搭建

本节的主要内容是复现论文”Reproducing Spectre Attack with gem5: How To Do It Right?”的环境配置。

编译gem5

编译ARM架构的gem5:

1
$ scons build/ARM/gem5.opt -j5

编译m5term:

1
2
$ cd util/term
$ make

树莓派4B配置文件

从[3]中克隆代码到本地:

1
$ git clone https://github.com/pierreay/reproduce-spectre-gem5.git

在gem5目录下有树莓派4和A72处理器核的配置文件:

配置文件列表

操作系统和内核

下载系统和内核镜像文件:

1
2
$ wget -O - http://dist.gem5.org/dist/current/arm/disks/linaro-minimal-aarch64.img.bz2 | bunzip2 > linaro-minimal-aarch64.img
$ wget -O - http://dist.gem5.org/dist/current/arm/aarch-system-201901106.tar.bz2 | tar xjv

解压缩后的文件目录为:

系统文件列表

创建工作镜像

接下来利用dd命令创建workload.img文件:

1
$ dd if=/dev/zero of=workload.img count=200K

创建一个回环设备以便将镜像文件作为块设备访问:

1
2
$ dev=$(sudo losetup -f)
$ sudo losetup -fP workload.img

创建分区表以及ext4文件系统:

1
2
$ echo "," | sudo sfdisk $dev
$ sudo mkfs.ext4 ${dev}p1

创建分区表

最后,从回环设备中卸载:

1
$ sudo losetup -d $dev

修改配置文件

这里如果直接按照[2]中执行,会遇到以下问题:

(1)没有将gem5的config添加到python的搜索路径中,会报找不到common的错误:

1
ModuleNotFoundError: No module named 'common'

因此,需要修改RPIv4.py文件,添加:

1
sys.path.append("/home/gem5/gem5/configs/")

(2)在gem5的commit中(5195c801156d1f9ff08d7ef4aceff2ff532c852),参数ArmITB和ArmDTB被统一换成了ArmTLB:

1
2
3
arch-arm, configs: Remove ArmITB/ArmDTB
Removing ArmITB and ArmDTB makes sense as it implies a fixed 2 TLBs system;
by using the generic ArmTLB class we open up to a more generic configuration

因此,修改ARMv8A_Cortex_A72.py文件,将ArmITB和ArmDTB替换成ArmTLB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ARM_A72_TLB_L1D(ArmTLB):
entry_type="data"
size = 48

class ARM_A72_TLB_L1I(ArmTLB):
entry_type="instruction"
size = 32

class ARM_A72_Cluster(SubSystem):
def connectDirect(self, bus):
for cpu in self.cpus:
cpu.mmu.dtb_walker.port = bus.slave
cpu.mmu.itb_walker.port = bus.slave
cpu.dcache_port = bus.slave
cpu.icache_port = bus.slave

(3)在gem5的commit中(6ecf110b06d7333aae13bcc16216cc127fdda7f0),flags_addr被移除:

同时,参考configs/example/arm/devices.py文件,将RPIv4.py中的对应代码去掉:

1
# system.flags_addr = system.realview.realview_io.pio_addr + 0x30

(4)在gem5的commit中(5f95d7a89a56513876a7bb5dd8055d6b1d080c8b),IntrControl被移除:

1
2
3
4
5
cpu: IntrControl, clear all and check helpers
This patch extends the IntrControl to provided additional member functions for
(1) clearing all pending interrupts in a PE and
(2) checking for any pending interrupt in a PE.
These are intended to be used from interrupt management related peripherals.

因此,直接将RPIv4.py中的以下代码注释掉:

1
# system.intrctrl = IntrControl()

(5)slave和master的接口变化:

修改RPIv4.py文件:

1
2
3
4
5
6
7
8
9
10
11
# Wire up the system port to the previously created memory bus (gem5
# uses it to load the kernel and to perform debug accesses).
self.system_port = self.membus.cpu_side_ports

...

# Connect the two IO bridges to the IO bus and the system bus.
system.iobridge.iobus.mem_side_port = system.iobus.cpu_side_ports
system.iobridge.iobus.cpu_side_port = system.membus.mem_side_ports
system.iobridge.membus.mem_side_port = system.membus.cpu_side_ports
system.iobridge.membus.cpu_side_port = system.iobus.mem_side_ports

修改A72.py文件:

1
2
3
4
5
6
7
8
9
10
11
def connectCacheL2(self, bus):
self.l2.mem_side = bus.cpu_side_ports

...

def connectDirect(self, bus):
for cpu in self.cpus:
cpu.mmu.itb_walker.port = bus.cpu_side_ports
cpu.mmu.dtb_walker.port = bus.cpu_side_ports
cpu.dcache_port = bus.cpu_side_ports
cpu.icache_port = bus.cpu_side_ports

启动系统

首先,配置M5_PATH环境变量:

1
$ export M5_PATH=$PWD/img/

接着,引导系统:

1
2
3
4
5
$ build/ARM/gem5.opt -q -d 01boot \
../reproduce-spectre-gem5/gem5/RPIv4.py -v --num-cores=4 --fs \
--fs-kernel=./img/binaries/vmlinux.arm64 \
--fs-disk-image=./img/linaro-minimal-aarch64.img \
--fs-workload-image=./img/workload.img

引导过程如下:

引导过程

然后,在另一个终端连接到m5term:

1
$ util/term/m5term localhost 3456

但是这一步可能是因为版本的问题失败了。尽管终端的输出显示已经开始模拟,连接m5term也有输出和提示,但是没有拿到ARM模拟器的shell,也没有引导成功的说明。

gem5官方推荐环境搭建

下载系统和内核

下载Linux系统和内核镜像文件:

1
2
$ wget -O - http://dist.gem5.org/dist/v22-0/arm/aarch-system-20220707.tar.bz2 | tar xjv
$ wget -O - http://dist.gem5.org/dist/v22-0/arm/disks/ubuntu-18.04-arm64-docker.img.bz2 | bunzip2 > ubuntu-18.04-arm64-docker.img

引导系统

引导系统:

1
2
3
$ build/ARM/gem5.opt -q ./configs/example/fs.py --num-cpu=4 \ 
--kernel=./ubuntu-1804/binaries/vmlinux.arm64 \
--disk-image=./ubuntu-1804/ubuntu-18.04-arm64-docker.img

连接m5term:

1
$ util/term/m5term localhost 3456

引导成功的截图如下:

引导成功

挂载镜像

挂载disk镜像并写入攻击程序:

1
2
3
$ mkdir -p disk
$ util/gem5img.py mount ~/ubuntu-1804/ubuntu-18.04-arm64-docker.img ./disk
$ sudo cp -r ~/reproduce-spectre-gem5/spectre ./root/

执行Spectre攻击

执行攻击:

1
2
$ cd spectre
$ ./spectre -m 10 -l 100 -t 999

但是没有得到预期的结果,攻击失败,猜测应该是环境与论文中的不一致导致的。

参考文献

  1. Ayoub, P., & Maurice, C. (2021, April). Reproducing spectre attack with gem5: How to do it right?. In Proceedings of the 14th European Workshop on Systems Security (pp. 15-20).
  2. https://pierreay.github.io/reproduce-spectre-gem5/
  3. https://github.com/pierreay/reproduce-spectre-gem5
  4. https://github.com/gem5/gem5
  5. https://www.gem5.org/documentation/general_docs/fullsystem/guest_binaries
 评论