我有以下代码,我尝试在堆栈中写入内容。我写在堆栈的底部,应用程序仍然没有触及(注意堆栈向下增长, stackaddr 在这里指向底部)。
然而,即使在执行 mprotect 以向该内存区域提供写入和读取权限之后,我也会出现分段错误。即使我使用编译标志 -fno-stack-protector ,我也会出现分段错误。这里发生了什么?
pthread_attr_t attr;
void * stackaddr;
int * plocal_var;
size_t stacksize;
pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack( &attr, &stackaddr, &stacksize );
printf( "stackaddr = %p, stacksize = %d\n", stackaddr, stacksize );
plocal_var = (int*)stackaddr;
mprotect((void*)plocal_var, 4096, PROT_READ | PROT_WRITE);
*plocal_var = 4;
printf( "local_var = %d!\n", *plocal_var );
答案 0 :(得分:3)
您几乎肯定会尝试mprotect()
尚未映射的页面。您应该检查返回代码:mprotect()
可能返回-1并将errno
设置为ENOMEM
(这在mprotect(2)
man page中有记录)。
堆栈页面是按需映射的,但是内核足够聪明,可以区分由当前堆栈指针处或之上的访问引起的页面错误(这是由向下扩展堆栈的有效尝试引起的,通过递减堆栈指针,然后执行读取或写入新值的某些正偏移量),以及由堆栈指针下方的访问引起的页面错误(无效)。