Commit 7ff13969 authored by Reshetova, Elena's avatar Reshetova, Elena Committed by David S. Miller

net, sunrpc: convert gss_upcall_msg.count from atomic_t to refcount_t

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: default avatarElena Reshetova <elena.reshetova@intel.com>
Signed-off-by: default avatarHans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarDavid Windsor <dwindsor@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0fa10472
...@@ -287,7 +287,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct ...@@ -287,7 +287,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
#define UPCALL_BUF_LEN 128 #define UPCALL_BUF_LEN 128
struct gss_upcall_msg { struct gss_upcall_msg {
atomic_t count; refcount_t count;
kuid_t uid; kuid_t uid;
struct rpc_pipe_msg msg; struct rpc_pipe_msg msg;
struct list_head list; struct list_head list;
...@@ -328,7 +328,7 @@ static void ...@@ -328,7 +328,7 @@ static void
gss_release_msg(struct gss_upcall_msg *gss_msg) gss_release_msg(struct gss_upcall_msg *gss_msg)
{ {
struct net *net = gss_msg->auth->net; struct net *net = gss_msg->auth->net;
if (!atomic_dec_and_test(&gss_msg->count)) if (!refcount_dec_and_test(&gss_msg->count))
return; return;
put_pipe_version(net); put_pipe_version(net);
BUG_ON(!list_empty(&gss_msg->list)); BUG_ON(!list_empty(&gss_msg->list));
...@@ -348,7 +348,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth ...@@ -348,7 +348,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth
continue; continue;
if (auth && pos->auth->service != auth->service) if (auth && pos->auth->service != auth->service)
continue; continue;
atomic_inc(&pos->count); refcount_inc(&pos->count);
dprintk("RPC: %s found msg %p\n", __func__, pos); dprintk("RPC: %s found msg %p\n", __func__, pos);
return pos; return pos;
} }
...@@ -369,7 +369,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg) ...@@ -369,7 +369,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg)
spin_lock(&pipe->lock); spin_lock(&pipe->lock);
old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth); old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
if (old == NULL) { if (old == NULL) {
atomic_inc(&gss_msg->count); refcount_inc(&gss_msg->count);
list_add(&gss_msg->list, &pipe->in_downcall); list_add(&gss_msg->list, &pipe->in_downcall);
} else } else
gss_msg = old; gss_msg = old;
...@@ -383,7 +383,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg) ...@@ -383,7 +383,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
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);
atomic_dec(&gss_msg->count); refcount_dec(&gss_msg->count);
} }
static void static void
...@@ -506,7 +506,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, ...@@ -506,7 +506,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
INIT_LIST_HEAD(&gss_msg->list); INIT_LIST_HEAD(&gss_msg->list);
rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
init_waitqueue_head(&gss_msg->waitqueue); init_waitqueue_head(&gss_msg->waitqueue);
atomic_set(&gss_msg->count, 1); refcount_set(&gss_msg->count, 1);
gss_msg->uid = uid; gss_msg->uid = uid;
gss_msg->auth = gss_auth; gss_msg->auth = gss_auth;
switch (vers) { switch (vers) {
...@@ -542,11 +542,11 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred) ...@@ -542,11 +542,11 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred)
gss_msg = gss_add_msg(gss_new); gss_msg = gss_add_msg(gss_new);
if (gss_msg == gss_new) { if (gss_msg == gss_new) {
int res; int res;
atomic_inc(&gss_msg->count); refcount_inc(&gss_msg->count);
res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg);
if (res) { if (res) {
gss_unhash_msg(gss_new); gss_unhash_msg(gss_new);
atomic_dec(&gss_msg->count); refcount_dec(&gss_msg->count);
gss_release_msg(gss_new); gss_release_msg(gss_new);
gss_msg = ERR_PTR(res); gss_msg = ERR_PTR(res);
} }
...@@ -595,7 +595,7 @@ gss_refresh_upcall(struct rpc_task *task) ...@@ -595,7 +595,7 @@ gss_refresh_upcall(struct rpc_task *task)
task->tk_timeout = 0; task->tk_timeout = 0;
gss_cred->gc_upcall = gss_msg; gss_cred->gc_upcall = gss_msg;
/* gss_upcall_callback will release the reference to gss_upcall_msg */ /* gss_upcall_callback will release the reference to gss_upcall_msg */
atomic_inc(&gss_msg->count); refcount_inc(&gss_msg->count);
rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
} else { } else {
gss_handle_downcall_result(gss_cred, gss_msg); gss_handle_downcall_result(gss_cred, gss_msg);
...@@ -815,7 +815,7 @@ gss_pipe_release(struct inode *inode) ...@@ -815,7 +815,7 @@ gss_pipe_release(struct inode *inode)
if (!list_empty(&gss_msg->msg.list)) if (!list_empty(&gss_msg->msg.list))
continue; continue;
gss_msg->msg.errno = -EPIPE; gss_msg->msg.errno = -EPIPE;
atomic_inc(&gss_msg->count); refcount_inc(&gss_msg->count);
__gss_unhash_msg(gss_msg); __gss_unhash_msg(gss_msg);
spin_unlock(&pipe->lock); spin_unlock(&pipe->lock);
gss_release_msg(gss_msg); gss_release_msg(gss_msg);
...@@ -834,7 +834,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) ...@@ -834,7 +834,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
if (msg->errno < 0) { if (msg->errno < 0) {
dprintk("RPC: %s releasing msg %p\n", dprintk("RPC: %s releasing msg %p\n",
__func__, gss_msg); __func__, gss_msg);
atomic_inc(&gss_msg->count); refcount_inc(&gss_msg->count);
gss_unhash_msg(gss_msg); gss_unhash_msg(gss_msg);
if (msg->errno == -ETIMEDOUT) if (msg->errno == -ETIMEDOUT)
warn_gssd(); warn_gssd();
......
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