«Отказано в разрешении» при попытке доступа к общей памяти из контейнера docker, даже если для —ipc установлено значение «хост»

#docker #ipc #shared-memory

#docker #ipc #разделяемая память

Вопрос:

Я пытаюсь настроить общую память на своем главном компьютере и получить к ней доступ в centos:7 контейнере docker с shmat помощью функции. Я создал общую память, используя ipcmk -M 1024 и написал программу на 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 очень прост, все, что я делаю, это копирую скомпилированную программу и сохраняю контейнер в рабочем состоянии, чтобы я мог проверять его с помощью интерактивной оболочки:

 # 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
  

Я пробовал:

  • Запуск контейнера docker с -v /dev/:/dev/ помощью и -v /dev/shm/:/dev/shm/ , без какой-либо удачи
  • Предоставление моей программе возможности CAP_IPC_OWNER и CAP_IPC_LOCK с setcap помощью; тогда я не смог его запустить ( ./shmtest: Operation not permitted )
  • Переключение centos:7 в моем Dockerfile с ubuntu:18.04 помощью , по-прежнему не сработало, что означает, что эта проблема не характерна для centos

К сожалению, я мало что знаю о разрешениях, но я заметил, что моя общая память показывает номер 644 при запуске ipcs , а также различные другие 600 . Я также пытался получить к ним доступ, и я все еще получаю ту же ошибку.

Чего мне здесь не хватает? Действительно ли моя идея верна или невозможно получить доступ к общей памяти таким образом?

Ответ №1:

Разрешения 644 общей памяти позволяют ее владельцу читать и записывать (первые 6), но предоставляют доступ на чтение только всем остальным (последние 4).

root Пользователь в контейнере docker не является владельцем общей памяти, поэтому у него нет разрешения на запись в общую память.

Если у вас есть доступ к инструменту, который создает общую память, вы можете изменить разрешения на что-то вроде 606 , что означает доступ на чтение и запись для владельца и всех остальных тоже. Например, у ipcmk команды есть -p опция, поэтому вы должны выполнить ipcmk -M 1024 -p 0606 .

Если вы не можете изменить способ создания общей памяти, это можно решить, добавив --privileged флаг или, точнее, --cap-add=IPC_OWNER флаг в docker run команду. Из ссылки на запуск docker:

Когда оператор выполняет 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, который представляет собой интерактивный инструмент, позволяющий увидеть, как разрешения кодируются восьмеричными цифрами и символами.