aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-17 16:53:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-04-19 16:55:15 -0400
commit7b6962b0a6000df48c8a5fd967d262f77704101b (patch)
tree8902c9232242ac48c49f3e7a4ff0a94045974726 /net
parent7c1d71cf56feebfb5b98219b9d11dfc3a2feca62 (diff)
SUNRPC: Fix a race in gss_refresh_upcall()
If the downcall completes before we get the spin_lock then we currently fail to refresh the credential. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 46f7ec800af9..6f1b4e2f5e81 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -117,6 +117,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
117 struct gss_cl_ctx *old; 117 struct gss_cl_ctx *old;
118 118
119 old = gss_cred->gc_ctx; 119 old = gss_cred->gc_ctx;
120 gss_get_ctx(ctx);
120 rcu_assign_pointer(gss_cred->gc_ctx, ctx); 121 rcu_assign_pointer(gss_cred->gc_ctx, ctx);
121 set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 122 set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
122 clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); 123 clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
@@ -340,7 +341,7 @@ gss_upcall_callback(struct rpc_task *task)
340 341
341 spin_lock(&inode->i_lock); 342 spin_lock(&inode->i_lock);
342 if (gss_msg->ctx) 343 if (gss_msg->ctx)
343 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx)); 344 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
344 else 345 else
345 task->tk_status = gss_msg->msg.errno; 346 task->tk_status = gss_msg->msg.errno;
346 gss_cred->gc_upcall = NULL; 347 gss_cred->gc_upcall = NULL;
@@ -417,7 +418,11 @@ gss_refresh_upcall(struct rpc_task *task)
417 spin_lock(&inode->i_lock); 418 spin_lock(&inode->i_lock);
418 if (gss_cred->gc_upcall != NULL) 419 if (gss_cred->gc_upcall != NULL)
419 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); 420 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
420 else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { 421 else if (gss_msg->ctx != NULL) {
422 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
423 gss_cred->gc_upcall = NULL;
424 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
425 } else if (gss_msg->msg.errno >= 0) {
421 task->tk_timeout = 0; 426 task->tk_timeout = 0;
422 gss_cred->gc_upcall = gss_msg; 427 gss_cred->gc_upcall = gss_msg;
423 /* gss_upcall_callback will release the reference to gss_upcall_msg */ 428 /* gss_upcall_callback will release the reference to gss_upcall_msg */
@@ -462,7 +467,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
462 schedule(); 467 schedule();
463 } 468 }
464 if (gss_msg->ctx) 469 if (gss_msg->ctx)
465 gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx)); 470 gss_cred_set_ctx(cred, gss_msg->ctx);
466 else 471 else
467 err = gss_msg->msg.errno; 472 err = gss_msg->msg.errno;
468 spin_unlock(&inode->i_lock); 473 spin_unlock(&inode->i_lock);