| From 94513069eb549737bcfc3d988d6ed4da948a2de8 Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Mon, 27 Sep 2021 11:58:39 +0200 |
| Subject: mac80211: fix use-after-free in CCMP/GCMP RX |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| commit 94513069eb549737bcfc3d988d6ed4da948a2de8 upstream. |
| |
| When PN checking is done in mac80211, for fragmentation we need |
| to copy the PN to the RX struct so we can later use it to do a |
| comparison, since commit bf30ca922a0c ("mac80211: check defrag |
| PN against current frame"). |
| |
| Unfortunately, in that commit I used the 'hdr' variable without |
| it being necessarily valid, so use-after-free could occur if it |
| was necessary to reallocate (parts of) the frame. |
| |
| Fix this by reloading the variable after the code that results |
| in the reallocations, if any. |
| |
| This fixes https://bugzilla.kernel.org/show_bug.cgi?id=214401. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: bf30ca922a0c ("mac80211: check defrag PN against current frame") |
| Link: https://lore.kernel.org/r/20210927115838.12b9ac6bb233.I1d066acd5408a662c3b6e828122cd314fcb28cdb@changeid |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/mac80211/wpa.c | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| --- a/net/mac80211/wpa.c |
| +++ b/net/mac80211/wpa.c |
| @@ -520,6 +520,9 @@ ieee80211_crypto_ccmp_decrypt(struct iee |
| return RX_DROP_UNUSABLE; |
| } |
| |
| + /* reload hdr - skb might have been reallocated */ |
| + hdr = (void *)rx->skb->data; |
| + |
| data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; |
| if (!rx->sta || data_len < 0) |
| return RX_DROP_UNUSABLE; |
| @@ -749,6 +752,9 @@ ieee80211_crypto_gcmp_decrypt(struct iee |
| return RX_DROP_UNUSABLE; |
| } |
| |
| + /* reload hdr - skb might have been reallocated */ |
| + hdr = (void *)rx->skb->data; |
| + |
| data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len; |
| if (!rx->sta || data_len < 0) |
| return RX_DROP_UNUSABLE; |