Newer
Older
if (!check_mnt(new_nd.path.mnt))
error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd);
if (error)
goto out1;
error = security_sb_pivotroot(&old_nd, &new_nd);
if (error) {
goto out1;
}
read_lock(¤t->fs->lock);
user_nd.path = current->fs->root;
path_get(¤t->fs->root);
mutex_lock(&old_nd.path.dentry->d_inode->i_mutex);
if (IS_MNT_SHARED(old_nd.path.mnt) ||
IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
IS_MNT_SHARED(user_nd.path.mnt->mnt_parent))
if (!check_mnt(user_nd.path.mnt))
if (IS_DEADDIR(new_nd.path.dentry->d_inode))
if (d_unhashed(new_nd.path.dentry) && !IS_ROOT(new_nd.path.dentry))
if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry))
if (new_nd.path.mnt == user_nd.path.mnt ||
old_nd.path.mnt == user_nd.path.mnt)
goto out2; /* loop, on the same file system */
error = -EINVAL;
if (user_nd.path.mnt->mnt_root != user_nd.path.dentry)
if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt)
goto out2; /* not attached */
if (new_nd.path.mnt->mnt_root != new_nd.path.dentry)
if (new_nd.path.mnt->mnt_parent == new_nd.path.mnt)
goto out2; /* not attached */
/* make sure we can reach put_old from new_root */
tmp = old_nd.path.mnt;
if (tmp != new_nd.path.mnt) {
for (;;) {
if (tmp->mnt_parent == tmp)
goto out3; /* already mounted on put_old */
if (tmp->mnt_parent == new_nd.path.mnt)
if (!is_subdir(tmp->mnt_mountpoint, new_nd.path.dentry))
} else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
detach_mnt(new_nd.path.mnt, &parent_path);
detach_mnt(user_nd.path.mnt, &root_parent);
/* mount old root on put_old */
attach_mnt(user_nd.path.mnt, &old_nd.path);
/* mount new_root on / */
attach_mnt(new_nd.path.mnt, &root_parent);
touch_mnt_namespace(current->nsproxy->mnt_ns);
chroot_fs_refs(&user_nd.path, &new_nd.path);
security_sb_post_pivotroot(&user_nd, &new_nd);
error = 0;
path_put(&root_parent);
path_put(&parent_path);
mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
path_put(&user_nd.path);
path_put(&old_nd.path);
out0:
unlock_kernel();
return error;
out3:
spin_unlock(&vfsmount_lock);
goto out2;
}
static void __init init_mount_tree(void)
{
struct vfsmount *mnt;
struct mnt_namespace *ns;
mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
if (IS_ERR(mnt))
panic("Can't create rootfs");
ns = kmalloc(sizeof(*ns), GFP_KERNEL);
if (!ns)
atomic_set(&ns->count, 1);
INIT_LIST_HEAD(&ns->list);
init_waitqueue_head(&ns->poll);
ns->event = 0;
list_add(&mnt->mnt_list, &ns->list);
ns->root = mnt;
mnt->mnt_ns = ns;
init_task.nsproxy->mnt_ns = ns;
get_mnt_ns(ns);
root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);
mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
if (!mount_hashtable)
panic("Failed to allocate mount hash table\n");
printk("Mount-cache hash table entries: %lu\n", HASH_SIZE);
for (u = 0; u < HASH_SIZE; u++)
INIT_LIST_HEAD(&mount_hashtable[u]);
err = sysfs_init();
if (err)
printk(KERN_WARNING "%s: sysfs_init error: %d\n",
__FUNCTION__, err);
fs_kobj = kobject_create_and_add("fs", NULL);
if (!fs_kobj)
printk(KERN_WARNING "%s: kobj create error\n", __FUNCTION__);
void __put_mnt_ns(struct mnt_namespace *ns)
struct vfsmount *root = ns->root;
ns->root = NULL;
spin_unlock(&vfsmount_lock);