Commit 3b68aaea authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent b185f835
...@@ -306,8 +306,6 @@ gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) ...@@ -306,8 +306,6 @@ gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
static void static void
__gss_unhash_msg(struct gss_upcall_msg *gss_msg) __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{ {
if (list_empty(&gss_msg->list))
return;
list_del_init(&gss_msg->list); list_del_init(&gss_msg->list);
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
wake_up_all(&gss_msg->waitqueue); wake_up_all(&gss_msg->waitqueue);
...@@ -320,8 +318,11 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg) ...@@ -320,8 +318,11 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
struct gss_auth *gss_auth = gss_msg->auth; struct gss_auth *gss_auth = gss_msg->auth;
struct inode *inode = gss_auth->dentry->d_inode; struct inode *inode = gss_auth->dentry->d_inode;
if (list_empty(&gss_msg->list))
return;
spin_lock(&inode->i_lock); 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); spin_unlock(&inode->i_lock);
} }
...@@ -493,12 +494,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) ...@@ -493,12 +494,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
void *buf; void *buf;
struct rpc_clnt *clnt; struct rpc_clnt *clnt;
struct gss_auth *gss_auth; struct gss_auth *gss_auth;
struct rpc_cred *cred;
struct gss_upcall_msg *gss_msg; struct gss_upcall_msg *gss_msg;
struct inode *inode = filp->f_path.dentry->d_inode; struct inode *inode = filp->f_path.dentry->d_inode;
struct gss_cl_ctx *ctx; struct gss_cl_ctx *ctx;
uid_t uid; uid_t uid;
int err = -EFBIG; ssize_t err = -EFBIG;
if (mlen > MSG_BUF_MAXSIZE) if (mlen > MSG_BUF_MAXSIZE)
goto out; goto out;
...@@ -523,43 +523,39 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) ...@@ -523,43 +523,39 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
ctx = gss_alloc_context(); ctx = gss_alloc_context();
if (ctx == NULL) if (ctx == NULL)
goto err; goto err;
err = 0;
err = -ENOENT;
/* Find a matching upcall */
gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth); 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); p = gss_fill_context(p, end, ctx, gss_auth->mech);
if (IS_ERR(p)) { if (IS_ERR(p)) {
err = PTR_ERR(p); err = PTR_ERR(p);
if (err != -EACCES) gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
goto err_put_ctx; goto err_release_msg;
} }
gss_msg->ctx = gss_get_ctx(ctx);
err = mlen;
err_release_msg:
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
gss_msg = __gss_find_upcall(gss_auth, uid); __gss_unhash_msg(gss_msg);
if (gss_msg) { spin_unlock(&inode->i_lock);
if (err == 0 && gss_msg->ctx == NULL) gss_release_msg(gss_msg);
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;
err_put_ctx: err_put_ctx:
gss_put_ctx(ctx); gss_put_ctx(ctx);
err: err:
kfree(buf); kfree(buf);
out: out:
dprintk("RPC: gss_pipe_downcall returning %d\n", err); dprintk("RPC: gss_pipe_downcall returning %Zd\n", err);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment