aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/auth.c')
-rw-r--r--net/sunrpc/auth.c157
1 files changed, 109 insertions, 48 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 8dc47f1d0001..880d0de3f50f 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -19,6 +19,15 @@
19# define RPCDBG_FACILITY RPCDBG_AUTH 19# define RPCDBG_FACILITY RPCDBG_AUTH
20#endif 20#endif
21 21
22#define RPC_CREDCACHE_DEFAULT_HASHBITS (4)
23struct rpc_cred_cache {
24 struct hlist_head *hashtable;
25 unsigned int hashbits;
26 spinlock_t lock;
27};
28
29static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
30
22static DEFINE_SPINLOCK(rpc_authflavor_lock); 31static DEFINE_SPINLOCK(rpc_authflavor_lock);
23static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { 32static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
24 &authnull_ops, /* AUTH_NULL */ 33 &authnull_ops, /* AUTH_NULL */
@@ -29,6 +38,42 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
29static LIST_HEAD(cred_unused); 38static LIST_HEAD(cred_unused);
30static unsigned long number_cred_unused; 39static unsigned long number_cred_unused;
31 40
41#define MAX_HASHTABLE_BITS (10)
42static int param_set_hashtbl_sz(const char *val, struct kernel_param *kp)
43{
44 unsigned long num;
45 unsigned int nbits;
46 int ret;
47
48 if (!val)
49 goto out_inval;
50 ret = strict_strtoul(val, 0, &num);
51 if (ret == -EINVAL)
52 goto out_inval;
53 nbits = fls(num);
54 if (num > (1U << nbits))
55 nbits++;
56 if (nbits > MAX_HASHTABLE_BITS || nbits < 2)
57 goto out_inval;
58 *(unsigned int *)kp->arg = nbits;
59 return 0;
60out_inval:
61 return -EINVAL;
62}
63
64static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp)
65{
66 unsigned int nbits;
67
68 nbits = *(unsigned int *)kp->arg;
69 return sprintf(buffer, "%u", 1U << nbits);
70}
71
72#define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int);
73
74module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644);
75MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
76
32static u32 77static u32
33pseudoflavor_to_flavor(u32 flavor) { 78pseudoflavor_to_flavor(u32 flavor) {
34 if (flavor >= RPC_AUTH_MAXFLAVOR) 79 if (flavor >= RPC_AUTH_MAXFLAVOR)
@@ -145,16 +190,23 @@ int
145rpcauth_init_credcache(struct rpc_auth *auth) 190rpcauth_init_credcache(struct rpc_auth *auth)
146{ 191{
147 struct rpc_cred_cache *new; 192 struct rpc_cred_cache *new;
148 int i; 193 unsigned int hashsize;
149 194
150 new = kmalloc(sizeof(*new), GFP_KERNEL); 195 new = kmalloc(sizeof(*new), GFP_KERNEL);
151 if (!new) 196 if (!new)
152 return -ENOMEM; 197 goto out_nocache;
153 for (i = 0; i < RPC_CREDCACHE_NR; i++) 198 new->hashbits = auth_hashbits;
154 INIT_HLIST_HEAD(&new->hashtable[i]); 199 hashsize = 1U << new->hashbits;
200 new->hashtable = kcalloc(hashsize, sizeof(new->hashtable[0]), GFP_KERNEL);
201 if (!new->hashtable)
202 goto out_nohashtbl;
155 spin_lock_init(&new->lock); 203 spin_lock_init(&new->lock);
156 auth->au_credcache = new; 204 auth->au_credcache = new;
157 return 0; 205 return 0;
206out_nohashtbl:
207 kfree(new);
208out_nocache:
209 return -ENOMEM;
158} 210}
159EXPORT_SYMBOL_GPL(rpcauth_init_credcache); 211EXPORT_SYMBOL_GPL(rpcauth_init_credcache);
160 212
@@ -183,11 +235,12 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache)
183 LIST_HEAD(free); 235 LIST_HEAD(free);
184 struct hlist_head *head; 236 struct hlist_head *head;
185 struct rpc_cred *cred; 237 struct rpc_cred *cred;
238 unsigned int hashsize = 1U << cache->hashbits;
186 int i; 239 int i;
187 240
188 spin_lock(&rpc_credcache_lock); 241 spin_lock(&rpc_credcache_lock);
189 spin_lock(&cache->lock); 242 spin_lock(&cache->lock);
190 for (i = 0; i < RPC_CREDCACHE_NR; i++) { 243 for (i = 0; i < hashsize; i++) {
191 head = &cache->hashtable[i]; 244 head = &cache->hashtable[i];
192 while (!hlist_empty(head)) { 245 while (!hlist_empty(head)) {
193 cred = hlist_entry(head->first, struct rpc_cred, cr_hash); 246 cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
@@ -216,6 +269,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth)
216 if (cache) { 269 if (cache) {
217 auth->au_credcache = NULL; 270 auth->au_credcache = NULL;
218 rpcauth_clear_credcache(cache); 271 rpcauth_clear_credcache(cache);
272 kfree(cache->hashtable);
219 kfree(cache); 273 kfree(cache);
220 } 274 }
221} 275}
@@ -297,7 +351,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
297 *entry, *new; 351 *entry, *new;
298 unsigned int nr; 352 unsigned int nr;
299 353
300 nr = hash_long(acred->uid, RPC_CREDCACHE_HASHBITS); 354 nr = hash_long(acred->uid, cache->hashbits);
301 355
302 rcu_read_lock(); 356 rcu_read_lock();
303 hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { 357 hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
@@ -390,16 +444,16 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
390} 444}
391EXPORT_SYMBOL_GPL(rpcauth_init_cred); 445EXPORT_SYMBOL_GPL(rpcauth_init_cred);
392 446
393void 447struct rpc_cred *
394rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) 448rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags)
395{ 449{
396 task->tk_msg.rpc_cred = get_rpccred(cred);
397 dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid, 450 dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
398 cred->cr_auth->au_ops->au_name, cred); 451 cred->cr_auth->au_ops->au_name, cred);
452 return get_rpccred(cred);
399} 453}
400EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred); 454EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred);
401 455
402static void 456static struct rpc_cred *
403rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) 457rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
404{ 458{
405 struct rpc_auth *auth = task->tk_client->cl_auth; 459 struct rpc_auth *auth = task->tk_client->cl_auth;
@@ -407,45 +461,43 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
407 .uid = 0, 461 .uid = 0,
408 .gid = 0, 462 .gid = 0,
409 }; 463 };
410 struct rpc_cred *ret;
411 464
412 dprintk("RPC: %5u looking up %s cred\n", 465 dprintk("RPC: %5u looking up %s cred\n",
413 task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); 466 task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
414 ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags); 467 return auth->au_ops->lookup_cred(auth, &acred, lookupflags);
415 if (!IS_ERR(ret))
416 task->tk_msg.rpc_cred = ret;
417 else
418 task->tk_status = PTR_ERR(ret);
419} 468}
420 469
421static void 470static struct rpc_cred *
422rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) 471rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags)
423{ 472{
424 struct rpc_auth *auth = task->tk_client->cl_auth; 473 struct rpc_auth *auth = task->tk_client->cl_auth;
425 struct rpc_cred *ret;
426 474
427 dprintk("RPC: %5u looking up %s cred\n", 475 dprintk("RPC: %5u looking up %s cred\n",
428 task->tk_pid, auth->au_ops->au_name); 476 task->tk_pid, auth->au_ops->au_name);
429 ret = rpcauth_lookupcred(auth, lookupflags); 477 return rpcauth_lookupcred(auth, lookupflags);
430 if (!IS_ERR(ret))
431 task->tk_msg.rpc_cred = ret;
432 else
433 task->tk_status = PTR_ERR(ret);
434} 478}
435 479
436void 480static int
437rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) 481rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags)
438{ 482{
483 struct rpc_rqst *req = task->tk_rqstp;
484 struct rpc_cred *new;
439 int lookupflags = 0; 485 int lookupflags = 0;
440 486
441 if (flags & RPC_TASK_ASYNC) 487 if (flags & RPC_TASK_ASYNC)
442 lookupflags |= RPCAUTH_LOOKUP_NEW; 488 lookupflags |= RPCAUTH_LOOKUP_NEW;
443 if (cred != NULL) 489 if (cred != NULL)
444 cred->cr_ops->crbind(task, cred, lookupflags); 490 new = cred->cr_ops->crbind(task, cred, lookupflags);
445 else if (flags & RPC_TASK_ROOTCREDS) 491 else if (flags & RPC_TASK_ROOTCREDS)
446 rpcauth_bind_root_cred(task, lookupflags); 492 new = rpcauth_bind_root_cred(task, lookupflags);
447 else 493 else
448 rpcauth_bind_new_cred(task, lookupflags); 494 new = rpcauth_bind_new_cred(task, lookupflags);
495 if (IS_ERR(new))
496 return PTR_ERR(new);
497 if (req->rq_cred != NULL)
498 put_rpccred(req->rq_cred);
499 req->rq_cred = new;
500 return 0;
449} 501}
450 502
451void 503void
@@ -484,22 +536,10 @@ out_nodestroy:
484} 536}
485EXPORT_SYMBOL_GPL(put_rpccred); 537EXPORT_SYMBOL_GPL(put_rpccred);
486 538
487void
488rpcauth_unbindcred(struct rpc_task *task)
489{
490 struct rpc_cred *cred = task->tk_msg.rpc_cred;
491
492 dprintk("RPC: %5u releasing %s cred %p\n",
493 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
494
495 put_rpccred(cred);
496 task->tk_msg.rpc_cred = NULL;
497}
498
499__be32 * 539__be32 *
500rpcauth_marshcred(struct rpc_task *task, __be32 *p) 540rpcauth_marshcred(struct rpc_task *task, __be32 *p)
501{ 541{
502 struct rpc_cred *cred = task->tk_msg.rpc_cred; 542 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
503 543
504 dprintk("RPC: %5u marshaling %s cred %p\n", 544 dprintk("RPC: %5u marshaling %s cred %p\n",
505 task->tk_pid, cred->cr_auth->au_ops->au_name, cred); 545 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
@@ -510,7 +550,7 @@ rpcauth_marshcred(struct rpc_task *task, __be32 *p)
510__be32 * 550__be32 *
511rpcauth_checkverf(struct rpc_task *task, __be32 *p) 551rpcauth_checkverf(struct rpc_task *task, __be32 *p)
512{ 552{
513 struct rpc_cred *cred = task->tk_msg.rpc_cred; 553 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
514 554
515 dprintk("RPC: %5u validating %s cred %p\n", 555 dprintk("RPC: %5u validating %s cred %p\n",
516 task->tk_pid, cred->cr_auth->au_ops->au_name, cred); 556 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
@@ -522,7 +562,7 @@ int
522rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, 562rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
523 __be32 *data, void *obj) 563 __be32 *data, void *obj)
524{ 564{
525 struct rpc_cred *cred = task->tk_msg.rpc_cred; 565 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
526 566
527 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", 567 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
528 task->tk_pid, cred->cr_ops->cr_name, cred); 568 task->tk_pid, cred->cr_ops->cr_name, cred);
@@ -536,7 +576,7 @@ int
536rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, 576rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
537 __be32 *data, void *obj) 577 __be32 *data, void *obj)
538{ 578{
539 struct rpc_cred *cred = task->tk_msg.rpc_cred; 579 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
540 580
541 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", 581 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
542 task->tk_pid, cred->cr_ops->cr_name, cred); 582 task->tk_pid, cred->cr_ops->cr_name, cred);
@@ -550,13 +590,21 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
550int 590int
551rpcauth_refreshcred(struct rpc_task *task) 591rpcauth_refreshcred(struct rpc_task *task)
552{ 592{
553 struct rpc_cred *cred = task->tk_msg.rpc_cred; 593 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
554 int err; 594 int err;
555 595
596 cred = task->tk_rqstp->rq_cred;
597 if (cred == NULL) {
598 err = rpcauth_bindcred(task, task->tk_msg.rpc_cred, task->tk_flags);
599 if (err < 0)
600 goto out;
601 cred = task->tk_rqstp->rq_cred;
602 };
556 dprintk("RPC: %5u refreshing %s cred %p\n", 603 dprintk("RPC: %5u refreshing %s cred %p\n",
557 task->tk_pid, cred->cr_auth->au_ops->au_name, cred); 604 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
558 605
559 err = cred->cr_ops->crrefresh(task); 606 err = cred->cr_ops->crrefresh(task);
607out:
560 if (err < 0) 608 if (err < 0)
561 task->tk_status = err; 609 task->tk_status = err;
562 return err; 610 return err;
@@ -565,7 +613,7 @@ rpcauth_refreshcred(struct rpc_task *task)
565void 613void
566rpcauth_invalcred(struct rpc_task *task) 614rpcauth_invalcred(struct rpc_task *task)
567{ 615{
568 struct rpc_cred *cred = task->tk_msg.rpc_cred; 616 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
569 617
570 dprintk("RPC: %5u invalidating %s cred %p\n", 618 dprintk("RPC: %5u invalidating %s cred %p\n",
571 task->tk_pid, cred->cr_auth->au_ops->au_name, cred); 619 task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
@@ -576,7 +624,7 @@ rpcauth_invalcred(struct rpc_task *task)
576int 624int
577rpcauth_uptodatecred(struct rpc_task *task) 625rpcauth_uptodatecred(struct rpc_task *task)
578{ 626{
579 struct rpc_cred *cred = task->tk_msg.rpc_cred; 627 struct rpc_cred *cred = task->tk_rqstp->rq_cred;
580 628
581 return cred == NULL || 629 return cred == NULL ||
582 test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0; 630 test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
@@ -587,14 +635,27 @@ static struct shrinker rpc_cred_shrinker = {
587 .seeks = DEFAULT_SEEKS, 635 .seeks = DEFAULT_SEEKS,
588}; 636};
589 637
590void __init rpcauth_init_module(void) 638int __init rpcauth_init_module(void)
591{ 639{
592 rpc_init_authunix(); 640 int err;
593 rpc_init_generic_auth(); 641
642 err = rpc_init_authunix();
643 if (err < 0)
644 goto out1;
645 err = rpc_init_generic_auth();
646 if (err < 0)
647 goto out2;
594 register_shrinker(&rpc_cred_shrinker); 648 register_shrinker(&rpc_cred_shrinker);
649 return 0;
650out2:
651 rpc_destroy_authunix();
652out1:
653 return err;
595} 654}
596 655
597void __exit rpcauth_remove_module(void) 656void __exit rpcauth_remove_module(void)
598{ 657{
658 rpc_destroy_authunix();
659 rpc_destroy_generic_auth();
599 unregister_shrinker(&rpc_cred_shrinker); 660 unregister_shrinker(&rpc_cred_shrinker);
600} 661}