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