【问题标题】:Shared executable memory共享可执行内存
【发布时间】:2014-10-06 04:47:51
【问题描述】:

我有这个 C 的简短 sn-p:

const char *name = "/asdf";
int desc = shm_open(name, O_RDWR | O_CREAT, 0777);
ftruncate(desc, 4096);
void *block = mmap(NULL, 4096, PROT_EXEC, MAP_SHARED, desc, 0);
shm_unlink(name);

它创建了一个共享内存对象,每个人都可以写、读和执行;然后将其映射到具有可执行权限的内存中。但是,由于某种原因,mmap 调用失败并显示为EPERM
Strace 给出以下信息:

statfs("/dev/shm/", {f_type=0x1021994, f_bsize=4096, f_blocks=450722, f_bfree=450372, f_bavail=450372, f_files=450722, f_ffree=450713, f_fsid={0, 0}, f_namelen=255, f_frsize=4096}) = 0
futex(0x7fa7f4c8b330, FUTEX_WAKE_PRIVATE, 2147483647) = 0
open("/dev/shm/asdf", O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0777) = 3
fcntl(3, F_GETFD)                       = 0x1 (flags FD_CLOEXEC)
ftruncate(3, 4096)                      = 0
mmap(NULL, 4096, PROT_EXEC, MAP_SHARED, 3, 0) = -1 EPERM (Operation not permitted)

问题似乎是由使用PROT_EXEC 引起的,因为只要没有PROT_EXECmmap 使用任何权限组合都会成功。
mmaping 没有执行权限,然后尝试@ 987654329@ 也失败了。

【问题讨论】:

    标签: executable virtual-memory shared-memory mmap


    【解决方案1】:

    假设您在此处运行 Linux,/dev/shm 挂载的 [no]exec'ness 会传播到当前 Linux 内核中由 shm_open 创建的共享内存区域。因此,如果您的 /dev/shm 使用 noexec 挂载选项(某些发行版(Debian?)默认情况下可能会这样做)挂载,您的问题就会发生。

    我已修改您的代码以添加 perror(并返回 2)以防 mmap 失败:

    testbox $ mount|grep shm
    tmpfs on /dev/shm type tmpfs (rw)
    testbox $ ./a.out ; echo $?
    0
    testbox $ sudo mount -o remount,noexec /dev/shm
    testbox $ mount|grep shm
    tmpfs on /dev/shm type tmpfs (rw,noexec)
    testbox $ ./a.out ; echo $?
    mmap: Operation not permitted
    2
    

    【讨论】:

    • 哦,是的,shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime),绝对不会猜到是 FS...
    • 这里有一个很长的讨论:lkml.org/lkml/2006/9/23/44 关于这个(首先有人提出一个补丁来基本上摆脱这种行为)。我没有全部阅读,但如果你好奇的话,里面可能有一些有趣的信息。
    猜你喜欢
    • 2019-08-08
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多