123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #include <linux/module.h>
- #include <linux/sched.h>
- #include <linux/fs.h>
- #include <linux/path.h>
- #include <linux/slab.h>
- /*
- * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
- * It can block.
- */
- void set_fs_root(struct fs_struct *fs, struct path *path)
- {
- struct path old_root;
- write_lock(&fs->lock);
- old_root = fs->root;
- fs->root = *path;
- path_get(path);
- write_unlock(&fs->lock);
- if (old_root.dentry)
- path_put(&old_root);
- }
- /*
- * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
- * It can block.
- */
- void set_fs_pwd(struct fs_struct *fs, struct path *path)
- {
- struct path old_pwd;
- write_lock(&fs->lock);
- old_pwd = fs->pwd;
- fs->pwd = *path;
- path_get(path);
- write_unlock(&fs->lock);
- if (old_pwd.dentry)
- path_put(&old_pwd);
- }
- void chroot_fs_refs(struct path *old_root, struct path *new_root)
- {
- struct task_struct *g, *p;
- struct fs_struct *fs;
- int count = 0;
- read_lock(&tasklist_lock);
- do_each_thread(g, p) {
- task_lock(p);
- fs = p->fs;
- if (fs) {
- write_lock(&fs->lock);
- if (fs->root.dentry == old_root->dentry
- && fs->root.mnt == old_root->mnt) {
- path_get(new_root);
- fs->root = *new_root;
- count++;
- }
- if (fs->pwd.dentry == old_root->dentry
- && fs->pwd.mnt == old_root->mnt) {
- path_get(new_root);
- fs->pwd = *new_root;
- count++;
- }
- write_unlock(&fs->lock);
- }
- task_unlock(p);
- } while_each_thread(g, p);
- read_unlock(&tasklist_lock);
- while (count--)
- path_put(old_root);
- }
- void put_fs_struct(struct fs_struct *fs)
- {
- /* No need to hold fs->lock if we are killing it */
- if (atomic_dec_and_test(&fs->count)) {
- path_put(&fs->root);
- path_put(&fs->pwd);
- kmem_cache_free(fs_cachep, fs);
- }
- }
- void exit_fs(struct task_struct *tsk)
- {
- struct fs_struct * fs = tsk->fs;
- if (fs) {
- task_lock(tsk);
- tsk->fs = NULL;
- task_unlock(tsk);
- put_fs_struct(fs);
- }
- }
- struct fs_struct *copy_fs_struct(struct fs_struct *old)
- {
- struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
- /* We don't need to lock fs - think why ;-) */
- if (fs) {
- atomic_set(&fs->count, 1);
- rwlock_init(&fs->lock);
- fs->umask = old->umask;
- read_lock(&old->lock);
- fs->root = old->root;
- path_get(&old->root);
- fs->pwd = old->pwd;
- path_get(&old->pwd);
- read_unlock(&old->lock);
- }
- return fs;
- }
- int unshare_fs_struct(void)
- {
- struct fs_struct *fsp = copy_fs_struct(current->fs);
- if (!fsp)
- return -ENOMEM;
- exit_fs(current);
- current->fs = fsp;
- return 0;
- }
- EXPORT_SYMBOL_GPL(unshare_fs_struct);
- /* to be mentioned only in INIT_TASK */
- struct fs_struct init_fs = {
- .count = ATOMIC_INIT(1),
- .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
- .umask = 0022,
- };
- void daemonize_fs_struct(void)
- {
- struct fs_struct *fs;
- exit_fs(current); /* current->fs->count--; */
- fs = &init_fs;
- current->fs = fs;
- atomic_inc(&fs->count);
- }
|