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