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が出たら試みを中止します。