LINUX.ORG.RU

unshared mount namespace

 , ,


1

2

Приветствую,

% sudo unshare --mount=/tmp/mnt1 /bin/bash
unshare: mount /proc/1178/ns/mnt on /tmp/mnt1 failed: Not a directory 

То есть как я понимаю, после успешного выполнения команды я буду в новом mount namespace'е с запущенным bash, и все примонтированные файловые системы будут изолированы от хоста.

Директория /tmp/mnt1 присутствует.

Возвращаемая ошибка -ENOTDIR, man говорит следующее:

ENOTDIR
              target, or a prefix of source, is not a directory.

Полез смотреть код в util-linux-2.31/sys-utils/unshare.c :

static int bind_ns_files(pid_t pid)
{
   struct namespace_file *ns;
   char src[PATH_MAX];

   for (ns = namespace_files; ns->name; ns++) {
      if (!ns->target)
         continue;

      snprintf(src, sizeof(src), "/proc/%u/%s", (unsigned) pid, ns->name);

      if (mount(src, ns->target, NULL, MS_BIND, NULL) != 0)
         err(EXIT_FAILURE, _("mount %s on %s failed"), src, ns->target);  /* здесь происходит ошибка */
   }

   return 0;
}

static void bind_ns_files_from_child(pid_t *child, int fds[2])
{
   char ch;
   pid_t ppid = getpid();
   ino_t ino = get_mnt_ino(ppid);
   
   if (pipe(fds) < 0)
      err(EXIT_FAILURE, _("pipe failed"));
      
   *child = fork();
   
   switch (*child) {
   case -1:
      err(EXIT_FAILURE, _("fork failed"));
      
   case 0:  /* child */
      close(fds[1]);
      fds[1] = -1;
      
      /* wait for parent */
      if (read_all(fds[0], &ch, 1) != 1 && ch != PIPE_SYNC_BYTE)
         err(EXIT_FAILURE, _("failed to read pipe"));
      if (get_mnt_ino(ppid) == ino)
         exit(EXIT_FAILURE);
      bind_ns_files(ppid);
      exit(EXIT_SUCCESS);
      break;

   default: /* parent */
      close(fds[0]);
      fds[0] = -1;
      break;
}

...

if (npersists && (unshare_flags & CLONE_NEWNS))
   bind_ns_files_from_child(&pid, fds);

if (-1 == unshare(unshare_flags))
   err(EXIT_FAILURE, _("unshare failed"));

Что я делаю не так?


Ответ на: комментарий от cruz7

IMHO нашел источник проблемы. В функции bind_ns_files() мы монтируем /proc/PID/ns/mnt на /tmp/unshare с флагом MS_BIND, однако точка монтирования /tmp/unshare должна быть на файловой системе смонтированной как private, MS_PRIVATE, а на моей Ubuntu-16.04 все ФС смонтированы как shared :

% mkdir /tmp/unshare
% mount --bind /tmp/unshare /tmp/unshare
% mount --make-private /tmp/unshare
% touch /tmp/unshare/mnt
% unshare --mount=/tmp/unshare/mnt /bin/bash

Теперь unshare выполняется без ошибки, однако в новой namespac'e я по-прежнему вижу хост-ФС и могу туда писАть. При этом на хосте теперь имеется примонтированная на /tmp/unshare/mnt ФС типа nsfs.

cruz7 ()
Ответ на: комментарий от cruz7

OK. Таки система делает то, что я и попросил - mount namespace-ы. То есть именно точки монтирования изолированы: например в контейнере я могу отмонтировать /proc или /dev/mqueue но на хосте этих изменений не будет. А вот R/W на файловые системы в контейнере — это наверное ближе к userns ??

cruz7 ()