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

问题描述

我正在尝试在主机计算机中设置共享内存,并使用centos:7函数shmat 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("Can't access shared memory!");
    abort();
}

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

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

# 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
  • 使用centos:7切换Dockerfile中的ubuntu:18.04仍然无法正常工作,这意味着此问题并非特定于centos

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

在这里想念什么?我的想法是否有效,还是无法通过这种方式访问​​共享内存?

解决方法

共享内存的权限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是了解权限的一个很好的工具,它是一种交互式工具,也可以查看权限如何以八位数字和字符编码。