From cf17de4c0e9ac5f7131c7da62f334ae3a00b2b74 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 19 Nov 2012 15:31:10 -0800 Subject: [PATCH] 3.4-stable patches added patches: cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch fanotify-fix-missing-break.patch mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch mac80211-don-t-send-null-data-packet-when-not-associated.patch mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch module-fix-out-by-one-error-in-kallsyms.patch pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch --- ...-overrun-in-cifs.idmap-handling-code.patch | 171 ++++++++++++++++++ ...ue_worker-to-prevent-data-corruption.patch | 53 ++++++ queue-3.4/fanotify-fix-missing-break.patch | 41 +++++ ...e_txskb-instead-of-__skb_queue_purge.patch | 97 ++++++++++ ...null-data-packet-when-not-associated.patch | 35 ++++ ...cess-to-tx_filtered-ps_tx_buf-queues.patch | 51 ++++++ ...ule-fix-out-by-one-error-in-kallsyms.patch | 78 ++++++++ ...unbinding-device-if-parent-in-d3cold.patch | 156 ++++++++++++++++ queue-3.4/series | 9 + ...io-reference-when-a-bad-bio-is-built.patch | 69 +++++++ 10 files changed, 760 insertions(+) create mode 100644 queue-3.4/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch create mode 100644 queue-3.4/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch create mode 100644 queue-3.4/fanotify-fix-missing-break.patch create mode 100644 queue-3.4/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch create mode 100644 queue-3.4/mac80211-don-t-send-null-data-packet-when-not-associated.patch create mode 100644 queue-3.4/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch create mode 100644 queue-3.4/module-fix-out-by-one-error-in-kallsyms.patch create mode 100644 queue-3.4/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch create mode 100644 queue-3.4/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch diff --git a/queue-3.4/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch b/queue-3.4/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch new file mode 100644 index 00000000000..7315eecf90a --- /dev/null +++ b/queue-3.4/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch @@ -0,0 +1,171 @@ +From 36960e440ccf94349c09fb944930d3bfe4bc473f Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Sat, 3 Nov 2012 09:37:28 -0400 +Subject: cifs: fix potential buffer overrun in cifs.idmap handling code + +From: Jeff Layton + +commit 36960e440ccf94349c09fb944930d3bfe4bc473f upstream. + +The userspace cifs.idmap program generally works with the wbclient libs +to generate binary SIDs in userspace. That program defines the struct +that holds these values as having a max of 15 subauthorities. The kernel +idmapping code however limits that value to 5. + +When the kernel copies those values around though, it doesn't sanity +check the num_subauths value handed back from userspace or from the +server. It's possible therefore for userspace to hand us back a bogus +num_subauths value (or one that's valid, but greater than 5) that could +cause the kernel to walk off the end of the cifs_sid->sub_auths array. + +Fix this by defining a new routine for copying sids and using that in +all of the places that copy it. If we end up with a sid that's longer +than expected then this approach will just lop off the "extra" subauths, +but that's basically what the code does today already. Better approaches +might be to fix this code to reject SIDs with >5 subauths, or fix it +to handle the subauths array dynamically. + +At the same time, change the kernel to check the length of the data +returned by userspace. If it's shorter than struct cifs_sid, reject it +and return -EIO. If that happens we'll end up with fields that are +basically uninitialized. + +Long term, it might make sense to redefine cifs_sid using a flexarray at +the end, to allow for variable-length subauth lists, and teach the code +to handle the case where the subauths array being passed in from +userspace is shorter than 5 elements. + +Note too, that I don't consider this a security issue since you'd need +a compromised cifs.idmap program. If you have that, you can do all sorts +of nefarious stuff. Still, this is probably reasonable for stable. + +Reviewed-by: Shirish Pargaonkar +Signed-off-by: Jeff Layton +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifsacl.c | 49 ++++++++++++++++++++----------------------------- + 1 file changed, 20 insertions(+), 29 deletions(-) + +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char + } + + static void ++cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) ++{ ++ memcpy(dst, src, sizeof(*dst)); ++ dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); ++} ++ ++static void + id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, + struct cifs_sid_id **psidid, char *typestr) + { +@@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struc + } + } + +- memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); ++ cifs_copy_sid(&(*psidid)->sid, sidptr); + (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); + (*psidid)->refcount = 0; + +@@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtyp + * any fields of the node after a reference is put . + */ + if (test_bit(SID_ID_MAPPED, &psidid->state)) { +- memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); ++ cifs_copy_sid(ssid, &psidid->sid); + psidid->time = jiffies; /* update ts for accessing */ + goto id_sid_out; + } +@@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtyp + if (IS_ERR(sidkey)) { + rc = -EINVAL; + cFYI(1, "%s: Can't map and id to a SID", __func__); ++ } else if (sidkey->datalen < sizeof(struct cifs_sid)) { ++ rc = -EIO; ++ cFYI(1, "%s: Downcall contained malformed key " ++ "(datalen=%hu)", __func__, sidkey->datalen); + } else { + lsid = (struct cifs_sid *)sidkey->payload.data; +- memcpy(&psidid->sid, lsid, +- sidkey->datalen < sizeof(struct cifs_sid) ? +- sidkey->datalen : sizeof(struct cifs_sid)); +- memcpy(ssid, &psidid->sid, +- sidkey->datalen < sizeof(struct cifs_sid) ? +- sidkey->datalen : sizeof(struct cifs_sid)); ++ cifs_copy_sid(&psidid->sid, lsid); ++ cifs_copy_sid(ssid, &psidid->sid); + set_bit(SID_ID_MAPPED, &psidid->state); + key_put(sidkey); + kfree(psidid->sidstr); +@@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtyp + return rc; + } + if (test_bit(SID_ID_MAPPED, &psidid->state)) +- memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); ++ cifs_copy_sid(ssid, &psidid->sid); + else + rc = -EINVAL; + } +@@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid * + static void copy_sec_desc(const struct cifs_ntsd *pntsd, + struct cifs_ntsd *pnntsd, __u32 sidsoffset) + { +- int i; +- + struct cifs_sid *owner_sid_ptr, *group_sid_ptr; + struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; + +@@ -692,26 +697,14 @@ static void copy_sec_desc(const struct c + owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + + le32_to_cpu(pntsd->osidoffset)); + nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); +- +- nowner_sid_ptr->revision = owner_sid_ptr->revision; +- nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; +- for (i = 0; i < 6; i++) +- nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; +- for (i = 0; i < 5; i++) +- nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; ++ cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); + + /* copy group sid */ + group_sid_ptr = (struct cifs_sid *)((char *)pntsd + + le32_to_cpu(pntsd->gsidoffset)); + ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + + sizeof(struct cifs_sid)); +- +- ngroup_sid_ptr->revision = group_sid_ptr->revision; +- ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; +- for (i = 0; i < 6; i++) +- ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; +- for (i = 0; i < 5; i++) +- ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; ++ cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); + + return; + } +@@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_nt + kfree(nowner_sid_ptr); + return rc; + } +- memcpy(owner_sid_ptr, nowner_sid_ptr, +- sizeof(struct cifs_sid)); ++ cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); + kfree(nowner_sid_ptr); + *aclflag = CIFS_ACL_OWNER; + } +@@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_nt + kfree(ngroup_sid_ptr); + return rc; + } +- memcpy(group_sid_ptr, ngroup_sid_ptr, +- sizeof(struct cifs_sid)); ++ cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); + kfree(ngroup_sid_ptr); + *aclflag = CIFS_ACL_GROUP; + } diff --git a/queue-3.4/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch b/queue-3.4/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch new file mode 100644 index 00000000000..8151a7aaa69 --- /dev/null +++ b/queue-3.4/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch @@ -0,0 +1,53 @@ +From 9efade1b3e981f5064f9db9ca971b4dc7557ae42 Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Sun, 21 Oct 2012 20:42:28 +0300 +Subject: crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption + +From: Jussi Kivilinna + +commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream. + +cryptd_queue_worker attempts to prevent simultaneous accesses to crypto +workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable. +However cryptd_enqueue_request might be called from softirq context, +so add local_bh_disable/local_bh_enable to prevent data corruption and +panics. + +Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2 + +v2: + - Disable software interrupts instead of hardware interrupts + +Reported-by: Gurucharan Shetty +Signed-off-by: Jussi Kivilinna +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/cryptd.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct w + struct crypto_async_request *req, *backlog; + + cpu_queue = container_of(work, struct cryptd_cpu_queue, work); +- /* Only handle one request at a time to avoid hogging crypto +- * workqueue. preempt_disable/enable is used to prevent +- * being preempted by cryptd_enqueue_request() */ ++ /* ++ * Only handle one request at a time to avoid hogging crypto workqueue. ++ * preempt_disable/enable is used to prevent being preempted by ++ * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent ++ * cryptd_enqueue_request() being accessed from software interrupts. ++ */ ++ local_bh_disable(); + preempt_disable(); + backlog = crypto_get_backlog(&cpu_queue->queue); + req = crypto_dequeue_request(&cpu_queue->queue); + preempt_enable(); ++ local_bh_enable(); + + if (!req) + return; diff --git a/queue-3.4/fanotify-fix-missing-break.patch b/queue-3.4/fanotify-fix-missing-break.patch new file mode 100644 index 00000000000..ff57c4214f8 --- /dev/null +++ b/queue-3.4/fanotify-fix-missing-break.patch @@ -0,0 +1,41 @@ +From 848561d368751a1c0f679b9f045a02944506a801 Mon Sep 17 00:00:00 2001 +From: Eric Paris +Date: Thu, 8 Nov 2012 15:53:37 -0800 +Subject: fanotify: fix missing break + +From: Eric Paris + +commit 848561d368751a1c0f679b9f045a02944506a801 upstream. + +Anders Blomdell noted in 2010 that Fanotify lost events and provided a +test case. Eric Paris confirmed it was a bug and posted a fix to the +list + + https://groups.google.com/forum/?fromgroups=#!topic/linux.kernel/RrJfTfyW2BE + +but never applied it. Repeated attempts over time to actually get him +to apply it have never had a reply from anyone who has raised it + +So apply it anyway + +Signed-off-by: Alan Cox +Reported-by: Anders Blomdell +Cc: Eric Paris +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/notify/fanotify/fanotify.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/notify/fanotify/fanotify.c ++++ b/fs/notify/fanotify/fanotify.c +@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify + if ((old->path.mnt == new->path.mnt) && + (old->path.dentry == new->path.dentry)) + return true; ++ break; + case (FSNOTIFY_EVENT_NONE): + return true; + default: diff --git a/queue-3.4/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch b/queue-3.4/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch new file mode 100644 index 00000000000..aa42b466b21 --- /dev/null +++ b/queue-3.4/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch @@ -0,0 +1,97 @@ +From 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 10 Nov 2012 03:44:14 +0100 +Subject: mac80211: call skb_dequeue/ieee80211_free_txskb instead of __skb_queue_purge + +From: Felix Fietkau + +commit 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 upstream. + +Fixes more wifi status skb leaks, leading to hostapd/wpa_supplicant hangs. + +Signed-off-by: Felix Fietkau +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/ieee80211_i.h | 2 ++ + net/mac80211/sta_info.c | 6 +++--- + net/mac80211/status.c | 9 +++++++++ + net/mac80211/tx.c | 9 ++++++--- + 4 files changed, 20 insertions(+), 6 deletions(-) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1297,6 +1297,8 @@ netdev_tx_t ieee80211_monitor_start_xmit + struct net_device *dev); + netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, + struct net_device *dev); ++void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, ++ struct sk_buff_head *skbs); + + /* HT */ + bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -738,8 +738,8 @@ int __must_check __sta_info_destroy(stru + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); +- __skb_queue_purge(&sta->ps_tx_buf[ac]); +- __skb_queue_purge(&sta->tx_filtered[ac]); ++ ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); ++ ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); + } + + #ifdef CONFIG_MAC80211_MESH +@@ -774,7 +774,7 @@ int __must_check __sta_info_destroy(stru + tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); + if (!tid_tx) + continue; +- __skb_queue_purge(&tid_tx->pending); ++ ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); + kfree(tid_tx); + } + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -660,3 +660,12 @@ void ieee80211_free_txskb(struct ieee802 + dev_kfree_skb_any(skb); + } + EXPORT_SYMBOL(ieee80211_free_txskb); ++ ++void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, ++ struct sk_buff_head *skbs) ++{ ++ struct sk_buff *skb; ++ ++ while ((skb = __skb_dequeue(skbs))) ++ ieee80211_free_txskb(hw, skb); ++} +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1357,7 +1357,7 @@ static int invoke_tx_handlers(struct iee + if (tx->skb) + dev_kfree_skb(tx->skb); + else +- __skb_queue_purge(&tx->skbs); ++ ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); + return -1; + } else if (unlikely(res == TX_QUEUED)) { + I802_DEBUG_INC(tx->local->tx_handlers_queued); +@@ -2126,10 +2126,13 @@ netdev_tx_t ieee80211_subif_start_xmit(s + */ + void ieee80211_clear_tx_pending(struct ieee80211_local *local) + { ++ struct sk_buff *skb; + int i; + +- for (i = 0; i < local->hw.queues; i++) +- skb_queue_purge(&local->pending[i]); ++ for (i = 0; i < local->hw.queues; i++) { ++ while ((skb = skb_dequeue(&local->pending[i])) != NULL) ++ ieee80211_free_txskb(&local->hw, skb); ++ } + } + + /* diff --git a/queue-3.4/mac80211-don-t-send-null-data-packet-when-not-associated.patch b/queue-3.4/mac80211-don-t-send-null-data-packet-when-not-associated.patch new file mode 100644 index 00000000000..83615fc7543 --- /dev/null +++ b/queue-3.4/mac80211-don-t-send-null-data-packet-when-not-associated.patch @@ -0,0 +1,35 @@ +From 20f544eea03db4b498942558b882d463ce575c3e Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 8 Nov 2012 14:06:28 +0100 +Subject: mac80211: don't send null data packet when not associated + +From: Johannes Berg + +commit 20f544eea03db4b498942558b882d463ce575c3e upstream. + +On resume or firmware recovery, mac80211 sends a null +data packet to see if the AP is still around and hasn't +disconnected us. However, it always does this even if +it wasn't even connected before, leading to a warning +in the new channel context code. Fix this by checking +that it's associated. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/util.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1341,6 +1341,8 @@ int ieee80211_reconfig(struct ieee80211_ + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_STATION) + continue; ++ if (!sdata->u.mgd.associated) ++ continue; + + ieee80211_send_nullfunc(local, sdata, 0); + } diff --git a/queue-3.4/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch b/queue-3.4/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch new file mode 100644 index 00000000000..68f73c69570 --- /dev/null +++ b/queue-3.4/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch @@ -0,0 +1,51 @@ +From 987c285c2ae2e4e32aca3a9b3252d28171c75711 Mon Sep 17 00:00:00 2001 +From: Arik Nemtsov +Date: Mon, 5 Nov 2012 10:27:52 +0200 +Subject: mac80211: sync acccess to tx_filtered/ps_tx_buf queues + +From: Arik Nemtsov + +commit 987c285c2ae2e4e32aca3a9b3252d28171c75711 upstream. + +These are accessed without a lock when ending STA PSM. If the +sta_cleanup timer accesses these lists at the same time, we might crash. + +This may fix some mysterious crashes we had during +ieee80211_sta_ps_deliver_wakeup. + +Signed-off-by: Arik Nemtsov +Signed-off-by: Ido Yariv +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/sta_info.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -959,6 +959,7 @@ void ieee80211_sta_ps_deliver_wakeup(str + struct ieee80211_local *local = sdata->local; + struct sk_buff_head pending; + int filtered = 0, buffered = 0, ac; ++ unsigned long flags; + + clear_sta_flag(sta, WLAN_STA_SP); + +@@ -974,12 +975,16 @@ void ieee80211_sta_ps_deliver_wakeup(str + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + int count = skb_queue_len(&pending), tmp; + ++ spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); + skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); ++ spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); + tmp = skb_queue_len(&pending); + filtered += tmp - count; + count = tmp; + ++ spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); + skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); ++ spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); + tmp = skb_queue_len(&pending); + buffered += tmp - count; + } diff --git a/queue-3.4/module-fix-out-by-one-error-in-kallsyms.patch b/queue-3.4/module-fix-out-by-one-error-in-kallsyms.patch new file mode 100644 index 00000000000..008739c567f --- /dev/null +++ b/queue-3.4/module-fix-out-by-one-error-in-kallsyms.patch @@ -0,0 +1,78 @@ +From 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 Mon Sep 17 00:00:00 2001 +From: Rusty Russell +Date: Thu, 25 Oct 2012 10:49:25 +1030 +Subject: module: fix out-by-one error in kallsyms + +From: Rusty Russell + +commit 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 upstream. + +Masaki found and patched a kallsyms issue: the last symbol in a +module's symtab wasn't transferred. This is because we manually copy +the zero'th entry (which is always empty) then copy the rest in a loop +starting at 1, though from src[0]. His fix was minimal, I prefer to +rewrite the loops in more standard form. + +There are two loops: one to get the size, and one to copy. Make these +identical: always count entry 0 and any defined symbol in an allocated +non-init section. + +This bug exists since the following commit was introduced. + module: reduce symbol table for loaded modules (v2) + commit: 4a4962263f07d14660849ec134ee42b63e95ea9a + +LKML: http://lkml.org/lkml/2012/10/24/27 +Reported-by: Masaki Kimura +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/module.c | 27 ++++++++++++++++----------- + 1 file changed, 16 insertions(+), 11 deletions(-) + +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2273,12 +2273,17 @@ static void layout_symtab(struct module + src = (void *)info->hdr + symsect->sh_offset; + nsrc = symsect->sh_size / sizeof(*src); + ++ /* strtab always starts with a nul, so offset 0 is the empty string. */ ++ strtab_size = 1; ++ + /* Compute total space required for the core symbols' strtab. */ +- for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) +- if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { +- strtab_size += strlen(&info->strtab[src->st_name]) + 1; ++ for (ndst = i = 0; i < nsrc; i++) { ++ if (i == 0 || ++ is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { ++ strtab_size += strlen(&info->strtab[src[i].st_name])+1; + ndst++; + } ++ } + + /* Append room for core symbols at end of core part. */ + info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); +@@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module * + mod->core_symtab = dst = mod->module_core + info->symoffs; + mod->core_strtab = s = mod->module_core + info->stroffs; + src = mod->symtab; +- *dst = *src; + *s++ = 0; +- for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { +- if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) +- continue; +- +- dst[ndst] = *src; +- dst[ndst++].st_name = s - mod->core_strtab; +- s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; ++ for (ndst = i = 0; i < mod->num_symtab; i++) { ++ if (i == 0 || ++ is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { ++ dst[ndst] = src[i]; ++ dst[ndst++].st_name = s - mod->core_strtab; ++ s += strlcpy(s, &mod->strtab[src[i].st_name], ++ KSYM_NAME_LEN) + 1; ++ } + } + mod->core_num_syms = ndst; + } diff --git a/queue-3.4/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch b/queue-3.4/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch new file mode 100644 index 00000000000..1d4156f0431 --- /dev/null +++ b/queue-3.4/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch @@ -0,0 +1,156 @@ +From 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e Mon Sep 17 00:00:00 2001 +From: Huang Ying +Date: Wed, 24 Oct 2012 14:54:13 +0800 +Subject: PCI/PM: Fix deadlock when unbinding device if parent in D3cold + +From: Huang Ying + +commit 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e upstream. + +If a PCI device and its parents are put into D3cold, unbinding the +device will trigger deadlock as follow: + +- driver_unbind + - device_release_driver + - device_lock(dev) <--- previous lock here + - __device_release_driver + - pm_runtime_get_sync + ... + - rpm_resume(dev) + - rpm_resume(dev->parent) + ... + - pci_pm_runtime_resume + ... + - pci_set_power_state + - __pci_start_power_transition + - pci_wakeup_bus(dev->parent->subordinate) + - pci_walk_bus + - device_lock(dev) <--- deadlock here + + +If we do not do device_lock in pci_walk_bus, we can avoid deadlock. +Device_lock in pci_walk_bus is introduced in commit: +d71374dafbba7ec3f67371d3b7e9f6310a588808, corresponding email thread +is: https://lkml.org/lkml/2006/5/26/38. The patch author Zhang Yanmin +said device_lock is added to pci_walk_bus because: + + Some error handling functions call pci_walk_bus. For example, PCIe + aer. Here we lock the device, so the driver wouldn't detach from the + device, as the cb might call driver's callback function. + +So I fixed the deadlock as follows: + +- remove device_lock from pci_walk_bus +- add device_lock into callback if callback will call driver's callback + +I checked pci_walk_bus users one by one, and found only PCIe aer needs +device lock. + +Signed-off-by: Huang Ying +Signed-off-by: Bjorn Helgaas +Acked-by: Rafael J. Wysocki +CC: Zhang Yanmin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/bus.c | 3 --- + drivers/pci/pcie/aer/aerdrv_core.c | 20 ++++++++++++++++---- + 2 files changed, 16 insertions(+), 7 deletions(-) + +--- a/drivers/pci/bus.c ++++ b/drivers/pci/bus.c +@@ -314,10 +314,7 @@ void pci_walk_bus(struct pci_bus *top, i + } else + next = dev->bus_list.next; + +- /* Run device routines with the device locked */ +- device_lock(&dev->dev); + retval = cb(dev, userdata); +- device_unlock(&dev->dev); + if (retval) + break; + } +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -244,6 +244,7 @@ static int report_error_detected(struct + struct aer_broadcast_data *result_data; + result_data = (struct aer_broadcast_data *) data; + ++ device_lock(&dev->dev); + dev->error_state = result_data->state; + + if (!dev->driver || +@@ -262,12 +263,14 @@ static int report_error_detected(struct + dev->driver ? + "no AER-aware driver" : "no driver"); + } +- return 0; ++ goto out; + } + + err_handler = dev->driver->err_handler; + vote = err_handler->error_detected(dev, result_data->state); + result_data->result = merge_result(result_data->result, vote); ++out: ++ device_unlock(&dev->dev); + return 0; + } + +@@ -278,14 +281,17 @@ static int report_mmio_enabled(struct pc + struct aer_broadcast_data *result_data; + result_data = (struct aer_broadcast_data *) data; + ++ device_lock(&dev->dev); + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->mmio_enabled) +- return 0; ++ goto out; + + err_handler = dev->driver->err_handler; + vote = err_handler->mmio_enabled(dev); + result_data->result = merge_result(result_data->result, vote); ++out: ++ device_unlock(&dev->dev); + return 0; + } + +@@ -296,14 +302,17 @@ static int report_slot_reset(struct pci_ + struct aer_broadcast_data *result_data; + result_data = (struct aer_broadcast_data *) data; + ++ device_lock(&dev->dev); + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->slot_reset) +- return 0; ++ goto out; + + err_handler = dev->driver->err_handler; + vote = err_handler->slot_reset(dev); + result_data->result = merge_result(result_data->result, vote); ++out: ++ device_unlock(&dev->dev); + return 0; + } + +@@ -311,15 +320,18 @@ static int report_resume(struct pci_dev + { + struct pci_error_handlers *err_handler; + ++ device_lock(&dev->dev); + dev->error_state = pci_channel_io_normal; + + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->resume) +- return 0; ++ goto out; + + err_handler = dev->driver->err_handler; + err_handler->resume(dev); ++out: ++ device_unlock(&dev->dev); + return 0; + } + diff --git a/queue-3.4/series b/queue-3.4/series index 32b3a24649b..afb2348acb1 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -1 +1,10 @@ mm-bugfix-set-current-reclaim_state-to-null-while-returning-from-kswapd.patch +xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch +mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch +mac80211-don-t-send-null-data-packet-when-not-associated.patch +mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch +pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch +fanotify-fix-missing-break.patch +module-fix-out-by-one-error-in-kallsyms.patch +cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch +crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch diff --git a/queue-3.4/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch b/queue-3.4/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch new file mode 100644 index 00000000000..941d36733f0 --- /dev/null +++ b/queue-3.4/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch @@ -0,0 +1,69 @@ +From d69043c42d8c6414fa28ad18d99973aa6c1c2e24 Mon Sep 17 00:00:00 2001 +From: Dave Chinner +Date: Mon, 12 Nov 2012 22:09:46 +1100 +Subject: xfs: drop buffer io reference when a bad bio is built + +From: Dave Chinner + +commit d69043c42d8c6414fa28ad18d99973aa6c1c2e24 upstream. + +Error handling in xfs_buf_ioapply_map() does not handle IO reference +counts correctly. We increment the b_io_remaining count before +building the bio, but then fail to decrement it in the failure case. +This leads to the buffer never running IO completion and releasing +the reference that the IO holds, so at unmount we can leak the +buffer. This leak is captured by this assert failure during unmount: + +XFS: Assertion failed: atomic_read(&pag->pag_ref) == 0, file: fs/xfs/xfs_mount.c, line: 273 + +This is not a new bug - the b_io_remaining accounting has had this +problem for a long, long time - it's just very hard to get a +zero length bio being built by this code... + +Further, the buffer IO error can be overwritten on a multi-segment +buffer by subsequent bio completions for partial sections of the +buffer. Hence we should only set the buffer error status if the +buffer is not already carrying an error status. This ensures that a +partial IO error on a multi-segment buffer will not be lost. This +part of the problem is a regression, however. + +Signed-off-by: Dave Chinner +Reviewed-by: Mark Tinguely +Signed-off-by: Ben Myers +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_buf.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/fs/xfs/xfs_buf.c ++++ b/fs/xfs/xfs_buf.c +@@ -1165,9 +1165,14 @@ xfs_buf_bio_end_io( + { + xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; + +- xfs_buf_ioerror(bp, -error); ++ /* ++ * don't overwrite existing errors - otherwise we can lose errors on ++ * buffers that require multiple bios to complete. ++ */ ++ if (!bp->b_error) ++ xfs_buf_ioerror(bp, -error); + +- if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) ++ if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) + invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); + + _xfs_buf_ioend(bp, 1); +@@ -1243,6 +1248,11 @@ next_chunk: + if (size) + goto next_chunk; + } else { ++ /* ++ * This is guaranteed not to be the last io reference count ++ * because the caller (xfs_buf_iorequest) holds a count itself. ++ */ ++ atomic_dec(&bp->b_io_remaining); + xfs_buf_ioerror(bp, EIO); + bio_put(bio); + } -- 2.47.3