Commit 0aeffa70 authored by Elena Reshetova's avatar Elena Reshetova Committed by Kalle Valo

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