web-dev-qa-db-ja.com

マウント名前空間の入力がどのように機能するのかわかりません

新しいマウント名前空間にフォークするか、既存の名前空間を入力する場合。

外部マウント名前空間からのファイル記述子を保持することが可能です。 [kdevtmpfs]などの外部マウント名前空間でプロセスを見つけて/proc/$PID/rootを開くことにより、これを非常に簡単に示すことができます。 (このディレクトリに移動して/bin/pwdを実行すると、すばらしいエラーメッセージ/usr/bin/pwd: couldn't find directory entry in ‘..’ with matching i-nodeが出力されるようで、stracegetcwd()(unreachable)/を返したことを示しています)。

新しいマウント名前空間を入力するときに、プロセスが現在のマウント名前空間(現在のディレクトリと現在のルート(chroot))に対して保持する既存の参照がどうなるかを定義してください。

これらの参照のどちらも変更されていない場合、新しいマウント名前空間を入力してもあまり意味がありません。例えば。プロセスのルートがまだ古いマウント名前空間を指している場合、ファイルを開く/path/to/fileは古いマウント名前空間からファイルを開きます。

繰り返しになりますが、CLONENEWNSを使用したclone()の場合(unshareコマンドなど)とsetns()の場合(nsenterコマンドなど)の両方を理解したいと思います。

2
sourcejedi

現在の作業ディレクトリとルートの両方が、入力されたマウント名前空間のルートファイルシステムにリセットされます。

たとえば、nsenter -m --target $$を実行してchrootをエスケープできることをテストしました。

(リマインダー:chrootは、まだルートにいるときに簡単にエスケープできます。man chrootは、これを行うためのよく知られた方法を文書化しています)。


ソース

https://elixir.bootlin.com/linux/latest/source/fs/namespace.c?v=4.17#L3507

static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
{
    struct fs_struct *fs = current->fs;

注:currentは、現在のタスク(現在のスレッド/プロセス)を意味します。

->fsは、そのタスクのファイルシステムデータになります。これは、同じプロセス内のスレッドであるタスク間で共有されます。例えば。以下に、作業ディレクトリの変更が->fsの操作であることがわかります。

例えば。作業ディレクトリを変更すると、同じプロセスのすべてのスレッドに影響します。このようなPOSIX互換スレッドは、clone()のCLONE_FSフラグを使用して実装されます。

    struct mnt_namespace *mnt_ns = to_mnt_ns(ns), *old_mnt_ns;
    struct path root;
    int err;

...

    /* Find the root */
    err = vfs_path_lookup(mnt_ns->root->mnt.mnt_root, &mnt_ns->root->mnt,
                "/", LOOKUP_DOWN, &root);

問題の行は次のとおりです。

    /* Update the pwd and root */
    set_fs_pwd(fs, &root);
    set_fs_root(fs, &root);

...

}

...

const struct proc_ns_operations mntns_operations = {
    .name       = "mnt",
    .type       = CLONE_NEWNS,
    .get        = mntns_get,
    .put        = mntns_put,
    .install    = mntns_install,
    .owner      = mntns_owner,
};
2
sourcejedi