| From f5563318ff1bde15b10e736e97ffce13be08bc1a Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Fri, 11 Oct 2013 14:47:05 +0200 |
| Subject: wireless: radiotap: fix parsing buffer overrun |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| commit f5563318ff1bde15b10e736e97ffce13be08bc1a upstream. |
| |
| When parsing an invalid radiotap header, the parser can overrun |
| the buffer that is passed in because it doesn't correctly check |
| 1) the minimum radiotap header size |
| 2) the space for extended bitmaps |
| |
| The first issue doesn't affect any in-kernel user as they all |
| check the minimum size before calling the radiotap function. |
| The second issue could potentially affect the kernel if an skb |
| is passed in that consists only of the radiotap header with a |
| lot of extended bitmaps that extend past the SKB. In that case |
| a read-only buffer overrun by at most 4 bytes is possible. |
| |
| Fix this by adding the appropriate checks to the parser. |
| |
| Reported-by: Evan Huus <eapache@gmail.com> |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/wireless/radiotap.c | 7 ++++++- |
| 1 file changed, 6 insertions(+), 1 deletion(-) |
| |
| --- a/net/wireless/radiotap.c |
| +++ b/net/wireless/radiotap.c |
| @@ -97,6 +97,10 @@ int ieee80211_radiotap_iterator_init( |
| struct ieee80211_radiotap_header *radiotap_header, |
| int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) |
| { |
| + /* check the radiotap header can actually be present */ |
| + if (max_length < sizeof(struct ieee80211_radiotap_header)) |
| + return -EINVAL; |
| + |
| /* Linux only supports version 0 radiotap format */ |
| if (radiotap_header->it_version) |
| return -EINVAL; |
| @@ -131,7 +135,8 @@ int ieee80211_radiotap_iterator_init( |
| */ |
| |
| if ((unsigned long)iterator->_arg - |
| - (unsigned long)iterator->_rtheader > |
| + (unsigned long)iterator->_rtheader + |
| + sizeof(uint32_t) > |
| (unsigned long)iterator->_max_length) |
| return -EINVAL; |
| } |