From: Greg Kroah-Hartman Date: Mon, 19 Nov 2012 23:31:34 +0000 (-0800) Subject: 3.6-stable patches X-Git-Tag: v3.0.53~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=384ba1c4853348b2af0a26885f464f51fa12df80;p=thirdparty%2Fkernel%2Fstable-queue.git 3.6-stable patches added patches: arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.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 fanotify-fix-missing-break.patch libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.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 pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch pci-pm-resume-device-before-shutdown.patch virtio-don-t-access-index-after-unregister.patch xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch --- diff --git a/queue-3.6/arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch b/queue-3.6/arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch new file mode 100644 index 00000000000..2c47538adfe --- /dev/null +++ b/queue-3.6/arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch @@ -0,0 +1,57 @@ +From 097965ee447e5ccec9776f9b075e64cf7607e5eb Mon Sep 17 00:00:00 2001 +From: Nicolas Royer +Date: Tue, 6 Nov 2012 17:31:03 +0100 +Subject: ARM: at91/AT91SAM9G45: fix crypto peripherals irq issue due to sparse irq support + +From: Nicolas Royer + +commit 097965ee447e5ccec9776f9b075e64cf7607e5eb upstream. + +Spare irq support introduced by commit 8fe82a5 (ARM: at91: sparse irq support) +involves to add the NR_IRQS_LEGACY offset to irq number. + +Signed-off-by: Nicolas Royer +Acked-by: Nicolas Ferre +Acked-by: Eric Bénard +Tested-by: Eric Bénard +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-at91/at91sam9g45_devices.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/arch/arm/mach-at91/at91sam9g45_devices.c ++++ b/arch/arm/mach-at91/at91sam9g45_devices.c +@@ -1847,8 +1847,8 @@ static struct resource sha_resources[] = + .flags = IORESOURCE_MEM, + }, + [1] = { +- .start = AT91SAM9G45_ID_AESTDESSHA, +- .end = AT91SAM9G45_ID_AESTDESSHA, ++ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, ++ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .flags = IORESOURCE_IRQ, + }, + }; +@@ -1880,8 +1880,8 @@ static struct resource tdes_resources[] + .flags = IORESOURCE_MEM, + }, + [1] = { +- .start = AT91SAM9G45_ID_AESTDESSHA, +- .end = AT91SAM9G45_ID_AESTDESSHA, ++ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, ++ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .flags = IORESOURCE_IRQ, + }, + }; +@@ -1916,8 +1916,8 @@ static struct resource aes_resources[] = + .flags = IORESOURCE_MEM, + }, + [1] = { +- .start = AT91SAM9G45_ID_AESTDESSHA, +- .end = AT91SAM9G45_ID_AESTDESSHA, ++ .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, ++ .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .flags = IORESOURCE_IRQ, + }, + }; diff --git a/queue-3.6/cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch b/queue-3.6/cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch new file mode 100644 index 00000000000..45e55f79409 --- /dev/null +++ b/queue-3.6/cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch @@ -0,0 +1,46 @@ +From 3798f47aa276b332c30da499cb4df4577e2f8872 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Mon, 5 Nov 2012 11:39:32 +0000 +Subject: cifs: Do not lookup hashed negative dentry in cifs_atomic_open + +From: Sachin Prabhu + +commit 3798f47aa276b332c30da499cb4df4577e2f8872 upstream. + +We do not need to lookup a hashed negative directory since we have +already revalidated it before and have found it to be fine. + +This also prevents a crash in cifs_lookup() when it attempts to rehash +the already hashed negative lookup dentry. + +The patch has been tested using the reproducer at +https://bugzilla.redhat.com/show_bug.cgi?id=867344#c28 + +Reported-by: Vit Zahradka +Signed-off-by: Sachin Prabhu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/dir.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -392,7 +392,16 @@ cifs_atomic_open(struct inode *inode, st + * in network traffic in the other paths. + */ + if (!(oflags & O_CREAT)) { +- struct dentry *res = cifs_lookup(inode, direntry, 0); ++ struct dentry *res; ++ ++ /* ++ * Check for hashed negative dentry. We have already revalidated ++ * the dentry and it is fine. No need to perform another lookup. ++ */ ++ if (!d_unhashed(direntry)) ++ return -ENOENT; ++ ++ res = cifs_lookup(inode, direntry, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + diff --git a/queue-3.6/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch b/queue-3.6/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch new file mode 100644 index 00000000000..7315eecf90a --- /dev/null +++ b/queue-3.6/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.6/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch b/queue-3.6/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.6/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.6/fanotify-fix-missing-break.patch b/queue-3.6/fanotify-fix-missing-break.patch new file mode 100644 index 00000000000..ff57c4214f8 --- /dev/null +++ b/queue-3.6/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.6/libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch b/queue-3.6/libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch new file mode 100644 index 00000000000..55722fb34cf --- /dev/null +++ b/queue-3.6/libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch @@ -0,0 +1,49 @@ +From 60817a680b1bd3341b6909fab7d8a1fcc3a78369 Mon Sep 17 00:00:00 2001 +From: Aaron Lu +Date: Tue, 9 Oct 2012 15:37:48 +0800 +Subject: libata-acpi: Fix NULL ptr derference in ata_acpi_dev_handle + +From: Aaron Lu + +commit 60817a680b1bd3341b6909fab7d8a1fcc3a78369 upstream. + +commit 6b66d95895c149cbc04d4fac5a2f5477c543a8ae didn't handle SATA PMP +case in ata_acpi_bind_device and will cause a NULL ptr dereference when +user attached a SATA drive to the PMP port. Fix this by checking PMP +support. + +This bug is reported by Dan van der Ster in the following bugzilla page: +https://bugzilla.kernel.org/show_bug.cgi?id=48211 + +Reported-by: Dan van der Ster +Tested-by: Dan van der Ster +Signed-off-by: Aaron Lu +Signed-off-by: Jeff Garzik +Tested-by: Simon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-acpi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/ata/libata-acpi.c ++++ b/drivers/ata/libata-acpi.c +@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct a + struct acpi_device *acpi_dev; + struct acpi_device_power_state *states; + +- if (ap->flags & ATA_FLAG_ACPI_SATA) +- ata_dev = &ap->link.device[sdev->channel]; +- else ++ if (ap->flags & ATA_FLAG_ACPI_SATA) { ++ if (!sata_pmp_attached(ap)) ++ ata_dev = &ap->link.device[sdev->id]; ++ else ++ ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id]; ++ } ++ else { + ata_dev = &ap->link.device[sdev->id]; ++ } + + *handle = ata_dev_acpi_handle(ata_dev); + diff --git a/queue-3.6/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch b/queue-3.6/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch new file mode 100644 index 00000000000..2079fec0fb6 --- /dev/null +++ b/queue-3.6/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 +@@ -1304,6 +1304,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 */ + void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -730,8 +730,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 +@@ -765,7 +765,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 +@@ -648,3 +648,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 +@@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct iee + if (tx->skb) + ieee80211_free_txskb(&tx->local->hw, 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); +@@ -2132,10 +2132,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.6/mac80211-don-t-send-null-data-packet-when-not-associated.patch b/queue-3.6/mac80211-don-t-send-null-data-packet-when-not-associated.patch new file mode 100644 index 00000000000..2f0f49c420d --- /dev/null +++ b/queue-3.6/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 +@@ -1434,6 +1434,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.6/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch b/queue-3.6/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch new file mode 100644 index 00000000000..b8e1ef73ffb --- /dev/null +++ b/queue-3.6/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 +@@ -948,6 +948,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); + +@@ -963,12 +964,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.6/module-fix-out-by-one-error-in-kallsyms.patch b/queue-3.6/module-fix-out-by-one-error-in-kallsyms.patch new file mode 100644 index 00000000000..008739c567f --- /dev/null +++ b/queue-3.6/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.6/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch b/queue-3.6/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch new file mode 100644 index 00000000000..9b2faf31fa9 --- /dev/null +++ b/queue-3.6/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 +@@ -316,10 +316,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.6/pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch b/queue-3.6/pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch new file mode 100644 index 00000000000..ec67650d9da --- /dev/null +++ b/queue-3.6/pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch @@ -0,0 +1,174 @@ +From b3c32c4f9565f93407921c0d8a4458042eb8998e Mon Sep 17 00:00:00 2001 +From: Huang Ying +Date: Thu, 25 Oct 2012 09:36:03 +0800 +Subject: PCI/PM: Fix proc config reg access for D3cold and bridge suspending + +From: Huang Ying + +commit b3c32c4f9565f93407921c0d8a4458042eb8998e upstream. + +In https://bugzilla.kernel.org/show_bug.cgi?id=48981 +Peter reported that /proc/bus/pci/??/??.? does not work for 3.6. +This is because the device configuration space registers are +not accessible if the corresponding parent bridge is suspended or +the device is put into D3cold state. + +This is the same as /sys/bus/pci/devices/0000:??:??.?/config access +issue. So the function used to solve sysfs issue is used to solve +this issue. + +This patch moves pci_config_pm_runtime_get()/_put() from pci/pci-sysfs.c +to pci/pci.c and makes them extern so they can be used by both the +sysfs and proc paths. + +[bhelgaas: changelog, references, reporters] +Reference: https://bugzilla.kernel.org/show_bug.cgi?id=48981 +Reference: https://bugzilla.kernel.org/show_bug.cgi?id=49031 +Reported-by: Forrest Loomis +Reported-by: Peter +Reported-by: Micael Dias +Signed-off-by: Huang Ying +Signed-off-by: Bjorn Helgaas +Acked-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/pci-sysfs.c | 34 ---------------------------------- + drivers/pci/pci.c | 32 ++++++++++++++++++++++++++++++++ + drivers/pci/pci.h | 2 ++ + drivers/pci/proc.c | 8 ++++++++ + 4 files changed, 42 insertions(+), 34 deletions(-) + +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct + } + struct device_attribute vga_attr = __ATTR_RO(boot_vga); + +-static void +-pci_config_pm_runtime_get(struct pci_dev *pdev) +-{ +- struct device *dev = &pdev->dev; +- struct device *parent = dev->parent; +- +- if (parent) +- pm_runtime_get_sync(parent); +- pm_runtime_get_noresume(dev); +- /* +- * pdev->current_state is set to PCI_D3cold during suspending, +- * so wait until suspending completes +- */ +- pm_runtime_barrier(dev); +- /* +- * Only need to resume devices in D3cold, because config +- * registers are still accessible for devices suspended but +- * not in D3cold. +- */ +- if (pdev->current_state == PCI_D3cold) +- pm_runtime_resume(dev); +-} +- +-static void +-pci_config_pm_runtime_put(struct pci_dev *pdev) +-{ +- struct device *dev = &pdev->dev; +- struct device *parent = dev->parent; +- +- pm_runtime_put(dev); +- if (parent) +- pm_runtime_put_sync(parent); +-} +- + static ssize_t + pci_read_config(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -1910,6 +1910,38 @@ bool pci_dev_run_wake(struct pci_dev *de + } + EXPORT_SYMBOL_GPL(pci_dev_run_wake); + ++void pci_config_pm_runtime_get(struct pci_dev *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device *parent = dev->parent; ++ ++ if (parent) ++ pm_runtime_get_sync(parent); ++ pm_runtime_get_noresume(dev); ++ /* ++ * pdev->current_state is set to PCI_D3cold during suspending, ++ * so wait until suspending completes ++ */ ++ pm_runtime_barrier(dev); ++ /* ++ * Only need to resume devices in D3cold, because config ++ * registers are still accessible for devices suspended but ++ * not in D3cold. ++ */ ++ if (pdev->current_state == PCI_D3cold) ++ pm_runtime_resume(dev); ++} ++ ++void pci_config_pm_runtime_put(struct pci_dev *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device *parent = dev->parent; ++ ++ pm_runtime_put(dev); ++ if (parent) ++ pm_runtime_put_sync(parent); ++} ++ + /** + * pci_pm_init - Initialize PM functions of given PCI device + * @dev: PCI device to handle. +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(s + extern int pci_finish_runtime_suspend(struct pci_dev *dev); + extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); + extern void pci_wakeup_bus(struct pci_bus *bus); ++extern void pci_config_pm_runtime_get(struct pci_dev *dev); ++extern void pci_config_pm_runtime_put(struct pci_dev *dev); + extern void pci_pm_init(struct pci_dev *dev); + extern void platform_pci_wakeup_init(struct pci_dev *dev); + extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); +--- a/drivers/pci/proc.c ++++ b/drivers/pci/proc.c +@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, cha + if (!access_ok(VERIFY_WRITE, buf, cnt)) + return -EINVAL; + ++ pci_config_pm_runtime_get(dev); ++ + if ((pos & 1) && cnt) { + unsigned char val; + pci_user_read_config_byte(dev, pos, &val); +@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, cha + cnt--; + } + ++ pci_config_pm_runtime_put(dev); ++ + *ppos = pos; + return nbytes; + } +@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, co + if (!access_ok(VERIFY_READ, buf, cnt)) + return -EINVAL; + ++ pci_config_pm_runtime_get(dev); ++ + if ((pos & 1) && cnt) { + unsigned char val; + __get_user(val, buf); +@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, co + cnt--; + } + ++ pci_config_pm_runtime_put(dev); ++ + *ppos = pos; + i_size_write(ino, dp->size); + return nbytes; diff --git a/queue-3.6/pci-pm-resume-device-before-shutdown.patch b/queue-3.6/pci-pm-resume-device-before-shutdown.patch new file mode 100644 index 00000000000..a7ce170ec62 --- /dev/null +++ b/queue-3.6/pci-pm-resume-device-before-shutdown.patch @@ -0,0 +1,53 @@ +From 3ff2de9ba1a2e22e548979dbcd46e999b22c93d8 Mon Sep 17 00:00:00 2001 +From: Huang Ying +Date: Wed, 24 Oct 2012 14:54:14 +0800 +Subject: PCI/PM: Resume device before shutdown + +From: Huang Ying + +commit 3ff2de9ba1a2e22e548979dbcd46e999b22c93d8 upstream. + +Some actions during shutdown need device to be in D0 state, such as +MSI shutdown etc, so resume device before shutdown. + +Without this patch, a device may not be enumerated after a kexec +because the corresponding bridge is not in D0, so that +configuration space of the device is not accessible. + +Signed-off-by: Huang Ying +Signed-off-by: Bjorn Helgaas +Acked-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/pci-driver.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -421,6 +421,8 @@ static void pci_device_shutdown(struct d + struct pci_dev *pci_dev = to_pci_dev(dev); + struct pci_driver *drv = pci_dev->driver; + ++ pm_runtime_resume(dev); ++ + if (drv && drv->shutdown) + drv->shutdown(pci_dev); + pci_msi_shutdown(pci_dev); +@@ -431,16 +433,6 @@ static void pci_device_shutdown(struct d + * continue to do DMA + */ + pci_disable_device(pci_dev); +- +- /* +- * Devices may be enabled to wake up by runtime PM, but they need not +- * be supposed to wake up the system from its "power off" state (e.g. +- * ACPI S5). Therefore disable wakeup for all devices that aren't +- * supposed to wake up the system at this point. The state argument +- * will be ignored by pci_enable_wake(). +- */ +- if (!device_may_wakeup(dev)) +- pci_enable_wake(pci_dev, PCI_UNKNOWN, false); + } + + #ifdef CONFIG_PM diff --git a/queue-3.6/series b/queue-3.6/series index 32b3a24649b..7d2e724ba8c 100644 --- a/queue-3.6/series +++ b/queue-3.6/series @@ -1 +1,16 @@ mm-bugfix-set-current-reclaim_state-to-null-while-returning-from-kswapd.patch +libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.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 +pci-pm-resume-device-before-shutdown.patch +pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch +fanotify-fix-missing-break.patch +module-fix-out-by-one-error-in-kallsyms.patch +virtio-don-t-access-index-after-unregister.patch +cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch +cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch +crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch +arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch diff --git a/queue-3.6/virtio-don-t-access-index-after-unregister.patch b/queue-3.6/virtio-don-t-access-index-after-unregister.patch new file mode 100644 index 00000000000..03ceac297a8 --- /dev/null +++ b/queue-3.6/virtio-don-t-access-index-after-unregister.patch @@ -0,0 +1,54 @@ +From 237242bddc99041e15a4ca51b8439657cadaff17 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Fri, 9 Nov 2012 14:54:12 +1030 +Subject: virtio: Don't access index after unregister. + +From: Cornelia Huck + +commit 237242bddc99041e15a4ca51b8439657cadaff17 upstream. + +Virtio wants to release used indices after the corresponding +virtio device has been unregistered. However, virtio does not +hold an extra reference, giving up its last reference with +device_unregister(), making accessing dev->index afterwards +invalid. + +I actually saw problems when testing my (not-yet-merged) +virtio-ccw code: + +- device_add virtio-net,id=xxx +-> creates device virtio with n>0 + +- device_del xxx +-> deletes virtio, but calls ida_simple_remove with an + index of 0 + +- device_add virtio-net,id=xxx +-> tries to add virtio0, which is still in use... + +So let's save the index we want to release before calling +device_unregister(). + +Signed-off-by: Cornelia Huck +Acked-by: Sjur Brændeland +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/virtio/virtio.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/virtio/virtio.c ++++ b/drivers/virtio/virtio.c +@@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device + + void unregister_virtio_device(struct virtio_device *dev) + { ++ int index = dev->index; /* save for after device release */ ++ + device_unregister(&dev->dev); +- ida_simple_remove(&virtio_index_ida, dev->index); ++ ida_simple_remove(&virtio_index_ida, index); + } + EXPORT_SYMBOL_GPL(unregister_virtio_device); + diff --git a/queue-3.6/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch b/queue-3.6/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch new file mode 100644 index 00000000000..d404366181b --- /dev/null +++ b/queue-3.6/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 +@@ -1197,9 +1197,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); +@@ -1279,6 +1284,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); + }