尝试从 docker 容器访问共享内存时出现“权限被拒绝”,即使 --ipc 设置为“主机”

Posted

技术标签:

【中文标题】尝试从 docker 容器访问共享内存时出现“权限被拒绝”,即使 --ipc 设置为“主机”【英文标题】:"Permission denied" when trying to access a shared memory from a docker container even though --ipc is set to "host" 【发布时间】:2020-09-17 13:08:00 【问题描述】:

我正在尝试在我的主机中设置一个共享内存,并使用shmat 函数在centos:7 docker 容器中访问它。 我使用ipcmk -M 1024 创建了一个共享内存,并编写了一个ID 硬编码的C 程序(用于调试目的):

// shmtest.c
const char* shm_id = "98321";

shared_memory = shmat(atoi(shm_id), NULL, 0);

if (shared_memory == (void*)-1) 
    perror("No shared memory area");
    abort();


fprintf(stdout, "Shared memory found!\n");

我的 Dockerfile 非常简单,我所做的只是复制编译后的程序并保持容器处于活动状态,以便我可以使用交互式 shell 对其进行检查:

# Dockerfile
FROM centos:7
COPY ./shmtest /root/
CMD tail -f /dev/null

我使用

构建和启动容器
docker build -t shm-docker .
docker run --ipc="host" shm-docker

在 docker 容器中,我运行我的 shmtest 程序,但无法访问共享内存:

./shmtest 
No shared memory area: Permission denied
Aborted

但是,ipcs 显示共享内存:

ipcs -m | grep 98321
0x8a39b8b3 98321      1000       644        65536      0

我试过了:

使用 -v /dev/:/dev/-v /dev/shm/:/dev/shm/ 启动 docker 容器,没有任何运气 使用setcap 为我的程序提供CAP_IPC_OWNER 和CAP_IPC_LOCK 功能;然后我无法运行它 (./shmtest: Operation not permitted) 在我的 Dockerfile 中用ubuntu:18.04 切换出centos:7,仍然没有工作,这意味着这个问题不是特定于centos 的

不幸的是,我不太了解权限,但我注意到我的共享内存在运行ipcs 时显示数字644,而其他各种显示600。我也尝试过访问这些,但仍然遇到同样的错误。

我在这里缺少什么?我的想法是否有效,或者无法以这种方式访问​​共享内存?

【问题讨论】:

【参考方案1】:

共享内存的权限644 允许其所有者读取和写入(前 6 个),但只授予其他所有人读取权限(后 4 个)。

docker 容器中的root 用户不是共享内存的所有者,因此他没有写入共享内存的权限。

如果您有权访问创建共享内存的工具,则可以将权限更改为 606 之类的内容,这意味着对所有者和其他所有人也有读写权限。例如,ipcmk 命令有一个-p 选项,因此您将运行ipcmk -M 1024 -p 0606

如果您无法更改共享内存的创建方式,可以通过将--privileged 标志或更准确地说,将--cap-add=IPC_OWNER 标志添加到docker run 命令来解决此问题。来自docker run reference:

当操作员执行 docker run --privileged 时,Docker 将启用对主机上所有设备的访问,并在 AppArmor 或 SELinux 中设置一些配置,以允许容器几乎与在容器外运行的进程一样访问主机在主机上。

除了 --privileged 之外,操作员还可以使用 --cap-add 和 --cap-drop 对功能进行细粒度控制。

关于IPC_OWNER 功能:

IPC_OWNER - 绕过对 System V IPC 对象的操作的权限检查。

现在是完整的命令

docker run --ipc="host" --privileged shm-docker

docker run --ipc="host" --cap-add=IPC_OWNER shm-docker

了解权限的好工具是Chmod Calculator,它是一个交互式工具,可以查看权限是如何以八进制数字和字符编码的。

【讨论】:

以上是关于尝试从 docker 容器访问共享内存时出现“权限被拒绝”,即使 --ipc 设置为“主机”的主要内容,如果未能解决你的问题,请参考以下文章

访问共享内存时出现分段错误

访问共享进程内存时出现分段错误(核心转储)

尝试从主机连接到 mysql docker 容器时出现“读取初始通信数据包”错误

使用 rust 二进制文件运行 docker 映像时出现权限被拒绝错误

访问 postgres docker 容器时出现连接错误

尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为啥?