From 638a72daa5ce011023e0d0311ca48bb454ce9c28 Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Fri, 17 Jun 2016 10:34:58 +0200 Subject: Kernel: net: mac80211: CVE-2014-2706 crash dues to AP powersave TX vs. wakeup race Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-2706 Reference to upstream fix: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/ commit/?id=a7ee1a84a81555b19ec3d02f104bfd70cf0b668a Signed-off-by: Sona Sarmadi Signed-off-by: Tudor Florea --- .../linux/files/mac80211-CVE-2014-2706.patch | 166 +++++++++++++++++++++ recipes-kernel/linux/linux-qoriq-sdk.bbappend | 1 + 2 files changed, 167 insertions(+) create mode 100644 recipes-kernel/linux/files/mac80211-CVE-2014-2706.patch diff --git a/recipes-kernel/linux/files/mac80211-CVE-2014-2706.patch b/recipes-kernel/linux/files/mac80211-CVE-2014-2706.patch new file mode 100644 index 0000000..5c79ed2 --- /dev/null +++ b/recipes-kernel/linux/files/mac80211-CVE-2014-2706.patch @@ -0,0 +1,166 @@ +From a7ee1a84a81555b19ec3d02f104bfd70cf0b668a Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Thu, 20 Feb 2014 09:22:11 +0200 +Subject: mac80211: fix AP powersave TX vs. wakeup race + +commit 1d147bfa64293b2723c4fec50922168658e613ba upstream. + +There is a race between the TX path and the STA wakeup: while +a station is sleeping, mac80211 buffers frames until it wakes +up, then the frames are transmitted. However, the RX and TX +path are concurrent, so the packet indicating wakeup can be +processed while a packet is being transmitted. + +This can lead to a situation where the buffered frames list +is emptied on the one side, while a frame is being added on +the other side, as the station is still seen as sleeping in +the TX path. + +As a result, the newly added frame will not be send anytime +soon. It might be sent much later (and out of order) when the +station goes to sleep and wakes up the next time. + +Additionally, it can lead to the crash below. + +Fix all this by synchronising both paths with a new lock. +Both path are not fastpath since they handle PS situations. + +In a later patch we'll remove the extra skb queue locks to +reduce locking overhead. + +BUG: unable to handle kernel +NULL pointer dereference at 000000b0 +IP: [] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] +*pde = 00000000 +Oops: 0000 [#1] SMP DEBUG_PAGEALLOC +EIP: 0060:[] EFLAGS: 00210282 CPU: 1 +EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211] +EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000 +ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0 + DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 +CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0 +DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 +DR6: ffff0ff0 DR7: 00000400 +Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000) +iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9 +Stack: + e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0 + ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210 + ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002 +Call Trace: + [] ieee80211_free_txskb+0x15/0x20 [mac80211] + [] invoke_tx_handlers+0x1661/0x1780 [mac80211] + [] ieee80211_tx+0x75/0x100 [mac80211] + [] ieee80211_xmit+0x8f/0xc0 [mac80211] + [] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] + [] dev_hard_start_xmit+0x450/0x950 + [] sch_direct_xmit+0xa9/0x250 + [] __qdisc_run+0x4b/0x150 + [] dev_queue_xmit+0x2c2/0xca0 + +CVE: CVE-2014-2706 +Upstream-Status: Backport + +Reported-by: Yaara Rozenblum +Signed-off-by: Emmanuel Grumbach +Reviewed-by: Stanislaw Gruszka +[reword commit log, use a separate lock] +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sona Sarmadi +--- + net/mac80211/sta_info.c | 4 ++++ + net/mac80211/sta_info.h | 7 +++---- + net/mac80211/tx.c | 15 +++++++++++++++ + 3 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index 11216bc..a66d006 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -339,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, + return NULL; + + spin_lock_init(&sta->lock); ++ spin_lock_init(&sta->ps_lock); + INIT_WORK(&sta->drv_unblock_wk, sta_unblock); + INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); + mutex_init(&sta->ampdu_mlme.mtx); +@@ -1045,6 +1046,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) + + skb_queue_head_init(&pending); + ++ /* sync with ieee80211_tx_h_unicast_ps_buf */ ++ spin_lock(&sta->ps_lock); + /* Send all buffered frames to the station */ + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + int count = skb_queue_len(&pending), tmp; +@@ -1064,6 +1067,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) + } + + ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); ++ spin_unlock(&sta->ps_lock); + + local->total_ps_buffered -= buffered; + +diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h +index adc3004..3184b2b 100644 +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -244,6 +244,7 @@ struct sta_ampdu_mlme { + * @drv_unblock_wk: used for driver PS unblocking + * @listen_interval: listen interval of this station, when we're acting as AP + * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly ++ * @ps_lock: used for powersave (when mac80211 is the AP) related locking + * @ps_tx_buf: buffers (per AC) of frames to transmit to this station + * when it leaves power saving state or polls + * @tx_filtered: buffers (per AC) of frames we already tried to +@@ -324,10 +325,8 @@ struct sta_info { + /* use the accessors defined below */ + unsigned long _flags; + +- /* +- * STA powersave frame queues, no more than the internal +- * locking required. +- */ ++ /* STA powersave lock and frame queues */ ++ spinlock_t ps_lock; + struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; + struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; + unsigned long driver_buffered_tids; +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index fe9d6e7..6d5791d 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -461,6 +461,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + sta->sta.addr, sta->sta.aid, ac); + if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) + purge_old_ps_buffers(tx->local); ++ ++ /* sync with ieee80211_sta_ps_deliver_wakeup */ ++ spin_lock(&sta->ps_lock); ++ /* ++ * STA woke up the meantime and all the frames on ps_tx_buf have ++ * been queued to pending queue. No reordering can happen, go ++ * ahead and Tx the packet. ++ */ ++ if (!test_sta_flag(sta, WLAN_STA_PS_STA) && ++ !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { ++ spin_unlock(&sta->ps_lock); ++ return TX_CONTINUE; ++ } ++ + if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { + struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); + ps_dbg(tx->sdata, +@@ -474,6 +488,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + info->control.vif = &tx->sdata->vif; + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; + skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); ++ spin_unlock(&sta->ps_lock); + + if (!timer_pending(&local->sta_cleanup)) + mod_timer(&local->sta_cleanup, +-- +cgit v0.12 + diff --git a/recipes-kernel/linux/linux-qoriq-sdk.bbappend b/recipes-kernel/linux/linux-qoriq-sdk.bbappend index c3ded18..6f76654 100644 --- a/recipes-kernel/linux/linux-qoriq-sdk.bbappend +++ b/recipes-kernel/linux/linux-qoriq-sdk.bbappend @@ -22,6 +22,7 @@ SRC_URI += "file://add-no-error-uninitialized.patch \ file://virt-kvm-CVE-2013-4587.patch \ file://floppy-CVE-2014-1737.patch \ file://floppy-CVE-2014-1738.patch \ + file://mac80211-CVE-2014-2706.patch \ file://Fix-CVE-2014-3153.patch \ file://CVE-2014-0196_n_tty_write_crash.patch \ file://Fix-CVE-2014-5471_CVE-2014-5472.patch \ -- cgit v1.2.3-54-g00ecf