关于Linux内核code段被改写的原因分析

本文基于Linux-4.19.125, ARM V7,dual core。

1 code 段

Linux的code段(或者说text段)自_stext开始,到_etext结束,这段内容一般情况下是只读的,在理论上来说,这段数据在设备上应该和kernel image中的内容完全一致。

symbol___|type_______|address____________|
_stext       |(char [0])    | P:C0008240
_etext       | (char [0])  | P:C02CA9A0

但在实测中发现,从设备中dump出来的这段数据,与kernel image中的数据存在多处不一致的情况:

2 数据对比

随机取几个差异点:

序号虚拟地址vmlinux内容板端内容
10xc0017f700x40010x4000
20xc00d21540x43010x4300
30xc00e895e0x40010x4000
40xc02852ca0x41010x4100

 通过trace32对比设备侧与vmlinux中的数据差异:

3. 数据何时被修改的

41 load boot image阶段

为方便调试,修改Linux内核源码arch/arm/kernel/head.S文件如下,让CPU停在SPL跳转到内核的第一条指令:

上电,CPU停止在0x40008000地址:

 

此时dump, 将_stext和_etext转换成物理地址分别是0x40008240和:0x402CA9A0

执行d.save.Binary text_dump_start.bin eaxi:0x40008240--eaxi:0x402CA9A0得到 text_dump_start.bin

对比text_dump_start.bin和text_vmlinux.bin文件发现二者完全一致,说明SPL加载boot image到内核过程中并没有修改code段内容。

3.2 __mmap_switched 阶段

__mmap_switched是开启mmu后的第一条语句,经过验证发现,进入到__mmap_switched时,监控的上述4个随机抽样点的数据已经被修改了,这说明修改动作发生在__mmap_switched之前。 

3.3 __fixup_pv_table阶段

经过调试发现,上述监控的4个随机抽样点的数据在__fixup_pv_table中被修改了。

__fixup_pv_table是在CONFIG_ARM_PATCH_PHYS_VIRT内核配置项打开的情况下才支持的,关于CONFIG_ARM_PATCH_PHYS_VIRT的作用,概括来说就是:
开发人员需要让内核在不重新编译的情况下,在不同内存配置的系统中能够正常运行。
内核可能被编译成在特定的虚拟地址(如 0xC0000000 )处执行,但实际可能被加载到 物理地址0x10000000、0x40000000或其他地址。
CONFIG_ARM_PATCH_PHYS_VIRT的作用就是实现同一kernel image被加载到不同物理地址后仍然能够正常运行这一目的的。
__fixup_pv_table的实现很复杂,其核心思想:
每当在内核中调用 __virt_to_phys() 或 __phys_to_virt() 时,被替换成一段内联汇编代码(位于arch/arm/include/asm/memory.h)
然后连接器就会将section 切换到一个名为 .pv_table 的section 上,然后在该section 中添加一个指针,指向刚刚添加的汇编指令的位置
这就是说,.pv_table 接会扩展成一个指针的表格,指向所有这些内联汇编代码所在的位置。
在__fixup_pv_table过程中,会遍历整个pv_table 表格,取出每一个指针,检查指针所指位置的指令,然后利用物理和虚拟内存之间的偏移量对这些指令打补丁。 

Patching phys to virt

4 检验

根据我们前面随机取的几4个取样点:

序号虚拟地址vmlinux内容板端内容
10xc0017f700x40010x4000
20xc00d21540x43010x4300
30xc00e895e0x40010x4000
40xc02852ca0x41010x4100

 0xc0017f70

 对应代码:

0xc00d2154

对应代码:

0xc00e895e

0xc02852ca

以上4个随机取样点,均验证被修改的代码确实都与pv_table有关,可以证实这些被修改的内容是在__fixup_pv_table过程中修改的。 

5 参考文档

  1. How the ARM32 kernel starts — linusw
  2. 万字长文揭秘 ARM 32 内核是如何启动的!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值