我想知道是否有一种方法可以在 Linux 中对每个页面进行写保护
进程的地址空间(从进程本身的内部,通过
mprotect()
)。所谓“每一页”,我的意思是
可能被普通程序写入的进程的地址空间
在用户模式下运行的程序——所以,程序文本,常量,
全局变量和堆——但我对常量很满意,
全局变量和堆。我不想对堆栈进行写保护——那
似乎是个坏主意。
一个问题是不知道从哪里开始写保护
内存。查看 /proc/pid/maps
,它显示了内存的各个部分
在用于给定的 pid 时,它们似乎总是以地址开头
0x08048000
,带有程序文本。 (在 Linux 中,据我所知,
进程的内存与程序文本一起布置在
底部,然后是上面的常量,然后是全局变量,然后是堆,然后
一个不同大小的空白空间,具体取决于堆的大小或
堆栈,然后堆栈从内存顶部向下增长
虚拟地址 0xffffffff
。)有一种方法可以判断顶部在哪里
堆是(通过调用 sbrk(0)
,它只是返回一个指向
当前的“中断”,即堆的顶部),但不是真正的方法
告诉堆从哪里开始。
如果我尝试保护所有页面免受 0x08048000
的破坏,我
最终得到一个 mprotect: Cannot allocate memory
错误。我不知道为什么 mprotect
会是
无论如何都要分配内存——谷歌并不是很有帮助。有什么想法吗?
顺便说一句,我想这样做的原因是因为我想创建一个 在程序运行期间写入的所有页面的列表,以及 我能想到的方法是写保护所有页面, 让任何尝试的写入导致写入错误,然后实现写入 将页面添加到列表然后删除写入的故障处理程序 保护。我想我知道如何实现处理程序,如果我能的话 弄清楚要保护哪些页面以及如何保护。
谢谢!
最佳答案
如果您尝试在未映射的页面上调用它,您会从 mprotect()
收到 ENOMEM
。
最好的办法是打开/proc/self/maps
,然后使用fgets()
一次读取一行以找到进程中的所有映射.对于不是堆栈(在最后一个字段中指示)的每个可写映射(在第二个字段中指示),使用正确的基地址和长度(从开始和结束计算)调用 mprotect()
第一个字段中的地址)。
请注意,此时您需要设置故障处理程序,因为读取 maps
文件本身的行为可能会导致在您的地址空间内进行写入。
关于linux - 我可以写保护 Linux 进程地址空间中的每一页吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3444052/