"Permission denied" 当尝试从 docker 容器访问共享内存时,即使 --ipc 设置为 "host"

"Permission denied" when trying to access a shared memory from a docker container even though --ipc is set to "host"

我正在尝试在我的主机中设置一个共享内存,并使用 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

我试过:

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

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

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

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

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

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

When the operator executes docker run --privileged, Docker will enable access to all devices on the host as well as set some configuration in AppArmor or SELinux to allow the container nearly all the same access to the host as processes running outside containers on the host.

In addition to --privileged, the operator can have fine grain control over the capabilities using --cap-add and --cap-drop.

关于 IPC_OWNER 能力:

IPC_OWNER - Bypass permission checks for operations on System V IPC objects.

完整的命令现在是

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

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

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