猿问

在mmap中执行代码以生成可执行代码段错误

我试图编写一个函数来复制一个函数(并最终修改其程序集)并返回它。对于一个间接级别来说,这很好用,但在两个级别上,我都遇到了段错误。


这是一个最小的(不)工作示例:


#include <stdio.h>

#include <string.h>

#include <sys/mman.h>


#define BODY_SIZE 100


int f(void) { return 42; }

int (*G(void))(void) { return f; }

int (*(*H(void))(void))(void) { return G; }


int (*g(void))(void) {

    void *r = mmap(0, BODY_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

    memcpy(r, f, BODY_SIZE);

    return r;

}


int (*(*h(void))(void))(void) {

    void *r = mmap(0, BODY_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

    memcpy(r, g, BODY_SIZE);

    return r;

}


int main() {

    printf("%d\n", f());

    printf("%d\n", G()());

    printf("%d\n", g()());

    printf("%d\n", H()()());

    printf("%d\n", h()()()); // This one fails - why?


    return 0;

}

我可以一次将内存转移到mmap'ed区域中,以创建一个可以称为(g()())的有效函数。但是,如果我尝试再次应用(h()()()),则会出现段错误。我已经确认它可以正确创建的复制版本g,但是当我执行该版本时,就会出现段错误。


我为什么不能在一个mmap'ed区域中执行代码而又不能在另一个mmap'ed区域中执行代码呢?从带有x/i检查的探索性gdb-ing看来,我可以成功调用,但是当我返回该函数时,我所来自的函数已被擦除并替换为0。


如何使这种行为起作用?可能吗?


Qyouu
浏览 335回答 3
3回答
随时随地看视频慕课网APP
我要回答