【发布时间】:2011-03-27 12:31:13
【问题描述】:
我想知道是否有办法对 Linux 中的每个页面进行写保护
进程的地址空间(从进程本身内部,通过
mprotect())。我所说的“每一页”是指每一页
普通进程可能写入的进程地址空间
在用户模式下运行的程序——所以,程序文本,常量,
全局变量和堆——但我会对常量感到满意,
全局变量和堆。我不想写保护堆栈——那个
似乎是个坏主意。
一个问题是我不知道从哪里开始写保护
记忆。查看/proc/pid/maps,它显示了内存的部分
在用于给定 pid 时,它们似乎总是以地址开头
0x08048000,带有程序文本。 (在 Linux 中,据我所知,
进程的内存由程序文本在
底部,然后是上面的常量,然后是全局变量,然后是堆,然后
不同大小的空白空间,具体取决于堆的大小或
堆栈,然后堆栈从内存顶部向下增长
虚拟地址0xffffffff。)有一种方法可以告诉顶部在哪里
堆是(通过调用sbrk(0),它只是返回一个指向
当前的“中断”,即堆顶),但不是真正的方法
告诉堆从哪里开始。
如果我尝试保护所有页面免受 0x08048000 的影响直到中断,我
最终得到一个mprotect: Cannot allocate memory 错误。我不知道为什么mprotect 会是
无论如何分配内存——谷歌不是很有帮助。有什么想法吗?
顺便说一句,我想这样做的原因是因为我想创建一个 在程序运行期间写入的所有页面的列表,以及 我能想到的方法是对所有页面进行写保护, 让任何尝试的写入导致写入错误,然后执行写入 将页面添加到列表中然后删除写入的故障处理程序 保护。我想我知道如何实现处理程序,只要我能 弄清楚要保护哪些页面以及如何保护。
谢谢!
【问题讨论】:
-
我实际上已经有代码可以完全按照您的要求进行操作。您的想法可行,但您无法保护您的“这些页面已编写”列表所在的页面,否则您的 SEGV 处理程序将导致 SEGV!
-
@Borealid,谢谢,这就是我现在要解决的问题(我现在已经有了 segfault 处理程序和 /proc/self/maps 解析工作)。如何避免保护包含该列表的页面?在堆栈上分配列表会起作用,但是我看不到任何将它传递给处理程序的方法。或者,我可以将其分配为全局,但我想使用比固定长度数组(如 STL 容器)更高级的数据结构,而且我可能并不总是知道要写入的列表的位置在记忆中。
-
@borealid:你说你有代码可以做到这一点——你介意分享你的代码吗?我是新来的,我找不到直接联系你的方法(反向渠道)。我正在努力做 Linsey 正在做的事情,所以任何代码示例都会非常有帮助。
标签: linux segmentation-fault signal-handling mprotect