diff options
author | Sona Sarmadi <sona.sarmadi@enea.com> | 2016-06-17 10:34:58 +0200 |
---|---|---|
committer | Tudor Florea <tudor.florea@enea.com> | 2016-06-17 19:49:38 +0200 |
commit | 638a72daa5ce011023e0d0311ca48bb454ce9c28 (patch) | |
tree | 4ca570430d4952efc548650e36c1a0a9d17a557d | |
parent | 8bd62a6ded78e4a1116e23fb66bb5103f856bf89 (diff) | |
download | meta-enea-daisy-enea.tar.gz |
Kernel: net: mac80211: CVE-2014-2706daisy-enea
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 <sona.sarmadi@enea.com>
Signed-off-by: Tudor Florea <tudor.florea@enea.com>
-rw-r--r-- | recipes-kernel/linux/files/mac80211-CVE-2014-2706.patch | 166 | ||||
-rw-r--r-- | recipes-kernel/linux/linux-qoriq-sdk.bbappend | 1 |
2 files changed, 167 insertions, 0 deletions
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 @@ | |||
1 | From a7ee1a84a81555b19ec3d02f104bfd70cf0b668a Mon Sep 17 00:00:00 2001 | ||
2 | From: Emmanuel Grumbach <emmanuel.grumbach@intel.com> | ||
3 | Date: Thu, 20 Feb 2014 09:22:11 +0200 | ||
4 | Subject: mac80211: fix AP powersave TX vs. wakeup race | ||
5 | |||
6 | commit 1d147bfa64293b2723c4fec50922168658e613ba upstream. | ||
7 | |||
8 | There is a race between the TX path and the STA wakeup: while | ||
9 | a station is sleeping, mac80211 buffers frames until it wakes | ||
10 | up, then the frames are transmitted. However, the RX and TX | ||
11 | path are concurrent, so the packet indicating wakeup can be | ||
12 | processed while a packet is being transmitted. | ||
13 | |||
14 | This can lead to a situation where the buffered frames list | ||
15 | is emptied on the one side, while a frame is being added on | ||
16 | the other side, as the station is still seen as sleeping in | ||
17 | the TX path. | ||
18 | |||
19 | As a result, the newly added frame will not be send anytime | ||
20 | soon. It might be sent much later (and out of order) when the | ||
21 | station goes to sleep and wakes up the next time. | ||
22 | |||
23 | Additionally, it can lead to the crash below. | ||
24 | |||
25 | Fix all this by synchronising both paths with a new lock. | ||
26 | Both path are not fastpath since they handle PS situations. | ||
27 | |||
28 | In a later patch we'll remove the extra skb queue locks to | ||
29 | reduce locking overhead. | ||
30 | |||
31 | BUG: unable to handle kernel | ||
32 | NULL pointer dereference at 000000b0 | ||
33 | IP: [<ff6f1791>] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] | ||
34 | *pde = 00000000 | ||
35 | Oops: 0000 [#1] SMP DEBUG_PAGEALLOC | ||
36 | EIP: 0060:[<ff6f1791>] EFLAGS: 00210282 CPU: 1 | ||
37 | EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211] | ||
38 | EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000 | ||
39 | ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0 | ||
40 | DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 | ||
41 | CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0 | ||
42 | DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 | ||
43 | DR6: ffff0ff0 DR7: 00000400 | ||
44 | Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000) | ||
45 | iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9 | ||
46 | Stack: | ||
47 | e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0 | ||
48 | ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210 | ||
49 | ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002 | ||
50 | Call Trace: | ||
51 | [<ff6f1b75>] ieee80211_free_txskb+0x15/0x20 [mac80211] | ||
52 | [<ff723dc1>] invoke_tx_handlers+0x1661/0x1780 [mac80211] | ||
53 | [<ff7248a5>] ieee80211_tx+0x75/0x100 [mac80211] | ||
54 | [<ff7249bf>] ieee80211_xmit+0x8f/0xc0 [mac80211] | ||
55 | [<ff72550e>] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] | ||
56 | [<c149ef70>] dev_hard_start_xmit+0x450/0x950 | ||
57 | [<c14b9aa9>] sch_direct_xmit+0xa9/0x250 | ||
58 | [<c14b9c9b>] __qdisc_run+0x4b/0x150 | ||
59 | [<c149f732>] dev_queue_xmit+0x2c2/0xca0 | ||
60 | |||
61 | CVE: CVE-2014-2706 | ||
62 | Upstream-Status: Backport | ||
63 | |||
64 | Reported-by: Yaara Rozenblum <yaara.rozenblum@intel.com> | ||
65 | Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> | ||
66 | Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com> | ||
67 | [reword commit log, use a separate lock] | ||
68 | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||
69 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
70 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
71 | --- | ||
72 | net/mac80211/sta_info.c | 4 ++++ | ||
73 | net/mac80211/sta_info.h | 7 +++---- | ||
74 | net/mac80211/tx.c | 15 +++++++++++++++ | ||
75 | 3 files changed, 22 insertions(+), 4 deletions(-) | ||
76 | |||
77 | diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c | ||
78 | index 11216bc..a66d006 100644 | ||
79 | --- a/net/mac80211/sta_info.c | ||
80 | +++ b/net/mac80211/sta_info.c | ||
81 | @@ -339,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | ||
82 | return NULL; | ||
83 | |||
84 | spin_lock_init(&sta->lock); | ||
85 | + spin_lock_init(&sta->ps_lock); | ||
86 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | ||
87 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | ||
88 | mutex_init(&sta->ampdu_mlme.mtx); | ||
89 | @@ -1045,6 +1046,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | ||
90 | |||
91 | skb_queue_head_init(&pending); | ||
92 | |||
93 | + /* sync with ieee80211_tx_h_unicast_ps_buf */ | ||
94 | + spin_lock(&sta->ps_lock); | ||
95 | /* Send all buffered frames to the station */ | ||
96 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
97 | int count = skb_queue_len(&pending), tmp; | ||
98 | @@ -1064,6 +1067,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | ||
99 | } | ||
100 | |||
101 | ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); | ||
102 | + spin_unlock(&sta->ps_lock); | ||
103 | |||
104 | local->total_ps_buffered -= buffered; | ||
105 | |||
106 | diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h | ||
107 | index adc3004..3184b2b 100644 | ||
108 | --- a/net/mac80211/sta_info.h | ||
109 | +++ b/net/mac80211/sta_info.h | ||
110 | @@ -244,6 +244,7 @@ struct sta_ampdu_mlme { | ||
111 | * @drv_unblock_wk: used for driver PS unblocking | ||
112 | * @listen_interval: listen interval of this station, when we're acting as AP | ||
113 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly | ||
114 | + * @ps_lock: used for powersave (when mac80211 is the AP) related locking | ||
115 | * @ps_tx_buf: buffers (per AC) of frames to transmit to this station | ||
116 | * when it leaves power saving state or polls | ||
117 | * @tx_filtered: buffers (per AC) of frames we already tried to | ||
118 | @@ -324,10 +325,8 @@ struct sta_info { | ||
119 | /* use the accessors defined below */ | ||
120 | unsigned long _flags; | ||
121 | |||
122 | - /* | ||
123 | - * STA powersave frame queues, no more than the internal | ||
124 | - * locking required. | ||
125 | - */ | ||
126 | + /* STA powersave lock and frame queues */ | ||
127 | + spinlock_t ps_lock; | ||
128 | struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; | ||
129 | struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; | ||
130 | unsigned long driver_buffered_tids; | ||
131 | diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c | ||
132 | index fe9d6e7..6d5791d 100644 | ||
133 | --- a/net/mac80211/tx.c | ||
134 | +++ b/net/mac80211/tx.c | ||
135 | @@ -461,6 +461,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | ||
136 | sta->sta.addr, sta->sta.aid, ac); | ||
137 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | ||
138 | purge_old_ps_buffers(tx->local); | ||
139 | + | ||
140 | + /* sync with ieee80211_sta_ps_deliver_wakeup */ | ||
141 | + spin_lock(&sta->ps_lock); | ||
142 | + /* | ||
143 | + * STA woke up the meantime and all the frames on ps_tx_buf have | ||
144 | + * been queued to pending queue. No reordering can happen, go | ||
145 | + * ahead and Tx the packet. | ||
146 | + */ | ||
147 | + if (!test_sta_flag(sta, WLAN_STA_PS_STA) && | ||
148 | + !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | ||
149 | + spin_unlock(&sta->ps_lock); | ||
150 | + return TX_CONTINUE; | ||
151 | + } | ||
152 | + | ||
153 | if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { | ||
154 | struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); | ||
155 | ps_dbg(tx->sdata, | ||
156 | @@ -474,6 +488,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | ||
157 | info->control.vif = &tx->sdata->vif; | ||
158 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
159 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); | ||
160 | + spin_unlock(&sta->ps_lock); | ||
161 | |||
162 | if (!timer_pending(&local->sta_cleanup)) | ||
163 | mod_timer(&local->sta_cleanup, | ||
164 | -- | ||
165 | cgit v0.12 | ||
166 | |||
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 \ | |||
22 | file://virt-kvm-CVE-2013-4587.patch \ | 22 | file://virt-kvm-CVE-2013-4587.patch \ |
23 | file://floppy-CVE-2014-1737.patch \ | 23 | file://floppy-CVE-2014-1737.patch \ |
24 | file://floppy-CVE-2014-1738.patch \ | 24 | file://floppy-CVE-2014-1738.patch \ |
25 | file://mac80211-CVE-2014-2706.patch \ | ||
25 | file://Fix-CVE-2014-3153.patch \ | 26 | file://Fix-CVE-2014-3153.patch \ |
26 | file://CVE-2014-0196_n_tty_write_crash.patch \ | 27 | file://CVE-2014-0196_n_tty_write_crash.patch \ |
27 | file://Fix-CVE-2014-5471_CVE-2014-5472.patch \ | 28 | file://Fix-CVE-2014-5471_CVE-2014-5472.patch \ |