xref: /openbmc/linux/fs/afs/dynroot.c (revision b5f184fbdb03b4fcc1141de34dd5ec964ca5d99e)
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  static atomic_t afs_autocell_ino;
14  
15  /*
16   * iget5() comparator for inode created by autocell operations
17   *
18   * These pseudo inodes don't match anything.
19   */
20  static int afs_iget5_pseudo_test(struct inode *inode, void *opaque)
21  {
22  	return 0;
23  }
24  
25  /*
26   * iget5() inode initialiser
27   */
28  static int afs_iget5_pseudo_set(struct inode *inode, void *opaque)
29  {
30  	struct afs_super_info *as = AFS_FS_S(inode->i_sb);
31  	struct afs_vnode *vnode = AFS_FS_I(inode);
32  	struct afs_fid *fid = opaque;
33  
34  	vnode->volume		= as->volume;
35  	vnode->fid		= *fid;
36  	inode->i_ino		= fid->vnode;
37  	inode->i_generation	= fid->unique;
38  	return 0;
39  }
40  
41  /*
42   * Create an inode for a dynamic root directory or an autocell dynamic
43   * automount dir.
44   */
45  struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
46  {
47  	struct afs_super_info *as = AFS_FS_S(sb);
48  	struct afs_vnode *vnode;
49  	struct inode *inode;
50  	struct afs_fid fid = {};
51  
52  	_enter("");
53  
54  	if (as->volume)
55  		fid.vid = as->volume->vid;
56  	if (root) {
57  		fid.vnode = 1;
58  		fid.unique = 1;
59  	} else {
60  		fid.vnode = atomic_inc_return(&afs_autocell_ino);
61  		fid.unique = 0;
62  	}
63  
64  	inode = iget5_locked(sb, fid.vnode,
65  			     afs_iget5_pseudo_test, afs_iget5_pseudo_set, &fid);
66  	if (!inode) {
67  		_leave(" = -ENOMEM");
68  		return ERR_PTR(-ENOMEM);
69  	}
70  
71  	_debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
72  	       inode, inode->i_ino, fid.vid, fid.vnode, fid.unique);
73  
74  	vnode = AFS_FS_I(inode);
75  
76  	/* there shouldn't be an existing inode */
77  	BUG_ON(!(inode->i_state & I_NEW));
78  
79  	inode->i_size		= 0;
80  	inode->i_mode		= S_IFDIR | S_IRUGO | S_IXUGO;
81  	if (root) {
82  		inode->i_op	= &afs_dynroot_inode_operations;
83  		inode->i_fop	= &simple_dir_operations;
84  	} else {
85  		inode->i_op	= &afs_autocell_inode_operations;
86  	}
87  	set_nlink(inode, 2);
88  	inode->i_uid		= GLOBAL_ROOT_UID;
89  	inode->i_gid		= GLOBAL_ROOT_GID;
90  	inode->i_ctime = inode->i_atime = inode->i_mtime = current_time(inode);
91  	inode->i_blocks		= 0;
92  	inode->i_generation	= 0;
93  
94  	set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags);
95  	if (!root) {
96  		set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
97  		inode->i_flags |= S_AUTOMOUNT;
98  	}
99  
100  	inode->i_flags |= S_NOATIME;
101  	unlock_new_inode(inode);
102  	_leave(" = %p", inode);
103  	return inode;
104  }
105  
106  /*
107   * Probe to see if a cell may exist.  This prevents positive dentries from
108   * being created unnecessarily.
109   */
110  static int afs_probe_cell_name(struct dentry *dentry)
111  {
112  	struct afs_cell *cell;
113  	struct afs_net *net = afs_d2net(dentry);
114  	const char *name = dentry->d_name.name;
115  	size_t len = dentry->d_name.len;
116  	int ret;
117  
118  	/* Names prefixed with a dot are R/W mounts. */
119  	if (name[0] == '.') {
120  		if (len == 1)
121  			return -EINVAL;
122  		name++;
123  		len--;
124  	}
125  
126  	cell = afs_find_cell(net, name, len, afs_cell_trace_use_probe);
127  	if (!IS_ERR(cell)) {
128  		afs_unuse_cell(net, cell, afs_cell_trace_unuse_probe);
129  		return 0;
130  	}
131  
132  	ret = dns_query(net->net, "afsdb", name, len, "srv=1",
133  			NULL, NULL, false);
134  	if (ret == -ENODATA)
135  		ret = -EDESTADDRREQ;
136  	return ret;
137  }
138  
139  /*
140   * Try to auto mount the mountpoint with pseudo directory, if the autocell
141   * operation is setted.
142   */
143  struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
144  {
145  	struct afs_vnode *vnode = AFS_FS_I(dir);
146  	struct inode *inode;
147  	int ret = -ENOENT;
148  
149  	_enter("%p{%pd}, {%llx:%llu}",
150  	       dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
151  
152  	if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
153  		goto out;
154  
155  	ret = afs_probe_cell_name(dentry);
156  	if (ret < 0)
157  		goto out;
158  
159  	inode = afs_iget_pseudo_dir(dir->i_sb, false);
160  	if (IS_ERR(inode)) {
161  		ret = PTR_ERR(inode);
162  		goto out;
163  	}
164  
165  	_leave("= %p", inode);
166  	return inode;
167  
168  out:
169  	_leave("= %d", ret);
170  	return ret == -ENOENT ? NULL : ERR_PTR(ret);
171  }
172  
173  /*
174   * Look up @cell in a dynroot directory.  This is a substitution for the
175   * local cell name for the net namespace.
176   */
177  static struct dentry *afs_lookup_atcell(struct dentry *dentry)
178  {
179  	struct afs_cell *cell;
180  	struct afs_net *net = afs_d2net(dentry);
181  	struct dentry *ret;
182  	char *name;
183  	int len;
184  
185  	if (!net->ws_cell)
186  		return ERR_PTR(-ENOENT);
187  
188  	ret = ERR_PTR(-ENOMEM);
189  	name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL);
190  	if (!name)
191  		goto out_p;
192  
193  	down_read(&net->cells_lock);
194  	cell = net->ws_cell;
195  	if (cell) {
196  		len = cell->name_len;
197  		memcpy(name, cell->name, len + 1);
198  	}
199  	up_read(&net->cells_lock);
200  
201  	ret = ERR_PTR(-ENOENT);
202  	if (!cell)
203  		goto out_n;
204  
205  	ret = lookup_one_len(name, dentry->d_parent, len);
206  
207  	/* We don't want to d_add() the @cell dentry here as we don't want to
208  	 * the cached dentry to hide changes to the local cell name.
209  	 */
210  
211  out_n:
212  	kfree(name);
213  out_p:
214  	return ret;
215  }
216  
217  /*
218   * Look up an entry in a dynroot directory.
219   */
220  static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry,
221  					 unsigned int flags)
222  {
223  	_enter("%pd", dentry);
224  
225  	ASSERTCMP(d_inode(dentry), ==, NULL);
226  
227  	if (flags & LOOKUP_CREATE)
228  		return ERR_PTR(-EOPNOTSUPP);
229  
230  	if (dentry->d_name.len >= AFSNAMEMAX) {
231  		_leave(" = -ENAMETOOLONG");
232  		return ERR_PTR(-ENAMETOOLONG);
233  	}
234  
235  	if (dentry->d_name.len == 5 &&
236  	    memcmp(dentry->d_name.name, "@cell", 5) == 0)
237  		return afs_lookup_atcell(dentry);
238  
239  	return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry);
240  }
241  
242  const struct inode_operations afs_dynroot_inode_operations = {
243  	.lookup		= afs_dynroot_lookup,
244  };
245  
246  /*
247   * Dirs in the dynamic root don't need revalidation.
248   */
249  static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags)
250  {
251  	return 1;
252  }
253  
254  /*
255   * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
256   * sleep)
257   * - called from dput() when d_count is going to 0.
258   * - return 1 to request dentry be unhashed, 0 otherwise
259   */
260  static int afs_dynroot_d_delete(const struct dentry *dentry)
261  {
262  	return d_really_is_positive(dentry);
263  }
264  
265  const struct dentry_operations afs_dynroot_dentry_operations = {
266  	.d_revalidate	= afs_dynroot_d_revalidate,
267  	.d_delete	= afs_dynroot_d_delete,
268  	.d_release	= afs_d_release,
269  	.d_automount	= afs_d_automount,
270  };
271  
272  /*
273   * Create a manually added cell mount directory.
274   * - The caller must hold net->proc_cells_lock
275   */
276  int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
277  {
278  	struct super_block *sb = net->dynroot_sb;
279  	struct dentry *root, *subdir;
280  	int ret;
281  
282  	if (!sb || atomic_read(&sb->s_active) == 0)
283  		return 0;
284  
285  	/* Let the ->lookup op do the creation */
286  	root = sb->s_root;
287  	inode_lock(root->d_inode);
288  	subdir = lookup_one_len(cell->name, root, cell->name_len);
289  	if (IS_ERR(subdir)) {
290  		ret = PTR_ERR(subdir);
291  		goto unlock;
292  	}
293  
294  	/* Note that we're retaining an extra ref on the dentry */
295  	subdir->d_fsdata = (void *)1UL;
296  	ret = 0;
297  unlock:
298  	inode_unlock(root->d_inode);
299  	return ret;
300  }
301  
302  /*
303   * Remove a manually added cell mount directory.
304   * - The caller must hold net->proc_cells_lock
305   */
306  void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
307  {
308  	struct super_block *sb = net->dynroot_sb;
309  	struct dentry *root, *subdir;
310  
311  	if (!sb || atomic_read(&sb->s_active) == 0)
312  		return;
313  
314  	root = sb->s_root;
315  	inode_lock(root->d_inode);
316  
317  	/* Don't want to trigger a lookup call, which will re-add the cell */
318  	subdir = try_lookup_one_len(cell->name, root, cell->name_len);
319  	if (IS_ERR_OR_NULL(subdir)) {
320  		_debug("lookup %ld", PTR_ERR(subdir));
321  		goto no_dentry;
322  	}
323  
324  	_debug("rmdir %pd %u", subdir, d_count(subdir));
325  
326  	if (subdir->d_fsdata) {
327  		_debug("unpin %u", d_count(subdir));
328  		subdir->d_fsdata = NULL;
329  		dput(subdir);
330  	}
331  	dput(subdir);
332  no_dentry:
333  	inode_unlock(root->d_inode);
334  	_leave("");
335  }
336  
337  /*
338   * Populate a newly created dynamic root with cell names.
339   */
340  int afs_dynroot_populate(struct super_block *sb)
341  {
342  	struct afs_cell *cell;
343  	struct afs_net *net = afs_sb2net(sb);
344  	int ret;
345  
346  	mutex_lock(&net->proc_cells_lock);
347  
348  	net->dynroot_sb = sb;
349  	hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
350  		ret = afs_dynroot_mkdir(net, cell);
351  		if (ret < 0)
352  			goto error;
353  	}
354  
355  	ret = 0;
356  out:
357  	mutex_unlock(&net->proc_cells_lock);
358  	return ret;
359  
360  error:
361  	net->dynroot_sb = NULL;
362  	goto out;
363  }
364  
365  /*
366   * When a dynamic root that's in the process of being destroyed, depopulate it
367   * of pinned directories.
368   */
369  void afs_dynroot_depopulate(struct super_block *sb)
370  {
371  	struct afs_net *net = afs_sb2net(sb);
372  	struct dentry *root = sb->s_root, *subdir, *tmp;
373  
374  	/* Prevent more subdirs from being created */
375  	mutex_lock(&net->proc_cells_lock);
376  	if (net->dynroot_sb == sb)
377  		net->dynroot_sb = NULL;
378  	mutex_unlock(&net->proc_cells_lock);
379  
380  	if (root) {
381  		inode_lock(root->d_inode);
382  
383  		/* Remove all the pins for dirs created for manually added cells */
384  		list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
385  			if (subdir->d_fsdata) {
386  				subdir->d_fsdata = NULL;
387  				dput(subdir);
388  			}
389  		}
390  
391  		inode_unlock(root->d_inode);
392  	}
393  }
394