無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

pivot_root(2)


旧バージョンで実行可能だった下記サンプルpivot_rootが、現バージョンではpivot_rootシステムコールがEINVALでの不可となっています。
[root@localhost v.north]# mount -t ramfs none /ramdisk
[root@localhost v.north]# mkdir /ramdisk/old-root
[root@localhost v.north]# strace -o babakaka pivot_root /ramdisk/ /ramdisk/old-root/
pivot_root: ルートディレクトリを `/ramdisk/' から `/ramdisk/old-root/' に変更する処理が失敗しました: 無効な引数です

[root@localhost v.north]# cat babakaka | grep "pivot_root("
pivot_root("/ramdisk/", "/ramdisk/old-root/") = -1 EINVAL (Invalid argument)

SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, const char __user *, put_old)
{
       struct path new, old, parent_path, root_parent, root;
       struct mount *new_mnt, *root_mnt;
       int error;

       if (!capable(CAP_SYS_ADMIN))
               return -EPERM;

       error = user_path_dir(new_root, &new);
       if (error)
               goto out0;

       error = user_path_dir(put_old, &old);
       if (error)
               goto out1;

       error = security_sb_pivotroot(&old, &new);
       if (error)
               goto out2;

       get_fs_root(current->fs, &root);
       error = lock_mount(&old);
       if (error)
               goto out3;

       error = -EINVAL;
       new_mnt = real_mount(new.mnt);
       root_mnt = real_mount(root.mnt);
       if (IS_MNT_SHARED(real_mount(old.mnt)) ||
               IS_MNT_SHARED(new_mnt->mnt_parent) ||
               IS_MNT_SHARED(root_mnt->mnt_parent))
               goto out4;
       if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
               goto out4;
       error = -ENOENT;
       if (d_unlinked(new.dentry))
               goto out4;
       if (d_unlinked(old.dentry))
               goto out4;
       error = -EBUSY;
       if (new.mnt == root.mnt ||
           old.mnt == root.mnt)
               goto out4; /* loop, on the same file system  */
       error = -EINVAL;
       if (root.mnt->mnt_root != root.dentry)
               goto out4; /* not a mountpoint */
       if (!mnt_has_parent(root_mnt))
               goto out4; /* not attached */
       if (new.mnt->mnt_root != new.dentry)
               goto out4; /* not a mountpoint */
       if (!mnt_has_parent(new_mnt))
               goto out4; /* not attached */
       /* make sure we can reach put_old from new_root */
       if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
               goto out4;
       br_write_lock(&vfsmount_lock);
       detach_mnt(new_mnt, &parent_path);
       detach_mnt(root_mnt, &root_parent);

       attach_mnt(root_mnt, &old);

       attach_mnt(new_mnt, &root_parent);
       touch_mnt_namespace(current->nsproxy->mnt_ns);
       br_write_unlock(&vfsmount_lock);
       chroot_fs_refs(&root, &new);
       error = 0;
out4:
       unlock_mount(&old);
       if (!error) {
               path_put(&root_parent);
               path_put(&parent_path);
       }
out3:
       path_put(&root);
out2:
       path_put(&old);
out1:
       path_put(&new);
out0:
       return error;
}
以前のバージョンからEINVALエラーに係る以下の条件が追加されています。
if (IS_MNT_SHARED(real_mount(old.mnt)) ||
    IS_MNT_SHARED(new_mnt->mnt_parent) ||
    IS_MNT_SHARED(root_mnt->mnt_parent))
    goto out4;
if (!mnt_has_parent(root_mnt))
    goto out4;

備考

MNT_SHAREDはmount後にマウント属性変更での設定で、mountでのMNT_SHAREDは設定できません。従ってサンプルのpivot_rootエラーは、if (!mnt_has_parent(root_mnt))で、プロセスのrootのデバイスが親を有しないシステム起動時のrootデバイス故です。

従って、現行バージョンでpivot_rootするには、プロセスのrootをカーネル起動時のmntでなく、mountされているディレクトリをchrootでプロセスのrootとする事でpivot_rootの実行が可能となるようです。

最終更新 2017/10/26 16:21:40 - north
(2017/10/26 16:17:55 作成)