You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU_RELRO程序头未页对齐时内存保护机制问询

RELRO保护与非页对齐GNU_RELRO段的工作机制

RELRO(Relocation Read-Only)的核心作用是在程序完成动态链接重定位后,将原本可写的重定位相关内存区域设为只读,防止篡改攻击。你观察到GNU_RELRO段头未按页对齐的情况是正常的,内存权限的页级分配和RELRO保护并不冲突,具体逻辑如下:

1. GNU_RELRO的本质是「范围标记」而非「内存段」

GNU_RELRO是程序头中的一个标记项,它的唯一作用是告诉动态加载器(如ld-linux-aarch64.so.1):在重定位完成后,把从VirtAddr到VirtAddr+MemSiz这个地址范围内的内存改成只读。它不需要页对齐,因为这个范围只是逻辑上的保护区域,而非实际的内存页划分。

2. 加载器自动处理页边界的权限转换

内存权限确实以页为单位分配(AArch64默认页大小为4KB,即0x1000),加载器会按以下逻辑处理:

  • 计算RELRO范围覆盖的所有内存页:包括包含RELRO起始地址的页、所有完整覆盖的中间页,以及包含RELRO结束地址的页。
  • 将这些页的权限从原本的RW(因为RELRO区域属于第二个LOAD段,默认是可写的)修改为R。

以你提供的程序头为例:

  • GNU_RELRO的起始地址是0x42e58,结束地址是0x42e58 + 0x11a8 = 0x43ff0。
  • 对应的内存页是0x42000~0x43000和0x43000~0x44000两个页。
  • 加载器会把这两个页的权限从RW改为R,而后续的.data段起始于0x44340,属于0x44000~0x45000页,仍保持RW权限,不会被误保护。

3. 链接器的布局保证不会冲突

GNU链接器在生成可执行文件时,会自动规划内存布局:

  • 将需要RELRO保护的段(.init_array、.fini_array、.data.rel.ro、.dynamic,甚至Full RELRO下的.got/.got.plt)集中放在LOAD段的前部。
  • 将不需要保护的可写段(.data、.bss)放在RELRO范围之后的独立页中。
    这就确保了加载器修改页权限时,不会影响到需要保持可写的区域。

你的程序头中的验证

看Section Headers:

  • RELRO覆盖的区域包含.init_array(0x42e58)、.fini_array(0x42e60)、.data.rel.ro(0x42e68)、.dynamic(0x43990),直到0x43ff0。
  • 之后的.got.plt起始于0x43fe8,属于RELRO范围,说明这是Full RELRO配置,.got.plt也会被设为只读;而.data起始于0x44340,已经在下一个页,不受影响。
Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  ...
  LOAD           0x032e58 0x0000000000042e58 0x0000000000042e58 0x0028d8 0x051018 RW  0x10000
  ...
  GNU_RELRO      0x032e58 0x0000000000042e58 0x0000000000042e58 0x0011a8 0x0011a8 R   0x1

内容的提问来源于stack exchange,提问作者Fee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 22:24:54