signal 11信号的处理

来源:互联网 发布:中国电信云计算北京 编辑:程序博客网 时间:2024/05/22 15:36

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <setjmp.h>
    

 char *buf;
 struct stat statbuf;

void handler(int signo)
{
      printf("permission denied/n");

/*  

     if(mprotect(buf, statbuf.st_size, PROT_READ|PROT_WRITE)==-1) //改变内存映射区访问权限
       {
                 perror("fail to alter permission");
                 exit(1);
       }
        printf("modify/n");

*/
}

int main(void)
{
     int fd;


     if((signal(SIGSEGV, handler)) == SIG_ERR)     //设置SIGSEGV信号处理程序

     {
              printf("can't set handler for SIGALRM");
              exit(0);
      }

      if(stat("test.txt", &statbuf) == -1) //得到文件状态信息
      {
               perror("fail to get stat");
               exit(1);
       }

       fd = open("test.txt", O_RDWR); //以读写方式打开文件
      if(fd == -1)
      {
               perror("fail to open");
               exit(1);
       }

       buf = (char *)mmap(NULL,statbuf.st_size,PROT_READ,MAP_SHARED,fd,0); //建立内存映射区,访问权限为只读

       printf("try to write/n");
       memcpy(buf, "china/n", 6); // 企图写一个只读的映射区,造成SIGSEGV错误


       if(mprotect(buf, statbuf.st_size, PROT_READ|PROT_WRITE)==-1) //改变内存映射区访问权限
       {
                 perror("fail to alter permission");
                 exit(1);
       }

       printf("write again/n");
       memcpy(buf, "china/n", 6); //再次写内存映射区

       if(munmap(buf, statbuf.st_size) == -1) //撤销内存映射
      {
             perror("fail to munmap");
             exit(1);
       }

             close(fd);

            return 0;

}

程序打印结果:

try to write
permission denied
permission denied
permission denied
permission denied
permission denied
permission denied
permission denied
permission denied

分析:

程序本意:该程序演示越权访问一个内存映射区。首先创建一个只读的内存映射区,之后对其进行写操作。该越权访问造成程序收到SIGSEGV信号。应用程序接收该信号,并输出提示信息不能关切输出提示信息。接下来程序调用mprotect函数改变映射区的访问权限为可读写。此时,再次向映射区进行写操作就可以成功了。

但是:当程序捕捉到SIGSEGV信号时,本意是希望捕获信号输出提示信息后,程序能继续运行。但是,中断返回点仍旧在非法访问处,如此则进入一个“非法访问--信号--处理--非法访问”的死循环中。

改进方法:

把红色的代码注掉,将蓝色的代码放开(把mprotect(...)的调用放在信号处理函数中)
打印结果:

try to write
permission denied
modify
write again

此时紫色的代码可以去掉,因为signal信号处理函数,会返回到memcpy函数调用处执行

原创粉丝点击