9 #include <linux/types.h>
10 #include <linux/sched.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/errno.h>
14 #include <linux/hash.h>
20 # define RPCDBG_FACILITY RPCDBG_AUTH
23 #define RPC_CREDCACHE_DEFAULT_HASHBITS (4)
33 static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
40 static unsigned long number_cred_unused;
42 #define MAX_HASHTABLE_BITS (14)
43 static int param_set_hashtbl_sz(
const char *
val,
const struct kernel_param *kp)
55 if (num > (1
U << nbits))
59 *(
unsigned int *)kp->
arg = nbits;
69 nbits = *(
unsigned int *)kp->
arg;
70 return sprintf(buffer,
"%u", 1
U << nbits);
73 #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int);
76 .set = param_set_hashtbl_sz,
77 .get = param_get_hashtbl_sz,
81 MODULE_PARM_DESC(auth_hashtable_size,
"RPC credential cache hashtable size");
84 pseudoflavor_to_flavor(
u32 flavor) {
85 if (flavor >= RPC_AUTH_MAXFLAVOR)
93 rpc_authflavor_t flavor;
96 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
98 spin_lock(&rpc_authflavor_lock);
99 if (auth_flavors[flavor] ==
NULL) {
100 auth_flavors[flavor] = ops;
103 spin_unlock(&rpc_authflavor_lock);
111 rpc_authflavor_t flavor;
114 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
116 spin_lock(&rpc_authflavor_lock);
117 if (auth_flavors[flavor] == ops) {
118 auth_flavors[flavor] =
NULL;
121 spin_unlock(&rpc_authflavor_lock);
139 rpc_authflavor_t flavor;
142 spin_lock(&rpc_authflavor_lock);
143 for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) {
144 const struct rpc_authops *
ops = auth_flavors[flavor];
145 rpc_authflavor_t pseudos[4];
148 if (result >= size) {
155 if (ops->list_pseudoflavors ==
NULL) {
156 array[result++] = ops->au_flavor;
159 len = ops->list_pseudoflavors(pseudos,
ARRAY_SIZE(pseudos));
164 for (i = 0; i < len; i++) {
165 if (result >= size) {
169 array[result++] = pseudos[
i];
172 spin_unlock(&rpc_authflavor_lock);
174 dprintk(
"RPC: %s returns %d\n", __func__, result);
182 struct rpc_auth *
auth;
183 const struct rpc_authops *
ops;
184 u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
187 if (flavor >= RPC_AUTH_MAXFLAVOR)
190 if ((ops = auth_flavors[flavor]) ==
NULL)
191 request_module(
"rpc-auth-%u", flavor);
192 spin_lock(&rpc_authflavor_lock);
193 ops = auth_flavors[flavor];
194 if (ops ==
NULL || !try_module_get(ops->owner)) {
195 spin_unlock(&rpc_authflavor_lock);
198 spin_unlock(&rpc_authflavor_lock);
199 auth = ops->create(clnt, pseudoflavor);
200 module_put(ops->owner);
217 auth->au_ops->destroy(auth);
223 rpcauth_unhash_cred_locked(
struct rpc_cred *
cred)
225 hlist_del_rcu(&cred->cr_hash);
227 clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
231 rpcauth_unhash_cred(
struct rpc_cred *
cred)
236 cache_lock = &cred->cr_auth->au_credcache->lock;
237 spin_lock(cache_lock);
240 rpcauth_unhash_cred_locked(cred);
241 spin_unlock(cache_lock);
252 unsigned int hashsize;
257 new->hashbits = auth_hashbits;
258 hashsize = 1
U <<
new->hashbits;
259 new->hashtable = kcalloc(hashsize,
sizeof(new->hashtable[0]),
GFP_KERNEL);
263 auth->au_credcache =
new;
278 struct rpc_cred *cred;
280 while (!list_empty(head)) {
282 list_del_init(&cred->cr_lru);
296 struct rpc_cred *cred;
297 unsigned int hashsize = 1
U << cache->
hashbits;
300 spin_lock(&rpc_credcache_lock);
301 spin_lock(&cache->
lock);
302 for (i = 0; i < hashsize; i++) {
304 while (!hlist_empty(head)) {
307 if (!list_empty(&cred->cr_lru)) {
309 number_cred_unused--;
312 rpcauth_unhash_cred_locked(cred);
315 spin_unlock(&cache->
lock);
316 spin_unlock(&rpc_credcache_lock);
317 rpcauth_destroy_credlist(&
free);
329 auth->au_credcache =
NULL;
338 #define RPC_AUTH_EXPIRY_MORATORIUM (60 * HZ)
344 rpcauth_prune_expired(
struct list_head *
free,
int nr_to_scan)
347 struct rpc_cred *cred, *
next;
352 if (nr_to_scan-- == 0)
359 test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
362 list_del_init(&cred->cr_lru);
363 number_cred_unused--;
367 cache_lock = &cred->cr_auth->au_credcache->lock;
368 spin_lock(cache_lock);
372 rpcauth_unhash_cred_locked(cred);
374 spin_unlock(cache_lock);
391 return (nr_to_scan == 0) ? 0 : -1;
392 if (list_empty(&cred_unused))
394 spin_lock(&rpc_credcache_lock);
395 res = rpcauth_prune_expired(&
free, nr_to_scan);
396 spin_unlock(&rpc_credcache_lock);
397 rpcauth_destroy_credlist(&
free);
411 struct rpc_cred *cred =
NULL,
415 nr = hash_long(acred->uid, cache->
hashbits);
418 hlist_for_each_entry_rcu(entry, pos, &cache->
hashtable[nr], cr_hash) {
419 if (!entry->cr_ops->crmatch(acred, entry, flags))
421 spin_lock(&cache->
lock);
422 if (
test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
423 spin_unlock(&cache->
lock);
426 cred = get_rpccred(entry);
427 spin_unlock(&cache->
lock);
435 new = auth->au_ops->crcreate(auth, acred, flags);
441 spin_lock(&cache->
lock);
443 if (!entry->cr_ops->crmatch(acred, entry, flags))
445 cred = get_rpccred(entry);
450 set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
451 hlist_add_head_rcu(&cred->cr_hash, &cache->
hashtable[nr]);
454 spin_unlock(&cache->
lock);
456 if (
test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
457 cred->cr_ops->cr_init !=
NULL &&
458 !(flags & RPCAUTH_LOOKUP_NEW)) {
459 int res = cred->cr_ops->cr_init(auth, cred);
465 rpcauth_destroy_credlist(&
free);
474 struct auth_cred acred;
475 struct rpc_cred *
ret;
478 dprintk(
"RPC: looking up %s cred\n",
479 auth->au_ops->au_name);
481 memset(&acred, 0,
sizeof(acred));
482 acred.uid = cred->
fsuid;
483 acred.gid = cred->
fsgid;
484 acred.group_info = get_group_info(((
struct cred *)cred)->
group_info);
486 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
493 struct rpc_auth *
auth,
const struct rpc_credops *ops)
495 INIT_HLIST_NODE(&cred->cr_hash);
496 INIT_LIST_HEAD(&cred->cr_lru);
498 cred->cr_auth =
auth;
502 cred->cr_magic = RPCAUTH_CRED_MAGIC;
504 cred->cr_uid = acred->uid;
511 dprintk(
"RPC: %5u holding %s cred %p\n", task->tk_pid,
512 cred->cr_auth->au_ops->au_name, cred);
513 return get_rpccred(cred);
517 static struct rpc_cred *
518 rpcauth_bind_root_cred(
struct rpc_task *
task,
int lookupflags)
521 struct auth_cred acred = {
526 dprintk(
"RPC: %5u looking up %s cred\n",
527 task->tk_pid, task->
tk_client->cl_auth->au_ops->au_name);
528 return auth->au_ops->lookup_cred(auth, &acred, lookupflags);
531 static struct rpc_cred *
532 rpcauth_bind_new_cred(
struct rpc_task *task,
int lookupflags)
534 struct rpc_auth *auth = task->
tk_client->cl_auth;
536 dprintk(
"RPC: %5u looking up %s cred\n",
537 task->tk_pid, auth->au_ops->au_name);
542 rpcauth_bindcred(
struct rpc_task *task,
struct rpc_cred *cred,
int flags)
545 struct rpc_cred *
new;
549 lookupflags |= RPCAUTH_LOOKUP_NEW;
551 new = cred->cr_ops->crbind(task, cred, lookupflags);
553 new = rpcauth_bind_root_cred(task, lookupflags);
555 new = rpcauth_bind_new_cred(task, lookupflags);
558 if (req->rq_cred !=
NULL)
568 if (
test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
570 cred->cr_ops->crdestroy(cred);
576 if (!list_empty(&cred->cr_lru)) {
577 number_cred_unused--;
578 list_del_init(&cred->cr_lru);
580 if (
test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
581 if (
test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
584 number_cred_unused++;
587 if (!rpcauth_unhash_cred(cred)) {
592 spin_unlock(&rpc_credcache_lock);
593 cred->cr_ops->crdestroy(cred);
596 spin_unlock(&rpc_credcache_lock);
603 struct rpc_cred *cred = task->
tk_rqstp->rq_cred;
605 dprintk(
"RPC: %5u marshaling %s cred %p\n",
606 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
608 return cred->cr_ops->crmarshal(task, p);
614 struct rpc_cred *cred = task->
tk_rqstp->rq_cred;
616 dprintk(
"RPC: %5u validating %s cred %p\n",
617 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
619 return cred->cr_ops->crvalidate(task, p);
622 static void rpcauth_wrap_req_encode(kxdreproc_t encode,
struct rpc_rqst *rqstp,
625 struct xdr_stream xdr;
628 encode(rqstp, &xdr, obj);
635 struct rpc_cred *cred = task->
tk_rqstp->rq_cred;
637 dprintk(
"RPC: %5u using %s cred %p to wrap rpc data\n",
638 task->tk_pid, cred->cr_ops->cr_name, cred);
639 if (cred->cr_ops->crwrap_req)
640 return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
642 rpcauth_wrap_req_encode(encode, rqstp, data, obj);
647 rpcauth_unwrap_req_decode(kxdrdproc_t decode,
struct rpc_rqst *rqstp,
650 struct xdr_stream xdr;
653 return decode(rqstp, &xdr, obj);
660 struct rpc_cred *cred = task->
tk_rqstp->rq_cred;
662 dprintk(
"RPC: %5u using %s cred %p to unwrap rpc data\n",
663 task->tk_pid, cred->cr_ops->cr_name, cred);
664 if (cred->cr_ops->crunwrap_resp)
665 return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
668 return rpcauth_unwrap_req_decode(decode, rqstp, data, obj);
674 struct rpc_cred *cred;
679 err = rpcauth_bindcred(task, task->
tk_msg.rpc_cred, task->
tk_flags);
684 dprintk(
"RPC: %5u refreshing %s cred %p\n",
685 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
687 err = cred->cr_ops->crrefresh(task);
697 struct rpc_cred *cred = task->
tk_rqstp->rq_cred;
699 dprintk(
"RPC: %5u invalidating %s cred %p\n",
700 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
702 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
708 struct rpc_cred *cred = task->
tk_rqstp->rq_cred;
710 return cred ==
NULL ||
711 test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
714 static struct shrinker rpc_cred_shrinker = {
715 .shrink = rpcauth_cache_shrinker,