2012-08-05 49 views
1

我在x86_64上编写了一个示例代码,尝试执行dynamiclly malloc代码。 有一个执行dynamiclly 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; 
} 
+1

你试过调试器吗? – 2012-08-05 06:13:02

+0

是的,我用gdb。 – hellolwq 2012-08-05 06:17:35

+0

它给你一个错误代码? – ChiefTwoPencils 2012-08-05 06:19:13

回答

0

问题是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; 
    } 
+1

如果有问题的区域穿过页面边界,则无法正确设置两个页面的保护。 – 2012-08-05 07:10:20

2

千万不要检查系统函数的返回这样的技巧。为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). 

所以不要做,与malloc编辑缓冲区。

另外:

  • 缓冲区的大小仅仅是sizeof(code_str),没有理由通过sizeof(char)分(这是保证为1,但是这并不能使它正确)。
  • 没有必要投下malloc(如果将其更改为)的回报。
  • code_str的正确类型是unsigned char而不是char
+0

谢谢!这是一个很好的帮助。 – hellolwq 2012-08-05 06:58:20

+0

不客气。但是考虑到这一点,正如人们在评论中所说的那样,主要的错误可能与'&bin'有关。 '0x0000000000601010'看起来不像'malloc'ed地址。 – 2012-08-05 07:02:28