Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -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);