在匿名的elf文件上调用execl是否安全?

时间:2019-05-21 14:35:29

标签: linux

首先通过

创建一个匿名内存块
int fd = memfd_create("", MFD_CLOEXEC);

请注意,我传递了MFD_CLOEXEC标志。 然后,我将elf文件的内容复制到该匿名内存中。 小精灵是这样执行的:

char cmd[128];
sprintf(cmd, "/proc/self/fd/%i", fd);
execl(cmd, "dummy", NULL);

MFD_CLOEXEC意味着fd将在execl之后关闭,但是execl需要从fd加载elf内容。我做了一个简单的测试,看来还可以。但是我不确定它是否安全。

更新:

#define _GNU_SOURCE 
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <stdio.h>

extern uint8_t foo_data[]      asm("_binary_htop_start");
extern uint8_t foo_data_size[] asm("_binary_htop_size");
extern uint8_t foo_data_end[]  asm("_binary_htop_end");
int main(int argc, char **argv)
{
    int exefd = memfd_create("", MFD_CLOEXEC);
    printf("%p %d %ld\n", foo_data, exefd, write(exefd, foo_data, foo_data_end-foo_data));
    char * const vv[] = {"htopp", NULL};
    //execveat(exefd, NULL, vv, NULL, AT_EMPTY_PATH);
    exefd = syscall(__NR_execveat, exefd, NULL, vv, NULL, AT_EMPTY_PATH);
    perror("");
    return 0;
}

我尝试使用execveat但失败了。 syscall将errno设置为“错误地址”,不知道原因。 elf内容由objcopy生成。

1 个答案:

答案 0 :(得分:0)

对于真正的二进制文件(如ELF文件),无论是静态链接还是动态链接,它都很好。

MFD_CLOEXEC不适用于可执行脚本(例如,以#! /bin/sh开头的文件)。在这种情况下,您必须忽略该标志并使fd保持打开状态。

您应该研究使用sprintf(而不是execl / execveat(fd, "", argv, env, AT_EMPTY_PATH)的把戏)(不幸的是,使用O_CLOEXEC打开的可执行脚本也有同样的问题,但事实并非如此) t依赖于/proc fs的安装)。

当然,对于变量函数,例如(void*)0,应该始终使用NULL而不是execl();-)