diff options
author | Reshetova, Elena <elena.reshetova@intel.com> | 2017-07-04 08:53:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-07-04 17:35:17 -0400 |
commit | 7ff139696d74d0d4917bd259347d00e3a4fcc410 (patch) | |
tree | 99defe75514e2bf358c299ca21ad39ccff97ca78 /net/sunrpc/auth_gss/auth_gss.c | |
parent | 0fa104726b6cc7b1ebb4c60d55cb6abda745f4b6 (diff) |
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: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 72f129c74acd..9463af4b32e8 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -287,7 +287,7 @@ err: | |||
287 | #define UPCALL_BUF_LEN 128 | 287 | #define UPCALL_BUF_LEN 128 |
288 | 288 | ||
289 | struct gss_upcall_msg { | 289 | struct gss_upcall_msg { |
290 | atomic_t count; | 290 | refcount_t count; |
291 | kuid_t uid; | 291 | kuid_t uid; |
292 | struct rpc_pipe_msg msg; | 292 | struct rpc_pipe_msg msg; |
293 | struct list_head list; | 293 | struct list_head list; |
@@ -328,7 +328,7 @@ static void | |||
328 | gss_release_msg(struct gss_upcall_msg *gss_msg) | 328 | gss_release_msg(struct gss_upcall_msg *gss_msg) |
329 | { | 329 | { |
330 | struct net *net = gss_msg->auth->net; | 330 | struct net *net = gss_msg->auth->net; |
331 | if (!atomic_dec_and_test(&gss_msg->count)) | 331 | if (!refcount_dec_and_test(&gss_msg->count)) |
332 | return; | 332 | return; |
333 | put_pipe_version(net); | 333 | put_pipe_version(net); |
334 | BUG_ON(!list_empty(&gss_msg->list)); | 334 | 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 | continue; | 348 | continue; |
349 | if (auth && pos->auth->service != auth->service) | 349 | if (auth && pos->auth->service != auth->service) |
350 | continue; | 350 | continue; |
351 | atomic_inc(&pos->count); | 351 | refcount_inc(&pos->count); |
352 | dprintk("RPC: %s found msg %p\n", __func__, pos); | 352 | dprintk("RPC: %s found msg %p\n", __func__, pos); |
353 | return pos; | 353 | return pos; |
354 | } | 354 | } |
@@ -369,7 +369,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg) | |||
369 | spin_lock(&pipe->lock); | 369 | spin_lock(&pipe->lock); |
370 | old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth); | 370 | old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth); |
371 | if (old == NULL) { | 371 | if (old == NULL) { |
372 | atomic_inc(&gss_msg->count); | 372 | refcount_inc(&gss_msg->count); |
373 | list_add(&gss_msg->list, &pipe->in_downcall); | 373 | list_add(&gss_msg->list, &pipe->in_downcall); |
374 | } else | 374 | } else |
375 | gss_msg = old; | 375 | gss_msg = old; |
@@ -383,7 +383,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg) | |||
383 | list_del_init(&gss_msg->list); | 383 | list_del_init(&gss_msg->list); |
384 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); | 384 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); |
385 | wake_up_all(&gss_msg->waitqueue); | 385 | wake_up_all(&gss_msg->waitqueue); |
386 | atomic_dec(&gss_msg->count); | 386 | refcount_dec(&gss_msg->count); |
387 | } | 387 | } |
388 | 388 | ||
389 | static void | 389 | static void |
@@ -506,7 +506,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, | |||
506 | INIT_LIST_HEAD(&gss_msg->list); | 506 | INIT_LIST_HEAD(&gss_msg->list); |
507 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 507 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
508 | init_waitqueue_head(&gss_msg->waitqueue); | 508 | init_waitqueue_head(&gss_msg->waitqueue); |
509 | atomic_set(&gss_msg->count, 1); | 509 | refcount_set(&gss_msg->count, 1); |
510 | gss_msg->uid = uid; | 510 | gss_msg->uid = uid; |
511 | gss_msg->auth = gss_auth; | 511 | gss_msg->auth = gss_auth; |
512 | switch (vers) { | 512 | switch (vers) { |
@@ -542,11 +542,11 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred) | |||
542 | gss_msg = gss_add_msg(gss_new); | 542 | gss_msg = gss_add_msg(gss_new); |
543 | if (gss_msg == gss_new) { | 543 | if (gss_msg == gss_new) { |
544 | int res; | 544 | int res; |
545 | atomic_inc(&gss_msg->count); | 545 | refcount_inc(&gss_msg->count); |
546 | res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); | 546 | res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); |
547 | if (res) { | 547 | if (res) { |
548 | gss_unhash_msg(gss_new); | 548 | gss_unhash_msg(gss_new); |
549 | atomic_dec(&gss_msg->count); | 549 | refcount_dec(&gss_msg->count); |
550 | gss_release_msg(gss_new); | 550 | gss_release_msg(gss_new); |
551 | gss_msg = ERR_PTR(res); | 551 | gss_msg = ERR_PTR(res); |
552 | } | 552 | } |
@@ -595,7 +595,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
595 | task->tk_timeout = 0; | 595 | task->tk_timeout = 0; |
596 | gss_cred->gc_upcall = gss_msg; | 596 | gss_cred->gc_upcall = gss_msg; |
597 | /* gss_upcall_callback will release the reference to gss_upcall_msg */ | 597 | /* gss_upcall_callback will release the reference to gss_upcall_msg */ |
598 | atomic_inc(&gss_msg->count); | 598 | refcount_inc(&gss_msg->count); |
599 | rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); | 599 | rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); |
600 | } else { | 600 | } else { |
601 | gss_handle_downcall_result(gss_cred, gss_msg); | 601 | gss_handle_downcall_result(gss_cred, gss_msg); |
@@ -815,7 +815,7 @@ restart: | |||
815 | if (!list_empty(&gss_msg->msg.list)) | 815 | if (!list_empty(&gss_msg->msg.list)) |
816 | continue; | 816 | continue; |
817 | gss_msg->msg.errno = -EPIPE; | 817 | gss_msg->msg.errno = -EPIPE; |
818 | atomic_inc(&gss_msg->count); | 818 | refcount_inc(&gss_msg->count); |
819 | __gss_unhash_msg(gss_msg); | 819 | __gss_unhash_msg(gss_msg); |
820 | spin_unlock(&pipe->lock); | 820 | spin_unlock(&pipe->lock); |
821 | gss_release_msg(gss_msg); | 821 | gss_release_msg(gss_msg); |
@@ -834,7 +834,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
834 | if (msg->errno < 0) { | 834 | if (msg->errno < 0) { |
835 | dprintk("RPC: %s releasing msg %p\n", | 835 | dprintk("RPC: %s releasing msg %p\n", |
836 | __func__, gss_msg); | 836 | __func__, gss_msg); |
837 | atomic_inc(&gss_msg->count); | 837 | refcount_inc(&gss_msg->count); |
838 | gss_unhash_msg(gss_msg); | 838 | gss_unhash_msg(gss_msg); |
839 | if (msg->errno == -ETIMEDOUT) | 839 | if (msg->errno == -ETIMEDOUT) |
840 | warn_gssd(); | 840 | warn_gssd(); |