- 论坛徽章:
- 0
|
回复 3楼 turbo99cn 的帖子
每个进程有一个namespace(current->namespace),
即进程所看到的文件系统树,
(different processes have different views of the filesystem)
在这个namespace下,进程可以改变根目录等属性,
进程的fs,应该从namespace来,
内核通过set_fs_root()把init进程的fs相关值设置为它的namespace->root,
见init_mount_tree()
这以后,通过clone(),子进程继承父进程的fs,
如果有必要,通过系统调用chroot(),改变fs结构的值。
请参考一下系统调用chroot(),以及内核的实现sys_chroot()
- static void __init init_mount_tree(void)
- {
- struct vfsmount *mnt;
- struct namespace *namespace;
- struct task_struct *g, *p;
- mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
- if (IS_ERR(mnt))
- panic("Can't create rootfs");
- namespace = kmalloc(sizeof(*namespace), GFP_KERNEL);
- if (!namespace)
- panic("Can't allocate initial namespace");
- atomic_set(&namespace->count, 1);
- INIT_LIST_HEAD(&namespace->list);
- init_rwsem(&namespace->sem);
- list_add(&mnt->mnt_list, &namespace->list);
- namespace->root = mnt;
- mnt->mnt_namespace = namespace;
- init_task.namespace = namespace;
- read_lock(&tasklist_lock);
- do_each_thread(g, p) {
- get_namespace(namespace);
- p->namespace = namespace;
- } while_each_thread(g, p);
- read_unlock(&tasklist_lock);
- set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
- set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
- }
- asmlinkage long sys_chroot(const char __user * filename)
- {
- struct nameidata nd;
- int error;
- error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
- if (error)
- goto out;
- error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
- if (error)
- goto dput_and_out;
- error = -EPERM;
- if (!capable(CAP_SYS_CHROOT))
- goto dput_and_out;
- set_fs_root(current->fs, nd.mnt, nd.dentry);
- set_fs_altroot();
- error = 0;
- dput_and_out:
- path_release(&nd);
- out:
- return error;
- }
- /*
- * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
- * It can block. Requires the big lock held.
- */
- void set_fs_root(struct fs_struct *fs, struct vfsmount *mnt,
- struct dentry *dentry)
- {
- struct dentry *old_root;
- struct vfsmount *old_rootmnt;
- write_lock(&fs->lock);
- old_root = fs->root;
- old_rootmnt = fs->rootmnt;
- fs->rootmnt = mntget(mnt);
- fs->root = dget(dentry);
- write_unlock(&fs->lock);
- if (old_root) {
- dput(old_root);
- mntput(old_rootmnt);
- }
- }
- void set_fs_altroot(void)
- {
- char *emul = __emul_prefix();
- struct nameidata nd;
- struct vfsmount *mnt = NULL, *oldmnt;
- struct dentry *dentry = NULL, *olddentry;
- int err;
- if (!emul)
- goto set_it;
- err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd);
- if (!err) {
- mnt = nd.mnt;
- dentry = nd.dentry;
- }
- set_it:
- write_lock(¤t->fs->lock);
- oldmnt = current->fs->altrootmnt;
- olddentry = current->fs->altroot;
- current->fs->altrootmnt = mnt;
- current->fs->altroot = dentry;
- write_unlock(¤t->fs->lock);
- if (olddentry) {
- dput(olddentry);
- mntput(oldmnt);
- }
- }
复制代码
[ 本帖最后由 wheelz 于 2006-1-6 20:46 编辑 ] |
|