Merge branch 'topic/hda' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[platform/kernel/linux-rpi.git] / fs / fs_struct.c
1 #include <linux/export.h>
2 #include <linux/sched/signal.h>
3 #include <linux/sched/task.h>
4 #include <linux/fs.h>
5 #include <linux/path.h>
6 #include <linux/slab.h>
7 #include <linux/fs_struct.h>
8 #include "internal.h"
9
10 /*
11  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
12  * It can block.
13  */
14 void set_fs_root(struct fs_struct *fs, const struct path *path)
15 {
16         struct path old_root;
17
18         path_get(path);
19         spin_lock(&fs->lock);
20         write_seqcount_begin(&fs->seq);
21         old_root = fs->root;
22         fs->root = *path;
23         write_seqcount_end(&fs->seq);
24         spin_unlock(&fs->lock);
25         if (old_root.dentry)
26                 path_put(&old_root);
27 }
28
29 /*
30  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
31  * It can block.
32  */
33 void set_fs_pwd(struct fs_struct *fs, const struct path *path)
34 {
35         struct path old_pwd;
36
37         path_get(path);
38         spin_lock(&fs->lock);
39         write_seqcount_begin(&fs->seq);
40         old_pwd = fs->pwd;
41         fs->pwd = *path;
42         write_seqcount_end(&fs->seq);
43         spin_unlock(&fs->lock);
44
45         if (old_pwd.dentry)
46                 path_put(&old_pwd);
47 }
48
49 static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
50 {
51         if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
52                 return 0;
53         *p = *new;
54         return 1;
55 }
56
57 void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
58 {
59         struct task_struct *g, *p;
60         struct fs_struct *fs;
61         int count = 0;
62
63         read_lock(&tasklist_lock);
64         do_each_thread(g, p) {
65                 task_lock(p);
66                 fs = p->fs;
67                 if (fs) {
68                         int hits = 0;
69                         spin_lock(&fs->lock);
70                         write_seqcount_begin(&fs->seq);
71                         hits += replace_path(&fs->root, old_root, new_root);
72                         hits += replace_path(&fs->pwd, old_root, new_root);
73                         write_seqcount_end(&fs->seq);
74                         while (hits--) {
75                                 count++;
76                                 path_get(new_root);
77                         }
78                         spin_unlock(&fs->lock);
79                 }
80                 task_unlock(p);
81         } while_each_thread(g, p);
82         read_unlock(&tasklist_lock);
83         while (count--)
84                 path_put(old_root);
85 }
86
87 void free_fs_struct(struct fs_struct *fs)
88 {
89         path_put(&fs->root);
90         path_put(&fs->pwd);
91         kmem_cache_free(fs_cachep, fs);
92 }
93
94 void exit_fs(struct task_struct *tsk)
95 {
96         struct fs_struct *fs = tsk->fs;
97
98         if (fs) {
99                 int kill;
100                 task_lock(tsk);
101                 spin_lock(&fs->lock);
102                 tsk->fs = NULL;
103                 kill = !--fs->users;
104                 spin_unlock(&fs->lock);
105                 task_unlock(tsk);
106                 if (kill)
107                         free_fs_struct(fs);
108         }
109 }
110
111 struct fs_struct *copy_fs_struct(struct fs_struct *old)
112 {
113         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
114         /* We don't need to lock fs - think why ;-) */
115         if (fs) {
116                 fs->users = 1;
117                 fs->in_exec = 0;
118                 spin_lock_init(&fs->lock);
119                 seqcount_init(&fs->seq);
120                 fs->umask = old->umask;
121
122                 spin_lock(&old->lock);
123                 fs->root = old->root;
124                 path_get(&fs->root);
125                 fs->pwd = old->pwd;
126                 path_get(&fs->pwd);
127                 spin_unlock(&old->lock);
128         }
129         return fs;
130 }
131
132 int unshare_fs_struct(void)
133 {
134         struct fs_struct *fs = current->fs;
135         struct fs_struct *new_fs = copy_fs_struct(fs);
136         int kill;
137
138         if (!new_fs)
139                 return -ENOMEM;
140
141         task_lock(current);
142         spin_lock(&fs->lock);
143         kill = !--fs->users;
144         current->fs = new_fs;
145         spin_unlock(&fs->lock);
146         task_unlock(current);
147
148         if (kill)
149                 free_fs_struct(fs);
150
151         return 0;
152 }
153 EXPORT_SYMBOL_GPL(unshare_fs_struct);
154
155 int current_umask(void)
156 {
157         return current->fs->umask;
158 }
159 EXPORT_SYMBOL(current_umask);
160
161 /* to be mentioned only in INIT_TASK */
162 struct fs_struct init_fs = {
163         .users          = 1,
164         .lock           = __SPIN_LOCK_UNLOCKED(init_fs.lock),
165         .seq            = SEQCNT_ZERO(init_fs.seq),
166         .umask          = 0022,
167 };