-
函数原型
int mprotect(void *addr, size_t len, int prot);
-
头文件
#include <sys/mman.h> #include <unistd.h>
-
描述
control the protection of pages.
The mprotect() system call changes the specified pages to have protection prot. When a program violates the protections of a page, it gets a SIGBUS or SIGSEGV signal.
主要是用来修改一段指定内存区域的保护属性。
使用mprotect这里最重要的一点是被保护的内存是按页对齐的,范围也是按页来的。这是因为Linux管理进程地址空间是一VMA(Virtual Memory Area)为单位来管理进程虚拟地址空间的,而VMA必须是page size大小的整数倍。
-
参数
PROT_NONE No permissions at all. PROT_READ The pages can be read. PROT_WRITE The pages can be written. PROT_EXEC The pages can be executed.
-
返回值
Upon successful completion, a value of 0 is returned. Otherwise, a value of -1 is returned and errno is set to indicate the error.
常见的错误有:
-
EACCES
该内存不能设置为相应权限。这是可能发生的,比如,如果你 mmap(2) 映射一个文件为只读的,接着使用 mprotect() 标志为 PROT_WRITE。
-
EINVAL
start 不是一个有效的指针,指向的不是某个内存页的开头。
-
ENOMEM
内核内部的结构体无法分配。
-
-
举个例子,修改虚函数表
#include <stdio.h> #include <unistd.h> #include <sys/mman.h> void print() { printf("print\n"); } class Base { public: virtual void print(){ printf("Base::print\n"); } }; void changeVtable() { Base base; void** vtable= *(void***)&base; // 获取页大小 unsigned long pagesize = sysconf(_SC_PAGE_SIZE); // 内存按页对齐 void* align_page_addr = reinterpret_cast<void*>(reinterpret_cast<unsigned long>(&vtable[0]) & (~(pagesize-1))); // 修改权限 int ret = mprotect(align_page_addr, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC); if(ret != 0) { printf("mprotect error\n"); return; } // 修改虚函数表内容 vtable[0] = reinterpret_cast<void*>(print); } int main() { Base* pbase = new Base(); Base base; printf("%p\n",print); printf("%p\n",reinterpret_cast<void*>(**(void***)(&base))); printf("%p\n",reinterpret_cast<void*>(**(void***)(pbase))); print(); base.print(); pbase->print(); changeVtable(); printf("%p\n",print); printf("%p\n",reinterpret_cast<void*>(**(void***)(&base))); printf("%p\n",reinterpret_cast<void*>(**(void***)(pbase))); print(); base.print(); pbase->print(); delete pbase; return 0; }
输出结果为:
0x10f7f1cd0 0x10f7f1ee0 0x10f7f1ee0 print Base::print Base::print 0x10f7f1cd0 0x10f7f1cd0 0x10f7f1cd0 print Base::print print
注意虚函数的调用时刻。
Linux mprotect函数 -- control the protection of pages
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.