Merge branch 'next-lockdown' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux-2.6-microblaze.git] / fs / afs / dynroot.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* AFS dynamic root handling
3  *
4  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7
8 #include <linux/fs.h>
9 #include <linux/namei.h>
10 #include <linux/dns_resolver.h>
11 #include "internal.h"
12
13 const struct file_operations afs_dynroot_file_operations = {
14         .open           = dcache_dir_open,
15         .release        = dcache_dir_close,
16         .iterate_shared = dcache_readdir,
17         .llseek         = dcache_dir_lseek,
18 };
19
20 /*
21  * Probe to see if a cell may exist.  This prevents positive dentries from
22  * being created unnecessarily.
23  */
24 static int afs_probe_cell_name(struct dentry *dentry)
25 {
26         struct afs_cell *cell;
27         struct afs_net *net = afs_d2net(dentry);
28         const char *name = dentry->d_name.name;
29         size_t len = dentry->d_name.len;
30         int ret;
31
32         /* Names prefixed with a dot are R/W mounts. */
33         if (name[0] == '.') {
34                 if (len == 1)
35                         return -EINVAL;
36                 name++;
37                 len--;
38         }
39
40         cell = afs_lookup_cell_rcu(net, name, len);
41         if (!IS_ERR(cell)) {
42                 afs_put_cell(net, cell);
43                 return 0;
44         }
45
46         ret = dns_query(net->net, "afsdb", name, len, "srv=1",
47                         NULL, NULL, false);
48         if (ret == -ENODATA)
49                 ret = -EDESTADDRREQ;
50         return ret;
51 }
52
53 /*
54  * Try to auto mount the mountpoint with pseudo directory, if the autocell
55  * operation is setted.
56  */
57 struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
58 {
59         struct afs_vnode *vnode = AFS_FS_I(dir);
60         struct inode *inode;
61         int ret = -ENOENT;
62
63         _enter("%p{%pd}, {%llx:%llu}",
64                dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
65
66         if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
67                 goto out;
68
69         ret = afs_probe_cell_name(dentry);
70         if (ret < 0)
71                 goto out;
72
73         inode = afs_iget_pseudo_dir(dir->i_sb, false);
74         if (IS_ERR(inode)) {
75                 ret = PTR_ERR(inode);
76                 goto out;
77         }
78
79         _leave("= %p", inode);
80         return inode;
81
82 out:
83         _leave("= %d", ret);
84         return ret == -ENOENT ? NULL : ERR_PTR(ret);
85 }
86
87 /*
88  * Look up @cell in a dynroot directory.  This is a substitution for the
89  * local cell name for the net namespace.
90  */
91 static struct dentry *afs_lookup_atcell(struct dentry *dentry)
92 {
93         struct afs_cell *cell;
94         struct afs_net *net = afs_d2net(dentry);
95         struct dentry *ret;
96         unsigned int seq = 0;
97         char *name;
98         int len;
99
100         if (!net->ws_cell)
101                 return ERR_PTR(-ENOENT);
102
103         ret = ERR_PTR(-ENOMEM);
104         name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL);
105         if (!name)
106                 goto out_p;
107
108         rcu_read_lock();
109         do {
110                 read_seqbegin_or_lock(&net->cells_lock, &seq);
111                 cell = rcu_dereference_raw(net->ws_cell);
112                 if (cell) {
113                         len = cell->name_len;
114                         memcpy(name, cell->name, len + 1);
115                 }
116         } while (need_seqretry(&net->cells_lock, seq));
117         done_seqretry(&net->cells_lock, seq);
118         rcu_read_unlock();
119
120         ret = ERR_PTR(-ENOENT);
121         if (!cell)
122                 goto out_n;
123
124         ret = lookup_one_len(name, dentry->d_parent, len);
125
126         /* We don't want to d_add() the @cell dentry here as we don't want to
127          * the cached dentry to hide changes to the local cell name.
128          */
129
130 out_n:
131         kfree(name);
132 out_p:
133         return ret;
134 }
135
136 /*
137  * Look up an entry in a dynroot directory.
138  */
139 static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry,
140                                          unsigned int flags)
141 {
142         _enter("%pd", dentry);
143
144         ASSERTCMP(d_inode(dentry), ==, NULL);
145
146         if (dentry->d_name.len >= AFSNAMEMAX) {
147                 _leave(" = -ENAMETOOLONG");
148                 return ERR_PTR(-ENAMETOOLONG);
149         }
150
151         if (dentry->d_name.len == 5 &&
152             memcmp(dentry->d_name.name, "@cell", 5) == 0)
153                 return afs_lookup_atcell(dentry);
154
155         return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry);
156 }
157
158 const struct inode_operations afs_dynroot_inode_operations = {
159         .lookup         = afs_dynroot_lookup,
160 };
161
162 /*
163  * Dirs in the dynamic root don't need revalidation.
164  */
165 static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags)
166 {
167         return 1;
168 }
169
170 /*
171  * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
172  * sleep)
173  * - called from dput() when d_count is going to 0.
174  * - return 1 to request dentry be unhashed, 0 otherwise
175  */
176 static int afs_dynroot_d_delete(const struct dentry *dentry)
177 {
178         return d_really_is_positive(dentry);
179 }
180
181 const struct dentry_operations afs_dynroot_dentry_operations = {
182         .d_revalidate   = afs_dynroot_d_revalidate,
183         .d_delete       = afs_dynroot_d_delete,
184         .d_release      = afs_d_release,
185         .d_automount    = afs_d_automount,
186 };
187
188 /*
189  * Create a manually added cell mount directory.
190  * - The caller must hold net->proc_cells_lock
191  */
192 int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
193 {
194         struct super_block *sb = net->dynroot_sb;
195         struct dentry *root, *subdir;
196         int ret;
197
198         if (!sb || atomic_read(&sb->s_active) == 0)
199                 return 0;
200
201         /* Let the ->lookup op do the creation */
202         root = sb->s_root;
203         inode_lock(root->d_inode);
204         subdir = lookup_one_len(cell->name, root, cell->name_len);
205         if (IS_ERR(subdir)) {
206                 ret = PTR_ERR(subdir);
207                 goto unlock;
208         }
209
210         /* Note that we're retaining an extra ref on the dentry */
211         subdir->d_fsdata = (void *)1UL;
212         ret = 0;
213 unlock:
214         inode_unlock(root->d_inode);
215         return ret;
216 }
217
218 /*
219  * Remove a manually added cell mount directory.
220  * - The caller must hold net->proc_cells_lock
221  */
222 void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
223 {
224         struct super_block *sb = net->dynroot_sb;
225         struct dentry *root, *subdir;
226
227         if (!sb || atomic_read(&sb->s_active) == 0)
228                 return;
229
230         root = sb->s_root;
231         inode_lock(root->d_inode);
232
233         /* Don't want to trigger a lookup call, which will re-add the cell */
234         subdir = try_lookup_one_len(cell->name, root, cell->name_len);
235         if (IS_ERR_OR_NULL(subdir)) {
236                 _debug("lookup %ld", PTR_ERR(subdir));
237                 goto no_dentry;
238         }
239
240         _debug("rmdir %pd %u", subdir, d_count(subdir));
241
242         if (subdir->d_fsdata) {
243                 _debug("unpin %u", d_count(subdir));
244                 subdir->d_fsdata = NULL;
245                 dput(subdir);
246         }
247         dput(subdir);
248 no_dentry:
249         inode_unlock(root->d_inode);
250         _leave("");
251 }
252
253 /*
254  * Populate a newly created dynamic root with cell names.
255  */
256 int afs_dynroot_populate(struct super_block *sb)
257 {
258         struct afs_cell *cell;
259         struct afs_net *net = afs_sb2net(sb);
260         int ret;
261
262         mutex_lock(&net->proc_cells_lock);
263
264         net->dynroot_sb = sb;
265         hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
266                 ret = afs_dynroot_mkdir(net, cell);
267                 if (ret < 0)
268                         goto error;
269         }
270
271         ret = 0;
272 out:
273         mutex_unlock(&net->proc_cells_lock);
274         return ret;
275
276 error:
277         net->dynroot_sb = NULL;
278         goto out;
279 }
280
281 /*
282  * When a dynamic root that's in the process of being destroyed, depopulate it
283  * of pinned directories.
284  */
285 void afs_dynroot_depopulate(struct super_block *sb)
286 {
287         struct afs_net *net = afs_sb2net(sb);
288         struct dentry *root = sb->s_root, *subdir, *tmp;
289
290         /* Prevent more subdirs from being created */
291         mutex_lock(&net->proc_cells_lock);
292         if (net->dynroot_sb == sb)
293                 net->dynroot_sb = NULL;
294         mutex_unlock(&net->proc_cells_lock);
295
296         inode_lock(root->d_inode);
297
298         /* Remove all the pins for dirs created for manually added cells */
299         list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
300                 if (subdir->d_fsdata) {
301                         subdir->d_fsdata = NULL;
302                         dput(subdir);
303                 }
304         }
305
306         inode_unlock(root->d_inode);
307 }