É possível montar um dispositivo no namespace de um processo depois de unshare ()

3

Digamos que eu tenha um processo com um namespace MOUNT isolado pid 1200 o processo chamado unshare() para isolar seu namespace do processo pai. Desejo então montar um dispositivo acessível somente fora do namespace pid 1200 dentro do namespace pid 1200 . Isso é possível?

Eu quero montar um dispositivo ou vincular a montagem de um diretório no host dentro de um contêiner LXC em execução que tenha lxc.monitor.unshare = 1 sem reiniciar o contêiner.

    
por user2059857 03.01.2016 / 07:26

2 respostas

2

Não é ideal, mas você sempre pode fazer uma montagem NFS ou outro sistema de arquivos de rede.

A parte abaixo faz not funcionar (pelo menos não com um kernel 4.2), colocando-o como referência para que um não tente por si mesmo.

Embora quando você insere um namespace de montagem ( nsenter -m ou setns(CLONE_NEWNS) ), seu diretório de trabalho é alterado automaticamente para a raiz ( / ) desse namespace, ainda é possível abrir um diretório em algum descritor de arquivo , insira o namespace e ainda tenha esse diretório aberto nesse fd (e, por exemplo, faça um fchdir() nele).

Então você acha que essa abordagem pode funcionar:

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <sched.h>

void die(char *msg) {perror(msg); exit(1);}
int main(int argc, char *argv[]) {
  int fd;
  if (argc != 3) {
    fprintf(stderr, "Usage: %s <source-in-current-namespace> <dest-in-namespace-on-stdin>\n");
    exit(1);
  }
  fd = open(argv[1], O_RDONLY|O_DIRECTORY);
  if (fd < 0) die("open");
  if (setns(0, CLONE_NEWNS) < 0) die("setns");
  if (fchdir(fd) < 0) die("fchdir");
  printf("cwd: %s\n", get_current_dir_name());
  if (mount(".", argv[2], 0, MS_BIND, 0) < 0) die("mount");
}

Ele funciona até o fchdir() , mas o mount falha com EINVAL :

# ~/a.out /home /mnt < /proc/1200/ns/mnt
cwd: (unreachable)/home
mount: Invalid argument
    
por 03.01.2016 / 16:52
0

Eu tive algum sucesso com isso - se não com um contêiner lxc, consegui fazê-lo funcionar para um namespace de montagem particular. Como o lxc é construído nos namespaces linux subjacentes que eu também estava usando, não vejo nenhum motivo para que ele não funcione para você.

Em primeiro lugar, eu configuro o namespace como:

sudo unshare -m sh -c '
    mount -ttmpfs none /tmp
    echo x > /tmp/mytmp
    findmnt -o+PROPAGATION /tmp
    echo "$$"
    cd   /tmp
    exec "$0" -i
TARGET SOURCE FSTYPE OPTIONS     PROPAGATION
/tmp   tmpfs  tmpfs  rw          private
/tmp   none   tmpfs  rw,relatime private
29384
$ 

... e eu tenho um shell interativo. A próxima coisa que fiz em uma sessão de terminal separada foi ...

sudo sh -c ' { cd /dev/fd/0 ; mkdir mnt
               ls -l;         cat mytmp
             } 3<$0/ns/mnt  <$0/29384/cwd
' /proc/29384
drwxr-xr-x 2 root root 40 Jan  4 02:52 mnt
-rw-r--r-- 1 root root  2 Jan  4 02:38 mytmp
x

... o que foi muito encorajador!

Mas eu não consegui montar uma montagem - toda vez que eu tentava mount um diretório pai ns sobre um no filho ns ele falhou - miseravelmente. Algumas pesquisas sugerem que isso é por design (em particular: veja as advertências em man 7 user_namespaces sobre bandeiras de PROPAGAÇÃO) . O que fez funcionar, porém, foi (em um novo namespace) :

sudo unshare --propagation slave -m sh -c '
     mount -ttmpfs none /tmp; cd /tmp
     exec "$0" -i'

E, em seguida, na sessão de namespace pai ...

sudo mount --bind / /mnt
sudo mount --bind / /tmp
sudo mount --bind /tmp /mnt/img/tmp

Agora, o acima funciona no primeiro caso, mas não no segundo. Como o filho ns não propaga as mudanças fs para cima, o pai não afeta as mudanças que ele fez na exibição fs. E assim, porque o filho tem sua própria montagem em /tmp , tudo o que o pai faz é irrelevante lá. No entanto, se houver alguma hierarquia comum e o filho ns estiver configurado para receber alterações no sistema de arquivos, então irá ver as alterações que o pai propaga para baixo.

No filho ns depois de executar o acima ...

ls /tmp /mnt /mnt/tmp
/mnt:
bin   dev  etc   lib    mnt  proc  run   srv  tmp  var
boot  esp  home  lib64  opt  root  sbin  sys  usr

/mnt/tmp:
serverauth.FT3Z6IFyWW
systemd-private-...systemd-timesyncd.service-YUkVU6

/tmp:

E então eu acho que para responder a pergunta - sim, eu acredito que é possível. Mas também tenho certeza que você precisa organizar para que seja tão adiantado.

    
por 04.01.2016 / 14:58