当前位置: 技术问答>linux和unix
请教关于SIGSEGV信号的问题
来源: 互联网 发布时间:2016-11-25
本文导语: 该程序演示越权访问一个内存映射区。首先创建一个只读的内存映射区,之后对其进行写操作。该越权访问造成程序收到SIGSEGV信号。应用程序接收该信号,并输出提示信息不能关切输出提示信息。接下来程序调用mprot...
该程序演示越权访问一个内存映射区。首先创建一个只读的内存映射区,之后对其进行写操作。该越权访问造成程序收到SIGSEGV信号。应用程序接收该信号,并输出提示信息不能关切输出提示信息。接下来程序调用mprotect函数改变映射区的访问权限为可读写。此时,再次向映射区进行写操作就可以成功了。(这是程序本意)
程序源代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sig_segv(int signo);
jmp_buf jmpbuffer;
/*void handler(int signo)
{
printf("permission deniedn");
}*/
int main(void)
{
int fd;
char *buf;
struct stat statbuf;
/*if(setjmp(jmpbuffer) != 0)
{
printf("permission deniedn");
}*/
/* if((signal(SIGSEGV, handler)) == SIG_ERR)
{
printf("can't set handler for SIGALRM");
exit(0);
}*/
if((signal(SIGSEGV, sig_segv)) == 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); //建立内存映射区,访问权限为只读
if(buf == MAP_FAILED)
{
perror("fail to mmap");
exit(1);
}
if(setjmp(jmpbuffer) != 0)
{
printf("permission deniedn");
}
printf("try to writen");
memcpy(buf, "chinan", 6); // 企图写一个只读的映射区,造成SIGSEGV错误
/*if(setjmp(jmpbuffer) != 0)
{
printf("permission deniedn");
}*/
if(mprotect(buf, statbuf.st_size, PROT_READ|PROT_WRITE)==-1) //改变内存映射区访问权限
{
perror("fail to alter permission");
exit(1);
}
printf("write againn");
memcpy(buf, "chinan", 6); //再次写内存映射区
if(munmap(buf, statbuf.st_size) == -1) //撤销内存映射
{
perror("fail to munmap");
exit(1);
}
close(fd);
return 0;
}
void sig_segv(int signo)
{
longjmp(jmpbuffer, 1);
}
当程序捕捉到SIGSEGV信号时,本意是希望捕获信号输出提示信息后,程序能继续运行。但是,中断返回点仍旧在非法访问处,如此则进入一个“非法访问--信号--处理--非法访问”的死循环中。本想借用setjmp和longjmp解决,奈何setjmp必须在调用longjmp之前调用,以确定jmpbuffer的值。所以,用了,跟没用一样。返回setjmp后,还是同样进入死循环。
我已经没办法了,望高手指点一二,感激不尽!
程序源代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
void sig_segv(int signo);
jmp_buf jmpbuffer;
/*void handler(int signo)
{
printf("permission deniedn");
}*/
int main(void)
{
int fd;
char *buf;
struct stat statbuf;
/*if(setjmp(jmpbuffer) != 0)
{
printf("permission deniedn");
}*/
/* if((signal(SIGSEGV, handler)) == SIG_ERR)
{
printf("can't set handler for SIGALRM");
exit(0);
}*/
if((signal(SIGSEGV, sig_segv)) == 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); //建立内存映射区,访问权限为只读
if(buf == MAP_FAILED)
{
perror("fail to mmap");
exit(1);
}
if(setjmp(jmpbuffer) != 0)
{
printf("permission deniedn");
}
printf("try to writen");
memcpy(buf, "chinan", 6); // 企图写一个只读的映射区,造成SIGSEGV错误
/*if(setjmp(jmpbuffer) != 0)
{
printf("permission deniedn");
}*/
if(mprotect(buf, statbuf.st_size, PROT_READ|PROT_WRITE)==-1) //改变内存映射区访问权限
{
perror("fail to alter permission");
exit(1);
}
printf("write againn");
memcpy(buf, "chinan", 6); //再次写内存映射区
if(munmap(buf, statbuf.st_size) == -1) //撤销内存映射
{
perror("fail to munmap");
exit(1);
}
close(fd);
return 0;
}
void sig_segv(int signo)
{
longjmp(jmpbuffer, 1);
}
当程序捕捉到SIGSEGV信号时,本意是希望捕获信号输出提示信息后,程序能继续运行。但是,中断返回点仍旧在非法访问处,如此则进入一个“非法访问--信号--处理--非法访问”的死循环中。本想借用setjmp和longjmp解决,奈何setjmp必须在调用longjmp之前调用,以确定jmpbuffer的值。所以,用了,跟没用一样。返回setjmp后,还是同样进入死循环。
我已经没办法了,望高手指点一二,感激不尽!
|
把mprotect(...)的调用放在信号处理函数中
需要把buf及struct stat statbuf定义为全局变量
需要把buf及struct stat statbuf定义为全局变量
|
SIGSEGV信号不只是发一次,会一直发发到你的程序结束哦。