unshare() 후에 프로세스의 네임스페이스에 장치를 마운트할 수 있습니까?

unshare() 후에 프로세스의 네임스페이스에 장치를 마운트할 수 있습니까?

pid 1200다음과 같은 격리된 MOUNT 네임스페이스를 가진 프로세스가 있다고 가정해 보겠습니다 .unshare()해당 네임스페이스를 상위 프로세스에서 격리합니다. 그런 다음 pid 1200네임스페이스 내부에서만 액세스할 수 있는 장치를 마운트하고 싶습니다 pid 1200. 가능합니까?

lxc.monitor.unshare = 1컨테이너를 다시 시작 하지 않고 실행 중인 LXC 컨테이너 내부의 호스트 시스템에 장치를 마운트하거나 디렉터리를 바인드 마운트하고 싶습니다 .

답변1

이상적이지는 않지만 항상 NFS 또는 기타 네트워크 파일 시스템을 마운트할 수 있습니다.


다음 부분이 완료되었습니다.아니요작동합니다(적어도 4.2 커널에서는 아님). 사람들이 직접 시도할 필요가 없도록 참조용으로 보관하세요.

nsenter -m마운트 네임스페이스( 또는 ) 를 입력하면 setns(CLONE_NEWNS)작업 디렉터리가 자동으로 해당 네임스페이스( )의 루트로 변경되지만 /일부 파일 설명자에서 디렉터리를 열고 네임스페이스를 입력하고 여전히 해당 네임스페이스에 있을 수 있습니다. 디렉터리 열기 공간적으로 fd합니다(예를 들어 fchdir()a를 실행합니다).

따라서 이 접근 방식이 효과가 있을 것이라고 생각할 수 있습니다.

#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");
}

까지 작동 fchdir()하지만 mount다음에서는 실패합니다 EINVAL.

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

답변2

나는 이것으로 약간의 성공을 거두었습니다. lxc 컨테이너를 사용하지 않는 경우 다른 개인 마운트 네임스페이스와 작동하도록 만들었습니다. lxc는 내가 사용하는 기본 Linux 네임스페이스를 기반으로 구축되었으므로 이것이 작동하지 않을 이유가 없습니다.

먼저 네임스페이스를 다음과 같이 설정했습니다.

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
$ 

...대화형 쉘이 생겼습니다. 별도의 터미널 세션에서 다음으로 한 일은...

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

...정말 고무적이네요!

하지만 거기에 마운트할 수는 없습니다. mount상위 ns 디렉토리를 하위 ns의 디렉토리에 덮어쓰려고 할 때마다 실패합니다. 비참하게도 말이죠. 일부 연구에 따르면 이는 의도적으로 설계된 것입니다.(특히 PROPAGATION 플래그에 대한 경고를 참조하세요 man 7 user_namespaces). 무엇했다그러나 직업은(새 네임스페이스에서):

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

그런 다음 상위 네임스페이스 세션에서...

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

이제 위의 방법은 첫 번째 경우에는 작동하지만 두 번째 경우에는 작동하지 않습니다. 하위 ns는 fs 변경 사항을 위쪽으로 전파하지 않기 때문에 상위 ns는 fs 보기에 대한 변경 사항에 영향을 주지 않습니다. 따라서 아이에게는 자신만의 탈 것이 있으므로 /tmp부모가 하는 일은 아무 것도 중요하지 않습니다. 그러나 공통 계층 구조가 있고 하위 ns가 파일 시스템 변경 사항을 수신하도록 구성된 경우~ 할 것이다상위 항목에서 아래로 전파된 변경 사항을 봅니다.

위 명령을 실행한 후 하위 ns에서...

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:

그래서 저는 그 질문에 대답하고 싶습니다. 예, 가능하다고 믿습니다. 그러나 나는 또한 당신이 필요하다고 확신합니다마련하다너무 이르다.

답변3

이 답변unshare(루트가 아님) 및 nsenter(컨테이너 내부의 루트)를 사용하여 바인드 마운트를 유발하고 동기적으로 호출하여 원하는 작업을 수행하는 몇 가지 작업 예제가 있습니다. 실제 루트 액세스가 필요하지 않습니다

안타깝게도 util-linux 2.39.1이 필요합니다. 이는 아마도 ubuntu 23.04 이상을 의미할 것입니다.

공유 해제 통화에는 이전에 상호 배타적인 옵션이 있었습니다.

나는 여전히 22.04(최신 LTS)와 같은 이전 우분투에서 작동하도록 노력하고 있습니다. 24.04가 나오면 시도를 중단하겠습니다.

관련 정보