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

Commit 50febf6a authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: use a counter for remain-on-channel cookie



Instead of using the pointer which can be re-used
fairly quickly due to allocator patterns and then
makes debugging difficult, maintain a counter and
use its value. Since it's a 64-bit value it can't
really wrap, but catch that case anyway since it
most likely points to a bug somewhere.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 8a2fbedc
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -2382,13 +2382,22 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
		list_add_tail(&roc->list, &local->roc_list);

	/*
	 * cookie is either the roc (for normal roc)
	 * cookie is either the roc cookie (for normal roc)
	 * or the SKB (for mgmt TX)
	 */
	if (txskb)
	if (!txskb) {
		/* local->mtx protects this */
		local->roc_cookie_counter++;
		roc->cookie = local->roc_cookie_counter;
		/* wow, you wrapped 64 bits ... more likely a bug */
		if (WARN_ON(roc->cookie == 0)) {
			roc->cookie = 1;
			local->roc_cookie_counter++;
		}
		*cookie = roc->cookie;
	} else {
		*cookie = (unsigned long)txskb;
	else
		*cookie = (unsigned long)roc;
	}

	return 0;
}
@@ -2423,7 +2432,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
		struct ieee80211_roc_work *dep, *tmp2;

		list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) {
			if (!mgmt_tx && (unsigned long)dep != cookie)
			if (!mgmt_tx && dep->cookie != cookie)
				continue;
			else if (mgmt_tx && dep->mgmt_tx_cookie != cookie)
				continue;
@@ -2435,7 +2444,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
			return 0;
		}

		if (!mgmt_tx && (unsigned long)roc != cookie)
		if (!mgmt_tx && roc->cookie != cookie)
			continue;
		else if (mgmt_tx && roc->mgmt_tx_cookie != cookie)
			continue;
+2 −1
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ struct ieee80211_roc_work {

	u32 duration, req_duration;
	struct sk_buff *frame;
	u64 mgmt_tx_cookie;
	u64 cookie, mgmt_tx_cookie;
};

/* flags used in struct ieee80211_if_managed.flags */
@@ -1142,6 +1142,7 @@ struct ieee80211_local {
	struct list_head roc_list;
	struct work_struct hw_roc_start, hw_roc_done;
	unsigned long hw_roc_start_time;
	u64 roc_cookie_counter;

	struct idr ack_status_frames;
	spinlock_t ack_status_lock;
+3 −4
Original line number Diff line number Diff line
@@ -204,7 +204,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
			roc->frame = NULL;
		}
	} else {
		cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc,
		cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie,
					  roc->chan, roc->chan_type,
					  roc->req_duration, GFP_KERNEL);
	}
@@ -320,9 +320,8 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)

	if (!roc->mgmt_tx_cookie)
		cfg80211_remain_on_channel_expired(&roc->sdata->wdev,
						   (unsigned long)roc,
						   roc->chan, roc->chan_type,
						   GFP_KERNEL);
						   roc->cookie, roc->chan,
						   roc->chan_type, GFP_KERNEL);

	list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
		ieee80211_roc_notify_destroy(dep);