我可以写保护Linux进程地址空间中的每个页面吗?

我可以写保护Linux进程地址空间中的每个页面吗?,linux,segmentation-fault,signal-handling,mprotect,Linux,Segmentation Fault,Signal Handling,Mprotect,我想知道是否有一种方法可以在Linux中写保护每个页面 进程的地址空间(从进程本身内部,通过 mprotect())。我所说的“每一页”,实际上是指 进程的地址空间,该地址空间可能由普通 在用户模式下运行的程序--程序文本,常量, 全局变量和堆,但我很乐意只使用常量, globals和heap。我不想写保护堆栈--那 这似乎是个坏主意 一个问题是我不知道从哪里开始写保护 记忆。查看显示内存部分的/proc/pid/maps 在使用给定的pid时,它们似乎总是以地址开头 0x08048000,带有

我想知道是否有一种方法可以在Linux中写保护每个页面 进程的地址空间(从进程本身内部,通过
mprotect()
)。我所说的“每一页”,实际上是指 进程的地址空间,该地址空间可能由普通 在用户模式下运行的程序--程序文本,常量, 全局变量和堆,但我很乐意只使用常量, globals和heap。我不想写保护堆栈--那 这似乎是个坏主意

一个问题是我不知道从哪里开始写保护 记忆。查看显示内存部分的
/proc/pid/maps
在使用给定的pid时,它们似乎总是以地址开头
0x08048000
,带有程序文本。(据我所知,在Linux中, 进程的内存与程序文本一起在 底部,然后是上面的常量,然后是全局变量,然后是堆,然后是 根据堆或堆的大小而变化大小的空白空间 堆栈,然后堆栈从内存顶部向下生长 虚拟地址
0xffffffff
)有一种方法可以告诉您 堆是(通过调用
sbrk(0)
,它只返回一个指向 当前的“中断”,即堆的顶部),但实际上不是 告诉堆从哪里开始

如果我试图保护所有页面,从
0x08048000
到中断,我 最终得到
m保护:无法分配内存
错误。我不知道为什么
mprotect
会 不管怎么说,分配内存——谷歌也没有什么帮助。有什么想法吗

顺便说一句,我之所以想这样做是因为我想创建一个 在程序运行期间写入的所有页面的列表,以及 我能想到的方法是写保护所有页面, 让任何尝试写入导致写入错误,然后实现写入 错误处理程序,将页面添加到列表中,然后删除写入 保护。我想我知道如何实现处理程序,如果我能的话 确定要保护哪些页面以及如何保护


谢谢

从简单开始。写几个页面,并确保您的信号处理程序适用于这些页面。然后担心扩大保护范围。例如,您可能不需要写保护代码部分:操作系统可以在内存上实现写保护或执行保护语义,从而防止代码部分被写入:


如果您试图在未映射的页面上调用它,您将从
mprotect()
接收到
ENOMEM

最好打开
/proc/self/maps
,然后使用
fgets()
一次读取一行,以查找流程中的所有映射。对于不是堆栈的每个可写映射(在第二个字段中指示)(在最后一个字段中指示),使用正确的基址和长度(从第一个字段中的起始地址和结束地址计算)调用
mprotect()


请注意,此时您需要已经设置了错误处理程序,因为读取
映射文件本身可能会导致在您的地址空间中写入内容。

我实际上已经有了与您尝试执行的操作完全相同的代码。你的想法会奏效,但你不能保护你的“这些页面被写入”列表将驻留的页面,否则你的SEGV处理程序将导致SEGV@Borelid,谢谢,这就是我现在要解决的问题(我现在已经有了segfault处理程序和/proc/self/maps解析程序)。如何避免保护包含该列表的页面?在堆栈上分配列表是可行的,但是我看不到任何方法可以将其传递给处理程序。或者,我可以将其分配为全局数组,但我希望使用比固定长度数组(如STL容器)更奇特的数据结构,而且我可能并不总是知道我要写入的列表在内存中的位置。@borealid:您说过您有这样做的代码——您介意共享您的代码吗?我是新来的,我找不到直接联系你的方法(后台)。我正试图做Linsey正在做的事情,所以任何代码示例都会非常有用。谢谢——我希望有一些方法可以避免必须手动解析/proc/self/maps,但是(从上的讨论中)似乎没有。是的,对于这个问题,我们现在可以假设没有自修改代码。我可以选择写保护代码段,也可以不写保护代码段,以较容易的为准。实际上,我想说的是,您的代码段很可能已经写保护了。