diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-23 12:28:40 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:22 -0400 |
commit | a220858d30604902f650074bfac5a7598bc97ea4 (patch) | |
tree | 3a4ad6d80713953598f6f872103291e69cf1ac6b /net/mac80211/tx.c | |
parent | b1720231ca07dee3382980f3b25e6581bd2e54e9 (diff) |
mac80211: add skb length sanity checking
We just found a bug in zd1211rw where it would reject
packets in the ->tx() method but leave them modified,
which would cause retransmit attempts with completely
bogus skbs, eventually leading to a panic due to not
having enough headroom in those.
This patch adds a sanity check to mac80211 to catch
such driver mistakes; in this case we warn and drop
the skb.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b909e4090e93..a0e00c6339ca 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1089,7 +1089,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1089 | { | 1089 | { |
1090 | struct sk_buff *skb = *skbp, *next; | 1090 | struct sk_buff *skb = *skbp, *next; |
1091 | struct ieee80211_tx_info *info; | 1091 | struct ieee80211_tx_info *info; |
1092 | int ret; | 1092 | int ret, len; |
1093 | bool fragm = false; | 1093 | bool fragm = false; |
1094 | 1094 | ||
1095 | local->mdev->trans_start = jiffies; | 1095 | local->mdev->trans_start = jiffies; |
@@ -1125,7 +1125,12 @@ static int __ieee80211_tx(struct ieee80211_local *local, | |||
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | next = skb->next; | 1127 | next = skb->next; |
1128 | len = skb->len; | ||
1128 | ret = local->ops->tx(local_to_hw(local), skb); | 1129 | ret = local->ops->tx(local_to_hw(local), skb); |
1130 | if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { | ||
1131 | dev_kfree_skb(skb); | ||
1132 | ret = NETDEV_TX_OK; | ||
1133 | } | ||
1129 | if (ret != NETDEV_TX_OK) | 1134 | if (ret != NETDEV_TX_OK) |
1130 | return IEEE80211_TX_AGAIN; | 1135 | return IEEE80211_TX_AGAIN; |
1131 | *skbp = skb = next; | 1136 | *skbp = skb = next; |