共享可执行内存

时间:2014-08-12 11:22:35

标签: executable virtual-memory shared-memory mmap

我有一小段C:

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,因为只要mmap没有PROT_EXECmmap成功使用任意权限组合。 mprotect没有执行权限,然后尝试{{1}}它也会失败。

1 个答案:

答案 0 :(得分:4)

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

我已修改您的代码,以便在perror失败的情况下添加mmap(并返回2):

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