首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >linux c/ mmap/mprotect问题

linux c/ mmap/mprotect问题
EN

Stack Overflow用户
提问于 2012-08-12 09:08:40
回答 2查看 2.9K关注 0票数 2

我需要做一个小的软件,它需要保护一个页面进行读/写,然后当内存被访问时,它需要增加一个计数器并允许读/写,之后它需要保护内存回来

我有这段代码,但它导致了无限循环

代码语言:javascript
复制
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static int alloc_size;
static char* memory;

void segv_handler (int signal_number) 
{
 printf ("memory accessed!\n");
 /* allow read and write */
 mprotect (memory, alloc_size, PROT_READ | PROT_WRITE);

 /* Protect memory back*/
 mprotect (memory, alloc_size, PROT_NONE);
} 

int main ()
{
 struct sigaction sa;

 /* Install segv_handler as the handler for SIGSEGV. */
 memset (&sa, 0, sizeof (sa));
 sa.sa_handler = &segv_handler;
 sigaction (SIGSEGV, &sa, NULL);

 alloc_size = 4096;
 memory = mmap (0, alloc_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);   /* anonymous mapping doesn't need a file desc */

 /* Write to the page to obtain a private copy. */
 memory[0] = 0;
 memory[1] = 0;

 /* Make the memory unwritable. */
 mprotect (memory, alloc_size, PROT_NONE);
 /* Write to the allocated memory region. */
 memory[0] = 1; //--> this should trigger the SIGSEGV
 memory[1] = 1;

 /* All done; unmap the memory. */
 printf ("all done\n");
 munmap (memory, alloc_size);
 return 0;
}
EN

回答 2

Stack Overflow用户

发布于 2012-08-13 06:26:25

您所说的基本上是(1)捕获无效的内存访问,(2)暂时取消对页面的保护,(3)允许内存访问,(4)重新保护页面,(5)恢复正常执行。但这不是您的代码所做的事情。你的segv_handler取消保护页面(步骤2),然后立即重新保护它(步骤4),所以当你的segv_handler返回的时候已经太晚了,步骤3.指令再次失败,你会得到一个无限循环。

安装信号处理程序不支持您需要执行的操作。您需要做的是做一些更改,执行一条指令,然后再做一些更改。只有在调试器下单步执行程序才能做到这一点。

ptrace是执行此操作所需的系统调用。有关于ptrace和单步执行的many questions,但我警告你: ptrace不是给胆小鬼用的,它比信号处理程序复杂得多。

票数 0
EN

Stack Overflow用户

发布于 2015-02-14 00:31:56

我认为你可以使用一些反汇编库,如Libasm来实现这一点,但它看起来不会那么好。

在你的segv_handler中,

counter)

  • Before

  • 允许对页进行读/写操作,并加载导致信号的最后一条指令,将其放入可执行内存并运行它。

  • segv_handler做您想做的事情(增加一个SIGSEGV返回,将堆栈上的返回地址修改为下一条指令,以便您不会两次运行该指令并再次捕获信号。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11918955

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档