2.6.27.23-stable review
Subsystems (20)
cover 2.6.27.23-stable review
This is the start of the stable review cycle for the 2.6.27.23 release. There are 18 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.
These patches are sent out with a number of different people on the Cc:
line. If you wish to be a reviewer, please email [email protected] to add your name to the list. If you want to be off the reviewer list, also email us.
Responses should be made by Friday, May 8, 20:00:00 UTC. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.23-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
Makefile | 2 +- arch/mips/Kconfig | 1 + arch/mips/kernel/linux32.c | 69 ++++++++++++++----------- arch/mips/kernel/scall32-o32.S | 4 +- arch/mips/kernel/scall64-64.S | 2 +- arch/mips/kernel/scall64-n32.S | 28 +++++----- arch/mips/kernel/scall64-o32.S | 40 +++++++------- arch/mips/kernel/signal.c | 5 +- arch/mips/kernel/signal32.c | 28 +++++----- arch/mips/kernel/syscall.c | 26 +++++----- arch/mips/mm/cache.c | 5 +- arch/x86/pci/mmconfig-shared.c | 6 +- drivers/acpi/resources/rscreate.c | 27 +--------- drivers/char/hw_random/virtio-rng.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 6 ++- drivers/net/forcedeth.c | 3 + drivers/net/mv643xx_eth.c | 2 - drivers/net/wireless/b43/dma.c | 50 ++++++++++++++---- drivers/net/wireless/rndis_wlan.c | 14 ++++-- drivers/pci/quirks.c | 1 + drivers/usb/serial/usb-serial.c | 97 ++++++++++++++++++++++++----------- drivers/usb/storage/unusual_devs.h | 6 ++ fs/proc/array.c | 13 +++-- fs/proc/base.c | 5 ++- fs/proc/task_mmu.c | 4 ++ include/drm/drm_pciids.h | 1 + kernel/time/tick-common.c | 12 ++++- mm/madvise.c | 8 +++ scripts/mod/modpost.c | 1 + 29 files changed, 287 insertions(+), 183 deletions(-)
PATCH 1/18 drm/i915: add support for G41 chipset
2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit 72021788678523047161e97b3dfed695e802a5fd upstream.
This had been delayed for some time due to failure to work on the one piece of G41 hardware we had, and lack of success reports from anybody else. Current hardware appears to be OK.
--- drivers/gpu/drm/i915/i915_drv.h | 6 ++++-- include/drm/drm_pciids.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +4 -2
@@ -1115,7 +1115,8 @@ extern int i915_wait_ring(struct drm_dev (dev)->pci_device == 0x2A42 || \ (dev)->pci_device == 0x2E02 || \ (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22) + (dev)->pci_device == 0x2E22 || \ + (dev)->pci_device == 0x2E32)#define IS_I965GM (dev) ((dev)->pci_device == 0x2A02)
@@ -1123,7 +1124,8 @@ extern int i915_wait_ring(struct drm_dev#define IS_G4X (dev) ((dev)->pci_device == 0x2E02 || \ (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22) + (dev)->pci_device == 0x2E22 || \ + (dev)->pci_device == 0x2E32)#define IS_G33 (dev) ((dev)->pci_device == 0x29C2 || \ (dev)->pci_device == 0x29B2 || \
include/drm/drm_pciids.h +1 -0
@@ -412,4 +412,5 @@ {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2e32, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0}
PATCH 11/18 ACPI: Revert conflicting workaround for BIOS w/ mangled PRT entries
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhang Rui <[email protected]>
upstream 82babbb3887e234c995626e4121d411ea9070ca5 backported to apply cleanly to 2.6.27.21 and apply with offset -1 to 2.6.28.9
2f894ef9c8b36a35d80709bedca276d2fc691941
in Linux-2.6.21 worked around BIOS with mangled _PRT entries:
http://bugzilla.kernel.org/show_bug.cgi?id=6859
d0e184abc5983281ef189db2c759d65d56eb1b80
worked around the same issue via ACPICA, and shipped in 2.6.27.
Unfortunately the two workarounds conflict:
http://bugzilla.kernel.org/show_bug.cgi?id=12270
So revert the Linux specific one.
--- drivers/acpi/resources/rscreate.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-)
drivers/acpi/resources/rscreate.c +2 -25
@@ -191,8 +191,6 @@ acpi_rs_create_pci_routing_table(union a user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);for (index =0 ; index < number_of_elements; index++) { -int source_name_index =2 ; -int source_index_index =3 ;/* * Point user_prt past this current structure
@@ -261,27 +259,6 @@ acpi_rs_create_pci_routing_table(union areturn_ACPI_STATUS (AE_BAD_DATA ); } -/* -* If BIOS erroneously reversed the _PRT source_name and source_index, -* then reverse them back. -*/ -if (ACPI_GET_OBJECT_TYPE (sub_object_list[3 ]) != -ACPI_TYPE_INTEGER ) { -if (acpi_gbl_enable_interpreter_slack) { - source_name_index =3 ; - source_index_index =2 ; -printk (KERN_WARNING -"ACPI: Handling Garbled _PRT entry\n" ); - }else { -ACPI_ERROR ((AE_INFO , -"(PRT[%X].source_index) Need Integer, found %s" , - index, -acpi_ut_get_object_type_name - (sub_object_list[3 ]))); -return_ACPI_STATUS (AE_BAD_DATA ); - } - } - user_prt->pin = (u32 ) obj_desc->integer.value;/*
@@ -305,7 +282,7 @@ acpi_rs_create_pci_routing_table(union a* 3) Third subobject: Dereference the PRT.source_name * The name may be unresolved (slack mode), so allow a null object */ - obj_desc = sub_object_list[source_name_index]; + obj_desc = sub_object_list[2 ];if (obj_desc) {switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {case ACPI_TYPE_LOCAL_REFERENCE :
@@ -380,7 +357,7 @@ acpi_rs_create_pci_routing_table(union a/* 4) Fourth subobject: Dereference the PRT.source_index */ - obj_desc = sub_object_list[source_index_index]; + obj_desc = sub_object_list[3 ];if (ACPI_GET_OBJECT_TYPE (obj_desc) !=ACPI_TYPE_INTEGER ) { ACPI_ERROR((AE_INFO, "(PRT[%X].SourceIndex) Need Integer, found %s",
PATCH 2/18 virtio-rng: Remove false BUG for spurious callbacks
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Christian Borntraeger <[email protected]>
upstream commit: e5b89542ea18020961882228c26db3ba87f6e608
The virtio-rng drivers checks for spurious callbacks. Since callbacks can be implemented via shared interrupts (e.g. PCI) this could lead to guest kernel oopses with lots of virtio devices.
--- drivers/char/hw_random/virtio-rng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/hw_random/virtio-rng.c +2 -2
@@ -37,9 +37,9 @@ static void random_recv_done(struct virt {int len; -/* We never get spurious callbacks. */ +/* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ if (!vq->vq_ops->get_buf (vq, &len)) -BUG (); +return ; data_left = len /sizeof (random_data[0 ]);complete (&have_data);
PATCH 3/18 USB: Unusual Device support for Gold MP3 Player Energy
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Chuck Short <[email protected]>
upstream commit: 46c6e93faa85d1362e1d127dc28cf9d0b304a6f1
Reported by Alessio Treglia on
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/125250
User was getting the following errors in dmesg:
[ 2158.139386] sd 5:0:0:1: ioctl_internal_command return code = 8000002 [ 2158.139390] : Current: sense key: No Sense [ 2158.139393] Additional sense: No additional sense information
Adds unusual device support.
modified: drivers/usb/storage/unusual_devs.h
--- drivers/usb/storage/unusual_devs.h | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/storage/unusual_devs.h +6 -0
@@ -2147,6 +2147,12 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_CAPACITY_HEURISTICS), +/* Reported by Alessio Treglia <[email protected]> */ +UNUSUAL_DEV (0xed10 ,0x7636 ,0x0001 ,0x0001 , +"TGE" , +"Digital MP3 Audio Player" , +US_SC_DEVICE ,US_PR_DEVICE ,NULL ,US_FL_NOT_LOCKABLE ), +/* Control/Bulk transport for all SubClass values */ USUAL_DEV (US_SC_RBC ,US_PR_CB ,USB_US_TYPE_STOR ), USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
PATCH 4/18 forcedeth: Fix resume from hibernation regression.
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Ed Swierk <[email protected]>
upstream commit: 35a7433c789ba6df6d96b70fa745ae9e6cac0038
Reset phy state on resume, fixing a regression caused by powering down the phy on hibernate.
--- drivers/net/forcedeth.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/forcedeth.c +3 -0
@@ -5967,6 +5967,9 @@ static int nv_resume(struct pci_dev *pdefor (i =0 ;i <= np->register_size/sizeof (u32); i++)writel (np->saved_config_space[i], base+i*sizeof (u32)); +/* restore phy state, including autoneg */ +phy_init (dev); +netif_device_attach (dev);if (netif_running (dev)) { rc =nv_open (dev);
PATCH 5/18 b43: Poison RX buffers
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Michael Buesch <[email protected]>
upstream commit: ec9a1d8c13e36440eda0f3c79b8149080e3ab5ba
This patch adds poisoning and sanity checking to the RX DMA buffers. This is used for protection against buggy hardware/firmware that raises RX interrupts without doing an actual DMA transfer.
This mechanism protects against rare "bad packets" (due to uninitialized skb data) and rare kernel crashes due to uninitialized RX headers.
The poison is selected to not match on valid frames and to be cheap for checking.
The poison check mechanism _might_ trigger incorrectly, if we are voluntarily receiving frames with bad PLCP headers. However, this is nonfatal, because the chance of such a match is basically zero and in case it happens it just results in dropping the packet.
Bad-PLCP RX defaults to off, and you should leave it off unless you want to listen to the latest news broadcasted by your microwave oven.
This patch also moves the initialization of the RX-header "length" field in front of the mapping of the DMA buffer. The CPU should not touch the buffer after we mapped it.
--- drivers/net/wireless/b43/dma.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-)
drivers/net/wireless/b43/dma.c +33 -4
@@ -551,11 +551,32 @@ address_error:return 1 ; } +static bool b43_rx_buffer_is_poisoned (struct b43_dmaring *ring,struct sk_buff *skb) +{ +unsigned char *f = skb->data + ring->frameoffset; + +return ((f[0 ] & f[1 ] & f[2 ] & f[3 ] & f[4 ] & f[5 ] & f[6 ] & f[7 ]) ==0xFF ); +} + +static void b43_poison_rx_buffer (struct b43_dmaring *ring,struct sk_buff *skb) +{ +struct b43_rxhdr_fw4 *rxhdr; +unsigned char *frame; + +/* This poisons the RX buffer to detect DMA failures. */ + + rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); + rxhdr->frame_len =0 ; + +B43_WARN_ON (ring->rx_buffersize < ring->frameoffset +sizeof (struct b43_plcp_hdr6 ) +2 ); + frame = skb->data + ring->frameoffset; +memset (frame,0xFF ,sizeof (struct b43_plcp_hdr6 ) +2 /* padding */ ); +} +static int setup_rx_descbuffer (struct b43_dmaring *ring,struct b43_dmadesc_generic *desc,struct b43_dmadesc_meta *meta,gfp_t gfp_flags) { -struct b43_rxhdr_fw4 *rxhdr;dma_addr_t dmaaddr;struct sk_buff *skb;
@@ -564,6 +585,7 @@ static int setup_rx_descbuffer(struct b4 skb =__dev_alloc_skb (ring->rx_buffersize, gfp_flags);if (unlikely (!skb))return -ENOMEM ; +b43_poison_rx_buffer (ring, skb); dmaaddr =map_descbuffer (ring, skb->data, ring->rx_buffersize,0 );if (b43_dma_mapping_error (ring, dmaaddr, ring->rx_buffersize,0 )) {/* ugh. try to realloc in zone_dma */
@@ -574,6 +596,7 @@ static int setup_rx_descbuffer(struct b4 skb =__dev_alloc_skb (ring->rx_buffersize, gfp_flags);if (unlikely (!skb))return -ENOMEM ; +b43_poison_rx_buffer (ring, skb); dmaaddr =map_descbuffer (ring, skb->data, ring->rx_buffersize,0 ); }
@@ -589,9 +612,6 @@ static int setup_rx_descbuffer(struct b4 ring->ops->fill_descriptor (ring, desc, dmaaddr, ring->rx_buffersize,0 ,0 ,0 ); - rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); - rxhdr->frame_len =0 ; -return 0 ; }
@@ -1484,6 +1504,15 @@ static void dma_rx(struct b43_dmaring *r goto drop; } } +if (unlikely (b43_rx_buffer_is_poisoned (ring, skb))) { +/* Something went wrong with the DMA. +* The device did not touch the buffer and did not overwrite the poison. */ +b43dbg (ring->dev->wl,"DMA RX: Dropping poisoned buffer.\n" ); +/* recycle the descriptor buffer. */ +sync_descbuffer_for_device (ring, meta->dmaaddr, + ring->rx_buffersize); + goto drop; + }if (unlikely (len > ring->rx_buffersize)) {/* The data did not fit into one descriptor buffer * and is split over multiple buffers.
PATCH 6/18 b43: Refresh RX poison on buffer recycling
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Michael Buesch <[email protected]>
upstream commit: cf68636a9773aa97915497fe54fa4a51e3f08f3a
The RX buffer poison needs to be refreshed, if we recycle an RX buffer, because it might be (partially) overwritten by some DMA operations.
--- drivers/net/wireless/b43/dma.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
drivers/net/wireless/b43/dma.c +11 -10
@@ -1498,20 +1498,16 @@ static void dma_rx(struct b43_dmaring *r len =le16_to_cpu (rxhdr->frame_len); }while (len ==0 && i++ <5 );if (unlikely (len ==0 )) { -/* recycle the descriptor buffer. */ -sync_descbuffer_for_device (ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; + dmaaddr = meta->dmaaddr; + goto drop_recycle_buffer; } }if (unlikely (b43_rx_buffer_is_poisoned (ring, skb))) {/* Something went wrong with the DMA. * The device did not touch the buffer and did not overwrite the poison. */ b43dbg (ring->dev->wl,"DMA RX: Dropping poisoned buffer.\n" ); -/* recycle the descriptor buffer. */ -sync_descbuffer_for_device (ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; + dmaaddr = meta->dmaaddr; + goto drop_recycle_buffer; }if (unlikely (len > ring->rx_buffersize)) {/* The data did not fit into one descriptor buffer
@@ -1525,6 +1521,7 @@ static void dma_rx(struct b43_dmaring *rwhile (1 ) { desc = ops->idx2desc (ring, *slot, &meta);/* recycle the descriptor buffer. */ +b43_poison_rx_buffer (ring, meta->skb);sync_descbuffer_for_device (ring, meta->dmaaddr, ring->rx_buffersize); *slot =next_slot (ring, *slot);
@@ -1543,8 +1540,7 @@ static void dma_rx(struct b43_dmaring *r err =setup_rx_descbuffer (ring, desc, meta,GFP_ATOMIC );if (unlikely (err)) {b43dbg (ring->dev->wl,"DMA RX: setup_rx_descbuffer() failed\n" ); -sync_descbuffer_for_device (ring, dmaaddr, ring->rx_buffersize); - goto drop; + goto drop_recycle_buffer; }unmap_descbuffer (ring, dmaaddr, ring->rx_buffersize,0 );
@@ -1554,6 +1550,11 @@ static void dma_rx(struct b43_dmaring *rb43_rx (ring->dev, skb, rxhdr); drop:return ; + +drop_recycle_buffer: +/* Poison and recycle the RX buffer. */ +b43_poison_rx_buffer (ring, skb); +sync_descbuffer_for_device (ring, dmaaddr, ring->rx_buffersize); }void b43_dma_rx (struct b43_dmaring *ring)
PATCH 7/18 kbuild: fix Module.markers permission error under cygwin
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Cedric Hombourger <[email protected]>
commit 99e3a1eb3c22bb671c6f3d22d8244bfc9fad8185 upstream.
While building the kernel, we end-up calling modpost with -K and -M options for the same file (Modules.markers). This is resulting in modpost's main function calling read_markers() and then write_markers() on the same file.
We then have read_markers() mmap'ing the file, and writer_markers() opening that same file for writing.
The issue is that read_markers() exits without munmap'ing the file and is as a matter holding a reference on Modules.markers. When write_markers() is opening that very same file for writing, we still have a reference on it and cygwin (Windows?) is then making fopen() fail with EPERM.
Calling release_file() before exiting read_markers() clears that reference (and memory leak) and fopen() then succeeds.
Tested on both cygwin (1.3.22) and Linux. Also ran modpost within valgrind on Linux to make sure that the munmap'ed file was not accessed after read_markers()
--- scripts/mod/modpost.c | 1 + 1 file changed, 1 insertion(+)
scripts/mod/modpost.c +1 -0
@@ -1997,6 +1997,7 @@ static void read_markers(const char *fnaif (!mod->skip)add_marker (mod, marker, fmt); } +release_file (file, size);return ; fail:fatal ("parse error in markers list file\n" );
PATCH 8/18 pagemap: require aligned-length, non-null reads of /proc/pid/pagemap
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Vitaly Mayatskikh <[email protected]>
commit 0816178638c15ce5472d39d771a96860dff4141a upstream.
The intention of commit aae8679b0ebcaa92f99c1c3cb0cd651594a43915 ("pagemap: fix bug in add_to_pagemap, require aligned-length reads of /proc/pid/pagemap") was to force reads of /proc/pid/pagemap to be a multiple of 8 bytes, but now it allows to read 0 bytes, which actually puts some data to user's buffer. According to POSIX, if count is zero, read() should return zero and has no other results.
--- fs/proc/task_mmu.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/proc/task_mmu.c +4 -0
@@ -665,6 +665,10 @@ static ssize_t pagemap_read(struct file goto out_task; ret =0 ; + +if (!count) + goto out_task; + mm =get_task_mm (task);if (!mm) goto out_task;
PATCH 9/18 PCI quirk: disable MSI on VIA VT3364 chipsets
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Thomas Renninger <[email protected]>
commit 162dedd39dcc6eca3fc0d29cf19658c6c13b840e upstream.
Without this patch, Broadcom BCM5906 Ethernet controllers set up via MSI cause the machine to hang. Tejun agreed that the best is to blacklist the whole chipset and after adding it, seeing the other VIA quirks disabling MSI, this very much looks like the right way.
--- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+)
drivers/pci/quirks.c +1 -0
@@ -1832,6 +1832,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATDECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_ATI ,PCI_DEVICE_ID_ATI_RS480 , quirk_disable_all_msi);DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_DEVICE_ID_VIA_VT3336 , quirk_disable_all_msi);DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_DEVICE_ID_VIA_VT3351 , quirk_disable_all_msi); +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_VIA ,PCI_DEVICE_ID_VIA_VT3364 , quirk_disable_all_msi);/* Disable MSI on chipsets that are known to not support it */ static void __devinit quirk_disable_msi (struct pci_dev *dev)
PATCH 10/18 x86/PCI: dont call e820_all_mapped with -1 in the mmconfig case
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Yinghai Lu <[email protected]>
commit 044cd80942e47b9de0915b627902adf05c52377f upstream.
e820_all_mapped need end is (addr + size) instead of (addr + size - 1)
--- arch/x86/pci/mmconfig-shared.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/pci/mmconfig-shared.c +3 -3
@@ -255,7 +255,7 @@ static acpi_status __init check_mcfg_resif (!fixmem32)return AE_OK ;if ((mcfg_res->start >= fixmem32->address) && - (mcfg_res->end < (fixmem32->address + + (mcfg_res->end <= (fixmem32->address + fixmem32->address_length))) { mcfg_res->flags =1 ;return AE_CTRL_TERMINATE ;
@@ -272,7 +272,7 @@ static acpi_status __init check_mcfg_resreturn AE_OK ;if ((mcfg_res->start >= address.minimum) && - (mcfg_res->end < (address.minimum + address.address_length))) { + (mcfg_res->end <= (address.minimum + address.address_length))) { mcfg_res->flags =1 ;return AE_CTRL_TERMINATE ; }
@@ -319,7 +319,7 @@ static int __init is_mmconf_reserved(cheu64 old_size = size;int valid =0 ; -while (!is_reserved (addr, addr + size -1 ,E820_RESERVED )) { +while (!is_reserved (addr, addr + size,E820_RESERVED )) { size >>=1 ;if (size < (16UL <<20 ))break ;
PATCH 12/18 MIPS: CVE-2009-0029: Enable syscall wrappers
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: dann frazier <[email protected]>
Backport of upstream commits by:
Ralf Baechle <[email protected]>
Xiaotian Feng <[email protected]>
upstream commits:
dbda6ac0897603f6c6dfadbbc37f9882177ec7ac
d6c178e9694e7e0c7ffe0289cf4389a498cac735
c189846ecf900cd6b3ad7d3cef5b45a746ce646b
--- arch/mips/Kconfig | 1 arch/mips/kernel/linux32.c | 69 +++++++++++++++++++++++------------------ arch/mips/kernel/scall32-o32.S | 4 +- arch/mips/kernel/scall64-64.S | 2 - arch/mips/kernel/scall64-n32.S | 28 ++++++++-------- arch/mips/kernel/scall64-o32.S | 40 +++++++++++------------ arch/mips/kernel/signal.c | 5 +- arch/mips/kernel/signal32.c | 28 ++++++++-------- arch/mips/kernel/syscall.c | 26 +++++++-------- arch/mips/mm/cache.c | 5 +- 10 files changed, 110 insertions(+), 98 deletions(-)
arch/mips/Kconfig +1 -0
@@ -1293,6 +1293,7 @@ config 32BIT config 64BIT bool "64-bit kernel" depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL + select HAVE_SYSCALL_WRAPPERS help Select this option if you want to build a 64-bit kernel.
arch/mips/kernel/linux32.c +39 -30
171 lines not on this page · raw message
arch/mips/kernel/scall32-o32.S +2 -2
@@ -402,7 +402,7 @@ einval: li v0, -EINVAL sys sys_swapon 2 sys sys_reboot 3 sys sys_old_readdir 3 - sys old_mmap 6 /* 4090 */ + sys sys_mips_mmap 6 /* 4090 */ sys sys_munmap 2 sys sys_truncate 2 sys sys_ftruncate 2
@@ -522,7 +522,7 @@ einval: li v0, -EINVAL sys sys_sendfile 4 sys sys_ni_syscall 0 sys sys_ni_syscall 0 - sys sys_mmap2 6 /* 4210 */ + sys sys_mips_mmap2 6 /* 4210 */ sys sys_truncate64 4 sys sys_ftruncate64 4 sys sys_stat64 2
arch/mips/kernel/scall64-64.S +1 -1
@@ -207,7 +207,7 @@ sys_call_table: PTR sys_newlstat PTR sys_poll PTR sys_lseek - PTR old_mmap + PTR sys_mips_mmap PTR sys_mprotect /* 5010 */ PTR sys_munmap PTR sys_brk
arch/mips/kernel/scall64-n32.S +14 -14
@@ -129,12 +129,12 @@ EXPORT(sysn32_call_table) PTR sys_newlstat PTR sys_poll PTR sys_lseek - PTR old_mmap + PTR sys_mips_mmap PTR sys_mprotect /* 6010 */ PTR sys_munmap PTR sys_brk - PTR sys32_rt_sigaction - PTR sys32_rt_sigprocmask + PTR sys_32_rt_sigaction + PTR sys_32_rt_sigprocmask PTR compat_sys_ioctl /* 6015 */ PTR sys_pread64 PTR sys_pwrite64
@@ -159,7 +159,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_setitimer PTR sys_alarm PTR sys_getpid - PTR sys32_sendfile + PTR sys_32_sendfile PTR sys_socket /* 6040 */ PTR sys_connect PTR sys_accept
@@ -181,14 +181,14 @@ EXPORT(sysn32_call_table) PTR sys_exit PTR compat_sys_wait4 PTR sys_kill /* 6060 */ - PTR sys32_newuname + PTR sys_32_newuname PTR sys_semget PTR sys_semop - PTR sysn32_semctl + PTR sys_n32_semctl PTR sys_shmdt /* 6065 */ PTR sys_msgget - PTR sysn32_msgsnd - PTR sysn32_msgrcv + PTR sys_n32_msgsnd + PTR sys_n32_msgrcv PTR compat_sys_msgctl PTR compat_sys_fcntl /* 6070 */ PTR sys_flock
@@ -245,15 +245,15 @@ EXPORT(sysn32_call_table) PTR sys_getsid PTR sys_capget PTR sys_capset - PTR sys32_rt_sigpending /* 6125 */ + PTR sys_32_rt_sigpending /* 6125 */ PTR compat_sys_rt_sigtimedwait - PTR sys32_rt_sigqueueinfo + PTR sys_32_rt_sigqueueinfo PTR sysn32_rt_sigsuspend PTR sys32_sigaltstack PTR compat_sys_utime /* 6130 */ PTR sys_mknod - PTR sys32_personality - PTR sys32_ustat + PTR sys_32_personality + PTR sys_32_ustat PTR compat_sys_statfs PTR compat_sys_fstatfs /* 6135 */ PTR sys_sysfs
@@ -265,14 +265,14 @@ EXPORT(sysn32_call_table) PTR sys_sched_getscheduler PTR sys_sched_get_priority_max PTR sys_sched_get_priority_min - PTR sys32_sched_rr_get_interval /* 6145 */ + PTR sys_32_sched_rr_get_interval /* 6145 */ PTR sys_mlock PTR sys_munlock PTR sys_mlockall PTR sys_munlockall PTR sys_vhangup /* 6150 */ PTR sys_pivot_root - PTR sys32_sysctl + PTR sys_32_sysctl PTR sys_prctl PTR compat_sys_adjtimex PTR compat_sys_setrlimit /* 6155 */
arch/mips/kernel/scall64-o32.S +20 -20
@@ -267,12 +267,12 @@ sys_call_table: PTR sys_olduname PTR sys_umask /* 4060 */ PTR sys_chroot - PTR sys32_ustat + PTR sys_32_ustat PTR sys_dup2 PTR sys_getppid PTR sys_getpgrp /* 4065 */ PTR sys_setsid - PTR sys32_sigaction + PTR sys_32_sigaction PTR sys_sgetmask PTR sys_ssetmask PTR sys_setreuid /* 4070 */
@@ -295,7 +295,7 @@ sys_call_table: PTR sys_swapon PTR sys_reboot PTR compat_sys_old_readdir - PTR old_mmap /* 4090 */ + PTR sys_mips_mmap /* 4090 */ PTR sys_munmap PTR sys_truncate PTR sys_ftruncate
@@ -322,12 +322,12 @@ sys_call_table: PTR compat_sys_wait4 PTR sys_swapoff /* 4115 */ PTR compat_sys_sysinfo - PTR sys32_ipc + PTR sys_32_ipc PTR sys_fsync PTR sys32_sigreturn PTR sys32_clone /* 4120 */ PTR sys_setdomainname - PTR sys32_newuname + PTR sys_32_newuname PTR sys_ni_syscall /* sys_modify_ldt */ PTR compat_sys_adjtimex PTR sys_mprotect /* 4125 */
@@ -341,11 +341,11 @@ sys_call_table: PTR sys_fchdir PTR sys_bdflush PTR sys_sysfs /* 4135 */ - PTR sys32_personality + PTR sys_32_personality PTR sys_ni_syscall /* for afs_syscall */ PTR sys_setfsuid PTR sys_setfsgid - PTR sys32_llseek /* 4140 */ + PTR sys_32_llseek /* 4140 */ PTR compat_sys_getdents PTR compat_sys_select PTR sys_flock
@@ -358,7 +358,7 @@ sys_call_table: PTR sys_ni_syscall /* 4150 */ PTR sys_getsid PTR sys_fdatasync - PTR sys32_sysctl + PTR sys_32_sysctl PTR sys_mlock PTR sys_munlock /* 4155 */ PTR sys_mlockall
@@ -370,7 +370,7 @@ sys_call_table: PTR sys_sched_yield PTR sys_sched_get_priority_max PTR sys_sched_get_priority_min - PTR sys32_sched_rr_get_interval /* 4165 */ + PTR sys_32_sched_rr_get_interval /* 4165 */ PTR compat_sys_nanosleep PTR sys_mremap PTR sys_accept
@@ -399,25 +399,25 @@ sys_call_table: PTR sys_getresgid PTR sys_prctl PTR sys32_rt_sigreturn - PTR sys32_rt_sigaction - PTR sys32_rt_sigprocmask /* 4195 */ - PTR sys32_rt_sigpending + PTR sys_32_rt_sigaction + PTR sys_32_rt_sigprocmask /* 4195 */ + PTR sys_32_rt_sigpending PTR compat_sys_rt_sigtimedwait - PTR sys32_rt_sigqueueinfo + PTR sys_32_rt_sigqueueinfo PTR sys32_rt_sigsuspend - PTR sys32_pread /* 4200 */ - PTR sys32_pwrite + PTR sys_32_pread /* 4200 */ + PTR sys_32_pwrite PTR sys_chown PTR sys_getcwd PTR sys_capget PTR sys_capset /* 4205 */ PTR sys32_sigaltstack - PTR sys32_sendfile + PTR sys_32_sendfile PTR sys_ni_syscall PTR sys_ni_syscall - PTR sys32_mmap2 /* 4210 */ - PTR sys32_truncate64 - PTR sys32_ftruncate64 + PTR sys_mips_mmap2 /* 4210 */ + PTR sys_32_truncate64 + PTR sys_32_ftruncate64 PTR sys_newstat PTR sys_newlstat PTR sys_newfstat /* 4215 */
@@ -483,7 +483,7 @@ sys_call_table: PTR compat_sys_mq_notify /* 4275 */ PTR compat_sys_mq_getsetattr PTR sys_ni_syscall /* sys_vserver */ - PTR sys32_waitid + PTR sys_32_waitid PTR sys_ni_syscall /* available, was setaltroot */ PTR sys_add_key /* 4280 */ PTR sys_request_key
arch/mips/kernel/signal32.c +14 -14
@@ -349,8 +349,8 @@ asmlinkage int sys32_rt_sigsuspend(nabi_return -ERESTARTNOHAND ; } -asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act, -struct sigaction32 __user *oact) +SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act, + struct sigaction32 __user *, oact) {struct k_sigaction new_ka, old_ka;int ret;
@@ -692,9 +692,9 @@ struct mips_abi mips_abi_32 = { .restart = __NR_O32_restart_syscall }; -asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, -struct sigaction32 __user *oact, -unsigned int sigsetsize) +SYSCALL_DEFINE4(32_rt_sigaction, int, sig, + const struct sigaction32 __user *, act, + struct sigaction32 __user *, oact, unsigned int, sigsetsize) {struct k_sigaction new_sa, old_sa;int ret = -EINVAL ;
@@ -736,8 +736,8 @@ out:return ret; } -asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, -compat_sigset_t __user *oset,unsigned int sigsetsize) +SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set, + compat_sigset_t __user *, oset, unsigned int, sigsetsize) {sigset_t old_set, new_set;int ret;
@@ -758,8 +758,8 @@ asmlinkage int sys32_rt_sigprocmask(intreturn ret; } -asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset, -unsigned int sigsetsize) +SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset, + unsigned int, sigsetsize) {int ret;sigset_t set;
@@ -775,7 +775,8 @@ asmlinkage int sys32_rt_sigpending(compareturn ret; } -asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) +SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig, + compat_siginfo_t __user *, uinfo) {siginfo_t info;int ret;
@@ -790,10 +791,9 @@ asmlinkage int sys32_rt_sigqueueinfo(intreturn ret; } -asmlinkage long -sys32_waitid (int which,compat_pid_t pid, -compat_siginfo_t __user *uinfo,int options, -struct compat_rusage __user *uru) +SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid, + compat_siginfo_t __user *, uinfo, int, options, + struct compat_rusage __user *, uru) {siginfo_t info;struct rusage ru;
arch/mips/kernel/signal.c +3 -2
@@ -19,6 +19,7 @@#include <linux/ptrace.h> #include <linux/unistd.h> #include <linux/compiler.h> +#include <linux/syscalls.h> #include <linux/uaccess.h> #include <asm/abi.h>
@@ -338,8 +339,8 @@ asmlinkage int sys_rt_sigsuspend(nabi_no }#ifdef CONFIG_TRAD_SIGNALS -asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act, -struct sigaction __user *oact) +SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act, + struct sigaction __user *, oact) {struct k_sigaction new_ka, old_ka;int ret;
arch/mips/kernel/syscall.c +13 -13
@@ -153,9 +153,9 @@ out:return error; } -asmlinkage unsigned long -old_mmap (unsigned long addr,unsigned long len,int prot, -int flags,int fd,off_t offset) +SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, unsigned long, + fd, off_t, offset) {unsigned long result;
@@ -169,9 +169,9 @@ out:return result; } -asmlinkage unsigned long -sys_mmap2 (unsigned long addr,unsigned long len,unsigned long prot, -unsigned long flags,unsigned long fd,unsigned long pgoff) +SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, unsigned long, fd, + unsigned long, pgoff) {if (pgoff & (~PAGE_MASK >>12 ))return -EINVAL ;
@@ -241,7 +241,7 @@ out:/* * Compacrapability ... */ -asmlinkage int sys_uname(struct old_utsname __user * name) +SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) {if (name && !copy_to_user (name,utsname (),sizeof (*name)))return 0 ;
@@ -251,7 +251,7 @@ asmlinkage int sys_uname(struct old_utsn/* * Compacrapability ... */ -asmlinkage int sys_olduname(struct oldold_utsname __user * name) +SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name) {int error;
@@ -280,7 +280,7 @@ asmlinkage int sys_olduname(struct oldolreturn error; } -asmlinkage int sys_set_thread_area(unsigned long addr) +SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) {struct thread_info *ti =task_thread_info (current);
@@ -291,7 +291,7 @@ asmlinkage int sys_set_thread_area(unsigreturn 0 ; } -asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) +asmlinkage int _sys_sysmips(long cmd, long arg1, long arg2, long arg3) {switch (cmd) {case MIPS_ATOMIC_SET :
@@ -326,8 +326,8 @@ asmlinkage int _sys_sysmips(int cmd, lon* * This is really horribly ugly. */ -asmlinkage int sys_ipc(unsigned int call, int first, int second, -unsigned long third,void __user *ptr,long fifth) +SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second, + unsigned long, third, void __user *, ptr, long, fifth) {int version, ret;
@@ -412,7 +412,7 @@ asmlinkage int sys_ipc(unsigned int call/* * No implemented yet ... */ -asmlinkage int sys_cachectl(char *addr, int nbytes, int op) +SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) {return -ENOSYS ; }
arch/mips/mm/cache.c +3 -2
@@ -13,6 +13,7 @@#include <linux/linkage.h> #include <linux/module.h> #include <linux/sched.h> +#include <linux/syscalls.h> #include <linux/mm.h> #include <asm/cacheflush.h>
@@ -58,8 +59,8 @@ EXPORT_SYMBOL(_dma_cache_wback_inv);* We could optimize the case where the cache argument is not BCACHE but * that seems very atypical use ... */ -asmlinkage int sys_cacheflush(unsigned long addr, -unsigned long bytes,unsigned int cache) +SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, + unsigned int, cache) {if (bytes ==0 )return 0 ;
PATCH 13/18 USB: serial: fix lifetime and locking problems
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
This is commit 2d93148ab6988cad872e65d694c95e8944e1b626 back-ported to 2.6.27.
This patch (as1229-1) fixes a few lifetime and locking problems in the usb-serial driver. The main symptom is that an invalid kevent is created when the serial device is unplugged while a connection is active.
Ports should be unregistered when device is disconnected, not when the parent usb_serial structure is deallocated.
Each open file should hold a reference to the corresponding port structure, and the reference should be released when the file is closed.
serial->disc_mutex should be acquired in serial_open(), to resolve the classic race between open and disconnect.
serial_close() doesn't need to hold both serial->disc_mutex and port->mutex at the same time.
Release the subdriver's module reference only after releasing all the other references, in case one of the release routines needs to invoke some code in the subdriver module.
Replace a call to flush_scheduled_work() (which is prone to deadlocks) with cancel_work_sync(). Also, add a call to cancel_work_sync() in the disconnect routine.
Reduce the scope of serial->disc_mutex in serial_disconnect(). The only place it really needs to protect is where the "disconnected" flag is set.
Call the shutdown method from within serial_disconnect() instead of destroy_serial(), because some subdrivers expect the port data structures still to be in existence when their shutdown method runs.
This fixes the bug reported in
http://bugs.freedesktop.org/show_bug.cgi?id=20703
--- drivers/usb/serial/usb-serial.c | 97 +++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 30 deletions(-)
drivers/usb/serial/usb-serial.c +67 -30
@@ -136,22 +136,10 @@ static void destroy_serial(struct kref *dbg ("%s - %s" , __func__, serial->type->description); - serial->type->shutdown (serial); -/* return the minor range that this device had */ if (serial->minor !=SERIAL_TTY_NO_MINOR )return_serial (serial); -for (i =0 ; i < serial->num_ports; ++i) - serial->port[i]->port.count =0 ; - -/* the ports are cleaned up and released in port_release() */ -for (i =0 ; i < serial->num_ports; ++i) -if (serial->port[i]->dev.parent !=NULL ) { -device_unregister (&serial->port[i]->dev); - serial->port[i] =NULL ; - } -/* If this is a "fake" port, we have to clean it up here, as it will * not get cleaned up in port_release() as it was never registered with * the driver core */
@@ -186,7 +174,7 @@ static int serial_open (struct tty_strucstruct usb_serial *serial;struct usb_serial_port *port;unsigned int portNumber; -int retval; +int retval =0 ;dbg ("%s" , __func__);
@@ -197,16 +185,24 @@ static int serial_open (struct tty_strucreturn -ENODEV ; } +mutex_lock (&serial->disc_mutex); portNumber = tty->index - serial->minor; port = serial->port[portNumber]; -if (!port) { +if (!port || serial->disconnected) retval = -ENODEV ; - goto bailout_kref_put; - } +else +get_device (&port->dev); +/* +* Note: Our locking order requirement does not allow port->mutex +* to be acquired while serial->disc_mutex is held. +*/ +mutex_unlock (&serial->disc_mutex); +if (retval) + goto bailout_serial_put;if (mutex_lock_interruptible (&port->mutex)) { retval = -ERESTARTSYS ; - goto bailout_kref_put; + goto bailout_port_put; } ++port->port.count;
@@ -226,14 +222,20 @@ static int serial_open (struct tty_struc goto bailout_mutex_unlock; } - retval =usb_autopm_get_interface (serial->interface); +mutex_lock (&serial->disc_mutex); +if (serial->disconnected) + retval = -ENODEV ; +else + retval =usb_autopm_get_interface (serial->interface);if (retval) goto bailout_module_put; +/* only call the device specific open if this * is the first time the port is opened */ retval = serial->type->open (tty, port, filp);if (retval) goto bailout_interface_put; +mutex_unlock (&serial->disc_mutex); }mutex_unlock (&port->mutex);
@@ -242,13 +244,16 @@ static int serial_open (struct tty_struc bailout_interface_put:usb_autopm_put_interface (serial->interface); bailout_module_put: +mutex_unlock (&serial->disc_mutex);module_put (serial->type->driver.owner); bailout_mutex_unlock: port->port.count =0 ; tty->driver_data =NULL ; port->port.tty =NULL ;mutex_unlock (&port->mutex); -bailout_kref_put: +bailout_port_put: +put_device (&port->dev); +bailout_serial_put:usb_serial_put (serial);return retval; }
@@ -256,6 +261,9 @@ bailout_kref_put:static void serial_close (struct tty_struct *tty,struct file *filp) {struct usb_serial_port *port = tty->driver_data; +struct usb_serial *serial; +struct module *owner; +int count;if (!port)return ;
@@ -263,6 +271,8 @@ static void serial_close(struct tty_strudbg ("%s - port %d" , __func__, port->number);mutex_lock (&port->mutex); + serial = port->serial; + owner = serial->type->driver.owner;if (port->port.count ==0 ) {mutex_unlock (&port->mutex);
@@ -273,7 +283,7 @@ static void serial_close(struct tty_struif (port->port.count ==0 )/* only call the device specific close if this * port is being closed by the last owner */ - port->serial->type->close (tty, port, filp); + serial->type->close (tty, port, filp);if (port->port.count == (port->console?1 :0 )) {if (port->port.tty) {
@@ -283,16 +293,22 @@ static void serial_close(struct tty_stru } } -if (port->port.count ==0 ) { -mutex_lock (&port->serial->disc_mutex); -if (!port->serial->disconnected) -usb_autopm_put_interface (port->serial->interface); -mutex_unlock (&port->serial->disc_mutex); -module_put (port->serial->type->driver.owner); + count = port->port.count; +mutex_unlock (&port->mutex); +put_device (&port->dev); + +/* Mustn't dereference port any more */ +if (count ==0 ) { +mutex_lock (&serial->disc_mutex); +if (!serial->disconnected) +usb_autopm_put_interface (serial->interface); +mutex_unlock (&serial->disc_mutex); } +usb_serial_put (serial); -mutex_unlock (&port->mutex); -usb_serial_put (port->serial); +/* Mustn't dereference serial any more */ +if (count ==0 ) +module_put (owner); } static int serial_write(struct tty_struct *tty, const unsigned char *buf,
@@ -544,7 +560,13 @@ static void kill_traffic(struct usb_seristatic void port_free (struct usb_serial_port *port) { +/* +* Stop all the traffic before cancelling the work, so that +* nobody will restart it by calling usb_serial_port_softint. +*/ kill_traffic (port); +cancel_work_sync (&port->work); +usb_free_urb (port->read_urb);usb_free_urb (port->write_urb);usb_free_urb (port->interrupt_in_urb);
@@ -553,7 +575,6 @@ static void port_free(struct usb_serial_kfree (port->bulk_out_buffer);kfree (port->interrupt_in_buffer);kfree (port->interrupt_out_buffer); -flush_scheduled_work ();/* port->work */ kfree (port); }
@@ -1037,17 +1058,33 @@ void usb_serial_disconnect(struct usb_inusb_set_intfdata (interface,NULL );/* must set a flag, to signal subdrivers */ serial->disconnected =1 ; +mutex_unlock (&serial->disc_mutex); + +/* Unfortunately, many of the sub-drivers expect the port structures +* to exist when their shutdown method is called, so we have to go +* through this awkward two-step unregistration procedure. +*/ for (i =0 ; i < serial->num_ports; ++i) { port = serial->port[i];if (port) {if (port->port.tty)tty_hangup (port->port.tty);kill_traffic (port); +cancel_work_sync (&port->work); +device_del (&port->dev); } } + serial->type->shutdown (serial); +for (i =0 ; i < serial->num_ports; ++i) { + port = serial->port[i]; +if (port) { +put_device (&port->dev); + serial->port[i] =NULL ; + } + } +/* let the last holder of this object * cause it to be cleaned up */ -mutex_unlock (&serial->disc_mutex);usb_serial_put (serial);dev_info (dev,"device disconnected\n" ); }
PATCH 14/18 clockevents: prevent endless loop in tick_handle_periodic()
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: john stultz <[email protected]>
commit 74a03b69d1b5ce00a568e142ca97e76b7f5239c6 upstream.
tick_handle_periodic() can lock up hard when a one shot clock event device is used in combination with jiffies clocksource.
Avoid an endless loop issue by requiring that a highres valid clocksource be installed before we call tick_periodic() in a loop when using ONESHOT mode. The result is we will only increment jiffies once per interrupt until a continuous hardware clocksource is available.
Without this, we can run into a endless loop, where each cycle through the loop, jiffies is updated which increments time by tick_period or more (due to clock steering), which can cause the event programming to think the next event was before the newly incremented time and fail causing tick_periodic() to be called again and the whole process loops forever.
[ Impact: prevent hard lock up ]
--- kernel/time/tick-common.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
kernel/time/tick-common.c +11 -1
@@ -93,7 +93,17 @@ void tick_handle_periodic(struct clock_efor (;;) {if (!clockevents_program_event (dev, next,ktime_get ()))return ; -tick_periodic (cpu); +/* +* Have to be careful here. If we're in oneshot mode, +* before we call tick_periodic() in a loop, we need +* to be sure we're using a real hardware clocksource. +* Otherwise we could get trapped in an infinite +* loop, as the tick_periodic() increments jiffies, +* when then will increment time, posibly causing +* the loop to trigger again and again. +*/ +if (timekeeping_valid_for_hres ()) +tick_periodic (cpu); next =ktime_add (next, tick_period); } }
PATCH 15/18 Ignore madvise(MADV_WILLNEED) for hugetlbfs-backed regions
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Mel Gorman <[email protected]>
commit a425a638c858fd10370b573bde81df3ba500e271 upstream.
madvise(MADV_WILLNEED) forces page cache readahead on a range of memory backed by a file. The assumption is made that the page required is order-0 and "normal" page cache.
On hugetlbfs, this assumption is not true and order-0 pages are allocated and inserted into the hugetlbfs page cache. This leaks hugetlbfs page reservations and can cause BUGs to trigger related to corrupted page tables.
This patch causes MADV_WILLNEED to be ignored for hugetlbfs-backed regions.
--- mm/madvise.c | 8 ++++++++ 1 file changed, 8 insertions(+)
mm/madvise.c +8 -0
@@ -112,6 +112,14 @@ static long madvise_willneed(struct vm_aif (!file)return -EBADF ; +/* +* Page cache readahead assumes page cache pages are order-0 which +* is not the case for hugetlbfs. Do not give a bad return value +* but ignore the advice. +*/ +if (vma->vm_flags &VM_HUGETLB ) +return 0 ; +if (file->f_mapping->a_ops->get_xip_mem) {/* no bad return value, but ignore advice */ return 0 ;
PATCH 16/18 mv643xx_eth: 64bit mib counter read fix
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Lennert Buytenhek <[email protected]>
commit 93af7aca44f0e82e67bda10a0fb73d383edcc8bd upstream.
On several mv643xx_eth hardware versions, the two 64bit mib counters for 'good octets received' and 'good octets sent' are actually 32bit counters, and reading from the upper half of the register has the same effect as reading from the lower half of the register: an atomic read-and-clear of the entire 32bit counter value. This can under heavy traffic occasionally lead to small numbers being added to the upper half of the 64bit mib counter even though no 32bit wrap has occured.
Since we poll the mib counters at least every 30 seconds anyway, we might as well just skip the reads of the upper halves of the hardware counters without breaking the stats, which this patch does.
--- drivers/net/mv643xx_eth.c | 2 -- 1 file changed, 2 deletions(-)
drivers/net/mv643xx_eth.c +0 -2
@@ -1060,7 +1060,6 @@ static void mib_counters_update(struct mstruct mib_counters *p = &mp->mib_counters; p->good_octets_received +=mib_read (mp,0x00 ); - p->good_octets_received += (u64 )mib_read (mp,0x04 ) <<32 ; p->bad_octets_received +=mib_read (mp,0x08 ); p->internal_mac_transmit_err +=mib_read (mp,0x0c ); p->good_frames_received +=mib_read (mp,0x10 );
@@ -1074,7 +1073,6 @@ static void mib_counters_update(struct m p->frames_512_to_1023_octets +=mib_read (mp,0x30 ); p->frames_1024_to_max_octets +=mib_read (mp,0x34 ); p->good_octets_sent +=mib_read (mp,0x38 ); - p->good_octets_sent += (u64 )mib_read (mp,0x3c ) <<32 ; p->good_frames_sent +=mib_read (mp,0x40 ); p->excessive_collision +=mib_read (mp,0x44 ); p->multicast_frames_sent +=mib_read (mp,0x48 );
PATCH 17/18 proc: avoid information leaks to non-privileged processes
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jake Edge <[email protected]>
commit f83ce3e6b02d5e48b3a43b001390e2b58820389d upstream.
By using the same test as is used for /proc/pid/maps and /proc/pid/smaps, only allow processes that can ptrace() a given process to see information that might be used to bypass address space layout randomization (ASLR). These include eip, esp, wchan, and start_stack in /proc/pid/stat as well as the non-symbolic output from /proc/pid/wchan.
ASLR can be bypassed by sampling eip as shown by the proof-of-concept code at http://code.google.com/p/fuzzyaslr/ As part of a presentation
(http://www.cr0.org/paper/to-jt-linux-alsr-leak.pdf) esp and wchan were also noted as possibly usable information leaks as well. The start_stack address also leaks potentially useful information.
--- fs/proc/array.c | 13 +++++++++---- fs/proc/base.c | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-)
fs/proc/array.c +9 -4
@@ -80,6 +80,7 @@#include <linux/delayacct.h> #include <linux/seq_file.h> #include <linux/pid_namespace.h> +#include <linux/ptrace.h> #include <linux/tracehook.h> #include <asm/pgtable.h>
@@ -347,6 +348,7 @@ static int do_task_stat(struct seq_filechar state;pid_t ppid =0 , pgid =-1 , sid =-1 ;int num_threads =0 ; +int permitted;struct mm_struct *mm;unsigned long long start_time;unsigned long cmin_flt =0 , cmaj_flt =0 ;
@@ -359,11 +361,14 @@ static int do_task_stat(struct seq_file state = *get_task_state (task); vsize = eip = esp =0 ; + permitted =ptrace_may_access (task,PTRACE_MODE_READ ); mm =get_task_mm (task);if (mm) { vsize =task_vsize (mm); - eip =KSTK_EIP (task); - esp =KSTK_ESP (task); +if (permitted) { + eip =KSTK_EIP (task); + esp =KSTK_ESP (task); + } }get_task_comm (tcomm, task);
@@ -419,7 +424,7 @@ static int do_task_stat(struct seq_fileunlock_task_sighand (task, &flags); } -if (!whole || num_threads <2 ) +if (permitted && (!whole || num_threads <2 )) wchan =get_wchan (task);if (!whole) { min_flt = task->min_flt;
@@ -471,7 +476,7 @@ static int do_task_stat(struct seq_file rsslim, mm ? mm->start_code :0 , mm ? mm->end_code :0 , - mm ? mm->start_stack :0 , + (permitted && mm) ? mm->start_stack :0 , esp, eip,/* The signal information here is obsolete.
fs/proc/base.c +4 -1
@@ -327,7 +327,10 @@ static int proc_pid_wchan(struct task_st wchan =get_wchan (task);if (lookup_symbol_name (wchan, symname) <0 ) -return sprintf (buffer,"%lu" , wchan); +if (!ptrace_may_access (task,PTRACE_MODE_READ )) +return 0 ; +else +return sprintf (buffer,"%lu" , wchan);else return sprintf (buffer,"%s" , symname); }
PATCH 18/18 rndis_wlan: fix initialization order for workqueue&workers
In reply to Greg KH2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jussi Kivilinna <[email protected]>
commit e805e4d0b53506dff4255a2792483f094e7fcd2c upstream.
rndis_wext_link_change() might be called from rndis_command() at initialization stage and priv->workqueue/priv->work have not been initialized yet. This causes invalid opcode at rndis_wext_bind on some brands of bcm4320.
Fix by initializing workqueue/workers in rndis_wext_bind() before rndis_command is used.
This bug has existed since 2.6.25, reported at:
http://bugzilla.kernel.org/show_bug.cgi?id=12794
--- drivers/net/wireless/rndis_wlan.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/net/wireless/rndis_wlan.c +10 -4
@@ -2556,6 +2556,11 @@ static int rndis_wext_bind(struct usbnetmutex_init (&priv->command_lock);spin_lock_init (&priv->stats_lock); +/* because rndis_command() sleeps we need to use workqueue */ + priv->workqueue =create_singlethread_workqueue ("rndis_wlan" ); +INIT_WORK (&priv->work, rndis_wext_worker); +INIT_DELAYED_WORK (&priv->stats_work, rndis_update_wireless_stats); +/* try bind rndis_host */ retval =generic_rndis_bind (usbdev, intf,FLAG_RNDIS_PHYM_WIRELESS );if (retval <0 )
@@ -2600,16 +2605,17 @@ static int rndis_wext_bind(struct usbnetdisassociate (usbdev,1 );netif_carrier_off (usbdev->net); -/* because rndis_command() sleeps we need to use workqueue */ - priv->workqueue =create_singlethread_workqueue ("rndis_wlan" ); -INIT_DELAYED_WORK (&priv->stats_work, rndis_update_wireless_stats);queue_delayed_work (priv->workqueue, &priv->stats_work,round_jiffies_relative (STATS_UPDATE_JIFFIES )); -INIT_WORK (&priv->work, rndis_wext_worker);return 0 ; fail: +cancel_delayed_work_sync (&priv->stats_work); +cancel_work_sync (&priv->work); +flush_workqueue (priv->workqueue); +destroy_workqueue (priv->workqueue); +kfree (priv);return retval; }