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 } 308