Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3b68aaeaf54065e5c44583a1d33ffb7793953ba4
Commit:     3b68aaeaf54065e5c44583a1d33ffb7793953ba4
Parent:     b185f835e243e654047ae85f42346827d3894171
Author:     Trond Myklebust <[EMAIL PROTECTED]>
AuthorDate: Thu Jun 7 10:14:15 2007 -0400
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Tue Jul 10 23:40:31 2007 -0400

    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 <[EMAIL PROTECTED]>
---
 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 653d712..e407a35 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)
 static void
 __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 {
-       if (list_empty(&gss_msg->list))
-               return;
        list_del_init(&gss_msg->list);
        rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
        wake_up_all(&gss_msg->waitqueue);
@@ -320,8 +318,11 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
        struct gss_auth *gss_auth = gss_msg->auth;
        struct inode *inode = gss_auth->dentry->d_inode;
 
+       if (list_empty(&gss_msg->list))
+               return;
        spin_lock(&inode->i_lock);
-       __gss_unhash_msg(gss_msg);
+       if (!list_empty(&gss_msg->list))
+               __gss_unhash_msg(gss_msg);
        spin_unlock(&inode->i_lock);
 }
 
@@ -493,12 +494,11 @@ gss_pipe_downcall(struct file *filp, const char __user 
*src, size_t mlen)
        void *buf;
        struct rpc_clnt *clnt;
        struct gss_auth *gss_auth;
-       struct rpc_cred *cred;
        struct gss_upcall_msg *gss_msg;
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct gss_cl_ctx *ctx;
        uid_t uid;
-       int err = -EFBIG;
+       ssize_t err = -EFBIG;
 
        if (mlen > MSG_BUF_MAXSIZE)
                goto out;
@@ -523,43 +523,39 @@ gss_pipe_downcall(struct file *filp, const char __user 
*src, size_t mlen)
        ctx = gss_alloc_context();
        if (ctx == NULL)
                goto err;
-       err = 0;
+
+       err = -ENOENT;
+       /* Find a matching upcall */
        gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
+       spin_lock(&inode->i_lock);
+       gss_msg = __gss_find_upcall(gss_auth, uid);
+       if (gss_msg == NULL) {
+               spin_unlock(&inode->i_lock);
+               goto err_put_ctx;
+       }
+       list_del_init(&gss_msg->list);
+       spin_unlock(&inode->i_lock);
+
        p = gss_fill_context(p, end, ctx, gss_auth->mech);
        if (IS_ERR(p)) {
                err = PTR_ERR(p);
-               if (err != -EACCES)
-                       goto err_put_ctx;
+               gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
+               goto err_release_msg;
        }
+       gss_msg->ctx = gss_get_ctx(ctx);
+       err = mlen;
+
+err_release_msg:
        spin_lock(&inode->i_lock);
-       gss_msg = __gss_find_upcall(gss_auth, uid);
-       if (gss_msg) {
-               if (err == 0 && gss_msg->ctx == NULL)
-                       gss_msg->ctx = gss_get_ctx(ctx);
-               gss_msg->msg.errno = err;
-               __gss_unhash_msg(gss_msg);
-               spin_unlock(&inode->i_lock);
-               gss_release_msg(gss_msg);
-       } else {
-               struct auth_cred acred = { .uid = uid };
-               spin_unlock(&inode->i_lock);
-               cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 
RPCAUTH_LOOKUP_NEW);
-               if (IS_ERR(cred)) {
-                       err = PTR_ERR(cred);
-                       goto err_put_ctx;
-               }
-               gss_cred_set_ctx(cred, gss_get_ctx(ctx));
-       }
-       gss_put_ctx(ctx);
-       kfree(buf);
-       dprintk("RPC:       gss_pipe_downcall returning length %Zu\n", mlen);
-       return mlen;
+       __gss_unhash_msg(gss_msg);
+       spin_unlock(&inode->i_lock);
+       gss_release_msg(gss_msg);
 err_put_ctx:
        gss_put_ctx(ctx);
 err:
        kfree(buf);
 out:
-       dprintk("RPC:       gss_pipe_downcall returning %d\n", err);
+       dprintk("RPC:       gss_pipe_downcall returning %Zd\n", err);
        return err;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to