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

これで、上記の方法は最初のケースでは機能しますが、2番目のケースでは機能しません。子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)などの以前のUbuntuで動作するように努めています。 24.04が出たら試みを中止します。

関連情報