Skip to content

Commit

Permalink
p54: fix oops on faulty devices
Browse files Browse the repository at this point in the history
This patch fixes an oops when the devices suddenly starts
to receive martian data frames.

bug reference:
http://marc.info/?l=linux-wireless&m=122872280317635&w=2

Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Christian Lamparter authored and John W. Linville committed Dec 12, 2008
1 parent b7a530d commit 59651e8
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions drivers/net/wireless/p54/p54common.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,14 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
size_t header_len = sizeof(*hdr);
u32 tsf32;

/*
* If the device is in a unspecified state we have to
* ignore all data frames. Else we could end up with a
* nasty crash.
*/
if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
return 0;

if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
if (priv->filter_flags & FIF_FCSFAIL)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
Expand Down Expand Up @@ -608,6 +616,12 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
return;

/*
* don't try to free an already unlinked skb
*/
if (unlikely((!skb->next) || (!skb->prev)))
return;

spin_lock_irqsave(&priv->tx_queue.lock, flags);
info = IEEE80211_SKB_CB(skb);
range = (void *)info->rate_driver_data;
Expand Down Expand Up @@ -1695,19 +1709,18 @@ static void p54_stop(struct ieee80211_hw *dev)
struct sk_buff *skb;

mutex_lock(&priv->conf_mutex);
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
del_timer(&priv->stats_timer);
p54_free_skb(dev, priv->cached_stats);
priv->cached_stats = NULL;
if (priv->cached_beacon)
p54_tx_cancel(dev, priv->cached_beacon);

priv->stop(dev);
while ((skb = skb_dequeue(&priv->tx_queue)))
kfree_skb(skb);

priv->cached_beacon = NULL;
priv->stop(dev);
priv->tsf_high32 = priv->tsf_low32 = 0;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
mutex_unlock(&priv->conf_mutex);
}

Expand Down

0 comments on commit 59651e8

Please sign in to comment.