1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* AFS security handling 3 * 4 * Copyright (C) 2007, 2017 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/init.h> 9 #include <linux/slab.h> 10 #include <linux/fs.h> 11 #include <linux/ctype.h> 12 #include <linux/sched.h> 13 #include <linux/hashtable.h> 14 #include <keys/rxrpc-type.h> 15 #include "internal.h" 16 17 static DEFINE_HASHTABLE(afs_permits_cache, 10); 18 static DEFINE_SPINLOCK(afs_permits_lock); 19 20 /* 21 * get a key 22 */ 23 struct key *afs_request_key(struct afs_cell *cell) 24 { 25 struct key *key; 26 27 _enter("{%x}", key_serial(cell->anonymous_key)); 28 29 _debug("key %s", cell->anonymous_key->description); 30 key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description, 31 cell->net->net, NULL); 32 if (IS_ERR(key)) { 33 if (PTR_ERR(key) != -ENOKEY) { 34 _leave(" = %ld", PTR_ERR(key)); 35 return key; 36 } 37 38 /* act as anonymous user */ 39 _leave(" = {%x} [anon]", key_serial(cell->anonymous_key)); 40 return key_get(cell->anonymous_key); 41 } else { 42 /* act as authorised user */ 43 _leave(" = {%x} [auth]", key_serial(key)); 44 return key; 45 } 46 } 47 48 /* 49 * Get a key when pathwalk is in rcuwalk mode. 50 */ 51 struct key *afs_request_key_rcu(struct afs_cell *cell) 52 { 53 struct key *key; 54 55 _enter("{%x}", key_serial(cell->anonymous_key)); 56 57 _debug("key %s", cell->anonymous_key->description); 58 key = request_key_net_rcu(&key_type_rxrpc, 59 cell->anonymous_key->description, 60 cell->net->net); 61 if (IS_ERR(key)) { 62 if (PTR_ERR(key) != -ENOKEY) { 63 _leave(" = %ld", PTR_ERR(key)); 64 return key; 65 } 66 67 /* act as anonymous user */ 68 _leave(" = {%x} [anon]", key_serial(cell->anonymous_key)); 69 return key_get(cell->anonymous_key); 70 } else { 71 /* act as authorised user */ 72 _leave(" = {%x} [auth]", key_serial(key)); 73 return key; 74 } 75 } 76 77 /* 78 * Dispose of a list of permits. 79 */ 80 static void afs_permits_rcu(struct rcu_head *rcu) 81 { 82 struct afs_permits *permits = 83 container_of(rcu, struct afs_permits, rcu); 84 int i; 85 86 for (i = 0; i < permits->nr_permits; i++) 87 key_put(permits->permits[i].key); 88 kfree(permits); 89 } 90 91 /* 92 * Discard a permission cache. 93 */ 94 void afs_put_permits(struct afs_permits *permits) 95 { 96 if (permits && refcount_dec_and_test(&permits->usage)) { 97 spin_lock(&afs_permits_lock); 98 hash_del_rcu(&permits->hash_node); 99 spin_unlock(&afs_permits_lock); 100 call_rcu(&permits->rcu, afs_permits_rcu); 101 } 102 } 103 104 /* 105 * Clear a permit cache on callback break. 106 */ 107 void afs_clear_permits(struct afs_vnode *vnode) 108 { 109 struct afs_permits *permits; 110 111 spin_lock(&vnode->lock); 112 permits = rcu_dereference_protected(vnode->permit_cache, 113 lockdep_is_held(&vnode->lock)); 114 RCU_INIT_POINTER(vnode->permit_cache, NULL); 115 spin_unlock(&vnode->lock); 116 117 afs_put_permits(permits); 118 } 119 120 /* 121 * Hash a list of permits. Use simple addition to make it easy to add an extra 122 * one at an as-yet indeterminate position in the list. 123 */ 124 static void afs_hash_permits(struct afs_permits *permits) 125 { 126 unsigned long h = permits->nr_permits; 127 int i; 128 129 for (i = 0; i < permits->nr_permits; i++) { 130 h += (unsigned long)permits->permits[i].key / sizeof(void *); 131 h += permits->permits[i].access; 132 } 133 134 permits->h = h; 135 } 136 137 /* 138 * Cache the CallerAccess result obtained from doing a fileserver operation 139 * that returned a vnode status for a particular key. If a callback break 140 * occurs whilst the operation was in progress then we have to ditch the cache 141 * as the ACL *may* have changed. 142 */ 143 void afs_cache_permit(struct afs_vnode *vnode, struct key *key, 144 unsigned int cb_break, struct afs_status_cb *scb) 145 { 146 struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL; 147 afs_access_t caller_access = scb->status.caller_access; 148 size_t size = 0; 149 bool changed = false; 150 int i, j; 151 152 _enter("{%llx:%llu},%x,%x", 153 vnode->fid.vid, vnode->fid.vnode, key_serial(key), caller_access); 154 155 rcu_read_lock(); 156 157 /* Check for the common case first: We got back the same access as last 158 * time we tried and already have it recorded. 159 */ 160 permits = rcu_dereference(vnode->permit_cache); 161 if (permits) { 162 if (!permits->invalidated) { 163 for (i = 0; i < permits->nr_permits; i++) { 164 if (permits->permits[i].key < key) 165 continue; 166 if (permits->permits[i].key > key) 167 break; 168 if (permits->permits[i].access != caller_access) { 169 changed = true; 170 break; 171 } 172 173 if (afs_cb_is_broken(cb_break, vnode, 174 rcu_dereference(vnode->cb_interest))) { 175 changed = true; 176 break; 177 } 178 179 /* The cache is still good. */ 180 rcu_read_unlock(); 181 return; 182 } 183 } 184 185 changed |= permits->invalidated; 186 size = permits->nr_permits; 187 188 /* If this set of permits is now wrong, clear the permits 189 * pointer so that no one tries to use the stale information. 190 */ 191 if (changed) { 192 spin_lock(&vnode->lock); 193 if (permits != rcu_access_pointer(vnode->permit_cache)) 194 goto someone_else_changed_it_unlock; 195 RCU_INIT_POINTER(vnode->permit_cache, NULL); 196 spin_unlock(&vnode->lock); 197 198 afs_put_permits(permits); 199 permits = NULL; 200 size = 0; 201 } 202 } 203 204 if (afs_cb_is_broken(cb_break, vnode, rcu_dereference(vnode->cb_interest))) 205 goto someone_else_changed_it; 206 207 /* We need a ref on any permits list we want to copy as we'll have to 208 * drop the lock to do memory allocation. 209 */ 210 if (permits && !refcount_inc_not_zero(&permits->usage)) 211 goto someone_else_changed_it; 212 213 rcu_read_unlock(); 214 215 /* Speculatively create a new list with the revised permission set. We 216 * discard this if we find an extant match already in the hash, but 217 * it's easier to compare with memcmp this way. 218 * 219 * We fill in the key pointers at this time, but we don't get the refs 220 * yet. 221 */ 222 size++; 223 new = kzalloc(sizeof(struct afs_permits) + 224 sizeof(struct afs_permit) * size, GFP_NOFS); 225 if (!new) 226 goto out_put; 227 228 refcount_set(&new->usage, 1); 229 new->nr_permits = size; 230 i = j = 0; 231 if (permits) { 232 for (i = 0; i < permits->nr_permits; i++) { 233 if (j == i && permits->permits[i].key > key) { 234 new->permits[j].key = key; 235 new->permits[j].access = caller_access; 236 j++; 237 } 238 new->permits[j].key = permits->permits[i].key; 239 new->permits[j].access = permits->permits[i].access; 240 j++; 241 } 242 } 243 244 if (j == i) { 245 new->permits[j].key = key; 246 new->permits[j].access = caller_access; 247 } 248 249 afs_hash_permits(new); 250 251 /* Now see if the permit list we want is actually already available */ 252 spin_lock(&afs_permits_lock); 253 254 hash_for_each_possible(afs_permits_cache, xpermits, hash_node, new->h) { 255 if (xpermits->h != new->h || 256 xpermits->invalidated || 257 xpermits->nr_permits != new->nr_permits || 258 memcmp(xpermits->permits, new->permits, 259 new->nr_permits * sizeof(struct afs_permit)) != 0) 260 continue; 261 262 if (refcount_inc_not_zero(&xpermits->usage)) { 263 replacement = xpermits; 264 goto found; 265 } 266 267 break; 268 } 269 270 for (i = 0; i < new->nr_permits; i++) 271 key_get(new->permits[i].key); 272 hash_add_rcu(afs_permits_cache, &new->hash_node, new->h); 273 replacement = new; 274 new = NULL; 275 276 found: 277 spin_unlock(&afs_permits_lock); 278 279 kfree(new); 280 281 rcu_read_lock(); 282 spin_lock(&vnode->lock); 283 zap = rcu_access_pointer(vnode->permit_cache); 284 if (!afs_cb_is_broken(cb_break, vnode, rcu_dereference(vnode->cb_interest)) && 285 zap == permits) 286 rcu_assign_pointer(vnode->permit_cache, replacement); 287 else 288 zap = replacement; 289 spin_unlock(&vnode->lock); 290 rcu_read_unlock(); 291 afs_put_permits(zap); 292 out_put: 293 afs_put_permits(permits); 294 return; 295 296 someone_else_changed_it_unlock: 297 spin_unlock(&vnode->lock); 298 someone_else_changed_it: 299 /* Someone else changed the cache under us - don't recheck at this 300 * time. 301 */ 302 rcu_read_unlock(); 303 return; 304 } 305 306 static bool afs_check_permit_rcu(struct afs_vnode *vnode, struct key *key, 307 afs_access_t *_access) 308 { 309 const struct afs_permits *permits; 310 int i; 311 312 _enter("{%llx:%llu},%x", 313 vnode->fid.vid, vnode->fid.vnode, key_serial(key)); 314 315 /* check the permits to see if we've got one yet */ 316 if (key == vnode->volume->cell->anonymous_key) { 317 *_access = vnode->status.anon_access; 318 _leave(" = t [anon %x]", *_access); 319 return true; 320 } 321 322 permits = rcu_dereference(vnode->permit_cache); 323 if (permits) { 324 for (i = 0; i < permits->nr_permits; i++) { 325 if (permits->permits[i].key < key) 326 continue; 327 if (permits->permits[i].key > key) 328 break; 329 330 *_access = permits->permits[i].access; 331 _leave(" = %u [perm %x]", !permits->invalidated, *_access); 332 return !permits->invalidated; 333 } 334 } 335 336 _leave(" = f"); 337 return false; 338 } 339 340 /* 341 * check with the fileserver to see if the directory or parent directory is 342 * permitted to be accessed with this authorisation, and if so, what access it 343 * is granted 344 */ 345 int afs_check_permit(struct afs_vnode *vnode, struct key *key, 346 afs_access_t *_access) 347 { 348 struct afs_permits *permits; 349 bool valid = false; 350 int i, ret; 351 352 _enter("{%llx:%llu},%x", 353 vnode->fid.vid, vnode->fid.vnode, key_serial(key)); 354 355 /* check the permits to see if we've got one yet */ 356 if (key == vnode->volume->cell->anonymous_key) { 357 _debug("anon"); 358 *_access = vnode->status.anon_access; 359 valid = true; 360 } else { 361 rcu_read_lock(); 362 permits = rcu_dereference(vnode->permit_cache); 363 if (permits) { 364 for (i = 0; i < permits->nr_permits; i++) { 365 if (permits->permits[i].key < key) 366 continue; 367 if (permits->permits[i].key > key) 368 break; 369 370 *_access = permits->permits[i].access; 371 valid = !permits->invalidated; 372 break; 373 } 374 } 375 rcu_read_unlock(); 376 } 377 378 if (!valid) { 379 /* Check the status on the file we're actually interested in 380 * (the post-processing will cache the result). 381 */ 382 _debug("no valid permit"); 383 384 ret = afs_fetch_status(vnode, key, false, _access); 385 if (ret < 0) { 386 *_access = 0; 387 _leave(" = %d", ret); 388 return ret; 389 } 390 } 391 392 _leave(" = 0 [access %x]", *_access); 393 return 0; 394 } 395 396 /* 397 * check the permissions on an AFS file 398 * - AFS ACLs are attached to directories only, and a file is controlled by its 399 * parent directory's ACL 400 */ 401 int afs_permission(struct inode *inode, int mask) 402 { 403 struct afs_vnode *vnode = AFS_FS_I(inode); 404 afs_access_t uninitialized_var(access); 405 struct key *key; 406 int ret = 0; 407 408 _enter("{{%llx:%llu},%lx},%x,", 409 vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); 410 411 if (mask & MAY_NOT_BLOCK) { 412 key = afs_request_key_rcu(vnode->volume->cell); 413 if (IS_ERR(key)) 414 return -ECHILD; 415 416 ret = -ECHILD; 417 if (!afs_check_validity(vnode) || 418 !afs_check_permit_rcu(vnode, key, &access)) 419 goto error; 420 } else { 421 key = afs_request_key(vnode->volume->cell); 422 if (IS_ERR(key)) { 423 _leave(" = %ld [key]", PTR_ERR(key)); 424 return PTR_ERR(key); 425 } 426 427 ret = afs_validate(vnode, key); 428 if (ret < 0) 429 goto error; 430 431 /* check the permits to see if we've got one yet */ 432 ret = afs_check_permit(vnode, key, &access); 433 if (ret < 0) 434 goto error; 435 } 436 437 /* interpret the access mask */ 438 _debug("REQ %x ACC %x on %s", 439 mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file"); 440 441 ret = 0; 442 if (S_ISDIR(inode->i_mode)) { 443 if (mask & (MAY_EXEC | MAY_READ | MAY_CHDIR)) { 444 if (!(access & AFS_ACE_LOOKUP)) 445 goto permission_denied; 446 } 447 if (mask & MAY_WRITE) { 448 if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */ 449 AFS_ACE_INSERT))) /* create, mkdir, symlink, rename to */ 450 goto permission_denied; 451 } 452 } else { 453 if (!(access & AFS_ACE_LOOKUP)) 454 goto permission_denied; 455 if ((mask & MAY_EXEC) && !(inode->i_mode & S_IXUSR)) 456 goto permission_denied; 457 if (mask & (MAY_EXEC | MAY_READ)) { 458 if (!(access & AFS_ACE_READ)) 459 goto permission_denied; 460 if (!(inode->i_mode & S_IRUSR)) 461 goto permission_denied; 462 } else if (mask & MAY_WRITE) { 463 if (!(access & AFS_ACE_WRITE)) 464 goto permission_denied; 465 if (!(inode->i_mode & S_IWUSR)) 466 goto permission_denied; 467 } 468 } 469 470 key_put(key); 471 _leave(" = %d", ret); 472 return ret; 473 474 permission_denied: 475 ret = -EACCES; 476 error: 477 key_put(key); 478 _leave(" = %d", ret); 479 return ret; 480 } 481 482 void __exit afs_clean_up_permit_cache(void) 483 { 484 int i; 485 486 for (i = 0; i < HASH_SIZE(afs_permits_cache); i++) 487 WARN_ON_ONCE(!hlist_empty(&afs_permits_cache[i])); 488 489 } 490