aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-06-07 10:14:15 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:31 -0400
commit3b68aaeaf54065e5c44583a1d33ffb7793953ba4 (patch)
tree7b2e142d018fece125cc6616c117af575a8c095b /net/sunrpc
parentb185f835e243e654047ae85f42346827d3894171 (diff)
SUNRPC: Always match an upcall message in gss_pipe_downcall()
It used to be possible for an rpc.gssd daemon to stuff the RPC credential cache for any rpc client simply by creating RPCSEC_GSS contexts and then doing downcalls. In practice, no daemons ever made use of this feature. Remove this feature now, since it will be impossible to figure out which mechanism a given context actually matches if we enable more than one gss mechanism to use the same upcall pipe. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c58
1 files changed, 27 insertions, 31 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 653d712a1ffb..e407a352440f 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -306,8 +306,6 @@ gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
306static void 306static void
307__gss_unhash_msg(struct gss_upcall_msg *gss_msg) 307__gss_unhash_msg(struct gss_upcall_msg *gss_msg)
308{ 308{
309 if (list_empty(&gss_msg->list))
310 return;
311 list_del_init(&gss_msg->list); 309 list_del_init(&gss_msg->list);
312 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); 310 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
313 wake_up_all(&gss_msg->waitqueue); 311 wake_up_all(&gss_msg->waitqueue);
@@ -320,8 +318,11 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
320 struct gss_auth *gss_auth = gss_msg->auth; 318 struct gss_auth *gss_auth = gss_msg->auth;
321 struct inode *inode = gss_auth->dentry->d_inode; 319 struct inode *inode = gss_auth->dentry->d_inode;
322 320
321 if (list_empty(&gss_msg->list))
322 return;
323 spin_lock(&inode->i_lock); 323 spin_lock(&inode->i_lock);
324 __gss_unhash_msg(gss_msg); 324 if (!list_empty(&gss_msg->list))
325 __gss_unhash_msg(gss_msg);
325 spin_unlock(&inode->i_lock); 326 spin_unlock(&inode->i_lock);
326} 327}
327 328
@@ -493,12 +494,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
493 void *buf; 494 void *buf;
494 struct rpc_clnt *clnt; 495 struct rpc_clnt *clnt;
495 struct gss_auth *gss_auth; 496 struct gss_auth *gss_auth;
496 struct rpc_cred *cred;
497 struct gss_upcall_msg *gss_msg; 497 struct gss_upcall_msg *gss_msg;
498 struct inode *inode = filp->f_path.dentry->d_inode; 498 struct inode *inode = filp->f_path.dentry->d_inode;
499 struct gss_cl_ctx *ctx; 499 struct gss_cl_ctx *ctx;
500 uid_t uid; 500 uid_t uid;
501 int err = -EFBIG; 501 ssize_t err = -EFBIG;
502 502
503 if (mlen > MSG_BUF_MAXSIZE) 503 if (mlen > MSG_BUF_MAXSIZE)
504 goto out; 504 goto out;
@@ -523,43 +523,39 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
523 ctx = gss_alloc_context(); 523 ctx = gss_alloc_context();
524 if (ctx == NULL) 524 if (ctx == NULL)
525 goto err; 525 goto err;
526 err = 0; 526
527 err = -ENOENT;
528 /* Find a matching upcall */
527 gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth); 529 gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
530 spin_lock(&inode->i_lock);
531 gss_msg = __gss_find_upcall(gss_auth, uid);
532 if (gss_msg == NULL) {
533 spin_unlock(&inode->i_lock);
534 goto err_put_ctx;
535 }
536 list_del_init(&gss_msg->list);
537 spin_unlock(&inode->i_lock);
538
528 p = gss_fill_context(p, end, ctx, gss_auth->mech); 539 p = gss_fill_context(p, end, ctx, gss_auth->mech);
529 if (IS_ERR(p)) { 540 if (IS_ERR(p)) {
530 err = PTR_ERR(p); 541 err = PTR_ERR(p);
531 if (err != -EACCES) 542 gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
532 goto err_put_ctx; 543 goto err_release_msg;
533 } 544 }
545 gss_msg->ctx = gss_get_ctx(ctx);
546 err = mlen;
547
548err_release_msg:
534 spin_lock(&inode->i_lock); 549 spin_lock(&inode->i_lock);
535 gss_msg = __gss_find_upcall(gss_auth, uid); 550 __gss_unhash_msg(gss_msg);
536 if (gss_msg) { 551 spin_unlock(&inode->i_lock);
537 if (err == 0 && gss_msg->ctx == NULL) 552 gss_release_msg(gss_msg);
538 gss_msg->ctx = gss_get_ctx(ctx);
539 gss_msg->msg.errno = err;
540 __gss_unhash_msg(gss_msg);
541 spin_unlock(&inode->i_lock);
542 gss_release_msg(gss_msg);
543 } else {
544 struct auth_cred acred = { .uid = uid };
545 spin_unlock(&inode->i_lock);
546 cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
547 if (IS_ERR(cred)) {
548 err = PTR_ERR(cred);
549 goto err_put_ctx;
550 }
551 gss_cred_set_ctx(cred, gss_get_ctx(ctx));
552 }
553 gss_put_ctx(ctx);
554 kfree(buf);
555 dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen);
556 return mlen;
557err_put_ctx: 553err_put_ctx:
558 gss_put_ctx(ctx); 554 gss_put_ctx(ctx);
559err: 555err:
560 kfree(buf); 556 kfree(buf);
561out: 557out:
562 dprintk("RPC: gss_pipe_downcall returning %d\n", err); 558 dprintk("RPC: gss_pipe_downcall returning %Zd\n", err);
563 return err; 559 return err;
564} 560}
565 561