diff --git a/Documentation/SecurityBugs b/Documentation/SecurityBugs new file mode 100644 --- /dev/null +++ b/Documentation/SecurityBugs @@ -0,0 +1,38 @@ +Linux kernel developers take security very seriously. As such, we'd +like to know when a security bug is found so that it can be fixed and +disclosed as quickly as possible. Please report security bugs to the +Linux kernel security team. + +1) Contact + +The Linux kernel security team can be contacted by email at +. This is a private list of security officers +who will help verify the bug report and develop and release a fix. +It is possible that the security team will bring in extra help from +area maintainers to understand and fix the security vulnerability. + +As it is with any bug, the more information provided the easier it +will be to diagnose and fix. Please review the procedure outlined in +REPORTING-BUGS if you are unclear about what information is helpful. +Any exploit code is very helpful and will not be released without +consent from the reporter unless it has already been made public. + +2) Disclosure + +The goal of the Linux kernel security team is to work with the +bug submitter to bug resolution as well as disclosure. We prefer +to fully disclose the bug as soon as possible. It is reasonable to +delay disclosure when the bug or the fix is not yet fully understood, +the solution is not well-tested or for vendor coordination. However, we +expect these delays to be short, measurable in days, not weeks or months. +A disclosure date is negotiated by the security team working with the +bug submitter as well as vendors. However, the kernel security team +holds the final say when setting a disclosure date. The timeframe for +disclosure is from immediate (esp. if it's already publically known) +to a few weeks. As a basic default policy, we expect report date to +disclosure date to be on the order of 7 days. + +3) Non-disclosure agreements + +The Linux kernel security team is not a formal body and therefore unable +to enter any non-disclosure agreements. diff --git a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1966,6 +1966,11 @@ M: christer@weinigel.se W: http://www.weinigel.se S: Supported +SECURITY CONTACT +P: Security Officers +M: security@kernel.org +S: Supported + SELINUX SECURITY MODULE P: Stephen Smalley M: sds@epoch.ncsc.mil diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 11 -EXTRAVERSION = -NAME=Woozy Numbat +EXTRAVERSION = .12 +NAME=Woozy Beaver # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/REPORTING-BUGS b/REPORTING-BUGS --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -16,6 +16,10 @@ code relevant to what you were doing. If describe how to recreate it. That is worth even more than the oops itself. The list of maintainers is in the MAINTAINERS file in this directory. + If it is a security bug, please copy the Security Contact listed +in the MAINTAINERS file. They can help coordinate bugfix and disclosure. +See Documentation/SecurityBugs for more infomation. + If you are totally stumped as to whom to send the report, send it to linux-kernel@vger.kernel.org. (For more information on the linux-kernel mailing list see http://www.tux.org/lkml/). diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S @@ -611,8 +611,10 @@ GLOBAL_ENTRY(fsys_bubble_down) movl r2=ia64_ret_from_syscall ;; mov rp=r2 // set the real return addr - tbit.z p8,p0=r3,TIF_SYSCALL_TRACE + and r3=_TIF_SYSCALL_TRACEAUDIT,r3 ;; + cmp.eq p8,p0=r3,r0 + (p10) br.cond.spnt.many ia64_ret_from_syscall // p10==true means out registers are more than 8 (p8) br.call.sptk.many b6=b6 // ignore this return addr br.cond.sptk ia64_trace_syscall diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -224,7 +224,8 @@ ia64_rt_sigreturn (struct sigscratch *sc * could be corrupted. */ retval = (long) &ia64_leave_kernel; - if (test_thread_flag(TIF_SYSCALL_TRACE)) + if (test_thread_flag(TIF_SYSCALL_TRACE) + || test_thread_flag(TIF_SYSCALL_AUDIT)) /* * strace expects to be notified after sigreturn returns even though the * context to which we return may not be in the middle of a syscall. diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c --- a/arch/ppc/oprofile/op_model_fsl_booke.c +++ b/arch/ppc/oprofile/op_model_fsl_booke.c @@ -150,7 +150,6 @@ static void fsl_booke_handle_interrupt(s int is_kernel; int val; int i; - unsigned int cpu = smp_processor_id(); /* set the PMM bit (see comment below) */ mtmsr(mfmsr() | MSR_PMM); @@ -162,7 +161,7 @@ static void fsl_booke_handle_interrupt(s val = ctr_read(i); if (val < 0) { if (oprofile_running && ctr[i].enabled) { - oprofile_add_sample(pc, is_kernel, i, cpu); + oprofile_add_pc(pc, is_kernel, i); ctr_write(i, reset_value[i]); } else { ctr_write(i, 0); diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -61,8 +61,8 @@ */ /* OpenBIOS defined UART mappings, used before early_serial_setup */ -#define UART0_IO_BASE (u8 *) 0xE0000200 -#define UART1_IO_BASE (u8 *) 0xE0000300 +#define UART0_IO_BASE 0xE0000200 +#define UART1_IO_BASE 0xE0000300 /* external Epson SG-615P */ #define BASE_BAUD 691200 diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h --- a/arch/ppc/platforms/4xx/luan.h +++ b/arch/ppc/platforms/4xx/luan.h @@ -47,9 +47,9 @@ #define RS_TABLE_SIZE 3 /* PIBS defined UART mappings, used before early_serial_setup */ -#define UART0_IO_BASE (u8 *) 0xa0000200 -#define UART1_IO_BASE (u8 *) 0xa0000300 -#define UART2_IO_BASE (u8 *) 0xa0000600 +#define UART0_IO_BASE 0xa0000200 +#define UART1_IO_BASE 0xa0000300 +#define UART2_IO_BASE 0xa0000600 #define BASE_BAUD 11059200 #define STD_UART_OP(num) \ diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h --- a/arch/ppc/platforms/4xx/ocotea.h +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -56,8 +56,8 @@ #define RS_TABLE_SIZE 2 /* OpenBIOS defined UART mappings, used before early_serial_setup */ -#define UART0_IO_BASE (u8 *) 0xE0000200 -#define UART1_IO_BASE (u8 *) 0xE0000300 +#define UART0_IO_BASE 0xE0000200 +#define UART1_IO_BASE 0xE0000300 #define BASE_BAUD 11059200/16 #define STD_UART_OP(num) \ diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c @@ -401,6 +401,8 @@ static void iommu_bus_setup_pSeriesLP(st struct device_node *dn, *pdn; unsigned int *dma_window = NULL; + DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); + dn = pci_bus_to_OF_node(bus); /* Find nearest ibm,dma-window, walking up the device tree */ @@ -455,6 +457,56 @@ static void iommu_dev_setup_pSeries(stru } } +static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) +{ + struct device_node *pdn, *dn; + struct iommu_table *tbl; + int *dma_window = NULL; + + DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name); + + /* dev setup for LPAR is a little tricky, since the device tree might + * contain the dma-window properties per-device and not neccesarily + * for the bus. So we need to search upwards in the tree until we + * either hit a dma-window property, OR find a parent with a table + * already allocated. + */ + dn = pci_device_to_OF_node(dev); + + for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) { + dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); + if (dma_window) + break; + } + + /* Check for parent == NULL so we don't try to setup the empty EADS + * slots on POWER4 machines. + */ + if (dma_window == NULL || pdn->parent == NULL) { + /* Fall back to regular (non-LPAR) dev setup */ + DBG("No dma window for device, falling back to regular setup\n"); + iommu_dev_setup_pSeries(dev); + return; + } else { + DBG("Found DMA window, allocating table\n"); + } + + if (!pdn->iommu_table) { + /* iommu_table_setparms_lpar needs bussubno. */ + pdn->bussubno = pdn->phb->bus->number; + + tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), + GFP_KERNEL); + + iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window); + + pdn->iommu_table = iommu_init_table(tbl); + } + + if (pdn != dn) + dn->iommu_table = pdn->iommu_table; +} + static void iommu_bus_setup_null(struct pci_bus *b) { } static void iommu_dev_setup_null(struct pci_dev *d) { } @@ -479,13 +531,14 @@ void iommu_init_early_pSeries(void) ppc_md.tce_free = tce_free_pSeriesLP; } ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; + ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; } else { ppc_md.tce_build = tce_build_pSeries; ppc_md.tce_free = tce_free_pSeries; ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; + ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; } - ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; pci_iommu_init(); } diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -531,18 +531,6 @@ asmlinkage void do_ptrace(struct pt_regs pt_error_return(regs, EIO); goto out_tsk; } - if (addr != 1) { - if (addr & 3) { - pt_error_return(regs, EINVAL); - goto out_tsk; - } -#ifdef DEBUG_PTRACE - printk ("Original: %08lx %08lx\n", child->thread.kregs->pc, child->thread.kregs->npc); - printk ("Continuing with %08lx %08lx\n", addr, addr+4); -#endif - child->thread.kregs->pc = addr; - child->thread.kregs->npc = addr + 4; - } if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -514,25 +514,6 @@ asmlinkage void do_ptrace(struct pt_regs pt_error_return(regs, EIO); goto out_tsk; } - if (addr != 1) { - unsigned long pc_mask = ~0UL; - - if ((child->thread_info->flags & _TIF_32BIT) != 0) - pc_mask = 0xffffffff; - - if (addr & 3) { - pt_error_return(regs, EINVAL); - goto out_tsk; - } -#ifdef DEBUG_PTRACE - printk ("Original: %016lx %016lx\n", - child->thread_info->kregs->tpc, - child->thread_info->kregs->tnpc); - printk ("Continuing with %016lx %016lx\n", addr, addr+4); -#endif - child->thread_info->kregs->tpc = (addr & pc_mask); - child->thread_info->kregs->tnpc = ((addr + 4) & pc_mask); - } if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -192,10 +192,13 @@ int copy_siginfo_to_user32(compat_siginf err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_FAULT >> 16: - case __SI_POLL >> 16: err |= __put_user(from->si_trapno, &to->si_trapno); err |= __put_user((unsigned long)from->si_addr, &to->si_addr); break; + case __SI_POLL >> 16: + err |= __put_user(from->si_band, &to->si_band); + err |= __put_user(from->si_fd, &to->si_fd); + break; case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ case __SI_MESGQ >> 16: err |= __put_user(from->si_pid, &to->si_pid); diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -75,7 +75,7 @@ sys_call_table32: /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink - .word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid + .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid /*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl #endif /* CONFIG_COMPAT */ diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h --- a/arch/um/include/sysdep-i386/syscalls.h +++ b/arch/um/include/sysdep-i386/syscalls.h @@ -23,6 +23,9 @@ extern long sys_mmap2(unsigned long addr unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff); +/* On i386 they choose a meaningless naming.*/ +#define __NR_kexec_load __NR_sys_kexec_load + #define ARCH_SYSCALLS \ [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \ [ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \ @@ -101,15 +104,12 @@ extern long sys_mmap2(unsigned long addr [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \ [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ - [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \ [ 251 ] = (syscall_handler_t *) sys_ni_syscall, \ - [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \ - [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \ - [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, - + [ 285 ] = (syscall_handler_t *) sys_ni_syscall, + /* 222 doesn't yet have a name in include/asm-i386/unistd.h */ -#define LAST_ARCH_SYSCALL __NR_vserver +#define LAST_ARCH_SYSCALL 285 /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h --- a/arch/um/include/sysdep-x86_64/syscalls.h +++ b/arch/um/include/sysdep-x86_64/syscalls.h @@ -71,12 +71,7 @@ extern syscall_handler_t sys_arch_prctl; [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \ [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \ - [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \ [ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \ - [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \ - [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \ - [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \ - [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, \ [ 251 ] = (syscall_handler_t *) sys_ni_syscall, #define LAST_ARCH_SYSCALL 251 diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -61,7 +61,8 @@ static void do_buffer_op(void *jmpbuf, v void *arg; int *res; - va_copy(args, *(va_list *)arg_ptr); + /* Some old gccs recognize __va_copy, but not va_copy */ + __va_copy(args, *(va_list *)arg_ptr); addr = va_arg(args, unsigned long); len = va_arg(args, int); is_write = va_arg(args, int); diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c --- a/arch/um/kernel/sys_call_table.c +++ b/arch/um/kernel/sys_call_table.c @@ -48,7 +48,6 @@ extern syscall_handler_t sys_vfork; extern syscall_handler_t old_select; extern syscall_handler_t sys_modify_ldt; extern syscall_handler_t sys_rt_sigsuspend; -extern syscall_handler_t sys_vserver; extern syscall_handler_t sys_mbind; extern syscall_handler_t sys_get_mempolicy; extern syscall_handler_t sys_set_mempolicy; @@ -242,6 +241,7 @@ syscall_handler_t *sys_call_table[] = { [ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create, [ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl, [ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait, + [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address, [ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create, [ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime, @@ -252,12 +252,10 @@ syscall_handler_t *sys_call_table[] = { [ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime, [ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres, [ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep, - [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64, - [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64, [ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill, [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, - [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, - [ __NR_vserver ] = (syscall_handler_t *) sys_vserver, + [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, + [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, [ __NR_mbind ] = (syscall_handler_t *) sys_mbind, [ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy, [ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy, @@ -267,9 +265,8 @@ syscall_handler_t *sys_call_table[] = { [ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive, [ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify, [ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr, - [ __NR_sys_kexec_load ] = (syscall_handler_t *) sys_ni_syscall, + [ __NR_kexec_load ] = (syscall_handler_t *) sys_ni_syscall, [ __NR_waitid ] = (syscall_handler_t *) sys_waitid, - [ 285 ] = (syscall_handler_t *) sys_ni_syscall, [ __NR_add_key ] = (syscall_handler_t *) sys_add_key, [ __NR_request_key ] = (syscall_handler_t *) sys_request_key, [ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl, diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -775,9 +775,7 @@ void __init setup_boot_APIC_clock (void) void __init setup_secondary_APIC_clock(void) { - local_irq_disable(); /* FIXME: Do we need this? --RR */ setup_APIC_timer(calibration_result); - local_irq_enable(); } void __init disable_APIC_timer(void) diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -129,13 +129,13 @@ static int putreg(struct task_struct *ch value &= 0xffff; return 0; case offsetof(struct user_regs_struct,fs_base): - if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) - return -EIO; + if (value >= TASK_SIZE) + return -EIO; child->thread.fs = value; return 0; case offsetof(struct user_regs_struct,gs_base): - if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) - return -EIO; + if (value >= TASK_SIZE) + return -EIO; child->thread.gs = value; return 0; case offsetof(struct user_regs_struct, eflags): @@ -149,6 +149,11 @@ static int putreg(struct task_struct *ch return -EIO; value &= 0xffff; break; + case offsetof(struct user_regs_struct, rip): + /* Check if the new RIP address is canonical */ + if (value >= TASK_SIZE) + return -EIO; + break; } put_stack_long(child, regno - sizeof(struct pt_regs), value); return 0; @@ -247,7 +252,7 @@ asmlinkage long sys_ptrace(long request, break; switch (addr) { - case 0 ... sizeof(struct user_regs_struct): + case 0 ... sizeof(struct user_regs_struct) - sizeof(long): tmp = getreg(child, addr); break; case offsetof(struct user, u_debugreg[0]): @@ -292,7 +297,7 @@ asmlinkage long sys_ptrace(long request, break; switch (addr) { - case 0 ... sizeof(struct user_regs_struct): + case 0 ... sizeof(struct user_regs_struct) - sizeof(long): ret = putreg(child, addr, data); break; /* Disallows to set a breakpoint into the vsyscall */ diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -309,8 +309,6 @@ void __init smp_callin(void) Dprintk("CALLIN, before setup_local_APIC().\n"); setup_local_APIC(); - local_irq_enable(); - /* * Get our bogomips. */ @@ -324,8 +322,6 @@ void __init smp_callin(void) */ smp_store_cpu_info(cpuid); - local_irq_disable(); - /* * Allow the master to continue. */ diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -236,6 +236,8 @@ static noinline void pgtable_bad(unsigne /* * Handle a fault on the vmalloc or module mapping area + * + * This assumes no large pages in there. */ static int vmalloc_fault(unsigned long address) { @@ -274,7 +276,10 @@ static int vmalloc_fault(unsigned long a if (!pte_present(*pte_ref)) return -1; pte = pte_offset_kernel(pmd, address); - if (!pte_present(*pte) || pte_page(*pte) != pte_page(*pte_ref)) + /* Don't use pte_page here, because the mappings can point + outside mem_map, and the NUMA hash lookup cannot handle + that. */ + if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref)) BUG(); __flush_tlb_all(); return 0; @@ -348,7 +353,9 @@ asmlinkage void do_page_fault(struct pt_ * protection error (error_code & 1) == 0. */ if (unlikely(address >= TASK_SIZE)) { - if (!(error_code & 5)) { + if (!(error_code & 5) && + ((address >= VMALLOC_START && address < VMALLOC_END) || + (address >= MODULES_VADDR && address < MODULES_END))) { if (vmalloc_fault(address) < 0) goto bad_area_nosemaphore; return; diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -266,7 +266,7 @@ void iounmap(volatile void __iomem *addr if ((p->flags >> 20) && p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) { /* p->size includes the guard page, but cpa doesn't like that */ - change_page_attr(virt_to_page(__va(p->phys_addr)), + change_page_attr_addr((unsigned long)(__va(p->phys_addr)), (p->size - PAGE_SIZE) >> PAGE_SHIFT, PAGE_KERNEL); global_flush_tlb(); diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c --- a/drivers/block/ioctl.c +++ b/drivers/block/ioctl.c @@ -237,3 +237,5 @@ long compat_blkdev_ioctl(struct file *fi } return ret; } + +EXPORT_SYMBOL_GPL(blkdev_ioctl); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2400,7 +2400,7 @@ static int pkt_ioctl(struct inode *inode case CDROM_LAST_WRITTEN: case CDROM_SEND_PACKET: case SCSI_IOCTL_SEND_COMMAND: - return ioctl_by_bdev(pd->bdev, cmd, arg); + return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); case CDROMEJECT: /* @@ -2408,7 +2408,7 @@ static int pkt_ioctl(struct inode *inode * have to unlock it or else the eject command fails. */ pkt_lock_door(pd, 0); - return ioctl_by_bdev(pd->bdev, cmd, arg); + return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); default: printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd); diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c @@ -326,6 +326,8 @@ int drm_setversion(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv)); + memset(&version, 0, sizeof(version)); + dev->driver->version(&version); retv.drm_di_major = DRM_IF_MAJOR; retv.drm_di_minor = DRM_IF_MINOR; diff --git a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -122,7 +122,7 @@ raw_ioctl(struct inode *inode, struct fi { struct block_device *bdev = filp->private_data; - return ioctl_by_bdev(bdev, command, arg); + return blkdev_ioctl(bdev->bd_inode, filp, command, arg); } static void bind_device(struct raw_config_request *rq) diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -130,7 +130,8 @@ static ssize_t eeprom_read(struct kobjec /* Hide Vaio security settings to regular users (16 first bytes) */ if (data->nature == VAIO && off < 16 && !capable(CAP_SYS_ADMIN)) { - int in_row1 = 16 - off; + size_t in_row1 = 16 - off; + in_row1 = min(in_row1, count); memset(buf, 0, in_row1); if (count - in_row1 > 0) memcpy(buf + in_row1, &data->data[16], count - in_row1); diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -631,7 +631,7 @@ static ssize_t show_alarms(struct device struct it87_data *data = it87_update_device(dev); return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms)); } -static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL); +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static ssize_t show_vrm_reg(struct device *dev, char *buf) diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c --- a/drivers/i2c/chips/via686a.c +++ b/drivers/i2c/chips/via686a.c @@ -554,7 +554,7 @@ static ssize_t show_alarms(struct device struct via686a_data *data = via686a_update_device(dev); return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms)); } -static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL); +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); /* The driver. I choose to use type i2c_driver, as at is identical to both smbus_driver and isa_driver, and clients could be of either kind */ diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -133,6 +133,8 @@ static ide_startstop_t __ide_do_rw_disk( if (hwif->no_lba48_dma && lba48 && dma) { if (block + rq->nr_sectors > 1ULL << 28) dma = 0; + else + lba48 = 0; } if (!dma) { @@ -146,7 +148,7 @@ static ide_startstop_t __ide_do_rw_disk( /* FIXME: SELECT_MASK(drive, 0) ? */ if (drive->select.b.lba) { - if (drive->addressing == 1) { + if (lba48) { task_ioreg_t tasklets[10]; pr_debug("%s: LBA=0x%012llx\n", drive->name, block); diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -88,7 +88,7 @@ static struct dmi_system_id __initdata i }; #endif -#ifdef CONFIG_ACPI +#if defined(__ia64__) && defined(CONFIG_ACPI) #include #include @@ -281,7 +281,7 @@ static inline int i8042_platform_init(vo i8042_kbd_irq = I8042_MAP_IRQ(1); i8042_aux_irq = I8042_MAP_IRQ(12); -#ifdef CONFIG_ACPI +#if defined(__ia64__) && defined(CONFIG_ACPI) if (i8042_acpi_init()) return -1; #endif @@ -300,7 +300,7 @@ static inline int i8042_platform_init(vo static inline void i8042_platform_exit(void) { -#ifdef CONFIG_ACPI +#if defined(__ia64__) && defined(CONFIG_ACPI) i8042_acpi_exit(); #endif } diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc --- a/drivers/md/raid6altivec.uc +++ b/drivers/md/raid6altivec.uc @@ -108,7 +108,11 @@ int raid6_have_altivec(void); int raid6_have_altivec(void) { /* This assumes either all CPUs have Altivec or none does */ +#ifdef CONFIG_PPC64 return cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC; +#else + return cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC; +#endif } #endif diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -130,7 +130,7 @@ adv7170_write_block (struct i2c_client * u8 block_data[32]; msg.addr = client->addr; - msg.flags = client->flags; + msg.flags = 0; while (len >= 2) { msg.buf = (char *) block_data; msg.len = 0; diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -126,7 +126,7 @@ adv7175_write_block (struct i2c_client * u8 block_data[32]; msg.addr = client->addr; - msg.flags = client->flags; + msg.flags = 0; while (len >= 2) { msg.buf = (char *) block_data; msg.len = 0; diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -146,7 +146,7 @@ bt819_write_block (struct i2c_client *cl u8 block_data[32]; msg.addr = client->addr; - msg.flags = client->flags; + msg.flags = 0; while (len >= 2) { msg.buf = (char *) block_data; msg.len = 0; diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -1939,7 +1939,6 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, - .no_video = 1, .pll = PLL_28, },{ .name = "Teppro TEV-560/InterVision IV-560", @@ -2718,8 +2717,6 @@ void __devinit bttv_init_card2(struct bt } btv->pll.pll_current = -1; - bttv_reset_audio(btv); - /* tuner configuration (from card list / autodetect / insmod option) */ if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -60,8 +60,10 @@ MODULE_PARM_DESC(debug, "Debug level (0- #define I2C_SAA7110 0x9C /* or 0x9E */ +#define SAA7110_NR_REG 0x35 + struct saa7110 { - unsigned char reg[54]; + u8 reg[SAA7110_NR_REG]; int norm; int input; @@ -95,31 +97,28 @@ saa7110_write_block (struct i2c_client * unsigned int len) { int ret = -1; - u8 reg = *data++; + u8 reg = *data; /* first register to write to */ - len--; + /* Sanity check */ + if (reg + (len - 1) > SAA7110_NR_REG) + return ret; /* the saa7110 has an autoincrement function, use it if * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { struct saa7110 *decoder = i2c_get_clientdata(client); struct i2c_msg msg; - u8 block_data[54]; - msg.len = 0; - msg.buf = (char *) block_data; + msg.len = len; + msg.buf = (char *) data; msg.addr = client->addr; - msg.flags = client->flags; - while (len >= 1) { - msg.len = 0; - block_data[msg.len++] = reg; - while (len-- >= 1 && msg.len < 54) - block_data[msg.len++] = - decoder->reg[reg++] = *data++; - ret = i2c_transfer(client->adapter, &msg, 1); - } + msg.flags = 0; + ret = i2c_transfer(client->adapter, &msg, 1); + + /* Cache the written data */ + memcpy(decoder->reg + reg, data + 1, len - 1); } else { - while (len-- >= 1) { + for (++data, --len; len; len--) { if ((ret = saa7110_write(client, reg++, *data++)) < 0) break; @@ -192,7 +191,7 @@ saa7110_selmux (struct i2c_client *clien return 0; } -static const unsigned char initseq[] = { +static const unsigned char initseq[1 + SAA7110_NR_REG] = { 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00, /* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90, /* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA, diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -163,7 +163,7 @@ saa7114_write_block (struct i2c_client * u8 block_data[32]; msg.addr = client->addr; - msg.flags = client->flags; + msg.flags = 0; while (len >= 2) { msg.buf = (char *) block_data; msg.len = 0; diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -118,7 +118,7 @@ saa7185_write_block (struct i2c_client * u8 block_data[32]; msg.addr = client->addr; - msg.flags = client->flags; + msg.flags = 0; while (len >= 2) { msg.buf = (char *) block_data; msg.len = 0; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1581,7 +1581,8 @@ vortex_up(struct net_device *dev) if (VORTEX_PCI(vp)) { pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */ - pci_restore_state(VORTEX_PCI(vp)); + if (vp->pm_state_valid) + pci_restore_state(VORTEX_PCI(vp)); pci_enable_device(VORTEX_PCI(vp)); } @@ -2741,6 +2742,7 @@ vortex_down(struct net_device *dev, int outl(0, ioaddr + DownListPtr); if (final_down && VORTEX_PCI(vp)) { + vp->pm_state_valid = 1; pci_save_state(VORTEX_PCI(vp)); acpi_set_WOL(dev); } @@ -3243,9 +3245,10 @@ static void acpi_set_WOL(struct net_devi outw(RxEnable, ioaddr + EL3_CMD); pci_enable_wake(VORTEX_PCI(vp), 0, 1); + + /* Change the power state to D3; RxEnable doesn't take effect. */ + pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); } - /* Change the power state to D3; RxEnable doesn't take effect. */ - pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); } diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1381,6 +1381,8 @@ static int amd8111e_open(struct net_devi if(amd8111e_restart(dev)){ spin_unlock_irq(&lp->lock); + if (dev->irq) + free_irq(dev->irq, dev); return -ENOMEM; } /* Start ipg timer */ diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -1000,7 +1000,7 @@ static void async_lcp_peek(struct asyncp data += 4; dlen -= 4; /* data[0] is code, data[1] is length */ - while (dlen >= 2 && dlen >= data[1]) { + while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) { switch (data[0]) { case LCP_MRU: val = (data[2] << 8) + data[3]; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1683,16 +1683,19 @@ static void rtl8169_free_rx_skb(struct r rtl8169_make_unusable_by_asic(desc); } -static inline void rtl8169_return_to_asic(struct RxDesc *desc, int rx_buf_sz) +static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) { - desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz); + u32 eor = le32_to_cpu(desc->opts1) & RingEnd; + + desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); } -static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping, - int rx_buf_sz) +static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, + u32 rx_buf_sz) { desc->addr = cpu_to_le64(mapping); - desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz); + wmb(); + rtl8169_mark_to_asic(desc, rx_buf_sz); } static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, @@ -1712,7 +1715,7 @@ static int rtl8169_alloc_rx_skb(struct p mapping = pci_map_single(pdev, skb->tail, rx_buf_sz, PCI_DMA_FROMDEVICE); - rtl8169_give_to_asic(desc, mapping, rx_buf_sz); + rtl8169_map_to_asic(desc, mapping, rx_buf_sz); out: return ret; @@ -2150,7 +2153,7 @@ static inline int rtl8169_try_rx_copy(st skb_reserve(skb, NET_IP_ALIGN); eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0); *sk_buff = skb; - rtl8169_return_to_asic(desc, rx_buf_sz); + rtl8169_mark_to_asic(desc, rx_buf_sz); ret = 0; } } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -236,7 +236,7 @@ static int __devinit sis900_get_mac_addr signature = (u16) read_eeprom(ioaddr, EEPROMSignature); if (signature == 0xffff || signature == 0x0000) { printk (KERN_INFO "%s: Error EERPOM read %x\n", - net_dev->name, signature); + pci_name(pci_dev), signature); return 0; } @@ -268,7 +268,7 @@ static int __devinit sis630e_get_mac_add if (!isa_bridge) isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge); if (!isa_bridge) { - printk("%s: Can not find ISA bridge\n", net_dev->name); + printk("%s: Can not find ISA bridge\n", pci_name(pci_dev)); return 0; } pci_read_config_byte(isa_bridge, 0x48, ®); @@ -456,10 +456,6 @@ static int __devinit sis900_probe(struct net_dev->tx_timeout = sis900_tx_timeout; net_dev->watchdog_timeo = TX_TIMEOUT; net_dev->ethtool_ops = &sis900_ethtool_ops; - - ret = register_netdev(net_dev); - if (ret) - goto err_unmap_rx; /* Get Mac address according to the chip revision */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); @@ -476,7 +472,7 @@ static int __devinit sis900_probe(struct if (ret == 0) { ret = -ENODEV; - goto err_out_unregister; + goto err_unmap_rx; } /* 630ET : set the mii access mode as software-mode */ @@ -486,7 +482,7 @@ static int __devinit sis900_probe(struct /* probe for mii transceiver */ if (sis900_mii_probe(net_dev) == 0) { ret = -ENODEV; - goto err_out_unregister; + goto err_unmap_rx; } /* save our host bridge revision */ @@ -496,6 +492,10 @@ static int __devinit sis900_probe(struct pci_dev_put(dev); } + ret = register_netdev(net_dev); + if (ret) + goto err_unmap_rx; + /* print some information about our NIC */ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name, card_name, ioaddr, net_dev->irq); @@ -505,8 +505,6 @@ static int __devinit sis900_probe(struct return 0; - err_out_unregister: - unregister_netdev(net_dev); err_unmap_rx: pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring, sis_priv->rx_ring_dma); @@ -533,6 +531,7 @@ static int __devinit sis900_probe(struct static int __init sis900_mii_probe(struct net_device * net_dev) { struct sis900_private * sis_priv = net_dev->priv; + const char *dev_name = pci_name(sis_priv->pci_dev); u16 poll_bit = MII_STAT_LINK, status = 0; unsigned long timeout = jiffies + 5 * HZ; int phy_addr; @@ -582,21 +581,20 @@ static int __init sis900_mii_probe(struc mii_phy->phy_types = (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME; printk(KERN_INFO "%s: %s transceiver found at address %d.\n", - net_dev->name, mii_chip_table[i].name, + dev_name, mii_chip_table[i].name, phy_addr); break; } if( !mii_chip_table[i].phy_id1 ) { printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n", - net_dev->name, phy_addr); + dev_name, phy_addr); mii_phy->phy_types = UNKNOWN; } } if (sis_priv->mii == NULL) { - printk(KERN_INFO "%s: No MII transceivers found!\n", - net_dev->name); + printk(KERN_INFO "%s: No MII transceivers found!\n", dev_name); return 0; } @@ -621,7 +619,7 @@ static int __init sis900_mii_probe(struc poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit); if (time_after_eq(jiffies, timeout)) { printk(KERN_WARNING "%s: reset phy and link down now\n", - net_dev->name); + dev_name); return -ETIME; } } @@ -691,7 +689,7 @@ static u16 sis900_default_phy(struct net sis_priv->mii = default_phy; sis_priv->cur_phy = default_phy->phy_addr; printk(KERN_INFO "%s: Using transceiver found at address %d as default\n", - net_dev->name,sis_priv->cur_phy); + pci_name(sis_priv->pci_dev), sis_priv->cur_phy); } status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); diff --git a/drivers/net/tun.c b/drivers/net/tun.c --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -229,7 +229,7 @@ static __inline__ ssize_t tun_get_user(s size_t len = count; if (!(tun->flags & TUN_NO_PI)) { - if ((len -= sizeof(pi)) > len) + if ((len -= sizeof(pi)) > count) return -EINVAL; if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1197,8 +1197,10 @@ static int rhine_open(struct net_device dev->name, rp->pdev->irq); rc = alloc_ring(dev); - if (rc) + if (rc) { + free_irq(rp->pdev->irq, dev); return rc; + } alloc_rbufs(dev); alloc_tbufs(dev); rhine_chip_reset(dev); @@ -1899,6 +1901,9 @@ static void rhine_shutdown (struct devic struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; + if (!(rp->quirks & rqWOL)) + return; /* Nothing to do for non-WOL adapters */ + rhine_power_init(dev); /* Make sure we use pattern 0, 1 and not 4, 5 */ diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c --- a/drivers/net/wan/hd6457x.c +++ b/drivers/net/wan/hd6457x.c @@ -315,7 +315,7 @@ static inline void sca_rx(card_t *card, #endif stats->rx_packets++; stats->rx_bytes += skb->len; - skb->dev->last_rx = jiffies; + dev->last_rx = jiffies; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -1354,10 +1354,11 @@ static u32 remove_board(struct pci_func dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); bridge_slot_remove(func); - } else + } else { dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); slot_remove(func); + } func = pciehp_slot_find(ctrl->slot_bus, device, 0); } diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -386,6 +386,7 @@ struct visor_private { int bytes_in; int bytes_out; int outstanding_urbs; + int throttled; }; /* number of outstanding urbs to prevent userspace DoS from happening */ @@ -415,6 +416,7 @@ static int visor_open (struct usb_serial priv->bytes_in = 0; priv->bytes_out = 0; priv->outstanding_urbs = 0; + priv->throttled = 0; spin_unlock_irqrestore(&priv->lock, flags); /* @@ -602,6 +604,7 @@ static void visor_read_bulk_callback (st struct tty_struct *tty; unsigned long flags; int i; + int throttled; int result; dbg("%s - port %d", __FUNCTION__, port->number); @@ -627,18 +630,21 @@ static void visor_read_bulk_callback (st } spin_lock_irqsave(&priv->lock, flags); priv->bytes_in += urb->actual_length; + throttled = priv->throttled; spin_unlock_irqrestore(&priv->lock, flags); - /* Continue trying to always read */ - usb_fill_bulk_urb (port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - visor_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + /* Continue trying to always read if we should */ + if (!throttled) { + usb_fill_bulk_urb (port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + visor_read_bulk_callback, port); + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + } return; } @@ -683,16 +689,26 @@ exit: static void visor_throttle (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); - usb_kill_urb(port->read_urb); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = 1; + spin_unlock_irqrestore(&priv->lock, flags); } static void visor_unthrottle (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; int result; dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = 0; + spin_unlock_irqrestore(&priv->lock, flags); port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -438,13 +438,21 @@ static void matroxfb_1bpp_imageblit(WPMI } else if (step == 1) { /* Special case for 1..8bit widths */ while (height--) { - mga_writel(mmio, 0, *chardata); +#if defined(__BIG_ENDIAN) + fb_writel((*chardata) << 24, mmio.vaddr); +#else + fb_writel(*chardata, mmio.vaddr); +#endif chardata++; } } else if (step == 2) { /* Special case for 9..15bit widths */ while (height--) { - mga_writel(mmio, 0, *(u_int16_t*)chardata); +#if defined(__BIG_ENDIAN) + fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr); +#else + fb_writel(*(u_int16_t*)chardata, mmio.vaddr); +#endif chardata += 2; } } else { @@ -454,7 +462,7 @@ static void matroxfb_1bpp_imageblit(WPMI for (i = 0; i < step; i += 4) { /* Hope that there are at least three readable bytes beyond the end of bitmap */ - mga_writel(mmio, 0, get_unaligned((u_int32_t*)(chardata + i))); + fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr); } chardata += step; } diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -170,14 +170,14 @@ static inline void mga_memcpy_toio(vaddr if ((unsigned long)src & 3) { while (len >= 4) { - writel(get_unaligned((u32 *)src), addr); + fb_writel(get_unaligned((u32 *)src), addr); addr++; len -= 4; src += 4; } } else { while (len >= 4) { - writel(*(u32 *)src, addr); + fb_writel(*(u32 *)src, addr); addr++; len -= 4; src += 4; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -257,7 +257,7 @@ create_elf_tables(struct linux_binprm *b } /* Populate argv and envp */ - p = current->mm->arg_start; + p = current->mm->arg_end = current->mm->arg_start; while (argc-- > 0) { size_t len; __put_user((elf_addr_t)p, argv++); @@ -1008,6 +1008,7 @@ out_free_ph: static int load_elf_library(struct file *file) { struct elf_phdr *elf_phdata; + struct elf_phdr *eppnt; unsigned long elf_bss, bss, len; int retval, error, i, j; struct elfhdr elf_ex; @@ -1031,44 +1032,47 @@ static int load_elf_library(struct file /* j < ELF_MIN_ALIGN because elf_ex.e_phnum <= 2 */ error = -ENOMEM; - elf_phdata = (struct elf_phdr *) kmalloc(j, GFP_KERNEL); + elf_phdata = kmalloc(j, GFP_KERNEL); if (!elf_phdata) goto out; + eppnt = elf_phdata; error = -ENOEXEC; - retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata, j); + retval = kernel_read(file, elf_ex.e_phoff, (char *)eppnt, j); if (retval != j) goto out_free_ph; for (j = 0, i = 0; ip_type == PT_LOAD) j++; + if ((eppnt + i)->p_type == PT_LOAD) + j++; if (j != 1) goto out_free_ph; - while (elf_phdata->p_type != PT_LOAD) elf_phdata++; + while (eppnt->p_type != PT_LOAD) + eppnt++; /* Now use mmap to map the library into memory. */ down_write(¤t->mm->mmap_sem); error = do_mmap(file, - ELF_PAGESTART(elf_phdata->p_vaddr), - (elf_phdata->p_filesz + - ELF_PAGEOFFSET(elf_phdata->p_vaddr)), + ELF_PAGESTART(eppnt->p_vaddr), + (eppnt->p_filesz + + ELF_PAGEOFFSET(eppnt->p_vaddr)), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, - (elf_phdata->p_offset - - ELF_PAGEOFFSET(elf_phdata->p_vaddr))); + (eppnt->p_offset - + ELF_PAGEOFFSET(eppnt->p_vaddr))); up_write(¤t->mm->mmap_sem); - if (error != ELF_PAGESTART(elf_phdata->p_vaddr)) + if (error != ELF_PAGESTART(eppnt->p_vaddr)) goto out_free_ph; - elf_bss = elf_phdata->p_vaddr + elf_phdata->p_filesz; + elf_bss = eppnt->p_vaddr + eppnt->p_filesz; if (padzero(elf_bss)) { error = -EFAULT; goto out_free_ph; } - len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1); - bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; + len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); + bss = eppnt->p_memsz + eppnt->p_vaddr; if (bss > len) { down_write(¤t->mm->mmap_sem); do_brk(len, bss - len); @@ -1275,7 +1279,7 @@ static void fill_prstatus(struct elf_prs static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, struct mm_struct *mm) { - int i, len; + unsigned int i, len; /* first copy the parameters from user space */ memset(psinfo, 0, sizeof(struct elf_prpsinfo)); diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -70,6 +70,7 @@ static struct inode *get_cramfs_inode(st inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; + inode->i_blocks = 0; init_special_inode(inode, inode->i_mode, old_decode_dev(cramfs_inode->size)); } diff --git a/fs/eventpoll.c b/fs/eventpoll.c --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -619,6 +619,7 @@ eexit_1: return error; } +#define MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) /* * Implement the event wait interface for the eventpoll file. It is the kernel @@ -635,7 +636,7 @@ asmlinkage long sys_epoll_wait(int epfd, current, epfd, events, maxevents, timeout)); /* The maximum number of event must be greater than zero */ - if (maxevents <= 0) + if (maxevents <= 0 || maxevents > MAX_EVENTS) return -EINVAL; /* Verify that the area passed by the user is writeable */ diff --git a/fs/exec.c b/fs/exec.c --- a/fs/exec.c +++ b/fs/exec.c @@ -814,7 +814,7 @@ void get_task_comm(char *buf, struct tas { /* buf must be at least sizeof(tsk->comm) in size */ task_lock(tsk); - memcpy(buf, tsk->comm, sizeof(tsk->comm)); + strncpy(buf, tsk->comm, sizeof(tsk->comm)); task_unlock(tsk); } diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -592,6 +592,7 @@ int ext2_make_empty(struct inode *inode, goto fail; } kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr, 0, chunk_size); de = (struct ext2_dir_entry_2 *)kaddr; de->name_len = 1; de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1)); diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -268,7 +268,8 @@ void ext3_discard_reservation(struct ino if (!rsv_is_empty(&rsv->rsv_window)) { spin_lock(rsv_lock); - rsv_window_remove(inode->i_sb, rsv); + if (!rsv_is_empty(&rsv->rsv_window)) + rsv_window_remove(inode->i_sb, rsv); spin_unlock(rsv_lock); } } diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -333,6 +333,8 @@ void hfs_mdb_close(struct super_block *s * Release the resources associated with the in-core MDB. */ void hfs_mdb_put(struct super_block *sb) { + if (!HFS_SB(sb)) + return; /* free the B-trees */ hfs_btree_close(HFS_SB(sb)->ext_tree); hfs_btree_close(HFS_SB(sb)->cat_tree); @@ -340,4 +342,7 @@ void hfs_mdb_put(struct super_block *sb) /* free the buffers holding the primary and alternate MDBs */ brelse(HFS_SB(sb)->mdb_bh); brelse(HFS_SB(sb)->alt_mdb_bh); + + kfree(HFS_SB(sb)); + sb->s_fs_info = NULL; } diff --git a/fs/hfs/super.c b/fs/hfs/super.c --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -263,7 +263,7 @@ static int hfs_fill_super(struct super_b res = -EINVAL; if (!parse_options((char *)data, sbi)) { hfs_warn("hfs_fs: unable to parse mount options.\n"); - goto bail3; + goto bail; } sb->s_op = &hfs_super_operations; @@ -276,7 +276,7 @@ static int hfs_fill_super(struct super_b hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n", hfs_mdb_name(sb)); res = -EINVAL; - goto bail2; + goto bail; } /* try to get the root inode */ @@ -306,10 +306,8 @@ bail_iput: iput(root_inode); bail_no_root: hfs_warn("hfs_fs: get root inode failed.\n"); +bail: hfs_mdb_put(sb); -bail2: -bail3: - kfree(sbi); return res; } diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -207,7 +207,9 @@ static void hfsplus_write_super(struct s static void hfsplus_put_super(struct super_block *sb) { dprint(DBG_SUPER, "hfsplus_put_super\n"); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb->s_fs_info) + return; + if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; vhdr->modify_date = hfsp_now2mt(); @@ -223,6 +225,8 @@ static void hfsplus_put_super(struct sup iput(HFSPLUS_SB(sb).alloc_file); iput(HFSPLUS_SB(sb).hidden_dir); brelse(HFSPLUS_SB(sb).s_vhbh); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; } static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -685,6 +685,8 @@ root_found: sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size); sbi->s_max_size = isonum_733(h_pri->volume_space_size); } else { + if (!pri) + goto out_freebh; rootp = (struct iso_directory_record *) pri->root_directory_record; sbi->s_nzones = isonum_733 (pri->volume_space_size); sbi->s_log_zone_size = isonum_723 (pri->logical_block_size); @@ -1395,6 +1397,9 @@ struct inode *isofs_iget(struct super_bl struct inode *inode; struct isofs_iget5_callback_data data; + if (offset >= 1ul << sb->s_blocksize_bits) + return NULL; + data.block = block; data.offset = offset; diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -53,6 +53,7 @@ if(LEN & 1) LEN++; \ CHR = ((unsigned char *) DE) + LEN; \ LEN = *((unsigned char *) DE) - LEN; \ + if (LEN<0) LEN=0; \ if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \ { \ LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \ @@ -73,6 +74,10 @@ offset1 = 0; \ pbh = sb_bread(DEV->i_sb, block); \ if(pbh){ \ + if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \ + brelse(pbh); \ + goto out; \ + } \ memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \ brelse(pbh); \ chr = (unsigned char *) buffer; \ @@ -103,12 +108,13 @@ int get_rock_ridge_filename(struct iso_d struct rock_ridge * rr; int sig; - while (len > 1){ /* There may be one byte for padding somewhere */ + while (len > 2){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; - if (rr->len == 0) goto out; /* Something got screwed up here */ + if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; + if (len < 0) goto out; /* corrupted isofs */ switch(sig){ case SIG('R','R'): @@ -122,6 +128,7 @@ int get_rock_ridge_filename(struct iso_d break; case SIG('N','M'): if (truncate) break; + if (rr->len < 5) break; /* * If the flags are 2 or 4, this indicates '.' or '..'. * We don't want to do anything with this, because it @@ -186,12 +193,13 @@ parse_rock_ridge_inode_internal(struct i struct rock_ridge * rr; int rootflag; - while (len > 1){ /* There may be one byte for padding somewhere */ + while (len > 2){ /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; - if (rr->len == 0) goto out; /* Something got screwed up here */ + if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; + if (len < 0) goto out; /* corrupted isofs */ switch(sig){ #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ @@ -462,7 +470,7 @@ static int rock_ridge_symlink_readpage(s struct rock_ridge *rr; if (!ISOFS_SB(inode->i_sb)->s_rock) - panic ("Cannot have symlink with high sierra variant of iso filesystem\n"); + goto error; block = ei->i_iget5_block; lock_kernel(); @@ -487,13 +495,15 @@ static int rock_ridge_symlink_readpage(s SETUP_ROCK_RIDGE(raw_inode, chr, len); repeat: - while (len > 1) { /* There may be one byte for padding somewhere */ + while (len > 2) { /* There may be one byte for padding somewhere */ rr = (struct rock_ridge *) chr; - if (rr->len == 0) + if (rr->len < 3) goto out; /* Something got screwed up here */ sig = isonum_721(chr); chr += rr->len; len -= rr->len; + if (len < 0) + goto out; /* corrupted isofs */ switch (sig) { case SIG('R', 'R'): @@ -543,6 +553,7 @@ static int rock_ridge_symlink_readpage(s fail: brelse(bh); unlock_kernel(); + error: SetPageError(page); kunmap(page); unlock_page(page); diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c @@ -339,8 +339,10 @@ int log_do_checkpoint(journal_t *journal } } while (jh != last_jh && !retry); - if (batch_count) + if (batch_count) { __flush_batch(journal, bhs, &batch_count); + retry = 1; + } /* * If someone cleaned up this transaction while we slept, we're diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1775,10 +1775,10 @@ static int journal_unmap_buffer(journal_ JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget"); ret = __dispose_buffer(jh, journal->j_running_transaction); + journal_put_journal_head(jh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); - journal_put_journal_head(jh); return ret; } else { /* There is no currently-running transaction. So the @@ -1789,10 +1789,10 @@ static int journal_unmap_buffer(journal_ JBUFFER_TRACE(jh, "give to committing trans"); ret = __dispose_buffer(jh, journal->j_committing_transaction); + journal_put_journal_head(jh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); - journal_put_journal_head(jh); return ret; } else { /* The orphan record's transaction has @@ -1813,10 +1813,10 @@ static int journal_unmap_buffer(journal_ journal->j_running_transaction); jh->b_next_transaction = NULL; } + journal_put_journal_head(jh); spin_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); spin_unlock(&journal->j_state_lock); - journal_put_journal_head(jh); return 0; } else { /* Good, the buffer belongs to the running transaction. diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -160,9 +160,9 @@ static inline void clear_in_cr4 (unsigne /* - * User space process size. 47bits. + * User space process size. 47bits minus one guard page. */ -#define TASK_SIZE (0x800000000000UL) +#define TASK_SIZE (0x800000000000UL - 4096) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. diff --git a/include/linux/err.h b/include/linux/err.h --- a/include/linux/err.h +++ b/include/linux/err.h @@ -13,6 +13,8 @@ * This should be a per-architecture thing, to allow different * error and pointer decisions. */ +#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L) + static inline void *ERR_PTR(long error) { return (void *) error; @@ -25,7 +27,7 @@ static inline long PTR_ERR(const void *p static inline long IS_ERR(const void *ptr) { - return unlikely((unsigned long)ptr > (unsigned long)-1000L); + return IS_ERR_VALUE((unsigned long)ptr); } #endif /* _LINUX_ERR_H */ diff --git a/kernel/exit.c b/kernel/exit.c --- a/kernel/exit.c +++ b/kernel/exit.c @@ -516,8 +516,6 @@ static inline void choose_new_parent(tas */ BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE); p->real_parent = reaper; - if (p->parent == p->real_parent) - BUG(); } static inline void reparent_thread(task_t *p, task_t *father, int traced) diff --git a/kernel/signal.c b/kernel/signal.c --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1728,6 +1728,7 @@ do_signal_stop(int signr) * with another processor delivering a stop signal, * then the SIGCONT that wakes us up should clear it. */ + read_unlock(&tasklist_lock); return 0; } diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -140,12 +140,12 @@ void fastcall __sched __down_read(struct rwsemtrace(sem, "Entering __down_read"); - spin_lock(&sem->wait_lock); + spin_lock_irq(&sem->wait_lock); if (sem->activity >= 0 && list_empty(&sem->wait_list)) { /* granted */ sem->activity++; - spin_unlock(&sem->wait_lock); + spin_unlock_irq(&sem->wait_lock); goto out; } @@ -160,7 +160,7 @@ void fastcall __sched __down_read(struct list_add_tail(&waiter.list, &sem->wait_list); /* we don't need to touch the semaphore struct anymore */ - spin_unlock(&sem->wait_lock); + spin_unlock_irq(&sem->wait_lock); /* wait to be given the lock */ for (;;) { @@ -181,10 +181,12 @@ void fastcall __sched __down_read(struct */ int fastcall __down_read_trylock(struct rw_semaphore *sem) { + unsigned long flags; int ret = 0; + rwsemtrace(sem, "Entering __down_read_trylock"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); if (sem->activity >= 0 && list_empty(&sem->wait_list)) { /* granted */ @@ -192,7 +194,7 @@ int fastcall __down_read_trylock(struct ret = 1; } - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving __down_read_trylock"); return ret; @@ -209,12 +211,12 @@ void fastcall __sched __down_write(struc rwsemtrace(sem, "Entering __down_write"); - spin_lock(&sem->wait_lock); + spin_lock_irq(&sem->wait_lock); if (sem->activity == 0 && list_empty(&sem->wait_list)) { /* granted */ sem->activity = -1; - spin_unlock(&sem->wait_lock); + spin_unlock_irq(&sem->wait_lock); goto out; } @@ -229,7 +231,7 @@ void fastcall __sched __down_write(struc list_add_tail(&waiter.list, &sem->wait_list); /* we don't need to touch the semaphore struct anymore */ - spin_unlock(&sem->wait_lock); + spin_unlock_irq(&sem->wait_lock); /* wait to be given the lock */ for (;;) { @@ -250,10 +252,12 @@ void fastcall __sched __down_write(struc */ int fastcall __down_write_trylock(struct rw_semaphore *sem) { + unsigned long flags; int ret = 0; + rwsemtrace(sem, "Entering __down_write_trylock"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); if (sem->activity == 0 && list_empty(&sem->wait_list)) { /* granted */ @@ -261,7 +265,7 @@ int fastcall __down_write_trylock(struct ret = 1; } - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving __down_write_trylock"); return ret; @@ -272,14 +276,16 @@ int fastcall __down_write_trylock(struct */ void fastcall __up_read(struct rw_semaphore *sem) { + unsigned long flags; + rwsemtrace(sem, "Entering __up_read"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); if (--sem->activity == 0 && !list_empty(&sem->wait_list)) sem = __rwsem_wake_one_writer(sem); - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving __up_read"); } @@ -289,15 +295,17 @@ void fastcall __up_read(struct rw_semaph */ void fastcall __up_write(struct rw_semaphore *sem) { + unsigned long flags; + rwsemtrace(sem, "Entering __up_write"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); sem->activity = 0; if (!list_empty(&sem->wait_list)) sem = __rwsem_do_wake(sem, 1); - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving __up_write"); } @@ -308,15 +316,17 @@ void fastcall __up_write(struct rw_semap */ void fastcall __downgrade_write(struct rw_semaphore *sem) { + unsigned long flags; + rwsemtrace(sem, "Entering __downgrade_write"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); sem->activity = 1; if (!list_empty(&sem->wait_list)) sem = __rwsem_do_wake(sem, 0); - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving __downgrade_write"); } diff --git a/lib/rwsem.c b/lib/rwsem.c --- a/lib/rwsem.c +++ b/lib/rwsem.c @@ -150,7 +150,7 @@ rwsem_down_failed_common(struct rw_semap set_task_state(tsk, TASK_UNINTERRUPTIBLE); /* set up my own style of waitqueue */ - spin_lock(&sem->wait_lock); + spin_lock_irq(&sem->wait_lock); waiter->task = tsk; get_task_struct(tsk); @@ -163,7 +163,7 @@ rwsem_down_failed_common(struct rw_semap if (!(count & RWSEM_ACTIVE_MASK)) sem = __rwsem_do_wake(sem, 0); - spin_unlock(&sem->wait_lock); + spin_unlock_irq(&sem->wait_lock); /* wait to be given the lock */ for (;;) { @@ -219,15 +219,17 @@ rwsem_down_write_failed(struct rw_semaph */ struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem) { + unsigned long flags; + rwsemtrace(sem, "Entering rwsem_wake"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); /* do nothing if list empty */ if (!list_empty(&sem->wait_list)) sem = __rwsem_do_wake(sem, 0); - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving rwsem_wake"); @@ -241,15 +243,17 @@ struct rw_semaphore fastcall *rwsem_wake */ struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem) { + unsigned long flags; + rwsemtrace(sem, "Entering rwsem_downgrade_wake"); - spin_lock(&sem->wait_lock); + spin_lock_irqsave(&sem->wait_lock, flags); /* do nothing if list empty */ if (!list_empty(&sem->wait_list)) sem = __rwsem_do_wake(sem, 1); - spin_unlock(&sem->wait_lock); + spin_unlock_irqrestore(&sem->wait_lock, flags); rwsemtrace(sem, "Leaving rwsem_downgrade_wake"); return sem; diff --git a/mm/mmap.c b/mm/mmap.c --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1315,37 +1315,40 @@ unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - if (flags & MAP_FIXED) { - unsigned long ret; + unsigned long ret; - if (addr > TASK_SIZE - len) - return -ENOMEM; - if (addr & ~PAGE_MASK) - return -EINVAL; - if (file && is_file_hugepages(file)) { - /* - * Check if the given range is hugepage aligned, and - * can be made suitable for hugepages. - */ - ret = prepare_hugepage_range(addr, len); - } else { - /* - * Ensure that a normal request is not falling in a - * reserved hugepage range. For some archs like IA-64, - * there is a separate region for hugepages. - */ - ret = is_hugepage_only_range(addr, len); - } - if (ret) - return -EINVAL; - return addr; - } + if (!(flags & MAP_FIXED)) { + unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - if (file && file->f_op && file->f_op->get_unmapped_area) - return file->f_op->get_unmapped_area(file, addr, len, - pgoff, flags); + get_area = current->mm->get_unmapped_area; + if (file && file->f_op && file->f_op->get_unmapped_area) + get_area = file->f_op->get_unmapped_area; + addr = get_area(file, addr, len, pgoff, flags); + if (IS_ERR_VALUE(addr)) + return addr; + } - return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); + if (addr > TASK_SIZE - len) + return -ENOMEM; + if (addr & ~PAGE_MASK) + return -EINVAL; + if (file && is_file_hugepages(file)) { + /* + * Check if the given range is hugepage aligned, and + * can be made suitable for hugepages. + */ + ret = prepare_hugepage_range(addr, len); + } else { + /* + * Ensure that a normal request is not falling in a + * reserved hugepage range. For some archs like IA-64, + * there is a separate region for hugepages. + */ + ret = is_hugepage_only_range(addr, len); + } + if (ret) + return -EINVAL; + return addr; } EXPORT_SYMBOL(get_unmapped_area); diff --git a/mm/rmap.c b/mm/rmap.c --- a/mm/rmap.c +++ b/mm/rmap.c @@ -641,7 +641,7 @@ static void try_to_unmap_cluster(unsigne pgd_t *pgd; pud_t *pud; pmd_t *pmd; - pte_t *pte; + pte_t *pte, *original_pte; pte_t pteval; struct page *page; unsigned long address; @@ -673,7 +673,7 @@ static void try_to_unmap_cluster(unsigne if (!pmd_present(*pmd)) goto out_unlock; - for (pte = pte_offset_map(pmd, address); + for (original_pte = pte = pte_offset_map(pmd, address); address < end; pte++, address += PAGE_SIZE) { if (!pte_present(*pte)) @@ -710,7 +710,7 @@ static void try_to_unmap_cluster(unsigne (*mapcount)--; } - pte_unmap(pte); + pte_unmap(original_pte); out_unlock: spin_unlock(&mm->page_table_lock); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -64,7 +64,7 @@ static kmem_cache_t *bt_sock_cache; int bt_sock_register(int proto, struct net_proto_family *ops) { - if (proto >= BT_MAX_PROTO) + if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; if (bt_proto[proto]) @@ -77,7 +77,7 @@ EXPORT_SYMBOL(bt_sock_register); int bt_sock_unregister(int proto) { - if (proto >= BT_MAX_PROTO) + if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; if (!bt_proto[proto]) @@ -92,7 +92,7 @@ static int bt_sock_create(struct socket { int err = 0; - if (proto >= BT_MAX_PROTO) + if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; #if defined(CONFIG_KMOD) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -54,6 +54,9 @@ int br_handle_frame_finish(struct sk_buf struct net_bridge_fdb_entry *dst; int passedup = 0; + /* insert into forwarding database after filtering to avoid spoofing */ + br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0); + if (br->dev->flags & IFF_PROMISC) { struct sk_buff *skb2; @@ -108,8 +111,7 @@ int br_handle_frame(struct net_bridge_po if (eth_hdr(skb)->h_source[0] & 1) goto err; - if (p->state == BR_STATE_LEARNING || - p->state == BR_STATE_FORWARDING) + if (p->state == BR_STATE_LEARNING) br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0); if (p->br->stp_enabled && diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -140,6 +140,9 @@ int br_stp_handle_bpdu(struct sk_buff *s struct net_bridge *br = p->br; unsigned char *buf; + /* insert into forwarding database after filtering to avoid spoofing */ + br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0); + /* need at least the 802 and STP headers */ if (!pskb_may_pull(skb, sizeof(header)+1) || memcmp(skb->data, header, sizeof(header))) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -179,9 +179,10 @@ unsigned int ebt_do_table (unsigned int struct ebt_chainstack *cs; struct ebt_entries *chaininfo; char *base; - struct ebt_table_info *private = table->private; + struct ebt_table_info *private; read_lock_bh(&table->lock); + private = table->private; cb_base = COUNTER_BASE(private->counters, private->nentries, smp_processor_id()); if (private->chainstack) diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -919,13 +919,23 @@ out: return fa; } +static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos) +{ + struct fib_alias *fa = fib_get_first(seq); + + if (fa) + while (pos && (fa = fib_get_next(seq))) + --pos; + return pos ? NULL : fa; +} + static void *fib_seq_start(struct seq_file *seq, loff_t *pos) { void *v = NULL; read_lock(&fib_hash_lock); if (ip_fib_main_table) - v = *pos ? fib_get_next(seq) : SEQ_START_TOKEN; + v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; return v; } diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -3,6 +3,7 @@ * communicating with userspace via netlink. * * (C) 2000-2002 James Morris + * (C) 2003-2005 Netfilter Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,6 +15,7 @@ * Zander). * 2000-08-01: Added Nick Williams' MAC support. * 2002-06-25: Code cleanup. + * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte) * */ #include @@ -66,7 +68,15 @@ static DECLARE_MUTEX(ipqnl_sem); static void ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) { + /* TCP input path (and probably other bits) assume to be called + * from softirq context, not from syscall, like ipq_issue_verdict is + * called. TCP input path deadlocks with locks taken from timer + * softirq, e.g. We therefore emulate this by local_bh_disable() */ + + local_bh_disable(); nf_reinject(entry->skb, entry->info, verdict); + local_bh_enable(); + kfree(entry); } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1653,7 +1653,10 @@ static void DBGUNDO(struct sock *sk, str static void tcp_undo_cwr(struct tcp_sock *tp, int undo) { if (tp->prior_ssthresh) { - tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1); + if (tcp_is_bic(tp)) + tp->snd_cwnd = max(tp->snd_cwnd, tp->bictcp.last_max_cwnd); + else + tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1); if (undo && tp->prior_ssthresh > tp->snd_ssthresh) { tp->snd_ssthresh = tp->prior_ssthresh; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -38,6 +38,7 @@ static void tcp_keepalive_timer (unsigne #ifdef TCP_DEBUG const char tcp_timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n"; +EXPORT_SYMBOL(tcp_timer_bug_msg); #endif /* diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -103,17 +103,17 @@ int xfrm4_output(struct sk_buff *skb) goto error_nolock; } - spin_lock_bh(&x->lock); - err = xfrm_state_check(x, skb); - if (err) - goto error; - if (x->props.mode) { err = xfrm4_tunnel_check_size(skb); if (err) - goto error; + goto error_nolock; } + spin_lock_bh(&x->lock); + err = xfrm_state_check(x, skb); + if (err) + goto error; + xfrm4_encap(skb); err = x->type->output(skb); diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -103,17 +103,17 @@ int xfrm6_output(struct sk_buff *skb) goto error_nolock; } - spin_lock_bh(&x->lock); - err = xfrm_state_check(x, skb); - if (err) - goto error; - if (x->props.mode) { err = xfrm6_tunnel_check_size(skb); if (err) - goto error; + goto error_nolock; } + spin_lock_bh(&x->lock); + err = xfrm_state_check(x, skb); + if (err) + goto error; + xfrm6_encap(skb); err = x->type->output(skb); diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c @@ -74,7 +74,6 @@ static int nr_queue_rx_frame(struct sock static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) { - bh_lock_sock(sk); switch (frametype) { case NR_CONNACK: { nr_cb *nr = nr_sk(sk); @@ -103,8 +102,6 @@ static int nr_state1_machine(struct sock default: break; } - bh_unlock_sock(sk); - return 0; } @@ -116,7 +113,6 @@ static int nr_state1_machine(struct sock static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype) { - bh_lock_sock(sk); switch (frametype) { case NR_CONNACK | NR_CHOKE_FLAG: nr_disconnect(sk, ECONNRESET); @@ -132,8 +128,6 @@ static int nr_state2_machine(struct sock default: break; } - bh_unlock_sock(sk); - return 0; } @@ -154,7 +148,6 @@ static int nr_state3_machine(struct sock nr = skb->data[18]; ns = skb->data[17]; - bh_lock_sock(sk); switch (frametype) { case NR_CONNREQ: nr_write_internal(sk, NR_CONNACK); @@ -265,8 +258,6 @@ static int nr_state3_machine(struct sock default: break; } - bh_unlock_sock(sk); - return queued; } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -727,7 +727,8 @@ int rose_rt_ioctl(unsigned int cmd, void } if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ return -EINVAL; - + if (rose_route.ndigis > 8) /* No more than 8 digipeats */ + return -EINVAL; err = rose_add_node(&rose_route, dev); dev_put(dev); return err; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -184,10 +184,15 @@ static int netem_enqueue(struct sk_buff /* Random duplication */ if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) { struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); - - pr_debug("netem_enqueue: dup %p\n", skb2); - if (skb2) - delay_skb(sch, skb2); + if (skb2) { + struct Qdisc *rootq = sch->dev->qdisc; + u32 dupsave = q->duplicate; + + /* prevent duplicating a dup... */ + q->duplicate = 0; + rootq->enqueue(skb2, rootq); + q->duplicate = dupsave; + } } /* If doing simple delay then gap == 0 so all packets diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -609,7 +609,7 @@ static struct xfrm_state *__xfrm_find_ac for (i = 0; i < XFRM_DST_HSIZE; i++) { list_for_each_entry(x, xfrm_state_bydst+i, bydst) { - if (x->km.seq == seq) { + if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) { xfrm_state_hold(x); return x; } diff --git a/security/keys/key.c b/security/keys/key.c --- a/security/keys/key.c +++ b/security/keys/key.c @@ -57,9 +57,10 @@ struct key_user *key_user_lookup(uid_t u { struct key_user *candidate = NULL, *user; struct rb_node *parent = NULL; - struct rb_node **p = &key_user_tree.rb_node; + struct rb_node **p; try_again: + p = &key_user_tree.rb_node; spin_lock(&key_user_lock); /* search the tree for a user record with a matching UID */ diff --git a/sound/core/timer.c b/sound/core/timer.c --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1117,7 +1117,8 @@ static void snd_timer_user_append_to_tqu if (tu->qused >= tu->queue_size) { tu->overrun++; } else { - memcpy(&tu->queue[tu->qtail++], tread, sizeof(*tread)); + memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread)); + tu->qtail %= tu->queue_size; tu->qused++; } } @@ -1140,6 +1141,8 @@ static void snd_timer_user_ccallback(snd spin_lock(&tu->qlock); snd_timer_user_append_to_tqueue(tu, &r1); spin_unlock(&tu->qlock); + kill_fasync(&tu->fasync, SIGIO, POLL_IN); + wake_up(&tu->qchange_sleep); } static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1185,7 +1185,7 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_ /* * create mute switch(es) for normal stereo controls */ -static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac97) +static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int check_stereo, ac97_t *ac97) { snd_kcontrol_t *kctl; int err; @@ -1196,7 +1196,7 @@ static int snd_ac97_cmute_new(snd_card_t mute_mask = 0x8000; val = snd_ac97_read(ac97, reg); - if (ac97->flags & AC97_STEREO_MUTES) { + if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) { /* check whether both mute bits work */ val1 = val | 0x8080; snd_ac97_write(ac97, reg, val1); @@ -1254,7 +1254,7 @@ static int snd_ac97_cvol_new(snd_card_t /* * create a mute-switch and a volume for normal stereo/mono controls */ -static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, ac97_t *ac97) +static int snd_ac97_cmix_new_stereo(snd_card_t *card, const char *pfx, int reg, int check_stereo, ac97_t *ac97) { int err; char name[44]; @@ -1265,7 +1265,7 @@ static int snd_ac97_cmix_new(snd_card_t if (snd_ac97_try_bit(ac97, reg, 15)) { sprintf(name, "%s Switch", pfx); - if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0) + if ((err = snd_ac97_cmute_new_stereo(card, name, reg, check_stereo, ac97)) < 0) return err; } check_volume_resolution(ac97, reg, &lo_max, &hi_max); @@ -1277,6 +1277,8 @@ static int snd_ac97_cmix_new(snd_card_t return 0; } +#define snd_ac97_cmix_new(card, pfx, reg, ac97) snd_ac97_cmix_new_stereo(card, pfx, reg, 0, ac97) +#define snd_ac97_cmute_new(card, name, reg, ac97) snd_ac97_cmute_new_stereo(card, name, reg, 0, ac97) static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97); @@ -1327,7 +1329,8 @@ static int snd_ac97_mixer_build(ac97_t * /* build surround controls */ if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) { - if ((err = snd_ac97_cmix_new(card, "Surround Playback", AC97_SURROUND_MASTER, ac97)) < 0) + /* Surround Master (0x38) is with stereo mutes */ + if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) return err; } diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -3276,7 +3276,7 @@ static void snd_usb_audio_disconnect(str } usb_chip[chip->index] = NULL; up(®ister_mutex); - snd_card_free_in_thread(card); + snd_card_free(card); } else { up(®ister_mutex); } diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -1,6 +1,11 @@ /* * usbusy2y.c - ALSA USB US-428 Driver * +2005-04-14 Karsten Wiese + Version 0.8.7.2: + Call snd_card_free() instead of snd_card_free_in_thread() to prevent oops with dead keyboard symptom. + Tested ok with kernel 2.6.12-rc2. + 2004-12-14 Karsten Wiese Version 0.8.7.1: snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open. @@ -143,7 +148,7 @@ MODULE_AUTHOR("Karsten Wiese "); -MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.1"); +MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}"); @@ -430,8 +435,6 @@ static void usX2Y_usb_disconnect(struct if (ptr) { usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr); struct list_head* p; - if (usX2Y->chip_status == USX2Y_STAT_CHIP_HUP) // on 2.6.1 kernel snd_usbmidi_disconnect() - return; // calls us back. better leave :-) . usX2Y->chip.shutdown = 1; usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; usX2Y_unlinkSeq(&usX2Y->AS04); @@ -443,7 +446,7 @@ static void usX2Y_usb_disconnect(struct } if (usX2Y->us428ctls_sharedmem) wake_up(&usX2Y->us428ctls_wait_queue_head); - snd_card_free_in_thread((snd_card_t*)ptr); + snd_card_free((snd_card_t*)ptr); } }