aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/auth_gss.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c349
1 files changed, 226 insertions, 123 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4e4ccc5b6fea..baf4096d52d4 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -54,9 +54,10 @@
54#include <linux/sunrpc/gss_api.h> 54#include <linux/sunrpc/gss_api.h>
55#include <asm/uaccess.h> 55#include <asm/uaccess.h>
56 56
57static struct rpc_authops authgss_ops; 57static const struct rpc_authops authgss_ops;
58 58
59static struct rpc_credops gss_credops; 59static const struct rpc_credops gss_credops;
60static const struct rpc_credops gss_nullops;
60 61
61#ifdef RPC_DEBUG 62#ifdef RPC_DEBUG
62# define RPCDBG_FACILITY RPCDBG_AUTH 63# define RPCDBG_FACILITY RPCDBG_AUTH
@@ -64,7 +65,6 @@ static struct rpc_credops gss_credops;
64 65
65#define NFS_NGROUPS 16 66#define NFS_NGROUPS 16
66 67
67#define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */
68#define GSS_CRED_SLACK 1024 /* XXX: unused */ 68#define GSS_CRED_SLACK 1024 /* XXX: unused */
69/* length of a krb5 verifier (48), plus data added before arguments when 69/* length of a krb5 verifier (48), plus data added before arguments when
70 * using integrity (two 4-byte integers): */ 70 * using integrity (two 4-byte integers): */
@@ -79,19 +79,16 @@ static struct rpc_credops gss_credops;
79/* dump the buffer in `emacs-hexl' style */ 79/* dump the buffer in `emacs-hexl' style */
80#define isprint(c) ((c > 0x1f) && (c < 0x7f)) 80#define isprint(c) ((c > 0x1f) && (c < 0x7f))
81 81
82static DEFINE_RWLOCK(gss_ctx_lock);
83
84struct gss_auth { 82struct gss_auth {
83 struct kref kref;
85 struct rpc_auth rpc_auth; 84 struct rpc_auth rpc_auth;
86 struct gss_api_mech *mech; 85 struct gss_api_mech *mech;
87 enum rpc_gss_svc service; 86 enum rpc_gss_svc service;
88 struct list_head upcalls;
89 struct rpc_clnt *client; 87 struct rpc_clnt *client;
90 struct dentry *dentry; 88 struct dentry *dentry;
91 spinlock_t lock;
92}; 89};
93 90
94static void gss_destroy_ctx(struct gss_cl_ctx *); 91static void gss_free_ctx(struct gss_cl_ctx *);
95static struct rpc_pipe_ops gss_upcall_ops; 92static struct rpc_pipe_ops gss_upcall_ops;
96 93
97static inline struct gss_cl_ctx * 94static inline struct gss_cl_ctx *
@@ -105,20 +102,24 @@ static inline void
105gss_put_ctx(struct gss_cl_ctx *ctx) 102gss_put_ctx(struct gss_cl_ctx *ctx)
106{ 103{
107 if (atomic_dec_and_test(&ctx->count)) 104 if (atomic_dec_and_test(&ctx->count))
108 gss_destroy_ctx(ctx); 105 gss_free_ctx(ctx);
109} 106}
110 107
108/* gss_cred_set_ctx:
109 * called by gss_upcall_callback and gss_create_upcall in order
110 * to set the gss context. The actual exchange of an old context
111 * and a new one is protected by the inode->i_lock.
112 */
111static void 113static void
112gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) 114gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
113{ 115{
114 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 116 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
115 struct gss_cl_ctx *old; 117 struct gss_cl_ctx *old;
116 write_lock(&gss_ctx_lock); 118
117 old = gss_cred->gc_ctx; 119 old = gss_cred->gc_ctx;
118 gss_cred->gc_ctx = ctx; 120 rcu_assign_pointer(gss_cred->gc_ctx, ctx);
119 cred->cr_flags |= RPCAUTH_CRED_UPTODATE; 121 set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
120 cred->cr_flags &= ~RPCAUTH_CRED_NEW; 122 clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
121 write_unlock(&gss_ctx_lock);
122 if (old) 123 if (old)
123 gss_put_ctx(old); 124 gss_put_ctx(old);
124} 125}
@@ -129,10 +130,10 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
129 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 130 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
130 int res = 0; 131 int res = 0;
131 132
132 read_lock(&gss_ctx_lock); 133 rcu_read_lock();
133 if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx) 134 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
134 res = 1; 135 res = 1;
135 read_unlock(&gss_ctx_lock); 136 rcu_read_unlock();
136 return res; 137 return res;
137} 138}
138 139
@@ -171,10 +172,10 @@ gss_cred_get_ctx(struct rpc_cred *cred)
171 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 172 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
172 struct gss_cl_ctx *ctx = NULL; 173 struct gss_cl_ctx *ctx = NULL;
173 174
174 read_lock(&gss_ctx_lock); 175 rcu_read_lock();
175 if (gss_cred->gc_ctx) 176 if (gss_cred->gc_ctx)
176 ctx = gss_get_ctx(gss_cred->gc_ctx); 177 ctx = gss_get_ctx(gss_cred->gc_ctx);
177 read_unlock(&gss_ctx_lock); 178 rcu_read_unlock();
178 return ctx; 179 return ctx;
179} 180}
180 181
@@ -269,10 +270,10 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
269} 270}
270 271
271static struct gss_upcall_msg * 272static struct gss_upcall_msg *
272__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid) 273__gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
273{ 274{
274 struct gss_upcall_msg *pos; 275 struct gss_upcall_msg *pos;
275 list_for_each_entry(pos, &gss_auth->upcalls, list) { 276 list_for_each_entry(pos, &rpci->in_downcall, list) {
276 if (pos->uid != uid) 277 if (pos->uid != uid)
277 continue; 278 continue;
278 atomic_inc(&pos->count); 279 atomic_inc(&pos->count);
@@ -290,24 +291,24 @@ __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
290static inline struct gss_upcall_msg * 291static inline struct gss_upcall_msg *
291gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) 292gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
292{ 293{
294 struct inode *inode = gss_auth->dentry->d_inode;
295 struct rpc_inode *rpci = RPC_I(inode);
293 struct gss_upcall_msg *old; 296 struct gss_upcall_msg *old;
294 297
295 spin_lock(&gss_auth->lock); 298 spin_lock(&inode->i_lock);
296 old = __gss_find_upcall(gss_auth, gss_msg->uid); 299 old = __gss_find_upcall(rpci, gss_msg->uid);
297 if (old == NULL) { 300 if (old == NULL) {
298 atomic_inc(&gss_msg->count); 301 atomic_inc(&gss_msg->count);
299 list_add(&gss_msg->list, &gss_auth->upcalls); 302 list_add(&gss_msg->list, &rpci->in_downcall);
300 } else 303 } else
301 gss_msg = old; 304 gss_msg = old;
302 spin_unlock(&gss_auth->lock); 305 spin_unlock(&inode->i_lock);
303 return gss_msg; 306 return gss_msg;
304} 307}
305 308
306static void 309static void
307__gss_unhash_msg(struct gss_upcall_msg *gss_msg) 310__gss_unhash_msg(struct gss_upcall_msg *gss_msg)
308{ 311{
309 if (list_empty(&gss_msg->list))
310 return;
311 list_del_init(&gss_msg->list); 312 list_del_init(&gss_msg->list);
312 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); 313 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
313 wake_up_all(&gss_msg->waitqueue); 314 wake_up_all(&gss_msg->waitqueue);
@@ -318,10 +319,14 @@ static void
318gss_unhash_msg(struct gss_upcall_msg *gss_msg) 319gss_unhash_msg(struct gss_upcall_msg *gss_msg)
319{ 320{
320 struct gss_auth *gss_auth = gss_msg->auth; 321 struct gss_auth *gss_auth = gss_msg->auth;
322 struct inode *inode = gss_auth->dentry->d_inode;
321 323
322 spin_lock(&gss_auth->lock); 324 if (list_empty(&gss_msg->list))
323 __gss_unhash_msg(gss_msg); 325 return;
324 spin_unlock(&gss_auth->lock); 326 spin_lock(&inode->i_lock);
327 if (!list_empty(&gss_msg->list))
328 __gss_unhash_msg(gss_msg);
329 spin_unlock(&inode->i_lock);
325} 330}
326 331
327static void 332static void
@@ -330,16 +335,16 @@ gss_upcall_callback(struct rpc_task *task)
330 struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, 335 struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
331 struct gss_cred, gc_base); 336 struct gss_cred, gc_base);
332 struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; 337 struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
338 struct inode *inode = gss_msg->auth->dentry->d_inode;
333 339
334 BUG_ON(gss_msg == NULL); 340 spin_lock(&inode->i_lock);
335 if (gss_msg->ctx) 341 if (gss_msg->ctx)
336 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx)); 342 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
337 else 343 else
338 task->tk_status = gss_msg->msg.errno; 344 task->tk_status = gss_msg->msg.errno;
339 spin_lock(&gss_msg->auth->lock);
340 gss_cred->gc_upcall = NULL; 345 gss_cred->gc_upcall = NULL;
341 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); 346 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
342 spin_unlock(&gss_msg->auth->lock); 347 spin_unlock(&inode->i_lock);
343 gss_release_msg(gss_msg); 348 gss_release_msg(gss_msg);
344} 349}
345 350
@@ -386,11 +391,12 @@ static inline int
386gss_refresh_upcall(struct rpc_task *task) 391gss_refresh_upcall(struct rpc_task *task)
387{ 392{
388 struct rpc_cred *cred = task->tk_msg.rpc_cred; 393 struct rpc_cred *cred = task->tk_msg.rpc_cred;
389 struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth, 394 struct gss_auth *gss_auth = container_of(cred->cr_auth,
390 struct gss_auth, rpc_auth); 395 struct gss_auth, rpc_auth);
391 struct gss_cred *gss_cred = container_of(cred, 396 struct gss_cred *gss_cred = container_of(cred,
392 struct gss_cred, gc_base); 397 struct gss_cred, gc_base);
393 struct gss_upcall_msg *gss_msg; 398 struct gss_upcall_msg *gss_msg;
399 struct inode *inode = gss_auth->dentry->d_inode;
394 int err = 0; 400 int err = 0;
395 401
396 dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, 402 dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
@@ -400,7 +406,7 @@ gss_refresh_upcall(struct rpc_task *task)
400 err = PTR_ERR(gss_msg); 406 err = PTR_ERR(gss_msg);
401 goto out; 407 goto out;
402 } 408 }
403 spin_lock(&gss_auth->lock); 409 spin_lock(&inode->i_lock);
404 if (gss_cred->gc_upcall != NULL) 410 if (gss_cred->gc_upcall != NULL)
405 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL); 411 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
406 else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { 412 else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
@@ -411,7 +417,7 @@ gss_refresh_upcall(struct rpc_task *task)
411 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL); 417 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
412 } else 418 } else
413 err = gss_msg->msg.errno; 419 err = gss_msg->msg.errno;
414 spin_unlock(&gss_auth->lock); 420 spin_unlock(&inode->i_lock);
415 gss_release_msg(gss_msg); 421 gss_release_msg(gss_msg);
416out: 422out:
417 dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", 423 dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
@@ -422,6 +428,7 @@ out:
422static inline int 428static inline int
423gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) 429gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
424{ 430{
431 struct inode *inode = gss_auth->dentry->d_inode;
425 struct rpc_cred *cred = &gss_cred->gc_base; 432 struct rpc_cred *cred = &gss_cred->gc_base;
426 struct gss_upcall_msg *gss_msg; 433 struct gss_upcall_msg *gss_msg;
427 DEFINE_WAIT(wait); 434 DEFINE_WAIT(wait);
@@ -435,12 +442,11 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
435 } 442 }
436 for (;;) { 443 for (;;) {
437 prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); 444 prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
438 spin_lock(&gss_auth->lock); 445 spin_lock(&inode->i_lock);
439 if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { 446 if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
440 spin_unlock(&gss_auth->lock);
441 break; 447 break;
442 } 448 }
443 spin_unlock(&gss_auth->lock); 449 spin_unlock(&inode->i_lock);
444 if (signalled()) { 450 if (signalled()) {
445 err = -ERESTARTSYS; 451 err = -ERESTARTSYS;
446 goto out_intr; 452 goto out_intr;
@@ -451,6 +457,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
451 gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx)); 457 gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
452 else 458 else
453 err = gss_msg->msg.errno; 459 err = gss_msg->msg.errno;
460 spin_unlock(&inode->i_lock);
454out_intr: 461out_intr:
455 finish_wait(&gss_msg->waitqueue, &wait); 462 finish_wait(&gss_msg->waitqueue, &wait);
456 gss_release_msg(gss_msg); 463 gss_release_msg(gss_msg);
@@ -489,12 +496,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
489 const void *p, *end; 496 const void *p, *end;
490 void *buf; 497 void *buf;
491 struct rpc_clnt *clnt; 498 struct rpc_clnt *clnt;
492 struct gss_auth *gss_auth;
493 struct rpc_cred *cred;
494 struct gss_upcall_msg *gss_msg; 499 struct gss_upcall_msg *gss_msg;
500 struct inode *inode = filp->f_path.dentry->d_inode;
495 struct gss_cl_ctx *ctx; 501 struct gss_cl_ctx *ctx;
496 uid_t uid; 502 uid_t uid;
497 int err = -EFBIG; 503 ssize_t err = -EFBIG;
498 504
499 if (mlen > MSG_BUF_MAXSIZE) 505 if (mlen > MSG_BUF_MAXSIZE)
500 goto out; 506 goto out;
@@ -503,7 +509,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
503 if (!buf) 509 if (!buf)
504 goto out; 510 goto out;
505 511
506 clnt = RPC_I(filp->f_path.dentry->d_inode)->private; 512 clnt = RPC_I(inode)->private;
507 err = -EFAULT; 513 err = -EFAULT;
508 if (copy_from_user(buf, src, mlen)) 514 if (copy_from_user(buf, src, mlen))
509 goto err; 515 goto err;
@@ -519,43 +525,38 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
519 ctx = gss_alloc_context(); 525 ctx = gss_alloc_context();
520 if (ctx == NULL) 526 if (ctx == NULL)
521 goto err; 527 goto err;
522 err = 0; 528
523 gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth); 529 err = -ENOENT;
524 p = gss_fill_context(p, end, ctx, gss_auth->mech); 530 /* Find a matching upcall */
531 spin_lock(&inode->i_lock);
532 gss_msg = __gss_find_upcall(RPC_I(inode), uid);
533 if (gss_msg == NULL) {
534 spin_unlock(&inode->i_lock);
535 goto err_put_ctx;
536 }
537 list_del_init(&gss_msg->list);
538 spin_unlock(&inode->i_lock);
539
540 p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
525 if (IS_ERR(p)) { 541 if (IS_ERR(p)) {
526 err = PTR_ERR(p); 542 err = PTR_ERR(p);
527 if (err != -EACCES) 543 gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
528 goto err_put_ctx; 544 goto err_release_msg;
529 }
530 spin_lock(&gss_auth->lock);
531 gss_msg = __gss_find_upcall(gss_auth, uid);
532 if (gss_msg) {
533 if (err == 0 && gss_msg->ctx == NULL)
534 gss_msg->ctx = gss_get_ctx(ctx);
535 gss_msg->msg.errno = err;
536 __gss_unhash_msg(gss_msg);
537 spin_unlock(&gss_auth->lock);
538 gss_release_msg(gss_msg);
539 } else {
540 struct auth_cred acred = { .uid = uid };
541 spin_unlock(&gss_auth->lock);
542 cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
543 if (IS_ERR(cred)) {
544 err = PTR_ERR(cred);
545 goto err_put_ctx;
546 }
547 gss_cred_set_ctx(cred, gss_get_ctx(ctx));
548 } 545 }
549 gss_put_ctx(ctx); 546 gss_msg->ctx = gss_get_ctx(ctx);
550 kfree(buf); 547 err = mlen;
551 dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen); 548
552 return mlen; 549err_release_msg:
550 spin_lock(&inode->i_lock);
551 __gss_unhash_msg(gss_msg);
552 spin_unlock(&inode->i_lock);
553 gss_release_msg(gss_msg);
553err_put_ctx: 554err_put_ctx:
554 gss_put_ctx(ctx); 555 gss_put_ctx(ctx);
555err: 556err:
556 kfree(buf); 557 kfree(buf);
557out: 558out:
558 dprintk("RPC: gss_pipe_downcall returning %d\n", err); 559 dprintk("RPC: gss_pipe_downcall returning %Zd\n", err);
559 return err; 560 return err;
560} 561}
561 562
@@ -563,27 +564,21 @@ static void
563gss_pipe_release(struct inode *inode) 564gss_pipe_release(struct inode *inode)
564{ 565{
565 struct rpc_inode *rpci = RPC_I(inode); 566 struct rpc_inode *rpci = RPC_I(inode);
566 struct rpc_clnt *clnt; 567 struct gss_upcall_msg *gss_msg;
567 struct rpc_auth *auth;
568 struct gss_auth *gss_auth;
569 568
570 clnt = rpci->private; 569 spin_lock(&inode->i_lock);
571 auth = clnt->cl_auth; 570 while (!list_empty(&rpci->in_downcall)) {
572 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
573 spin_lock(&gss_auth->lock);
574 while (!list_empty(&gss_auth->upcalls)) {
575 struct gss_upcall_msg *gss_msg;
576 571
577 gss_msg = list_entry(gss_auth->upcalls.next, 572 gss_msg = list_entry(rpci->in_downcall.next,
578 struct gss_upcall_msg, list); 573 struct gss_upcall_msg, list);
579 gss_msg->msg.errno = -EPIPE; 574 gss_msg->msg.errno = -EPIPE;
580 atomic_inc(&gss_msg->count); 575 atomic_inc(&gss_msg->count);
581 __gss_unhash_msg(gss_msg); 576 __gss_unhash_msg(gss_msg);
582 spin_unlock(&gss_auth->lock); 577 spin_unlock(&inode->i_lock);
583 gss_release_msg(gss_msg); 578 gss_release_msg(gss_msg);
584 spin_lock(&gss_auth->lock); 579 spin_lock(&inode->i_lock);
585 } 580 }
586 spin_unlock(&gss_auth->lock); 581 spin_unlock(&inode->i_lock);
587} 582}
588 583
589static void 584static void
@@ -637,18 +632,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
637 gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); 632 gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
638 if (gss_auth->service == 0) 633 if (gss_auth->service == 0)
639 goto err_put_mech; 634 goto err_put_mech;
640 INIT_LIST_HEAD(&gss_auth->upcalls);
641 spin_lock_init(&gss_auth->lock);
642 auth = &gss_auth->rpc_auth; 635 auth = &gss_auth->rpc_auth;
643 auth->au_cslack = GSS_CRED_SLACK >> 2; 636 auth->au_cslack = GSS_CRED_SLACK >> 2;
644 auth->au_rslack = GSS_VERF_SLACK >> 2; 637 auth->au_rslack = GSS_VERF_SLACK >> 2;
645 auth->au_ops = &authgss_ops; 638 auth->au_ops = &authgss_ops;
646 auth->au_flavor = flavor; 639 auth->au_flavor = flavor;
647 atomic_set(&auth->au_count, 1); 640 atomic_set(&auth->au_count, 1);
648 641 kref_init(&gss_auth->kref);
649 err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
650 if (err)
651 goto err_put_mech;
652 642
653 gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, 643 gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
654 clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 644 clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
@@ -657,7 +647,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
657 goto err_put_mech; 647 goto err_put_mech;
658 } 648 }
659 649
650 err = rpcauth_init_credcache(auth);
651 if (err)
652 goto err_unlink_pipe;
653
660 return auth; 654 return auth;
655err_unlink_pipe:
656 rpc_unlink(gss_auth->dentry);
661err_put_mech: 657err_put_mech:
662 gss_mech_put(gss_auth->mech); 658 gss_mech_put(gss_auth->mech);
663err_free: 659err_free:
@@ -668,6 +664,25 @@ out_dec:
668} 664}
669 665
670static void 666static void
667gss_free(struct gss_auth *gss_auth)
668{
669 rpc_unlink(gss_auth->dentry);
670 gss_auth->dentry = NULL;
671 gss_mech_put(gss_auth->mech);
672
673 kfree(gss_auth);
674 module_put(THIS_MODULE);
675}
676
677static void
678gss_free_callback(struct kref *kref)
679{
680 struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref);
681
682 gss_free(gss_auth);
683}
684
685static void
671gss_destroy(struct rpc_auth *auth) 686gss_destroy(struct rpc_auth *auth)
672{ 687{
673 struct gss_auth *gss_auth; 688 struct gss_auth *gss_auth;
@@ -675,23 +690,51 @@ gss_destroy(struct rpc_auth *auth)
675 dprintk("RPC: destroying GSS authenticator %p flavor %d\n", 690 dprintk("RPC: destroying GSS authenticator %p flavor %d\n",
676 auth, auth->au_flavor); 691 auth, auth->au_flavor);
677 692
693 rpcauth_destroy_credcache(auth);
694
678 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 695 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
679 rpc_unlink(gss_auth->dentry); 696 kref_put(&gss_auth->kref, gss_free_callback);
680 gss_auth->dentry = NULL; 697}
681 gss_mech_put(gss_auth->mech);
682 698
683 rpcauth_free_credcache(auth); 699/*
684 kfree(gss_auth); 700 * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
685 module_put(THIS_MODULE); 701 * to the server with the GSS control procedure field set to
702 * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
703 * all RPCSEC_GSS state associated with that context.
704 */
705static int
706gss_destroying_context(struct rpc_cred *cred)
707{
708 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
709 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
710 struct rpc_task *task;
711
712 if (gss_cred->gc_ctx == NULL ||
713 gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
714 return 0;
715
716 gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
717 cred->cr_ops = &gss_nullops;
718
719 /* Take a reference to ensure the cred will be destroyed either
720 * by the RPC call or by the put_rpccred() below */
721 get_rpccred(cred);
722
723 task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
724 if (!IS_ERR(task))
725 rpc_put_task(task);
726
727 put_rpccred(cred);
728 return 1;
686} 729}
687 730
688/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure 731/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
689 * to create a new cred or context, so they check that things have been 732 * to create a new cred or context, so they check that things have been
690 * allocated before freeing them. */ 733 * allocated before freeing them. */
691static void 734static void
692gss_destroy_ctx(struct gss_cl_ctx *ctx) 735gss_do_free_ctx(struct gss_cl_ctx *ctx)
693{ 736{
694 dprintk("RPC: gss_destroy_ctx\n"); 737 dprintk("RPC: gss_free_ctx\n");
695 738
696 if (ctx->gc_gss_ctx) 739 if (ctx->gc_gss_ctx)
697 gss_delete_sec_context(&ctx->gc_gss_ctx); 740 gss_delete_sec_context(&ctx->gc_gss_ctx);
@@ -701,15 +744,46 @@ gss_destroy_ctx(struct gss_cl_ctx *ctx)
701} 744}
702 745
703static void 746static void
704gss_destroy_cred(struct rpc_cred *rc) 747gss_free_ctx_callback(struct rcu_head *head)
705{ 748{
706 struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base); 749 struct gss_cl_ctx *ctx = container_of(head, struct gss_cl_ctx, gc_rcu);
750 gss_do_free_ctx(ctx);
751}
707 752
708 dprintk("RPC: gss_destroy_cred \n"); 753static void
754gss_free_ctx(struct gss_cl_ctx *ctx)
755{
756 call_rcu(&ctx->gc_rcu, gss_free_ctx_callback);
757}
709 758
710 if (cred->gc_ctx) 759static void
711 gss_put_ctx(cred->gc_ctx); 760gss_free_cred(struct gss_cred *gss_cred)
712 kfree(cred); 761{
762 dprintk("RPC: gss_free_cred %p\n", gss_cred);
763 kfree(gss_cred);
764}
765
766static void
767gss_free_cred_callback(struct rcu_head *head)
768{
769 struct gss_cred *gss_cred = container_of(head, struct gss_cred, gc_base.cr_rcu);
770 gss_free_cred(gss_cred);
771}
772
773static void
774gss_destroy_cred(struct rpc_cred *cred)
775{
776 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
777 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
778 struct gss_cl_ctx *ctx = gss_cred->gc_ctx;
779
780 if (gss_destroying_context(cred))
781 return;
782 rcu_assign_pointer(gss_cred->gc_ctx, NULL);
783 call_rcu(&cred->cr_rcu, gss_free_cred_callback);
784 if (ctx)
785 gss_put_ctx(ctx);
786 kref_put(&gss_auth->kref, gss_free_callback);
713} 787}
714 788
715/* 789/*
@@ -734,16 +808,14 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
734 if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL))) 808 if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
735 goto out_err; 809 goto out_err;
736 810
737 atomic_set(&cred->gc_count, 1); 811 rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);
738 cred->gc_uid = acred->uid;
739 /* 812 /*
740 * Note: in order to force a call to call_refresh(), we deliberately 813 * Note: in order to force a call to call_refresh(), we deliberately
741 * fail to flag the credential as RPCAUTH_CRED_UPTODATE. 814 * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
742 */ 815 */
743 cred->gc_flags = 0; 816 cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
744 cred->gc_base.cr_ops = &gss_credops;
745 cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
746 cred->gc_service = gss_auth->service; 817 cred->gc_service = gss_auth->service;
818 kref_get(&gss_auth->kref);
747 return &cred->gc_base; 819 return &cred->gc_base;
748 820
749out_err: 821out_err:
@@ -774,7 +846,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
774 * we don't really care if the credential has expired or not, 846 * we don't really care if the credential has expired or not,
775 * since the caller should be prepared to reinitialise it. 847 * since the caller should be prepared to reinitialise it.
776 */ 848 */
777 if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) 849 if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
778 goto out; 850 goto out;
779 /* Don't match with creds that have expired. */ 851 /* Don't match with creds that have expired. */
780 if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) 852 if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
@@ -830,7 +902,7 @@ gss_marshal(struct rpc_task *task, __be32 *p)
830 mic.data = (u8 *)(p + 1); 902 mic.data = (u8 *)(p + 1);
831 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 903 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
832 if (maj_stat == GSS_S_CONTEXT_EXPIRED) { 904 if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
833 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 905 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
834 } else if (maj_stat != 0) { 906 } else if (maj_stat != 0) {
835 printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); 907 printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
836 goto out_put_ctx; 908 goto out_put_ctx;
@@ -855,6 +927,13 @@ gss_refresh(struct rpc_task *task)
855 return 0; 927 return 0;
856} 928}
857 929
930/* Dummy refresh routine: used only when destroying the context */
931static int
932gss_refresh_null(struct rpc_task *task)
933{
934 return -EACCES;
935}
936
858static __be32 * 937static __be32 *
859gss_validate(struct rpc_task *task, __be32 *p) 938gss_validate(struct rpc_task *task, __be32 *p)
860{ 939{
@@ -883,12 +962,15 @@ gss_validate(struct rpc_task *task, __be32 *p)
883 962
884 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 963 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
885 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 964 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
886 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 965 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
887 if (maj_stat) 966 if (maj_stat) {
967 dprintk("RPC: %5u gss_validate: gss_verify_mic returned"
968 "error 0x%08x\n", task->tk_pid, maj_stat);
888 goto out_bad; 969 goto out_bad;
970 }
889 /* We leave it to unwrap to calculate au_rslack. For now we just 971 /* We leave it to unwrap to calculate au_rslack. For now we just
890 * calculate the length of the verifier: */ 972 * calculate the length of the verifier: */
891 task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2; 973 cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
892 gss_put_ctx(ctx); 974 gss_put_ctx(ctx);
893 dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n", 975 dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n",
894 task->tk_pid); 976 task->tk_pid);
@@ -917,7 +999,9 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
917 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; 999 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
918 *p++ = htonl(rqstp->rq_seqno); 1000 *p++ = htonl(rqstp->rq_seqno);
919 1001
1002 lock_kernel();
920 status = encode(rqstp, p, obj); 1003 status = encode(rqstp, p, obj);
1004 unlock_kernel();
921 if (status) 1005 if (status)
922 return status; 1006 return status;
923 1007
@@ -937,7 +1021,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
937 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); 1021 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
938 status = -EIO; /* XXX? */ 1022 status = -EIO; /* XXX? */
939 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1023 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
940 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1024 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
941 else if (maj_stat) 1025 else if (maj_stat)
942 return status; 1026 return status;
943 q = xdr_encode_opaque(p, NULL, mic.len); 1027 q = xdr_encode_opaque(p, NULL, mic.len);
@@ -1011,7 +1095,9 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1011 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; 1095 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
1012 *p++ = htonl(rqstp->rq_seqno); 1096 *p++ = htonl(rqstp->rq_seqno);
1013 1097
1098 lock_kernel();
1014 status = encode(rqstp, p, obj); 1099 status = encode(rqstp, p, obj);
1100 unlock_kernel();
1015 if (status) 1101 if (status)
1016 return status; 1102 return status;
1017 1103
@@ -1036,7 +1122,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1036 /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was 1122 /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
1037 * done anyway, so it's safe to put the request on the wire: */ 1123 * done anyway, so it's safe to put the request on the wire: */
1038 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1124 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1039 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1125 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1040 else if (maj_stat) 1126 else if (maj_stat)
1041 return status; 1127 return status;
1042 1128
@@ -1070,12 +1156,16 @@ gss_wrap_req(struct rpc_task *task,
1070 /* The spec seems a little ambiguous here, but I think that not 1156 /* The spec seems a little ambiguous here, but I think that not
1071 * wrapping context destruction requests makes the most sense. 1157 * wrapping context destruction requests makes the most sense.
1072 */ 1158 */
1159 lock_kernel();
1073 status = encode(rqstp, p, obj); 1160 status = encode(rqstp, p, obj);
1161 unlock_kernel();
1074 goto out; 1162 goto out;
1075 } 1163 }
1076 switch (gss_cred->gc_service) { 1164 switch (gss_cred->gc_service) {
1077 case RPC_GSS_SVC_NONE: 1165 case RPC_GSS_SVC_NONE:
1166 lock_kernel();
1078 status = encode(rqstp, p, obj); 1167 status = encode(rqstp, p, obj);
1168 unlock_kernel();
1079 break; 1169 break;
1080 case RPC_GSS_SVC_INTEGRITY: 1170 case RPC_GSS_SVC_INTEGRITY:
1081 status = gss_wrap_req_integ(cred, ctx, encode, 1171 status = gss_wrap_req_integ(cred, ctx, encode,
@@ -1123,7 +1213,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1123 1213
1124 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); 1214 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
1125 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1215 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1126 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1216 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1127 if (maj_stat != GSS_S_COMPLETE) 1217 if (maj_stat != GSS_S_COMPLETE)
1128 return status; 1218 return status;
1129 return 0; 1219 return 0;
@@ -1148,7 +1238,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1148 1238
1149 maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); 1239 maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
1150 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1240 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1151 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1241 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
1152 if (maj_stat != GSS_S_COMPLETE) 1242 if (maj_stat != GSS_S_COMPLETE)
1153 return status; 1243 return status;
1154 if (ntohl(*(*p)++) != rqstp->rq_seqno) 1244 if (ntohl(*(*p)++) != rqstp->rq_seqno)
@@ -1188,10 +1278,12 @@ gss_unwrap_resp(struct rpc_task *task,
1188 break; 1278 break;
1189 } 1279 }
1190 /* take into account extra slack for integrity and privacy cases: */ 1280 /* take into account extra slack for integrity and privacy cases: */
1191 task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp) 1281 cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
1192 + (savedlen - head->iov_len); 1282 + (savedlen - head->iov_len);
1193out_decode: 1283out_decode:
1284 lock_kernel();
1194 status = decode(rqstp, p, obj); 1285 status = decode(rqstp, p, obj);
1286 unlock_kernel();
1195out: 1287out:
1196 gss_put_ctx(ctx); 1288 gss_put_ctx(ctx);
1197 dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid, 1289 dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,
@@ -1199,7 +1291,7 @@ out:
1199 return status; 1291 return status;
1200} 1292}
1201 1293
1202static struct rpc_authops authgss_ops = { 1294static const struct rpc_authops authgss_ops = {
1203 .owner = THIS_MODULE, 1295 .owner = THIS_MODULE,
1204 .au_flavor = RPC_AUTH_GSS, 1296 .au_flavor = RPC_AUTH_GSS,
1205#ifdef RPC_DEBUG 1297#ifdef RPC_DEBUG
@@ -1211,7 +1303,7 @@ static struct rpc_authops authgss_ops = {
1211 .crcreate = gss_create_cred 1303 .crcreate = gss_create_cred
1212}; 1304};
1213 1305
1214static struct rpc_credops gss_credops = { 1306static const struct rpc_credops gss_credops = {
1215 .cr_name = "AUTH_GSS", 1307 .cr_name = "AUTH_GSS",
1216 .crdestroy = gss_destroy_cred, 1308 .crdestroy = gss_destroy_cred,
1217 .cr_init = gss_cred_init, 1309 .cr_init = gss_cred_init,
@@ -1223,6 +1315,17 @@ static struct rpc_credops gss_credops = {
1223 .crunwrap_resp = gss_unwrap_resp, 1315 .crunwrap_resp = gss_unwrap_resp,
1224}; 1316};
1225 1317
1318static const struct rpc_credops gss_nullops = {
1319 .cr_name = "AUTH_GSS",
1320 .crdestroy = gss_destroy_cred,
1321 .crmatch = gss_match,
1322 .crmarshal = gss_marshal,
1323 .crrefresh = gss_refresh_null,
1324 .crvalidate = gss_validate,
1325 .crwrap_req = gss_wrap_req,
1326 .crunwrap_resp = gss_unwrap_resp,
1327};
1328
1226static struct rpc_pipe_ops gss_upcall_ops = { 1329static struct rpc_pipe_ops gss_upcall_ops = {
1227 .upcall = gss_pipe_upcall, 1330 .upcall = gss_pipe_upcall,
1228 .downcall = gss_pipe_downcall, 1331 .downcall = gss_pipe_downcall,