执行动态 malloc 代码时出现“分段错误”

Posted

技术标签:

【中文标题】执行动态 malloc 代码时出现“分段错误”【英文标题】:"Segmentation fault" while execute dynamiclly malloc code 【发布时间】:2012-08-05 06:08:33 【问题描述】:

我在 x86_64 上编写了一个示例代码,尝试执行动态 malloc 代码。 有一个

程序收到信号SIGSEGV,分段错误。 0x0000000000601010 在?? ()

0x0000000000601010 是 bin 的位置,谁能告诉我为什么?谢谢!!

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/mman.h>
volatile int sum(int a,int b)

    return a+b;


int main(int argc, char **argv)

   char* bin = NULL;    
   unsigned int len = 0;
   int ret = 0;
   /*code_str is the compiled code for function sum.*/
   char code_str[] =0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x89,
          0x75,0xf8,0x8b,0x45,0xf8,0x03,0x45,0xfc,0xc9,0xc3;
   len = sizeof(code_str)/sizeof(char);
   bin = (char*)malloc(len);
   memcpy(bin,code_str,len);
   mprotect(bin,len , PROT_EXEC | PROT_READ | PROT_WRITE);
   asm volatile ("mov $0x2,%%esi \n\t"
        "mov $0x8,%%edi \n\t"
        "mov %1,%%rbx \n\t"
        "call *%%rbx "
        :"=a"(ret)
        :"g"(bin)
        :"%rbx","%esi","%edi");

   printf("sum:%d\n",ret);
   return 0;

【问题讨论】:

它给你一个错误代码吗? 在mprotect中是否需要通过bin? pl。检查 &bin 是否正确。 不要将&amp;bin 传递给mprotect,而只是传递bin 【参考方案1】:

如果不检查系统函数的返回,千万不要这样做。我的mprotect 手册页特别指出:

   POSIX  says  that  the  behavior of mprotect() is unspecified if it
   is applied to a region of memory that was not obtained via mmap(2).

所以不要对malloced 缓冲区这样做。

还有:

缓冲区大小只是sizeof(code_str),没有理由除以sizeof(char)(保证为1,但这并不能使其正确)。 无需转换 malloc 的返回值(如果您将其更改为 mmap,也无需转换)。 code_str 的正确类型是 unsigned char 而不是 char

【讨论】:

不客气。但想想看,主要错误可能是人们在 cmets 中所说的 &amp;bin 的问题。 0x0000000000601010 看起来不像 malloced 地址。【参考方案2】:

问题是bin地址应该与多个PAGESIZE对齐,否则mprotect将返回-1,参数无效。

   bin = (char *)(((int) bin + PAGESIZE-1) & ~(PAGESIZE-1));//added....
   memcpy(bin,code_str,len);
   if(mprotect(bin, len , PROT_EXEC |PROT_READ | PROT_WRITE) == -1)
   
     printf("mprotect error:%d\n",errno);
     return 0;
   

【讨论】:

如果有问题的区域跨越页面边界,这将无法正确设置两个页面的保护。

以上是关于执行动态 malloc 代码时出现“分段错误”的主要内容,如果未能解决你的问题,请参考以下文章

访问结构时出现分段错误

创建列表时出现分段错误

打印指针时出现分段错误

调用printf%s时出现分段错误

编辑可执行文件代码时出现分段错误

尝试连接二维数组的元素时出现分段错误