I'm trying to set up a shared memory in my host computer and access it in a centos:7
docker container with the shmat
function.
I've created a shared memory using ipcmk -M 1024
and wrote a C program with the ID hardcoded (for debugging purposes):
// 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");
My Dockerfile is very simple, all I do is copy the compiled program and keep the container alive so that I can inspect it with an interactive shell:
# Dockerfile
FROM centos:7
COPY ./shmtest /root/
CMD tail -f /dev/null
I build and start the container using
docker build -t shm-docker .
docker run --ipc="host" shm-docker
Inside the docker container, I run my shmtest
program, but can't access the shared memory:
./shmtest
No shared memory area: Permission denied
Aborted
However, ipcs
shows the shared memory:
ipcs -m | grep 98321
0x8a39b8b3 98321 1000 644 65536 0
I've tried:
-v /dev/:/dev/
and -v /dev/shm/:/dev/shm/
, without any lucksetcap
; then I couldn't run it (./shmtest: Operation not permitted
)centos:7
in my Dockerfile with ubuntu:18.04
, still didn't work, which means that this problem is not specific to centosUnfortunately, I don't know a lot about permissions, but I've noticed that my shared memory shows the number 644
when running ipcs
and various other ones show 600
. I've also tried accessing those and I still get the same error.
What am I missing here? Is my idea even valid or is it not possible to access the shared memory this way?
The permissions 644
of the shared memory allow its owner to read and write (first 6) but only gives read access to everyone else (last 4).
The root
user in the docker container isn't the owner of the shared memory, so he doesn't have permission to write to the shared memory.
If you have access to the tool which creates the shared memory, you could change the permissions to something like 606
, which means read and write access to the owner and everyone else, too. For example, the ipcmk
command has a -p
option, so you would run ipcmk -M 1024 -p 0606
.
If you can't change how the shared memory is created, this can be solved by either adding the --privileged
flag or, more precisely, the --cap-add=IPC_OWNER
flag to the docker run
command. From the 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.
And regarding the IPC_OWNER
capability:
IPC_OWNER - Bypass permission checks for operations on System V IPC objects.
The full command is now either
docker run --ipc="host" --privileged shm-docker
or
docker run --ipc="host" --cap-add=IPC_OWNER shm-docker
A good tool to understand permissions is the Chmod Calculator, which is an interactive tool to see how permissions are encoded in octal digits and characters, too.