shm_open()的mode参数中执行位的作用及同组跨用户调用权限问题
关于shm_open执行位作用的核心解答
1. 同组用户调用失败的根因
你使用的共享内存对象名称是com/page,Linux下shm_open会将名称映射到/dev/shm/路径下,因此调用时需要先访问/dev/shm/com这个目录,再访问目录下的page共享内存对象。
当第一个进程带O_CREAT调用shm_open时,内核会自动创建不存在的中间目录/dev/shm/com,该目录的权限直接取自你传入的mode参数:
- 初始
mode没有设置执行位:/dev/shm/com目录的组权限只有读写,而目录的执行位对应遍历权限,同组用户没有执行位就无法进入目录、访问目录内的文件,因此第二个进程调用shm_open时就会报权限错误。 - 给
mode加上执行位后:创建的/dev/shm/com目录就有了组执行位,同组用户可以正常遍历目录访问内部的共享内存对象,调用自然成功。
这和你观察到的「目录缺少执行位无法cd进入」的现象完全一致。
补充你提前建目录报错的原因:shm_open的名称参数要求是基于共享内存tmpfs根路径的相对路径,不能传入/dev/shm/开头的绝对路径,也不能包含..这类相对路径标识,否则会直接返回EINVAL错误。
2. 执行位与shellcode执行的关系
共享内存对象的执行位不会直接让内存中的代码可执行,能否执行取决于两个条件同时满足:
- 共享内存对象对当前进程的有效用户/组有执行权限(也就是你
mode里设置的执行位) - 调用
mmap映射共享内存时,显式指定了PROT_EXEC权限
如果mmap时没有设置PROT_EXEC,哪怕共享内存对象有执行位,映射后的内存段也是不可执行的,无法直接运行其中的shellcode。反过来如果没有执行位,就算mmap指定PROT_EXEC,内核也会返回权限错误(root用户或特殊安全配置关闭的场景除外)。
额外优化建议
如果你的场景不需要层级结构的共享内存命名,建议直接使用开头带单个斜杠的扁平名称,比如/com_page,就不会涉及中间目录权限问题,不需要额外加执行位也能正常跨同组用户访问。
内容的提问来源于stack exchange,提问作者heldertz
相关产品推荐
相关产品推荐

