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: 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>
This commit is contained in:
parent
552aa585fa
commit
0aeffa7041
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue