orinoco_usb: convert request_context.refcount from atomic_t to refcount_t
authorElena Reshetova <elena.reshetova@intel.com>
Tue, 28 Mar 2017 08:56:43 +0000 (11:56 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 22 May 2017 15:24:18 +0000 (18:24 +0300)
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: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/intersil/orinoco/orinoco_usb.c

index 132f5fb..c84fd84 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 #include <linux/firmware.h>
+#include <linux/refcount.h>
 
 #include "mic.h"
 #include "orinoco.h"
@@ -268,7 +269,7 @@ enum ezusb_state {
 
 struct request_context {
        struct list_head list;
-       atomic_t refcount;
+       refcount_t refcount;
        struct completion done; /* Signals that CTX is dead */
        int killed;
        struct urb *outurb;     /* OUT for req pkt */
@@ -298,7 +299,7 @@ static inline u8 ezusb_reply_inc(u8 count)
 
 static void ezusb_request_context_put(struct request_context *ctx)
 {
-       if (!atomic_dec_and_test(&ctx->refcount))
+       if (!refcount_dec_and_test(&ctx->refcount))
                return;
 
        WARN_ON(!ctx->done.done);
@@ -328,7 +329,7 @@ static void ezusb_request_timerfn(u_long _ctx)
        } else {
                ctx->state = EZUSB_CTX_RESP_TIMEOUT;
                dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
-               atomic_inc(&ctx->refcount);
+               refcount_inc(&ctx->refcount);
                ctx->killed = 1;
                ezusb_ctx_complete(ctx);
                ezusb_request_context_put(ctx);
@@ -361,7 +362,7 @@ static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
        ctx->out_rid = out_rid;
        ctx->in_rid = in_rid;
 
-       atomic_set(&ctx->refcount, 1);
+       refcount_set(&ctx->refcount, 1);
        init_completion(&ctx->done);
 
        setup_timer(&ctx->timer, ezusb_request_timerfn, (u_long)ctx);
@@ -469,7 +470,7 @@ static void ezusb_req_queue_run(struct ezusb_priv *upriv)
        list_move_tail(&ctx->list, &upriv->req_active);
 
        if (ctx->state == EZUSB_CTX_QUEUED) {
-               atomic_inc(&ctx->refcount);
+               refcount_inc(&ctx->refcount);
                result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
                if (result) {
                        ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
@@ -507,7 +508,7 @@ static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
                spin_unlock_irqrestore(&upriv->req_lock, flags);
                goto done;
        }
-       atomic_inc(&ctx->refcount);
+       refcount_inc(&ctx->refcount);
        list_add_tail(&ctx->list, &upriv->req_pending);
        spin_unlock_irqrestore(&upriv->req_lock, flags);
 
@@ -1477,7 +1478,7 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
                int err;
 
                ctx = list_entry(item, struct request_context, list);
-               atomic_inc(&ctx->refcount);
+               refcount_inc(&ctx->refcount);
 
                ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
                err = usb_unlink_urb(ctx->outurb);