系统相关
首页 > 系统相关> > 我可以写保护Linux进程的地址空间中的每个页面吗?

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

作者:互联网

我想知道是否有办法在Linux中写保护每个页面
进程的地址空间(来自进程本身的内部,通过
的mprotect()).通过“每一页”,我的意思是每一页
进程的地址空间可能由普通用户写入
程序在用户模式下运行 – 所以,程序文本,常量,
全局变量和堆 – 但我会很满意常量,
全局和堆.我不想写保护堆栈 – 那
好像是个坏主意.

一个问题是我不知道从哪里开始写保护
记忆.查看/ proc / pid / maps,它显示了内存的各个部分
在使用给定的pid时,它们似乎始终以地址开头
0x08048000,带有程序文本. (据我所知,在Linux中,
过程的记忆与程序文本一起列出
下面,然后是常量,然后是全局,然后是堆
一个不同大小的空白空间,取决于堆的大小或
堆栈,然后堆栈从内存顶部向下生长
虚拟地址0xffffffff.)有一种方法可以告诉顶部的位置
堆是(通过调用sbrk(0),它只返回一个指针
当前的“休息”,即堆的顶部),但不是真正的方式
告诉堆开始的位置.

如果我尝试保护所有页面从0x08048000到中断,我
最终得到一个mprotect:无法分配内存错误.我不知道为什么mprotect会
无论如何都要分配内存 – 谷歌并不是很有帮助.有任何想法吗?

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

谢谢!

解决方法:

如果您尝试在未映射的页面上调用ENOMEM,则从mprotect()接收ENOMEM.

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

请注意,此时您需要设置故障处理程序,因为读取映射文件本身的行为可能会导致在您的地址空间内进行写入.

标签:linux,sigsegv,signal-handling,mprotect
来源: https://codeday.me/bug/20190518/1129753.html