diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-06-07 10:14:15 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:31 -0400 |
commit | 3b68aaeaf54065e5c44583a1d33ffb7793953ba4 (patch) | |
tree | 7b2e142d018fece125cc6616c117af575a8c095b /net/sunrpc | |
parent | b185f835e243e654047ae85f42346827d3894171 (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.c | 58 |
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) | |||
306 | static void | 306 | static 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 | |||
548 | err_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; | ||
557 | err_put_ctx: | 553 | err_put_ctx: |
558 | gss_put_ctx(ctx); | 554 | gss_put_ctx(ctx); |
559 | err: | 555 | err: |
560 | kfree(buf); | 556 | kfree(buf); |
561 | out: | 557 | out: |
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 | ||