From: Greg Kroah-Hartman Date: Thu, 17 May 2012 02:24:39 +0000 (-0700) Subject: 3.3-stable patches X-Git-Tag: v3.0.32~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4430ee2182303de4cc18eaddb36b4107803fdfa3;p=thirdparty%2Fkernel%2Fstable-queue.git 3.3-stable patches added patches: alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch namespaces-pid_ns-fix-leakage-on-fork-failure.patch usbnet-fix-skb-traversing-races-during-unlink-v2.patch --- diff --git a/queue-3.3/alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch b/queue-3.3/alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch new file mode 100644 index 00000000000..3a5b9370b56 --- /dev/null +++ b/queue-3.3/alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch @@ -0,0 +1,43 @@ +From b0791dda813c179e539b0fc1ecd3f5f30f2571e2 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 15 May 2012 08:07:31 +0200 +Subject: ALSA: hda/idt - Fix power-map for speaker-pins with some HP laptops + +From: Takashi Iwai + +commit b0791dda813c179e539b0fc1ecd3f5f30f2571e2 upstream. + +BIOS on some HP laptops don't set the speaker-pins as fixed but expose +as jacks, and this confuses the driver as if these pins are +jack-detectable. As a result, the machine doesn't get sounds from +speakers because the driver prepares the power-map update via jack +unsol events which never come up in reality. The bug was introduced +in some time in 3.2 for enabling the power-mapping feature. + +This patch fixes the problem by replacing the check of the persistent +power-map bits with a proper is_jack_detectable() call. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43240 + +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_sigmatel.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -4394,9 +4394,9 @@ static int stac92xx_init(struct hda_code + def_conf = get_defcfg_connect(def_conf); + /* skip any ports that don't have jacks since presence + * detection is useless */ +- if (def_conf != AC_JACK_PORT_COMPLEX) { +- if (def_conf != AC_JACK_PORT_NONE) +- stac_toggle_power_map(codec, nid, 1); ++ if (def_conf != AC_JACK_PORT_NONE && ++ !is_jack_detectable(codec, nid)) { ++ stac_toggle_power_map(codec, nid, 1); + continue; + } + if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) { diff --git a/queue-3.3/namespaces-pid_ns-fix-leakage-on-fork-failure.patch b/queue-3.3/namespaces-pid_ns-fix-leakage-on-fork-failure.patch new file mode 100644 index 00000000000..c2b2d9f3bb1 --- /dev/null +++ b/queue-3.3/namespaces-pid_ns-fix-leakage-on-fork-failure.patch @@ -0,0 +1,47 @@ +From 5e2bf0142231194d36fdc9596b36a261ed2b9fe7 Mon Sep 17 00:00:00 2001 +From: Mike Galbraith +Date: Thu, 10 May 2012 13:01:45 -0700 +Subject: namespaces, pid_ns: fix leakage on fork() failure + +From: Mike Galbraith + +commit 5e2bf0142231194d36fdc9596b36a261ed2b9fe7 upstream. + +Fork() failure post namespace creation for a child cloned with +CLONE_NEWPID leaks pid_namespace/mnt_cache due to proc being mounted +during creation, but not unmounted during cleanup. Call +pid_ns_release_proc() during cleanup. + +Signed-off-by: Mike Galbraith +Acked-by: Oleg Nesterov +Reviewed-by: "Eric W. Biederman" +Cc: Pavel Emelyanov +Cc: Cyrill Gorcunov +Cc: Louis Rilling +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/fork.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1438,6 +1439,8 @@ bad_fork_cleanup_io: + if (p->io_context) + exit_io_context(p); + bad_fork_cleanup_namespaces: ++ if (unlikely(clone_flags & CLONE_NEWPID)) ++ pid_ns_release_proc(p->nsproxy->pid_ns); + exit_task_namespaces(p); + bad_fork_cleanup_mm: + if (p->mm) diff --git a/queue-3.3/series b/queue-3.3/series index dfeb6a9f8fe..bcf3b63fa54 100644 --- a/queue-3.3/series +++ b/queue-3.3/series @@ -1,3 +1,6 @@ alsa-echoaudio-remove-incorrect-part-of-assertion.patch alsa-hda-lessen-cpu-usage-when-waiting-for-chip-to-respond.patch alsa-hda-realtek-add-missing-cd-input-pin-for-msi-7350-mobo.patch +alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch +usbnet-fix-skb-traversing-races-during-unlink-v2.patch +namespaces-pid_ns-fix-leakage-on-fork-failure.patch diff --git a/queue-3.3/usbnet-fix-skb-traversing-races-during-unlink-v2.patch b/queue-3.3/usbnet-fix-skb-traversing-races-during-unlink-v2.patch new file mode 100644 index 00000000000..72a176ad84d --- /dev/null +++ b/queue-3.3/usbnet-fix-skb-traversing-races-during-unlink-v2.patch @@ -0,0 +1,218 @@ +From 5b6e9bcdeb65634b4ad604eb4536404bbfc62cfa Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Thu, 26 Apr 2012 11:33:46 +0800 +Subject: usbnet: fix skb traversing races during unlink(v2) + +From: Ming Lei + +commit 5b6e9bcdeb65634b4ad604eb4536404bbfc62cfa upstream. + +Commit 4231d47e6fe69f061f96c98c30eaf9fb4c14b96d(net/usbnet: avoid +recursive locking in usbnet_stop()) fixes the recursive locking +problem by releasing the skb queue lock before unlink, but may +cause skb traversing races: + - after URB is unlinked and the queue lock is released, + the refered skb and skb->next may be moved to done queue, + even be released + - in skb_queue_walk_safe, the next skb is still obtained + by next pointer of the last skb + - so maybe trigger oops or other problems + +This patch extends the usage of entry->state to describe 'start_unlink' +state, so always holding the queue(rx/tx) lock to change the state if +the referd skb is in rx or tx queue because we need to know if the +refered urb has been started unlinking in unlink_urbs. + +The other part of this patch is based on Huajun's patch: +always traverse from head of the tx/rx queue to get skb which is +to be unlinked but not been started unlinking. + +Signed-off-by: Huajun Li +Signed-off-by: Ming Lei +Cc: Oliver Neukum +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/usb/usbnet.c | 54 +++++++++++++++++++++++++++++++-------------- + include/linux/usb/usbnet.h | 3 +- + 2 files changed, 40 insertions(+), 17 deletions(-) + +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -281,17 +281,32 @@ int usbnet_change_mtu (struct net_device + } + EXPORT_SYMBOL_GPL(usbnet_change_mtu); + ++/* The caller must hold list->lock */ ++static void __usbnet_queue_skb(struct sk_buff_head *list, ++ struct sk_buff *newsk, enum skb_state state) ++{ ++ struct skb_data *entry = (struct skb_data *) newsk->cb; ++ ++ __skb_queue_tail(list, newsk); ++ entry->state = state; ++} ++ + /*-------------------------------------------------------------------------*/ + + /* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from + * completion callbacks. 2.5 should have fixed those bugs... + */ + +-static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list) ++static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, ++ struct sk_buff_head *list, enum skb_state state) + { + unsigned long flags; ++ enum skb_state old_state; ++ struct skb_data *entry = (struct skb_data *) skb->cb; + + spin_lock_irqsave(&list->lock, flags); ++ old_state = entry->state; ++ entry->state = state; + __skb_unlink(skb, list); + spin_unlock(&list->lock); + spin_lock(&dev->done.lock); +@@ -299,6 +314,7 @@ static void defer_bh(struct usbnet *dev, + if (dev->done.qlen == 1) + tasklet_schedule(&dev->bh); + spin_unlock_irqrestore(&dev->done.lock, flags); ++ return old_state; + } + + /* some work can't be done in tasklets, so we use keventd +@@ -339,7 +355,6 @@ static int rx_submit (struct usbnet *dev + entry = (struct skb_data *) skb->cb; + entry->urb = urb; + entry->dev = dev; +- entry->state = rx_start; + entry->length = 0; + + usb_fill_bulk_urb (urb, dev->udev, dev->in, +@@ -371,7 +386,7 @@ static int rx_submit (struct usbnet *dev + tasklet_schedule (&dev->bh); + break; + case 0: +- __skb_queue_tail (&dev->rxq, skb); ++ __usbnet_queue_skb(&dev->rxq, skb, rx_start); + } + } else { + netif_dbg(dev, ifdown, dev->net, "rx: stopped\n"); +@@ -422,16 +437,17 @@ static void rx_complete (struct urb *urb + struct skb_data *entry = (struct skb_data *) skb->cb; + struct usbnet *dev = entry->dev; + int urb_status = urb->status; ++ enum skb_state state; + + skb_put (skb, urb->actual_length); +- entry->state = rx_done; ++ state = rx_done; + entry->urb = NULL; + + switch (urb_status) { + /* success */ + case 0: + if (skb->len < dev->net->hard_header_len) { +- entry->state = rx_cleanup; ++ state = rx_cleanup; + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + netif_dbg(dev, rx_err, dev->net, +@@ -470,7 +486,7 @@ static void rx_complete (struct urb *urb + "rx throttle %d\n", urb_status); + } + block: +- entry->state = rx_cleanup; ++ state = rx_cleanup; + entry->urb = urb; + urb = NULL; + break; +@@ -481,17 +497,18 @@ block: + // FALLTHROUGH + + default: +- entry->state = rx_cleanup; ++ state = rx_cleanup; + dev->net->stats.rx_errors++; + netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status); + break; + } + +- defer_bh(dev, skb, &dev->rxq); ++ state = defer_bh(dev, skb, &dev->rxq, state); + + if (urb) { + if (netif_running (dev->net) && +- !test_bit (EVENT_RX_HALT, &dev->flags)) { ++ !test_bit (EVENT_RX_HALT, &dev->flags) && ++ state != unlink_start) { + rx_submit (dev, urb, GFP_ATOMIC); + return; + } +@@ -577,16 +594,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rx + static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) + { + unsigned long flags; +- struct sk_buff *skb, *skbnext; ++ struct sk_buff *skb; + int count = 0; + + spin_lock_irqsave (&q->lock, flags); +- skb_queue_walk_safe(q, skb, skbnext) { ++ while (!skb_queue_empty(q)) { + struct skb_data *entry; + struct urb *urb; + int retval; + +- entry = (struct skb_data *) skb->cb; ++ skb_queue_walk(q, skb) { ++ entry = (struct skb_data *) skb->cb; ++ if (entry->state != unlink_start) ++ goto found; ++ } ++ break; ++found: ++ entry->state = unlink_start; + urb = entry->urb; + + /* +@@ -1037,8 +1061,7 @@ static void tx_complete (struct urb *urb + } + + usb_autopm_put_interface_async(dev->intf); +- entry->state = tx_done; +- defer_bh(dev, skb, &dev->txq); ++ (void) defer_bh(dev, skb, &dev->txq, tx_done); + } + + /*-------------------------------------------------------------------------*/ +@@ -1094,7 +1117,6 @@ netdev_tx_t usbnet_start_xmit (struct sk + entry = (struct skb_data *) skb->cb; + entry->urb = urb; + entry->dev = dev; +- entry->state = tx_start; + entry->length = length; + + usb_fill_bulk_urb (urb, dev->udev, dev->out, +@@ -1153,7 +1175,7 @@ netdev_tx_t usbnet_start_xmit (struct sk + break; + case 0: + net->trans_start = jiffies; +- __skb_queue_tail (&dev->txq, skb); ++ __usbnet_queue_skb(&dev->txq, skb, tx_start); + if (dev->txq.qlen >= TX_QLEN (dev)) + netif_stop_queue (net); + } +--- a/include/linux/usb/usbnet.h ++++ b/include/linux/usb/usbnet.h +@@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usb + enum skb_state { + illegal = 0, + tx_start, tx_done, +- rx_start, rx_done, rx_cleanup ++ rx_start, rx_done, rx_cleanup, ++ unlink_start + }; + + struct skb_data { /* skb->cb is one of these */