From: Greg Kroah-Hartman Date: Mon, 4 May 2009 23:08:50 +0000 (-0700) Subject: .29 patches X-Git-Tag: v2.6.27.23~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=880441c99a3b1d61cefdccd7b8b5822cadac9248;p=thirdparty%2Fkernel%2Fstable-queue.git .29 patches --- diff --git a/queue-2.6.29/acpi-revert-conflicting-workaround-for-bios-w-mangled-prt-entries.patch b/queue-2.6.29/acpi-revert-conflicting-workaround-for-bios-w-mangled-prt-entries.patch new file mode 100644 index 00000000000..7b4ec1cf435 --- /dev/null +++ b/queue-2.6.29/acpi-revert-conflicting-workaround-for-bios-w-mangled-prt-entries.patch @@ -0,0 +1,91 @@ +From lenb@kernel.org Mon May 4 16:01:55 2009 +From: Zhang Rui +Date: Fri, 01 May 2009 11:12:41 -0400 (EDT) +Subject: ACPI: Revert conflicting workaround for BIOS w/ mangled PRT entries +To: stable@kernel.org +Cc: linux-acpi@vger.kernel.org, tmb@mandriva.org +Message-ID: + + +From: Zhang Rui + +upstream 82babbb3887e234c995626e4121d411ea9070ca5 +backported to 2.6.29.2 + +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. + +Signed-off-by: Zhang Rui +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/acpica/rscreate.c | 27 ++------------------------- + 1 file changed, 2 insertions(+), 25 deletions(-) + +--- a/drivers/acpi/acpica/rscreate.c ++++ b/drivers/acpi/acpica/rscreate.c +@@ -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 a + return_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: +@@ -379,7 +356,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", diff --git a/queue-2.6.29/powerpc-sanitize-stack-pointer-in-signal-handling-code.patch b/queue-2.6.29/powerpc-sanitize-stack-pointer-in-signal-handling-code.patch new file mode 100644 index 00000000000..0dae4cec292 --- /dev/null +++ b/queue-2.6.29/powerpc-sanitize-stack-pointer-in-signal-handling-code.patch @@ -0,0 +1,126 @@ +From jwboyer@linux.vnet.ibm.com Mon May 4 16:02:51 2009 +From: Josh Boyer +Date: Tue, 28 Apr 2009 11:15:59 -0400 +Subject: powerpc: Sanitize stack pointer in signal handling code +To: stable@kernel.org +Cc: benh@kernel.crashing.org +Message-ID: <20090428151559.GC5281@yoda.jdub.homelinux.org> +Content-Disposition: inline + +From: Josh Boyer + +This has been backported to 2.6.29.x from commit efbda86098 in Linus' tree + +On powerpc64 machines running 32-bit userspace, we can get garbage bits in the +stack pointer passed into the kernel. Most places handle this correctly, but +the signal handling code uses the passed value directly for allocating signal +stack frames. + +This fixes the issue by introducing a get_clean_sp function that returns a +sanitized stack pointer. For 32-bit tasks on a 64-bit kernel, the stack +pointer is masked correctly. In all other cases, the stack pointer is simply +returned. + +Additionally, we pass an 'is_32' parameter to get_sigframe now in order to +get the properly sanitized stack. The callers are know to be 32 or 64-bit +statically. + +Signed-off-by: Josh Boyer +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/include/asm/processor.h | 19 +++++++++++++++++++ + arch/powerpc/kernel/signal.c | 4 ++-- + arch/powerpc/kernel/signal.h | 2 +- + arch/powerpc/kernel/signal_32.c | 4 ++-- + arch/powerpc/kernel/signal_64.c | 2 +- + 5 files changed, 25 insertions(+), 6 deletions(-) + +--- a/arch/powerpc/include/asm/processor.h ++++ b/arch/powerpc/include/asm/processor.h +@@ -313,6 +313,25 @@ static inline void prefetchw(const void + #define HAVE_ARCH_PICK_MMAP_LAYOUT + #endif + ++#ifdef CONFIG_PPC64 ++static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32) ++{ ++ unsigned long sp; ++ ++ if (is_32) ++ sp = regs->gpr[1] & 0x0ffffffffUL; ++ else ++ sp = regs->gpr[1]; ++ ++ return sp; ++} ++#else ++static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32) ++{ ++ return regs->gpr[1]; ++} ++#endif ++ + #endif /* __KERNEL__ */ + #endif /* __ASSEMBLY__ */ + #endif /* _ASM_POWERPC_PROCESSOR_H */ +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -836,7 +836,7 @@ int handle_rt_signal32(unsigned long sig + + /* Set up Signal Frame */ + /* Put a Real Time Context onto stack */ +- rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); ++ rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1); + addr = rt_sf; + if (unlikely(rt_sf == NULL)) + goto badframe; +@@ -1182,7 +1182,7 @@ int handle_signal32(unsigned long sig, s + unsigned long newsp = 0; + + /* Set up Signal Frame */ +- frame = get_sigframe(ka, regs, sizeof(*frame)); ++ frame = get_sigframe(ka, regs, sizeof(*frame), 1); + if (unlikely(frame == NULL)) + goto badframe; + sc = (struct sigcontext __user *) &frame->sctx; +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -402,7 +402,7 @@ int handle_rt_signal64(int signr, struct + unsigned long newsp = 0; + long err = 0; + +- frame = get_sigframe(ka, regs, sizeof(*frame)); ++ frame = get_sigframe(ka, regs, sizeof(*frame), 0); + if (unlikely(frame == NULL)) + goto badframe; + +--- a/arch/powerpc/kernel/signal.c ++++ b/arch/powerpc/kernel/signal.c +@@ -26,12 +26,12 @@ int show_unhandled_signals = 0; + * Allocate space for the signal frame + */ + void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, +- size_t frame_size) ++ size_t frame_size, int is_32) + { + unsigned long oldsp, newsp; + + /* Default to using normal stack */ +- oldsp = regs->gpr[1]; ++ oldsp = get_clean_sp(regs, is_32); + + /* Check for alt stack */ + if ((ka->sa.sa_flags & SA_ONSTACK) && +--- a/arch/powerpc/kernel/signal.h ++++ b/arch/powerpc/kernel/signal.h +@@ -15,7 +15,7 @@ + extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags); + + extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, +- size_t frame_size); ++ size_t frame_size, int is_32); + extern void restore_sigmask(sigset_t *set); + + extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, diff --git a/queue-2.6.29/series b/queue-2.6.29/series index 3341e8dc8fb..d67c88646cf 100644 --- a/queue-2.6.29/series +++ b/queue-2.6.29/series @@ -28,3 +28,6 @@ mm-fix-committed_as-underflow-on-large-nr_cpus-environment.patch pagemap-require-aligned-length-non-null-reads-of-proc-pid-pagemap.patch kbuild-fix-module.markers-permission-error-under-cygwin.patch ptrace-ptrace_attach-fix-the-usage-of-cred_exec_mutex.patch +usb-serial-fix-lifetime-and-locking-problems.patch +acpi-revert-conflicting-workaround-for-bios-w-mangled-prt-entries.patch +powerpc-sanitize-stack-pointer-in-signal-handling-code.patch diff --git a/queue-2.6.29/usb-serial-fix-lifetime-and-locking-problems.patch b/queue-2.6.29/usb-serial-fix-lifetime-and-locking-problems.patch new file mode 100644 index 00000000000..a2ca022c051 --- /dev/null +++ b/queue-2.6.29/usb-serial-fix-lifetime-and-locking-problems.patch @@ -0,0 +1,279 @@ +From stern@rowland.harvard.edu Mon May 4 16:00:35 2009 +From: Alan Stern +Date: Mon, 4 May 2009 11:30:32 -0400 (EDT) +Subject: USB: serial: fix lifetime and locking problems +To: stable@kernel.org +Message-ID: + +From: Alan Stern + +This is commit 2d93148ab6988cad872e65d694c95e8944e1b626 back-ported to +2.6.29. + +This patch (as1229-3) 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 + +Signed-off-by: Alan Stern + +--- + drivers/usb/serial/usb-serial.c | 99 +++++++++++++++++++++++++++------------- + 1 file changed, 68 insertions(+), 31 deletions(-) + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -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_struc + struct 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_struc + return -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; + tty_port_tty_set(&port->port, 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_stru + dbg("%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); +@@ -275,7 +285,7 @@ static void serial_close(struct tty_stru + * this before we drop the port count. The call is protected + * by the port mutex + */ +- port->serial->type->close(tty, port, filp); ++ serial->type->close(tty, port, filp); + + if (port->port.count == (port->console ? 2 : 1)) { + struct tty_struct *tty = tty_port_tty_get(&port->port); +@@ -289,17 +299,23 @@ static void serial_close(struct tty_stru + } + } + +- if (port->port.count == 1) { +- 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); +- } + --port->port.count; +- ++ count = port->port.count; + mutex_unlock(&port->mutex); +- usb_serial_put(port->serial); ++ 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); ++ ++ /* Mustn't dereference serial any more */ ++ if (count == 0) ++ module_put(owner); + } + + static int serial_write(struct tty_struct *tty, const unsigned char *buf, +@@ -548,7 +564,13 @@ static void kill_traffic(struct usb_seri + + static 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); +@@ -557,7 +579,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); + } + +@@ -1042,6 +1063,12 @@ void usb_serial_disconnect(struct usb_in + usb_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) { +@@ -1051,11 +1078,21 @@ void usb_serial_disconnect(struct usb_in + tty_kref_put(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"); + }