^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/net/sunrpc/auth.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Generic RPC client authentication API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/cred.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sunrpc/clnt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/sunrpc/gss_api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <trace/events/sunrpc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define RPC_CREDCACHE_DEFAULT_HASHBITS (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct rpc_cred_cache {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct hlist_head *hashtable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned int hashbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static const struct rpc_authops __rcu *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) [RPC_AUTH_NULL] = (const struct rpc_authops __force __rcu *)&authnull_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) [RPC_AUTH_UNIX] = (const struct rpc_authops __force __rcu *)&authunix_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) NULL, /* others can be loadable modules */
^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) static LIST_HEAD(cred_unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static unsigned long number_cred_unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static struct cred machine_cred = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .usage = ATOMIC_INIT(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifdef CONFIG_DEBUG_CREDENTIALS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .magic = CRED_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #endif
^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) * Return the machine_cred pointer to be used whenever
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * the a generic machine credential is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) const struct cred *rpc_machine_cred(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return &machine_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) EXPORT_SYMBOL_GPL(rpc_machine_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MAX_HASHTABLE_BITS (14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int nbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) goto out_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ret = kstrtoul(val, 0, &num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) goto out_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) nbits = fls(num - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (nbits > MAX_HASHTABLE_BITS || nbits < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) goto out_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *(unsigned int *)kp->arg = nbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) out_inval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int param_get_hashtbl_sz(char *buffer, const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int nbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) nbits = *(unsigned int *)kp->arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return sprintf(buffer, "%u\n", 1U << nbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const struct kernel_param_ops param_ops_hashtbl_sz = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .set = param_set_hashtbl_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .get = param_get_hashtbl_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static unsigned long auth_max_cred_cachesize = ULONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) module_param(auth_max_cred_cachesize, ulong, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) MODULE_PARM_DESC(auth_max_cred_cachesize, "RPC credential maximum total cache size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pseudoflavor_to_flavor(u32 flavor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (flavor > RPC_AUTH_MAXFLAVOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return RPC_AUTH_GSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return flavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) rpcauth_register(const struct rpc_authops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) const struct rpc_authops *old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) rpc_authflavor_t flavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) old = cmpxchg((const struct rpc_authops ** __force)&auth_flavors[flavor], NULL, ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (old == NULL || old == ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL_GPL(rpcauth_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) rpcauth_unregister(const struct rpc_authops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const struct rpc_authops *old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rpc_authflavor_t flavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) old = cmpxchg((const struct rpc_authops ** __force)&auth_flavors[flavor], ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (old == ops || old == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EXPORT_SYMBOL_GPL(rpcauth_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static const struct rpc_authops *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) rpcauth_get_authops(rpc_authflavor_t flavor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) const struct rpc_authops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (flavor >= RPC_AUTH_MAXFLAVOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ops = rcu_dereference(auth_flavors[flavor]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (ops == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) request_module("rpc-auth-%u", flavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ops = rcu_dereference(auth_flavors[flavor]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (ops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!try_module_get(ops->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rpcauth_put_authops(const struct rpc_authops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) module_put(ops->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * rpcauth_get_pseudoflavor - check if security flavor is supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * @flavor: a security flavor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * @info: a GSS mech OID, quality of protection, and service value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * Verifies that an appropriate kernel module is available or already loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * not supported locally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rpc_authflavor_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) const struct rpc_authops *ops = rpcauth_get_authops(flavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) rpc_authflavor_t pseudoflavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return RPC_AUTH_MAXFLAVOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pseudoflavor = flavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (ops->info2flavor != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) pseudoflavor = ops->info2flavor(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) rpcauth_put_authops(ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return pseudoflavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * rpcauth_get_gssinfo - find GSS tuple matching a GSS pseudoflavor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @pseudoflavor: GSS pseudoflavor to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * @info: rpcsec_gss_info structure to fill in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * Returns zero and fills in "info" if pseudoflavor matches a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * supported mechanism.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rpc_authflavor_t flavor = pseudoflavor_to_flavor(pseudoflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) const struct rpc_authops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ops = rpcauth_get_authops(flavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (ops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) result = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ops->flavor2info != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) result = ops->flavor2info(pseudoflavor, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) rpcauth_put_authops(ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct rpc_auth *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) rpcauth_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct rpc_auth *auth = ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) const struct rpc_authops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ops = rpcauth_get_authops(flavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) auth = ops->create(args, clnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) rpcauth_put_authops(ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (IS_ERR(auth))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (clnt->cl_auth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) rpcauth_release(clnt->cl_auth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) clnt->cl_auth = auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) EXPORT_SYMBOL_GPL(rpcauth_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) rpcauth_release(struct rpc_auth *auth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!refcount_dec_and_test(&auth->au_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) auth->au_ops->destroy(auth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static DEFINE_SPINLOCK(rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * On success, the caller is responsible for freeing the reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * held by the hashtable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) rpcauth_unhash_cred_locked(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (!test_and_clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) hlist_del_rcu(&cred->cr_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) rpcauth_unhash_cred(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) spinlock_t *cache_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) cache_lock = &cred->cr_auth->au_credcache->lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) spin_lock(cache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = rpcauth_unhash_cred_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) spin_unlock(cache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * Initialize RPC credential cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) rpcauth_init_credcache(struct rpc_auth *auth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct rpc_cred_cache *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) unsigned int hashsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) new = kmalloc(sizeof(*new), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) goto out_nocache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) new->hashbits = auth_hashbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) hashsize = 1U << new->hashbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) new->hashtable = kcalloc(hashsize, sizeof(new->hashtable[0]), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!new->hashtable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto out_nohashtbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) spin_lock_init(&new->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) auth->au_credcache = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) out_nohashtbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) out_nocache:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) EXPORT_SYMBOL_GPL(rpcauth_init_credcache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) char *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) rpcauth_stringify_acceptor(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!cred->cr_ops->crstringify_acceptor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return cred->cr_ops->crstringify_acceptor(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) EXPORT_SYMBOL_GPL(rpcauth_stringify_acceptor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * Destroy a list of credentials
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) void rpcauth_destroy_credlist(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct rpc_cred *cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) while (!list_empty(head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) cred = list_entry(head->next, struct rpc_cred, cr_lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) list_del_init(&cred->cr_lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) put_rpccred(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^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) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rpcauth_lru_add_locked(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (!list_empty(&cred->cr_lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) number_cred_unused++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) list_add_tail(&cred->cr_lru, &cred_unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) rpcauth_lru_add(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (!list_empty(&cred->cr_lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) spin_lock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) rpcauth_lru_add_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) spin_unlock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) rpcauth_lru_remove_locked(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (list_empty(&cred->cr_lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) number_cred_unused--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) list_del_init(&cred->cr_lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) rpcauth_lru_remove(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (list_empty(&cred->cr_lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) spin_lock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) rpcauth_lru_remove_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) spin_unlock(&rpc_credcache_lock);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * Clear the RPC credential cache, and delete those credentials
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * that are not referenced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) rpcauth_clear_credcache(struct rpc_cred_cache *cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) LIST_HEAD(free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct rpc_cred *cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) unsigned int hashsize = 1U << cache->hashbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) spin_lock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) spin_lock(&cache->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) for (i = 0; i < hashsize; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) head = &cache->hashtable[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) while (!hlist_empty(head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) rpcauth_unhash_cred_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /* Note: We now hold a reference to cred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) rpcauth_lru_remove_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) list_add_tail(&cred->cr_lru, &free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) spin_unlock(&cache->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) spin_unlock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) rpcauth_destroy_credlist(&free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * Destroy the RPC credential cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) rpcauth_destroy_credcache(struct rpc_auth *auth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct rpc_cred_cache *cache = auth->au_credcache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) auth->au_credcache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) rpcauth_clear_credcache(cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) kfree(cache->hashtable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) kfree(cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) #define RPC_AUTH_EXPIRY_MORATORIUM (60 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * Remove stale credentials. Avoid sleeping inside the loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct rpc_cred *cred, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) long freed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (nr_to_scan-- == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (refcount_read(&cred->cr_count) > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rpcauth_lru_remove_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * Enforce a 60 second garbage collection moratorium
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Note that the cred_unused list must be time-ordered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!time_in_range(cred->cr_expire, expired, jiffies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!rpcauth_unhash_cred(cred))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) rpcauth_lru_remove_locked(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) freed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) list_add_tail(&cred->cr_lru, free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return freed ? freed : SHRINK_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) rpcauth_cache_do_shrink(int nr_to_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) LIST_HEAD(free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) unsigned long freed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) spin_lock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) freed = rpcauth_prune_expired(&free, nr_to_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) spin_unlock(&rpc_credcache_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) rpcauth_destroy_credlist(&free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return freed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * Run memory cache shrinker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) rpcauth_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if ((sc->gfp_mask & GFP_KERNEL) != GFP_KERNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return SHRINK_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* nothing left, don't come back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (list_empty(&cred_unused))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return SHRINK_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return rpcauth_cache_do_shrink(sc->nr_to_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) rpcauth_cache_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return number_cred_unused * sysctl_vfs_cache_pressure / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) rpcauth_cache_enforce_limit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unsigned long diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) unsigned int nr_to_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (number_cred_unused <= auth_max_cred_cachesize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) diff = number_cred_unused - auth_max_cred_cachesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) nr_to_scan = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (diff < nr_to_scan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) nr_to_scan = diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) rpcauth_cache_do_shrink(nr_to_scan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * Look up a process' credentials in the authentication cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct rpc_cred *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) int flags, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) LIST_HEAD(free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct rpc_cred_cache *cache = auth->au_credcache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct rpc_cred *cred = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) *entry, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) unsigned int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) nr = auth->au_ops->hash_cred(acred, cache->hashbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) hlist_for_each_entry_rcu(entry, &cache->hashtable[nr], cr_hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!entry->cr_ops->crmatch(acred, entry, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) cred = get_rpccred(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (cred != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) new = auth->au_ops->crcreate(auth, acred, flags, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (IS_ERR(new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) cred = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) spin_lock(&cache->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) hlist_for_each_entry(entry, &cache->hashtable[nr], cr_hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!entry->cr_ops->crmatch(acred, entry, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) cred = get_rpccred(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (cred == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) cred = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) refcount_inc(&cred->cr_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) list_add_tail(&new->cr_lru, &free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) spin_unlock(&cache->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) rpcauth_cache_enforce_limit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) cred->cr_ops->cr_init != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) !(flags & RPCAUTH_LOOKUP_NEW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int res = cred->cr_ops->cr_init(auth, cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (res < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) put_rpccred(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) cred = ERR_PTR(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) rpcauth_destroy_credlist(&free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) EXPORT_SYMBOL_GPL(rpcauth_lookup_credcache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct rpc_cred *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) rpcauth_lookupcred(struct rpc_auth *auth, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct auth_cred acred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct rpc_cred *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) const struct cred *cred = current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) memset(&acred, 0, sizeof(acred));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) acred.cred = cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ret = auth->au_ops->lookup_cred(auth, &acred, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) EXPORT_SYMBOL_GPL(rpcauth_lookupcred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct rpc_auth *auth, const struct rpc_credops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) INIT_HLIST_NODE(&cred->cr_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) INIT_LIST_HEAD(&cred->cr_lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) refcount_set(&cred->cr_count, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) cred->cr_auth = auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) cred->cr_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) cred->cr_ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cred->cr_expire = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) cred->cr_cred = get_cred(acred->cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) EXPORT_SYMBOL_GPL(rpcauth_init_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static struct rpc_cred *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct rpc_auth *auth = task->tk_client->cl_auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct auth_cred acred = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .cred = get_task_cred(&init_task),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct rpc_cred *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) put_cred(acred.cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static struct rpc_cred *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) rpcauth_bind_machine_cred(struct rpc_task *task, int lookupflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct rpc_auth *auth = task->tk_client->cl_auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct auth_cred acred = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) .principal = task->tk_client->cl_principal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) .cred = init_task.cred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (!acred.principal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return auth->au_ops->lookup_cred(auth, &acred, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static struct rpc_cred *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct rpc_auth *auth = task->tk_client->cl_auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return rpcauth_lookupcred(auth, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) rpcauth_bindcred(struct rpc_task *task, const struct cred *cred, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct rpc_rqst *req = task->tk_rqstp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct rpc_cred *new = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) int lookupflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct rpc_auth *auth = task->tk_client->cl_auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct auth_cred acred = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .cred = cred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (flags & RPC_TASK_ASYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) lookupflags |= RPCAUTH_LOOKUP_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (task->tk_op_cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* Task must use exactly this rpc_cred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) new = get_rpccred(task->tk_op_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) else if (cred != NULL && cred != &machine_cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) new = auth->au_ops->lookup_cred(auth, &acred, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) else if (cred == &machine_cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) new = rpcauth_bind_machine_cred(task, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* If machine cred couldn't be bound, try a root cred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) else if (cred == &machine_cred || (flags & RPC_TASK_ROOTCREDS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) new = rpcauth_bind_root_cred(task, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) else if (flags & RPC_TASK_NULLCREDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) new = authnull_ops.lookup_cred(NULL, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) new = rpcauth_bind_new_cred(task, lookupflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (IS_ERR(new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return PTR_ERR(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) put_rpccred(req->rq_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) req->rq_cred = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) put_rpccred(struct rpc_cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (cred == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (refcount_dec_and_test(&cred->cr_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) goto destroy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (refcount_read(&cred->cr_count) != 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) !test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) cred->cr_expire = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) rpcauth_lru_add(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* Race breaker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (unlikely(!test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) rpcauth_lru_remove(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) } else if (rpcauth_unhash_cred(cred)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) rpcauth_lru_remove(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (refcount_dec_and_test(&cred->cr_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) goto destroy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) destroy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) cred->cr_ops->crdestroy(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) EXPORT_SYMBOL_GPL(put_rpccred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * rpcauth_marshcred - Append RPC credential to end of @xdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * @task: controlling RPC task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * @xdr: xdr_stream containing initial portion of RPC Call header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * On success, an appropriate verifier is added to @xdr, @xdr is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * updated to point past the verifier, and zero is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * Otherwise, @xdr is in an undefined state and a negative errno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int rpcauth_marshcred(struct rpc_task *task, struct xdr_stream *xdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return ops->crmarshal(task, xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * rpcauth_wrap_req_encode - XDR encode the RPC procedure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * @task: controlling RPC task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * @xdr: stream where on-the-wire bytes are to be marshalled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * On success, @xdr contains the encoded and wrapped message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * Otherwise, @xdr is in an undefined state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int rpcauth_wrap_req_encode(struct rpc_task *task, struct xdr_stream *xdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) kxdreproc_t encode = task->tk_msg.rpc_proc->p_encode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) encode(task->tk_rqstp, xdr, task->tk_msg.rpc_argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) EXPORT_SYMBOL_GPL(rpcauth_wrap_req_encode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * rpcauth_wrap_req - XDR encode and wrap the RPC procedure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * @task: controlling RPC task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * @xdr: stream where on-the-wire bytes are to be marshalled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * On success, @xdr contains the encoded and wrapped message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * and zero is returned. Otherwise, @xdr is in an undefined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * state and a negative errno is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return ops->crwrap_req(task, xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * rpcauth_checkverf - Validate verifier in RPC Reply header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * @task: controlling RPC task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * @xdr: xdr_stream containing RPC Reply header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * On success, @xdr is updated to point past the verifier and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * zero is returned. Otherwise, @xdr is in an undefined state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * and a negative errno is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return ops->crvalidate(task, xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * rpcauth_unwrap_resp_decode - Invoke XDR decode function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * @task: controlling RPC task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * @xdr: stream where the Reply message resides
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * Returns zero on success; otherwise a negative errno is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) rpcauth_unwrap_resp_decode(struct rpc_task *task, struct xdr_stream *xdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return decode(task->tk_rqstp, xdr, task->tk_msg.rpc_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) EXPORT_SYMBOL_GPL(rpcauth_unwrap_resp_decode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * rpcauth_unwrap_resp - Invoke unwrap and decode function for the cred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * @task: controlling RPC task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * @xdr: stream where the Reply message resides
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * Returns zero on success; otherwise a negative errno is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) rpcauth_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) const struct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return ops->crunwrap_resp(task, xdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) rpcauth_xmit_need_reencode(struct rpc_task *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct rpc_cred *cred = task->tk_rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (!cred || !cred->cr_ops->crneed_reencode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return cred->cr_ops->crneed_reencode(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) rpcauth_refreshcred(struct rpc_task *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct rpc_cred *cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) cred = task->tk_rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (cred == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) err = rpcauth_bindcred(task, task->tk_msg.rpc_cred, task->tk_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) cred = task->tk_rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) err = cred->cr_ops->crrefresh(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) task->tk_status = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) rpcauth_invalcred(struct rpc_task *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct rpc_cred *cred = task->tk_rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) rpcauth_uptodatecred(struct rpc_task *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct rpc_cred *cred = task->tk_rqstp->rq_cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return cred == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static struct shrinker rpc_cred_shrinker = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .count_objects = rpcauth_cache_shrink_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .scan_objects = rpcauth_cache_shrink_scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .seeks = DEFAULT_SEEKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int __init rpcauth_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) err = rpc_init_authunix();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) err = register_shrinker(&rpc_cred_shrinker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) rpc_destroy_authunix();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) void rpcauth_remove_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) rpc_destroy_authunix();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) unregister_shrinker(&rpc_cred_shrinker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }