我可以写保护 Linux 进程地址空间中的每个页面吗? [英] Can I write-protect every page in the address space of a Linux process?

查看:15
本文介绍了我可以写保护 Linux 进程地址空间中的每个页面吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有办法对 Linux 中的每个页面进行写保护进程的地址空间(从进程本身内部,通过mprotect()).我所说的每一页"是指每一页普通进程可能写入的进程地址空间在用户模式下运行的程序——所以,程序文本,常量,全局变量和堆——但我会对常量感到满意,全局变量和堆.我不想写保护堆栈——那个似乎是个坏主意.

I'm wondering if there's a way to write-protect every page in a Linux process' address space (from inside of the process itself, by way of mprotect()). By "every page", I really mean every page of the process's address space that might be written to by an ordinary program running in user mode -- so, the program text, the constants, the globals, and the heap -- but I would be happy with just constants, globals, and heap. I don't want to write-protect the stack -- that seems like a bad idea.

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

One problem is that I don't know where to start write-protecting memory. Looking at /proc/pid/maps, which shows the sections of memory in use for a given pid, they always seem to start with the address 0x08048000, with the program text. (In Linux, as far as I can tell, the memory of a process is laid out with the program text at the bottom, then constants above that, then globals, then the heap, then an empty space of varying size depending on the size of the heap or stack, and then the stack growing down from the top of memory at virtual address 0xffffffff.) There's a way to tell where the top of the heap is (by calling sbrk(0), which simply returns a pointer to the current "break", i.e., the top of the heap), but not really a way to tell where the heap begins.

如果我尝试保护所有页面免受 0x08048000 直到中断,我最终得到一个 mprotect: Cannot allocate memory 错误.我不知道为什么 mprotect 会无论如何分配内存——谷歌不是很有帮助.有什么想法吗?

If I try to protect all pages from 0x08048000 up to the break, I eventually get an mprotect: Cannot allocate memory error. I don't know why mprotect would be allocating memory anyway -- and Google is not very helpful. Any ideas?

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

By the way, the reason I want to do this is because I want to create a list of all pages that are written to during a run of the program, and the way that I can think of to do this is to write-protect all pages, let any attempted writes cause a write fault, then implement a write fault handler that will add the page to the list and then remove the write protection. I think I know how to implement the handler, if only I could figure out which pages to protect and how to do it.

谢谢!

推荐答案

如果您尝试在非映射.

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

Your best bet is to open /proc/self/maps, and read it a line at a time with fgets() to find all the mappings in your process. For each writeable mapping (indicated in the second field) that isn't the stack (indicated in the last field), call mprotect() with the right base address and length (calculated from the start and end addresses in the first field).

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

Note that you'll need to have your fault handler already set up at this point, because the act of reading the maps file itself will likely cause writes within your address space.

这篇关于我可以写保护 Linux 进程地址空间中的每个页面吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆