Blame view
fs/fs_struct.c
3.16 KB
3e93cd671
|
1 2 3 4 5 |
#include <linux/module.h> #include <linux/sched.h> #include <linux/fs.h> #include <linux/path.h> #include <linux/slab.h> |
5ad4e53bd
|
6 |
#include <linux/fs_struct.h> |
3e93cd671
|
7 8 9 10 11 12 13 14 |
/* * 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; |
2a4419b5b
|
15 |
spin_lock(&fs->lock); |
3e93cd671
|
16 17 18 |
old_root = fs->root; fs->root = *path; path_get(path); |
2a4419b5b
|
19 |
spin_unlock(&fs->lock); |
3e93cd671
|
20 21 22 23 24 25 26 27 28 29 30 |
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; |
2a4419b5b
|
31 |
spin_lock(&fs->lock); |
3e93cd671
|
32 33 34 |
old_pwd = fs->pwd; fs->pwd = *path; path_get(path); |
2a4419b5b
|
35 |
spin_unlock(&fs->lock); |
3e93cd671
|
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
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) { |
2a4419b5b
|
52 |
spin_lock(&fs->lock); |
3e93cd671
|
53 54 55 56 57 58 59 60 61 62 63 64 |
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++; } |
2a4419b5b
|
65 |
spin_unlock(&fs->lock); |
3e93cd671
|
66 67 68 69 70 71 72 |
} task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); while (count--) path_put(old_root); } |
498052bba
|
73 |
void free_fs_struct(struct fs_struct *fs) |
3e93cd671
|
74 |
{ |
498052bba
|
75 76 77 |
path_put(&fs->root); path_put(&fs->pwd); kmem_cache_free(fs_cachep, fs); |
3e93cd671
|
78 79 80 81 |
} void exit_fs(struct task_struct *tsk) { |
498052bba
|
82 |
struct fs_struct *fs = tsk->fs; |
3e93cd671
|
83 84 |
if (fs) { |
498052bba
|
85 |
int kill; |
3e93cd671
|
86 |
task_lock(tsk); |
2a4419b5b
|
87 |
spin_lock(&fs->lock); |
3e93cd671
|
88 |
tsk->fs = NULL; |
498052bba
|
89 |
kill = !--fs->users; |
2a4419b5b
|
90 |
spin_unlock(&fs->lock); |
3e93cd671
|
91 |
task_unlock(tsk); |
498052bba
|
92 93 |
if (kill) free_fs_struct(fs); |
3e93cd671
|
94 95 96 97 98 99 100 101 |
} } 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) { |
498052bba
|
102 103 |
fs->users = 1; fs->in_exec = 0; |
2a4419b5b
|
104 |
spin_lock_init(&fs->lock); |
3e93cd671
|
105 |
fs->umask = old->umask; |
f7ad3c6be
|
106 |
get_fs_root_and_pwd(old, &fs->root, &fs->pwd); |
3e93cd671
|
107 108 109 110 111 112 |
} return fs; } int unshare_fs_struct(void) { |
498052bba
|
113 114 115 116 117 |
struct fs_struct *fs = current->fs; struct fs_struct *new_fs = copy_fs_struct(fs); int kill; if (!new_fs) |
3e93cd671
|
118 |
return -ENOMEM; |
498052bba
|
119 120 |
task_lock(current); |
2a4419b5b
|
121 |
spin_lock(&fs->lock); |
498052bba
|
122 123 |
kill = !--fs->users; current->fs = new_fs; |
2a4419b5b
|
124 |
spin_unlock(&fs->lock); |
498052bba
|
125 126 127 128 |
task_unlock(current); if (kill) free_fs_struct(fs); |
3e93cd671
|
129 130 131 |
return 0; } EXPORT_SYMBOL_GPL(unshare_fs_struct); |
ce3b0f8d5
|
132 133 134 135 136 |
int current_umask(void) { return current->fs->umask; } EXPORT_SYMBOL(current_umask); |
3e93cd671
|
137 138 |
/* to be mentioned only in INIT_TASK */ struct fs_struct init_fs = { |
498052bba
|
139 |
.users = 1, |
2a4419b5b
|
140 |
.lock = __SPIN_LOCK_UNLOCKED(init_fs.lock), |
3e93cd671
|
141 142 143 144 145 |
.umask = 0022, }; void daemonize_fs_struct(void) { |
498052bba
|
146 147 148 149 150 151 |
struct fs_struct *fs = current->fs; if (fs) { int kill; task_lock(current); |
3e93cd671
|
152 |
|
2a4419b5b
|
153 |
spin_lock(&init_fs.lock); |
498052bba
|
154 |
init_fs.users++; |
2a4419b5b
|
155 |
spin_unlock(&init_fs.lock); |
498052bba
|
156 |
|
2a4419b5b
|
157 |
spin_lock(&fs->lock); |
498052bba
|
158 159 |
current->fs = &init_fs; kill = !--fs->users; |
2a4419b5b
|
160 |
spin_unlock(&fs->lock); |
498052bba
|
161 162 163 164 165 |
task_unlock(current); if (kill) free_fs_struct(fs); } |
3e93cd671
|
166 |
} |