diff options
author | Mike Pagano <mpagano@gentoo.org> | 2016-07-22 19:30:32 -0400 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2016-07-22 19:30:32 -0400 |
commit | bc466f94adf6e1cde4bee6b1d765d4706b5152c1 (patch) | |
tree | 0979275fb86d35b025ab516f6d64fd2ff9ff1fb0 | |
parent | Linux patch 3.12.61 (diff) | |
download | linux-patches-bc466f94adf6e1cde4bee6b1d765d4706b5152c1.tar.gz linux-patches-bc466f94adf6e1cde4bee6b1d765d4706b5152c1.tar.bz2 linux-patches-bc466f94adf6e1cde4bee6b1d765d4706b5152c1.zip |
Linux patch 3.12.623.12-61
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1061_linux-3.12.62.patch | 4643 |
2 files changed, 4647 insertions, 0 deletions
diff --git a/0000_README b/0000_README index d9fd7628..4de8594a 100644 --- a/0000_README +++ b/0000_README @@ -286,6 +286,10 @@ Patch: 1060_linux-3.12.61.patch From: http://www.kernel.org Desc: Linux 3.12.61 +Patch: 1061_linux-3.12.62.patch +From: http://www.kernel.org +Desc: Linux 3.12.62 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1061_linux-3.12.62.patch b/1061_linux-3.12.62.patch new file mode 100644 index 00000000..33b8b037 --- /dev/null +++ b/1061_linux-3.12.62.patch @@ -0,0 +1,4643 @@ +diff --git a/Makefile b/Makefile +index 59cb9a750d78..b742e9075b78 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 12 +-SUBLEVEL = 61 ++SUBLEVEL = 62 + EXTRAVERSION = + NAME = One Giant Leap for Frogkind + +diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h +index c98c9c89b95c..3f1b3a4150b6 100644 +--- a/arch/arm/include/asm/pgtable-2level.h ++++ b/arch/arm/include/asm/pgtable-2level.h +@@ -162,6 +162,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) + } + + #define pmd_bad(pmd) (pmd_val(pmd) & 2) ++#define pmd_present(pmd) (pmd_val(pmd)) + + #define copy_pmd(pmdpd,pmdps) \ + do { \ +diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h +index 6a171d0afc12..8afa39f81477 100644 +--- a/arch/arm/include/asm/pgtable-3level.h ++++ b/arch/arm/include/asm/pgtable-3level.h +@@ -209,6 +209,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) + : !!(pmd_val(pmd) & (val))) + #define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val))) + ++#define pmd_present(pmd) (pmd_isset((pmd), L_PMD_SECT_VALID)) + #define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF)) + + #define __HAVE_ARCH_PMD_WRITE +diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h +index a348bfd34f66..5bdf9864fb00 100644 +--- a/arch/arm/include/asm/pgtable.h ++++ b/arch/arm/include/asm/pgtable.h +@@ -182,7 +182,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) + + #define pmd_none(pmd) (!pmd_val(pmd)) +-#define pmd_present(pmd) (pmd_val(pmd)) + + static inline pte_t *pmd_page_vaddr(pmd_t pmd) + { +diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c +index 0dd3b79b15c3..ec33df500f86 100644 +--- a/arch/arm/kernel/ptrace.c ++++ b/arch/arm/kernel/ptrace.c +@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target, + if (ret) + return ret; + +- vfp_flush_hwstate(thread); + thread->vfpstate.hard = new_vfp; ++ vfp_flush_hwstate(thread); + + return 0; + } +diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h +index 4d6fa0bf1305..883a162083af 100644 +--- a/arch/mips/include/asm/kvm_host.h ++++ b/arch/mips/include/asm/kvm_host.h +@@ -349,6 +349,7 @@ struct kvm_mips_tlb { + #define KVM_MIPS_GUEST_TLB_SIZE 64 + struct kvm_vcpu_arch { + void *host_ebase, *guest_ebase; ++ int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu); + unsigned long host_stack; + unsigned long host_gp; + +diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h +index 3605b844ad87..efe9964ea9b4 100644 +--- a/arch/mips/include/asm/processor.h ++++ b/arch/mips/include/asm/processor.h +@@ -51,7 +51,7 @@ extern unsigned int vced_count, vcei_count; + * User space process size: 2GB. This is hardcoded into a few places, + * so don't change it unless you know what you are doing. + */ +-#define TASK_SIZE 0x7fff8000UL ++#define TASK_SIZE 0x80000000UL + #endif + + #ifdef __KERNEL__ +diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/kvm_locore.S +index ba5ce99c021d..d1fa2a57218b 100644 +--- a/arch/mips/kvm/kvm_locore.S ++++ b/arch/mips/kvm/kvm_locore.S +@@ -229,6 +229,7 @@ FEXPORT(__kvm_mips_load_k0k1) + + /* Jump to guest */ + eret ++EXPORT(__kvm_mips_vcpu_run_end) + + VECTOR(MIPSX(exception), unknown) + /* +diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c +index 7e7de1f2b8ed..08972791edb4 100644 +--- a/arch/mips/kvm/kvm_mips.c ++++ b/arch/mips/kvm/kvm_mips.c +@@ -347,6 +347,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) + memcpy(gebase + offset, mips32_GuestException, + mips32_GuestExceptionEnd - mips32_GuestException); + ++#ifdef MODULE ++ offset += mips32_GuestExceptionEnd - mips32_GuestException; ++ memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run, ++ __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run); ++ vcpu->arch.vcpu_run = gebase + offset; ++#else ++ vcpu->arch.vcpu_run = __kvm_mips_vcpu_run; ++#endif ++ + /* Invalidate the icache for these ranges */ + mips32_SyncICache((unsigned long) gebase, ALIGN(size, PAGE_SIZE)); + +@@ -430,7 +439,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) + + kvm_guest_enter(); + +- r = __kvm_mips_vcpu_run(run, vcpu); ++ r = vcpu->arch.vcpu_run(run, vcpu); + + kvm_guest_exit(); + local_irq_enable(); +diff --git a/arch/mips/kvm/kvm_mips_int.h b/arch/mips/kvm/kvm_mips_int.h +index 20da7d29eede..bf41ea36210e 100644 +--- a/arch/mips/kvm/kvm_mips_int.h ++++ b/arch/mips/kvm/kvm_mips_int.h +@@ -27,6 +27,8 @@ + #define MIPS_EXC_MAX 12 + /* XXXSL More to follow */ + ++extern char __kvm_mips_vcpu_run_end[]; ++ + #define C_TI (_ULCAST_(1) << 30) + + #define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0) +diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c +index d7c0acb35ec2..8d49614d600d 100644 +--- a/arch/parisc/kernel/unaligned.c ++++ b/arch/parisc/kernel/unaligned.c +@@ -666,7 +666,7 @@ void handle_unaligned(struct pt_regs *regs) + break; + } + +- if (modify && R1(regs->iir)) ++ if (ret == 0 && modify && R1(regs->iir)) + regs->gr[R1(regs->iir)] = newbase; + + +@@ -677,6 +677,14 @@ void handle_unaligned(struct pt_regs *regs) + + if (ret) + { ++ /* ++ * The unaligned handler failed. ++ * If we were called by __get_user() or __put_user() jump ++ * to it's exception fixup handler instead of crashing. ++ */ ++ if (!user_mode(regs) && fixup_exception(regs)) ++ return; ++ + printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); + die_if_kernel("Unaligned data reference", regs, 28); + +diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h +index 3ce6b7b5ca19..53762dbf547c 100644 +--- a/arch/powerpc/include/asm/reg.h ++++ b/arch/powerpc/include/asm/reg.h +@@ -647,7 +647,7 @@ + #define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */ + #define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */ + #define SPRN_MMCR1 798 +-#define SPRN_MMCR2 769 ++#define SPRN_MMCR2 785 + #define SPRN_MMCRA 0x312 + #define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */ + #define MMCRA_SDAR_DCACHE_MISS 0x40000000UL +@@ -681,13 +681,13 @@ + #define SPRN_PMC6 792 + #define SPRN_PMC7 793 + #define SPRN_PMC8 794 +-#define SPRN_SIAR 780 +-#define SPRN_SDAR 781 + #define SPRN_SIER 784 + #define SIER_SIPR 0x2000000 /* Sampled MSR_PR */ + #define SIER_SIHV 0x1000000 /* Sampled MSR_HV */ + #define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */ + #define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */ ++#define SPRN_SIAR 796 ++#define SPRN_SDAR 797 + + /* When EBB is enabled, some of MMCR0/MMCR2/SIER are user accessible */ + #define MMCR0_USER_MASK (MMCR0_FC | MMCR0_PMXE | MMCR0_PMAO) +diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c +index 74448701b636..76246a7ef10f 100644 +--- a/arch/powerpc/platforms/pseries/eeh_pseries.c ++++ b/arch/powerpc/platforms/pseries/eeh_pseries.c +@@ -612,29 +612,50 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) + { + int config_addr; + int ret; ++ /* Waiting 0.2s maximum before skipping configuration */ ++ int max_wait = 200; + + /* Figure out the PE address */ + config_addr = pe->config_addr; + if (pe->addr) + config_addr = pe->addr; + +- /* Use new configure-pe function, if supported */ +- if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { +- ret = rtas_call(ibm_configure_pe, 3, 1, NULL, +- config_addr, BUID_HI(pe->phb->buid), +- BUID_LO(pe->phb->buid)); +- } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { +- ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, +- config_addr, BUID_HI(pe->phb->buid), +- BUID_LO(pe->phb->buid)); +- } else { +- return -EFAULT; +- } ++ while (max_wait > 0) { ++ /* Use new configure-pe function, if supported */ ++ if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) { ++ ret = rtas_call(ibm_configure_pe, 3, 1, NULL, ++ config_addr, BUID_HI(pe->phb->buid), ++ BUID_LO(pe->phb->buid)); ++ } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) { ++ ret = rtas_call(ibm_configure_bridge, 3, 1, NULL, ++ config_addr, BUID_HI(pe->phb->buid), ++ BUID_LO(pe->phb->buid)); ++ } else { ++ return -EFAULT; ++ } + +- if (ret) +- pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", +- __func__, pe->phb->global_number, pe->addr, ret); ++ if (!ret) ++ return ret; ++ ++ /* ++ * If RTAS returns a delay value that's above 100ms, cut it ++ * down to 100ms in case firmware made a mistake. For more ++ * on how these delay values work see rtas_busy_delay_time ++ */ ++ if (ret > RTAS_EXTENDED_DELAY_MIN+2 && ++ ret <= RTAS_EXTENDED_DELAY_MAX) ++ ret = RTAS_EXTENDED_DELAY_MIN+2; ++ ++ max_wait -= rtas_busy_delay_time(ret); ++ ++ if (max_wait < 0) ++ break; ++ ++ rtas_busy_delay(ret); ++ } + ++ pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", ++ __func__, pe->phb->global_number, pe->addr, ret); + return ret; + } + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 261c5095d5d3..c06f9e75f8b1 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -861,7 +861,8 @@ machine_arch_initcall(pseries, find_existing_ddw_windows); + static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail, + struct ddw_query_response *query) + { +- struct eeh_dev *edev; ++ struct device_node *dn; ++ struct pci_dn *pdn; + u32 cfg_addr; + u64 buid; + int ret; +@@ -872,11 +873,10 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail, + * Retrieve them from the pci device, not the node with the + * dma-window property + */ +- edev = pci_dev_to_eeh_dev(dev); +- cfg_addr = edev->config_addr; +- if (edev->pe_config_addr) +- cfg_addr = edev->pe_config_addr; +- buid = edev->phb->buid; ++ dn = pci_device_to_OF_node(dev); ++ pdn = PCI_DN(dn); ++ buid = pdn->phb->buid; ++ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8)); + + ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query, + cfg_addr, BUID_HI(buid), BUID_LO(buid)); +@@ -890,7 +890,8 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail, + struct ddw_create_response *create, int page_shift, + int window_shift) + { +- struct eeh_dev *edev; ++ struct device_node *dn; ++ struct pci_dn *pdn; + u32 cfg_addr; + u64 buid; + int ret; +@@ -901,11 +902,10 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail, + * Retrieve them from the pci device, not the node with the + * dma-window property + */ +- edev = pci_dev_to_eeh_dev(dev); +- cfg_addr = edev->config_addr; +- if (edev->pe_config_addr) +- cfg_addr = edev->pe_config_addr; +- buid = edev->phb->buid; ++ dn = pci_device_to_OF_node(dev); ++ pdn = PCI_DN(dn); ++ buid = pdn->phb->buid; ++ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8)); + + do { + /* extra outputs are LIOBN and dma-addr (hi, lo) */ +diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h +index 10e9dabc4c41..f0700cfeedd7 100644 +--- a/arch/sparc/include/asm/head_64.h ++++ b/arch/sparc/include/asm/head_64.h +@@ -15,6 +15,10 @@ + + #define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ) + ++#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) ++#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) ++#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) ++ + #define __CHEETAH_ID 0x003e0014 + #define __JALAPENO_ID 0x003e0016 + #define __SERRANO_ID 0x003e0022 +diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h +index 71b5a67522ab..781b9f1dbdc2 100644 +--- a/arch/sparc/include/asm/ttable.h ++++ b/arch/sparc/include/asm/ttable.h +@@ -589,8 +589,8 @@ user_rtt_fill_64bit: \ + restored; \ + nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \ + ba,a,pt %xcc, user_rtt_fill_fixup; + + +@@ -652,8 +652,8 @@ user_rtt_fill_32bit: \ + restored; \ + nop; nop; nop; nop; nop; \ + nop; nop; nop; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ +- ba,a,pt %xcc, user_rtt_fill_fixup; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \ ++ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \ + ba,a,pt %xcc, user_rtt_fill_fixup; + + +diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile +index d15cc1794b0e..a0977a201114 100644 +--- a/arch/sparc/kernel/Makefile ++++ b/arch/sparc/kernel/Makefile +@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg + CFLAGS_REMOVE_pcr.o := -pg + endif + ++obj-$(CONFIG_SPARC64) += urtt_fill.o + obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o + obj-$(CONFIG_SPARC32) += etrap_32.o + obj-$(CONFIG_SPARC32) += rtrap_32.o +diff --git a/arch/sparc/kernel/cherrs.S b/arch/sparc/kernel/cherrs.S +index 4ee1ad420862..655628def68e 100644 +--- a/arch/sparc/kernel/cherrs.S ++++ b/arch/sparc/kernel/cherrs.S +@@ -214,8 +214,7 @@ do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ + subcc %g1, %g2, %g1 ! Next cacheline + bge,pt %icc, 1b + nop +- ba,pt %xcc, dcpe_icpe_tl1_common +- nop ++ ba,a,pt %xcc, dcpe_icpe_tl1_common + + do_dcpe_tl1_fatal: + sethi %hi(1f), %g7 +@@ -224,8 +223,7 @@ do_dcpe_tl1_fatal: + mov 0x2, %o0 + call cheetah_plus_parity_error + add %sp, PTREGS_OFF, %o1 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_dcpe_tl1,.-do_dcpe_tl1 + + .globl do_icpe_tl1 +@@ -259,8 +257,7 @@ do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ + subcc %g1, %g2, %g1 + bge,pt %icc, 1b + nop +- ba,pt %xcc, dcpe_icpe_tl1_common +- nop ++ ba,a,pt %xcc, dcpe_icpe_tl1_common + + do_icpe_tl1_fatal: + sethi %hi(1f), %g7 +@@ -269,8 +266,7 @@ do_icpe_tl1_fatal: + mov 0x3, %o0 + call cheetah_plus_parity_error + add %sp, PTREGS_OFF, %o1 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_icpe_tl1,.-do_icpe_tl1 + + .type dcpe_icpe_tl1_common,#function +@@ -456,7 +452,7 @@ __cheetah_log_error: + cmp %g2, 0x63 + be c_cee + nop +- ba,pt %xcc, c_deferred ++ ba,a,pt %xcc, c_deferred + .size __cheetah_log_error,.-__cheetah_log_error + + /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc +diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S +index 33c02b15f478..a83707c83be8 100644 +--- a/arch/sparc/kernel/entry.S ++++ b/arch/sparc/kernel/entry.S +@@ -948,7 +948,24 @@ linux_syscall_trace: + cmp %o0, 0 + bne 3f + mov -ENOSYS, %o0 ++ ++ /* Syscall tracing can modify the registers. */ ++ ld [%sp + STACKFRAME_SZ + PT_G1], %g1 ++ sethi %hi(sys_call_table), %l7 ++ ld [%sp + STACKFRAME_SZ + PT_I0], %i0 ++ or %l7, %lo(sys_call_table), %l7 ++ ld [%sp + STACKFRAME_SZ + PT_I1], %i1 ++ ld [%sp + STACKFRAME_SZ + PT_I2], %i2 ++ ld [%sp + STACKFRAME_SZ + PT_I3], %i3 ++ ld [%sp + STACKFRAME_SZ + PT_I4], %i4 ++ ld [%sp + STACKFRAME_SZ + PT_I5], %i5 ++ cmp %g1, NR_syscalls ++ bgeu 3f ++ mov -ENOSYS, %o0 ++ ++ sll %g1, 2, %l4 + mov %i0, %o0 ++ ld [%l7 + %l4], %l7 + mov %i1, %o1 + mov %i2, %o2 + mov %i3, %o3 +diff --git a/arch/sparc/kernel/fpu_traps.S b/arch/sparc/kernel/fpu_traps.S +index a6864826a4bd..336d2750fe78 100644 +--- a/arch/sparc/kernel/fpu_traps.S ++++ b/arch/sparc/kernel/fpu_traps.S +@@ -100,8 +100,8 @@ do_fpdis: + fmuld %f0, %f2, %f26 + faddd %f0, %f2, %f28 + fmuld %f0, %f2, %f30 +- b,pt %xcc, fpdis_exit +- nop ++ ba,a,pt %xcc, fpdis_exit ++ + 2: andcc %g5, FPRS_DU, %g0 + bne,pt %icc, 3f + fzero %f32 +@@ -144,8 +144,8 @@ do_fpdis: + fmuld %f32, %f34, %f58 + faddd %f32, %f34, %f60 + fmuld %f32, %f34, %f62 +- ba,pt %xcc, fpdis_exit +- nop ++ ba,a,pt %xcc, fpdis_exit ++ + 3: mov SECONDARY_CONTEXT, %g3 + add %g6, TI_FPREGS, %g1 + +@@ -197,8 +197,7 @@ fpdis_exit2: + fp_other_bounce: + call do_fpother + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size fp_other_bounce,.-fp_other_bounce + + .align 32 +diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S +index 3d61fcae7ee3..8ff57630a486 100644 +--- a/arch/sparc/kernel/head_64.S ++++ b/arch/sparc/kernel/head_64.S +@@ -461,9 +461,8 @@ sun4v_chip_type: + subcc %g3, 1, %g3 + bne,pt %xcc, 41b + add %g1, 1, %g1 +- mov SUN4V_CHIP_SPARC64X, %g4 + ba,pt %xcc, 5f +- nop ++ mov SUN4V_CHIP_SPARC64X, %g4 + + 49: + mov SUN4V_CHIP_UNKNOWN, %g4 +@@ -548,8 +547,7 @@ sun4u_init: + stxa %g0, [%g7] ASI_DMMU + membar #Sync + +- ba,pt %xcc, sun4u_continue +- nop ++ ba,a,pt %xcc, sun4u_continue + + sun4v_init: + /* Set ctx 0 */ +@@ -560,14 +558,12 @@ sun4v_init: + mov SECONDARY_CONTEXT, %g7 + stxa %g0, [%g7] ASI_MMU + membar #Sync +- ba,pt %xcc, niagara_tlb_fixup +- nop ++ ba,a,pt %xcc, niagara_tlb_fixup + + sun4u_continue: + BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup) + +- ba,pt %xcc, spitfire_tlb_fixup +- nop ++ ba,a,pt %xcc, spitfire_tlb_fixup + + niagara_tlb_fixup: + mov 3, %g2 /* Set TLB type to hypervisor. */ +@@ -639,8 +635,7 @@ niagara_patch: + call hypervisor_patch_cachetlbops + nop + +- ba,pt %xcc, tlb_fixup_done +- nop ++ ba,a,pt %xcc, tlb_fixup_done + + cheetah_tlb_fixup: + mov 2, %g2 /* Set TLB type to cheetah+. */ +@@ -659,8 +654,7 @@ cheetah_tlb_fixup: + call cheetah_patch_cachetlbops + nop + +- ba,pt %xcc, tlb_fixup_done +- nop ++ ba,a,pt %xcc, tlb_fixup_done + + spitfire_tlb_fixup: + /* Set TLB type to spitfire. */ +@@ -782,8 +776,7 @@ setup_trap_table: + call %o1 + add %sp, (2047 + 128), %o0 + +- ba,pt %xcc, 2f +- nop ++ ba,a,pt %xcc, 2f + + 1: sethi %hi(sparc64_ttable_tl0), %o0 + set prom_set_trap_table_name, %g2 +@@ -822,8 +815,7 @@ setup_trap_table: + + BRANCH_IF_ANY_CHEETAH(o2, o3, 1f) + +- ba,pt %xcc, 2f +- nop ++ ba,a,pt %xcc, 2f + + /* Disable STICK_INT interrupts. */ + 1: +diff --git a/arch/sparc/kernel/misctrap.S b/arch/sparc/kernel/misctrap.S +index 753b4f031bfb..34b4933900bf 100644 +--- a/arch/sparc/kernel/misctrap.S ++++ b/arch/sparc/kernel/misctrap.S +@@ -18,8 +18,7 @@ __do_privact: + 109: or %g7, %lo(109b), %g7 + call do_privact + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __do_privact,.-__do_privact + + .type do_mna,#function +@@ -46,8 +45,7 @@ do_mna: + mov %l5, %o2 + call mem_address_unaligned + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_mna,.-do_mna + + .type do_lddfmna,#function +@@ -65,8 +63,7 @@ do_lddfmna: + mov %l5, %o2 + call handle_lddfmna + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_lddfmna,.-do_lddfmna + + .type do_stdfmna,#function +@@ -84,8 +81,7 @@ do_stdfmna: + mov %l5, %o2 + call handle_stdfmna + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size do_stdfmna,.-do_stdfmna + + .type breakpoint_trap,#function +diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c +index cb021453de2a..80afbebfbf81 100644 +--- a/arch/sparc/kernel/pci.c ++++ b/arch/sparc/kernel/pci.c +@@ -930,6 +930,23 @@ void pcibios_set_master(struct pci_dev *dev) + /* No special bus mastering setup handling */ + } + ++#ifdef CONFIG_PCI_IOV ++int pcibios_add_device(struct pci_dev *dev) ++{ ++ struct pci_dev *pdev; ++ ++ /* Add sriov arch specific initialization here. ++ * Copy dev_archdata from PF to VF ++ */ ++ if (dev->is_virtfn) { ++ pdev = dev->physfn; ++ memcpy(&dev->dev.archdata, &pdev->dev.archdata, ++ sizeof(struct dev_archdata)); ++ } ++ return 0; ++} ++#endif /* CONFIG_PCI_IOV */ ++ + static int __init pcibios_init(void) + { + pci_dfl_cache_line_size = 64 >> 2; +diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S +index afa2a9e3d0a0..5c0b0254580d 100644 +--- a/arch/sparc/kernel/rtrap_64.S ++++ b/arch/sparc/kernel/rtrap_64.S +@@ -14,10 +14,6 @@ + #include <asm/visasm.h> + #include <asm/processor.h> + +-#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) +-#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV) +-#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) +- + .text + .align 32 + __handle_preemption: +@@ -230,52 +226,17 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 + wrpr %g1, %cwp + ba,a,pt %xcc, user_rtt_fill_64bit + +-user_rtt_fill_fixup: +- rdpr %cwp, %g1 +- add %g1, 1, %g1 +- wrpr %g1, 0x0, %cwp +- +- rdpr %wstate, %g2 +- sll %g2, 3, %g2 +- wrpr %g2, 0x0, %wstate +- +- /* We know %canrestore and %otherwin are both zero. */ +- +- sethi %hi(sparc64_kern_pri_context), %g2 +- ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2 +- mov PRIMARY_CONTEXT, %g1 +- +-661: stxa %g2, [%g1] ASI_DMMU +- .section .sun4v_1insn_patch, "ax" +- .word 661b +- stxa %g2, [%g1] ASI_MMU +- .previous +- +- sethi %hi(KERNBASE), %g1 +- flush %g1 ++user_rtt_fill_fixup_dax: ++ ba,pt %xcc, user_rtt_fill_fixup_common ++ mov 1, %g3 + +- or %g4, FAULT_CODE_WINFIXUP, %g4 +- stb %g4, [%g6 + TI_FAULT_CODE] +- stx %g5, [%g6 + TI_FAULT_ADDR] ++user_rtt_fill_fixup_mna: ++ ba,pt %xcc, user_rtt_fill_fixup_common ++ mov 2, %g3 + +- mov %g6, %l1 +- wrpr %g0, 0x0, %tl +- +-661: nop +- .section .sun4v_1insn_patch, "ax" +- .word 661b +- SET_GL(0) +- .previous +- +- wrpr %g0, RTRAP_PSTATE, %pstate +- +- mov %l1, %g6 +- ldx [%g6 + TI_TASK], %g4 +- LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3) +- call do_sparc64_fault +- add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++user_rtt_fill_fixup: ++ ba,pt %xcc, user_rtt_fill_fixup_common ++ clr %g3 + + user_rtt_pre_restore: + add %g1, 1, %g1 +diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c +index b524f91dd0e5..d45b112908c1 100644 +--- a/arch/sparc/kernel/signal32.c ++++ b/arch/sparc/kernel/signal32.c +@@ -137,12 +137,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + return 0; + } + ++/* Checks if the fp is valid. We always build signal frames which are ++ * 16-byte aligned, therefore we can always enforce that the restore ++ * frame has that property as well. ++ */ ++static bool invalid_frame_pointer(void __user *fp, int fplen) ++{ ++ if ((((unsigned long) fp) & 15) || ++ ((unsigned long)fp) > 0x100000000ULL - fplen) ++ return true; ++ return false; ++} ++ + void do_sigreturn32(struct pt_regs *regs) + { + struct signal_frame32 __user *sf; + compat_uptr_t fpu_save; + compat_uptr_t rwin_save; +- unsigned int psr; ++ unsigned int psr, ufp; + unsigned pc, npc; + sigset_t set; + unsigned seta[_COMPAT_NSIG_WORDS]; +@@ -157,11 +169,16 @@ void do_sigreturn32(struct pt_regs *regs) + sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP]; + + /* 1. Make sure we are not getting garbage from the user */ +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || +- (((unsigned long) sf) & 3)) ++ if (invalid_frame_pointer(sf, sizeof(*sf))) ++ goto segv; ++ ++ if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP])) ++ goto segv; ++ ++ if (ufp & 0x7) + goto segv; + +- if (get_user(pc, &sf->info.si_regs.pc) || ++ if (__get_user(pc, &sf->info.si_regs.pc) || + __get_user(npc, &sf->info.si_regs.npc)) + goto segv; + +@@ -230,7 +247,7 @@ segv: + asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) + { + struct rt_signal_frame32 __user *sf; +- unsigned int psr, pc, npc; ++ unsigned int psr, pc, npc, ufp; + compat_uptr_t fpu_save; + compat_uptr_t rwin_save; + sigset_t set; +@@ -245,11 +262,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) + sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP]; + + /* 1. Make sure we are not getting garbage from the user */ +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || +- (((unsigned long) sf) & 3)) ++ if (invalid_frame_pointer(sf, sizeof(*sf))) + goto segv; + +- if (get_user(pc, &sf->regs.pc) || ++ if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) ++ goto segv; ++ ++ if (ufp & 0x7) ++ goto segv; ++ ++ if (__get_user(pc, &sf->regs.pc) || + __get_user(npc, &sf->regs.npc)) + goto segv; + +@@ -315,14 +337,6 @@ segv: + force_sig(SIGSEGV, current); + } + +-/* Checks if the fp is valid */ +-static int invalid_frame_pointer(void __user *fp, int fplen) +-{ +- if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen) +- return 1; +- return 0; +-} +- + static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) + { + unsigned long sp; +diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c +index 7d5d8e1f8415..e751dbc527e2 100644 +--- a/arch/sparc/kernel/signal_32.c ++++ b/arch/sparc/kernel/signal_32.c +@@ -59,10 +59,22 @@ struct rt_signal_frame { + #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) + #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) + ++/* Checks if the fp is valid. We always build signal frames which are ++ * 16-byte aligned, therefore we can always enforce that the restore ++ * frame has that property as well. ++ */ ++static inline bool invalid_frame_pointer(void __user *fp, int fplen) ++{ ++ if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen)) ++ return true; ++ ++ return false; ++} ++ + asmlinkage void do_sigreturn(struct pt_regs *regs) + { ++ unsigned long up_psr, pc, npc, ufp; + struct signal_frame __user *sf; +- unsigned long up_psr, pc, npc; + sigset_t set; + __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; +@@ -76,10 +88,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) + sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; + + /* 1. Make sure we are not getting garbage from the user */ +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) ++ if (!invalid_frame_pointer(sf, sizeof(*sf))) ++ goto segv_and_exit; ++ ++ if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP])) + goto segv_and_exit; + +- if (((unsigned long) sf) & 3) ++ if (ufp & 0x7) + goto segv_and_exit; + + err = __get_user(pc, &sf->info.si_regs.pc); +@@ -126,7 +141,7 @@ segv_and_exit: + asmlinkage void do_rt_sigreturn(struct pt_regs *regs) + { + struct rt_signal_frame __user *sf; +- unsigned int psr, pc, npc; ++ unsigned int psr, pc, npc, ufp; + __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; + sigset_t set; +@@ -134,8 +149,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) + + synchronize_user_stack(); + sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP]; +- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || +- (((unsigned long) sf) & 0x03)) ++ if (!invalid_frame_pointer(sf, sizeof(*sf))) ++ goto segv; ++ ++ if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) ++ goto segv; ++ ++ if (ufp & 0x7) + goto segv; + + err = __get_user(pc, &sf->regs.pc); +@@ -177,15 +197,6 @@ segv: + force_sig(SIGSEGV, current); + } + +-/* Checks if the fp is valid */ +-static inline int invalid_frame_pointer(void __user *fp, int fplen) +-{ +- if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen)) +- return 1; +- +- return 0; +-} +- + static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) + { + unsigned long sp = regs->u_regs[UREG_FP]; +diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c +index 35923e8abd82..5a2e50bcc3b8 100644 +--- a/arch/sparc/kernel/signal_64.c ++++ b/arch/sparc/kernel/signal_64.c +@@ -49,7 +49,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) + unsigned char fenab; + int err; + +- flush_user_windows(); ++ synchronize_user_stack(); + if (get_thread_wsaved() || + (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || + (!__access_ok(ucp, sizeof(*ucp)))) +@@ -226,6 +226,17 @@ do_sigsegv: + force_sig(SIGSEGV, current); + } + ++/* Checks if the fp is valid. We always build rt signal frames which ++ * are 16-byte aligned, therefore we can always enforce that the ++ * restore frame has that property as well. ++ */ ++static bool invalid_frame_pointer(void __user *fp) ++{ ++ if (((unsigned long) fp) & 15) ++ return true; ++ return false; ++} ++ + struct rt_signal_frame { + struct sparc_stackf ss; + siginfo_t info; +@@ -238,8 +249,8 @@ struct rt_signal_frame { + + void do_rt_sigreturn(struct pt_regs *regs) + { ++ unsigned long tpc, tnpc, tstate, ufp; + struct rt_signal_frame __user *sf; +- unsigned long tpc, tnpc, tstate; + __siginfo_fpu_t __user *fpu_save; + __siginfo_rwin_t __user *rwin_save; + sigset_t set; +@@ -253,10 +264,16 @@ void do_rt_sigreturn(struct pt_regs *regs) + (regs->u_regs [UREG_FP] + STACK_BIAS); + + /* 1. Make sure we are not getting garbage from the user */ +- if (((unsigned long) sf) & 3) ++ if (invalid_frame_pointer(sf)) ++ goto segv; ++ ++ if (get_user(ufp, &sf->regs.u_regs[UREG_FP])) + goto segv; + +- err = get_user(tpc, &sf->regs.tpc); ++ if ((ufp + STACK_BIAS) & 0x7) ++ goto segv; ++ ++ err = __get_user(tpc, &sf->regs.tpc); + err |= __get_user(tnpc, &sf->regs.tnpc); + if (test_thread_flag(TIF_32BIT)) { + tpc &= 0xffffffff; +@@ -300,14 +317,6 @@ segv: + force_sig(SIGSEGV, current); + } + +-/* Checks if the fp is valid */ +-static int invalid_frame_pointer(void __user *fp) +-{ +- if (((unsigned long) fp) & 15) +- return 1; +- return 0; +-} +- + static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) + { + unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; +diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c +index 0f6eebe71e6c..e5fe8cef9a69 100644 +--- a/arch/sparc/kernel/sigutil_32.c ++++ b/arch/sparc/kernel/sigutil_32.c +@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) + int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) + { + int err; ++ ++ if (((unsigned long) fpu) & 3) ++ return -EFAULT; ++ + #ifdef CONFIG_SMP + if (test_tsk_thread_flag(current, TIF_USEDFPU)) + regs->psr &= ~PSR_EF; +@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp) + struct thread_info *t = current_thread_info(); + int i, wsaved, err; + +- __get_user(wsaved, &rp->wsaved); ++ if (((unsigned long) rp) & 3) ++ return -EFAULT; ++ ++ get_user(wsaved, &rp->wsaved); + if (wsaved > NSWINS) + return -EFAULT; + +diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c +index 387834a9c56a..36aadcbeac69 100644 +--- a/arch/sparc/kernel/sigutil_64.c ++++ b/arch/sparc/kernel/sigutil_64.c +@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) + unsigned long fprs; + int err; + +- err = __get_user(fprs, &fpu->si_fprs); ++ if (((unsigned long) fpu) & 7) ++ return -EFAULT; ++ ++ err = get_user(fprs, &fpu->si_fprs); + fprs_write(0); + regs->tstate &= ~TSTATE_PEF; + if (fprs & FPRS_DL) +@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp) + struct thread_info *t = current_thread_info(); + int i, wsaved, err; + +- __get_user(wsaved, &rp->wsaved); ++ if (((unsigned long) rp) & 7) ++ return -EFAULT; ++ ++ get_user(wsaved, &rp->wsaved); + if (wsaved > NSWINS) + return -EFAULT; + +diff --git a/arch/sparc/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S +index c357e40ffd01..4a73009f66a5 100644 +--- a/arch/sparc/kernel/spiterrs.S ++++ b/arch/sparc/kernel/spiterrs.S +@@ -85,8 +85,7 @@ __spitfire_cee_trap_continue: + ba,pt %xcc, etraptl1 + rd %pc, %g7 + +- ba,pt %xcc, 2f +- nop ++ ba,a,pt %xcc, 2f + + 1: ba,pt %xcc, etrap_irq + rd %pc, %g7 +@@ -100,8 +99,7 @@ __spitfire_cee_trap_continue: + mov %l5, %o2 + call spitfire_access_error + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_access_error,.-__spitfire_access_error + + /* This is the trap handler entry point for ECC correctable +@@ -179,8 +177,7 @@ __spitfire_data_access_exception_tl1: + mov %l5, %o2 + call spitfire_data_access_exception_tl1 + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1 + + .type __spitfire_data_access_exception,#function +@@ -200,8 +197,7 @@ __spitfire_data_access_exception: + mov %l5, %o2 + call spitfire_data_access_exception + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_data_access_exception,.-__spitfire_data_access_exception + + .type __spitfire_insn_access_exception_tl1,#function +@@ -220,8 +216,7 @@ __spitfire_insn_access_exception_tl1: + mov %l5, %o2 + call spitfire_insn_access_exception_tl1 + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1 + + .type __spitfire_insn_access_exception,#function +@@ -240,6 +235,5 @@ __spitfire_insn_access_exception: + mov %l5, %o2 + call spitfire_insn_access_exception + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + .size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception +diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S +index 6dee79575791..db4408e54bee 100644 +--- a/arch/sparc/kernel/syscalls.S ++++ b/arch/sparc/kernel/syscalls.S +@@ -148,7 +148,25 @@ linux_syscall_trace32: + add %sp, PTREGS_OFF, %o0 + brnz,pn %o0, 3f + mov -ENOSYS, %o0 ++ ++ /* Syscall tracing can modify the registers. */ ++ ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ++ sethi %hi(sys_call_table32), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 ++ or %l7, %lo(sys_call_table32), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 ++ ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ++ ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ++ ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ++ ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ++ ++ cmp %g1, NR_syscalls ++ bgeu,pn %xcc, 3f ++ mov -ENOSYS, %o0 ++ ++ sll %g1, 2, %l4 + srl %i0, 0, %o0 ++ lduw [%l7 + %l4], %l7 + srl %i4, 0, %o4 + srl %i1, 0, %o1 + srl %i2, 0, %o2 +@@ -160,7 +178,25 @@ linux_syscall_trace: + add %sp, PTREGS_OFF, %o0 + brnz,pn %o0, 3f + mov -ENOSYS, %o0 ++ ++ /* Syscall tracing can modify the registers. */ ++ ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ++ sethi %hi(sys_call_table64), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 ++ or %l7, %lo(sys_call_table64), %l7 ++ ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 ++ ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ++ ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ++ ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ++ ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ++ ++ cmp %g1, NR_syscalls ++ bgeu,pn %xcc, 3f ++ mov -ENOSYS, %o0 ++ ++ sll %g1, 2, %l4 + mov %i0, %o0 ++ lduw [%l7 + %l4], %l7 + mov %i1, %o1 + mov %i2, %o2 + mov %i3, %o3 +diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S +new file mode 100644 +index 000000000000..5604a2b051d4 +--- /dev/null ++++ b/arch/sparc/kernel/urtt_fill.S +@@ -0,0 +1,98 @@ ++#include <asm/thread_info.h> ++#include <asm/trap_block.h> ++#include <asm/spitfire.h> ++#include <asm/ptrace.h> ++#include <asm/head.h> ++ ++ .text ++ .align 8 ++ .globl user_rtt_fill_fixup_common ++user_rtt_fill_fixup_common: ++ rdpr %cwp, %g1 ++ add %g1, 1, %g1 ++ wrpr %g1, 0x0, %cwp ++ ++ rdpr %wstate, %g2 ++ sll %g2, 3, %g2 ++ wrpr %g2, 0x0, %wstate ++ ++ /* We know %canrestore and %otherwin are both zero. */ ++ ++ sethi %hi(sparc64_kern_pri_context), %g2 ++ ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2 ++ mov PRIMARY_CONTEXT, %g1 ++ ++661: stxa %g2, [%g1] ASI_DMMU ++ .section .sun4v_1insn_patch, "ax" ++ .word 661b ++ stxa %g2, [%g1] ASI_MMU ++ .previous ++ ++ sethi %hi(KERNBASE), %g1 ++ flush %g1 ++ ++ mov %g4, %l4 ++ mov %g5, %l5 ++ brnz,pn %g3, 1f ++ mov %g3, %l3 ++ ++ or %g4, FAULT_CODE_WINFIXUP, %g4 ++ stb %g4, [%g6 + TI_FAULT_CODE] ++ stx %g5, [%g6 + TI_FAULT_ADDR] ++1: ++ mov %g6, %l1 ++ wrpr %g0, 0x0, %tl ++ ++661: nop ++ .section .sun4v_1insn_patch, "ax" ++ .word 661b ++ SET_GL(0) ++ .previous ++ ++ wrpr %g0, RTRAP_PSTATE, %pstate ++ ++ mov %l1, %g6 ++ ldx [%g6 + TI_TASK], %g4 ++ LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3) ++ ++ brnz,pn %l3, 1f ++ nop ++ ++ call do_sparc64_fault ++ add %sp, PTREGS_OFF, %o0 ++ ba,pt %xcc, rtrap ++ nop ++ ++1: cmp %g3, 2 ++ bne,pn %xcc, 2f ++ nop ++ ++ sethi %hi(tlb_type), %g1 ++ lduw [%g1 + %lo(tlb_type)], %g1 ++ cmp %g1, 3 ++ bne,pt %icc, 1f ++ add %sp, PTREGS_OFF, %o0 ++ mov %l4, %o2 ++ call sun4v_do_mna ++ mov %l5, %o1 ++ ba,a,pt %xcc, rtrap ++1: mov %l4, %o1 ++ mov %l5, %o2 ++ call mem_address_unaligned ++ nop ++ ba,a,pt %xcc, rtrap ++ ++2: sethi %hi(tlb_type), %g1 ++ mov %l4, %o1 ++ lduw [%g1 + %lo(tlb_type)], %g1 ++ mov %l5, %o2 ++ cmp %g1, 3 ++ bne,pt %icc, 1f ++ add %sp, PTREGS_OFF, %o0 ++ call sun4v_data_access_exception ++ nop ++ ba,a,pt %xcc, rtrap ++ ++1: call spitfire_data_access_exception ++ nop ++ ba,a,pt %xcc, rtrap +diff --git a/arch/sparc/kernel/utrap.S b/arch/sparc/kernel/utrap.S +index b7f0f3f3a909..c731e8023d3e 100644 +--- a/arch/sparc/kernel/utrap.S ++++ b/arch/sparc/kernel/utrap.S +@@ -11,8 +11,7 @@ utrap_trap: /* %g3=handler,%g4=level */ + mov %l4, %o1 + call bad_trap + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + + invoke_utrap: + sllx %g3, 3, %g3 +diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S +index 09243057cb0b..7028b4dab903 100644 +--- a/arch/sparc/kernel/vmlinux.lds.S ++++ b/arch/sparc/kernel/vmlinux.lds.S +@@ -33,6 +33,10 @@ ENTRY(_start) + jiffies = jiffies_64; + #endif + ++#ifdef CONFIG_SPARC64 ++ASSERT((swapper_tsb == 0x0000000000408000), "Error: sparc64 early assembler too large") ++#endif ++ + SECTIONS + { + #ifdef CONFIG_SPARC64 +diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S +index 1e67ce958369..855019a8590e 100644 +--- a/arch/sparc/kernel/winfixup.S ++++ b/arch/sparc/kernel/winfixup.S +@@ -32,8 +32,7 @@ fill_fixup: + rd %pc, %g7 + call do_sparc64_fault + add %sp, PTREGS_OFF, %o0 +- ba,pt %xcc, rtrap +- nop ++ ba,a,pt %xcc, rtrap + + /* Be very careful about usage of the trap globals here. + * You cannot touch %g5 as that has the fault information. +diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c +index 4438e94822a2..9633e0706d6e 100644 +--- a/arch/sparc/mm/init_64.c ++++ b/arch/sparc/mm/init_64.c +@@ -2673,9 +2673,10 @@ void hugetlb_setup(struct pt_regs *regs) + * the Data-TLB for huge pages. + */ + if (tlb_type == cheetah_plus) { ++ bool need_context_reload = false; + unsigned long ctx; + +- spin_lock(&ctx_alloc_lock); ++ spin_lock_irq(&ctx_alloc_lock); + ctx = mm->context.sparc64_ctx_val; + ctx &= ~CTX_PGSZ_MASK; + ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT; +@@ -2694,9 +2695,12 @@ void hugetlb_setup(struct pt_regs *regs) + * also executing in this address space. + */ + mm->context.sparc64_ctx_val = ctx; +- on_each_cpu(context_reload, mm, 0); ++ need_context_reload = true; + } +- spin_unlock(&ctx_alloc_lock); ++ spin_unlock_irq(&ctx_alloc_lock); ++ ++ if (need_context_reload) ++ on_each_cpu(context_reload, mm, 0); + } + } + #endif +diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile +index 6cf0111783d3..368f3582c93e 100644 +--- a/arch/x86/boot/Makefile ++++ b/arch/x86/boot/Makefile +@@ -168,6 +168,9 @@ isoimage: $(obj)/bzImage + for i in lib lib64 share end ; do \ + if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \ + cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \ ++ if [ -f /usr/$$i/syslinux/ldlinux.c32 ]; then \ ++ cp /usr/$$i/syslinux/ldlinux.c32 $(obj)/isoimage ; \ ++ fi ; \ + break ; \ + fi ; \ + if [ $$i = end ] ; then exit 1 ; fi ; \ +diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c +index 6523534671b6..29957e8e2fc5 100644 +--- a/arch/x86/kernel/amd_nb.c ++++ b/arch/x86/kernel/amd_nb.c +@@ -69,8 +69,8 @@ int amd_cache_northbridges(void) + while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL) + i++; + +- if (i == 0) +- return 0; ++ if (!i) ++ return -ENODEV; + + nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL); + if (!nb) +diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c +index 0c8fc76b2d2c..04e7df068f0e 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel.c ++++ b/arch/x86/kernel/cpu/perf_event_intel.c +@@ -2538,13 +2538,13 @@ __init int intel_pmu_init(void) + * counter, so do not extend mask to generic counters + */ + for_each_event_constraint(c, x86_pmu.event_constraints) { +- if (c->cmask != FIXED_EVENT_FLAGS +- || c->idxmsk64 == INTEL_PMC_MSK_FIXED_REF_CYCLES) { +- continue; ++ if (c->cmask == FIXED_EVENT_FLAGS ++ && c->idxmsk64 != INTEL_PMC_MSK_FIXED_REF_CYCLES) { ++ c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1; + } +- +- c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1; +- c->weight += x86_pmu.num_counters; ++ c->idxmsk64 &= ++ ~(~0ULL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed)); ++ c->weight = hweight64(c->idxmsk64); + } + } + +diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c +index 490fee15fea5..6cd32acb376f 100644 +--- a/arch/x86/kernel/kprobes/core.c ++++ b/arch/x86/kernel/kprobes/core.c +@@ -911,7 +911,19 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) + * normal page fault. + */ + regs->ip = (unsigned long)cur->addr; ++ /* ++ * Trap flag (TF) has been set here because this fault ++ * happened where the single stepping will be done. ++ * So clear it by resetting the current kprobe: ++ */ ++ regs->flags &= ~X86_EFLAGS_TF; ++ ++ /* ++ * If the TF flag was set before the kprobe hit, ++ * don't touch it: ++ */ + regs->flags |= kcb->kprobe_old_flags; ++ + if (kcb->kprobe_status == KPROBE_REENTER) + restore_previous_kprobe(kcb); + else +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index b132551528e5..6620ac307215 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -437,6 +437,13 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, + entry->ecx &= kvm_supported_word6_x86_features; + cpuid_mask(&entry->ecx, 6); + break; ++ case 0x80000007: /* Advanced power management */ ++ /* invariant TSC is CPUID.80000007H:EDX[8] */ ++ entry->edx &= (1 << 8); ++ /* mask against host */ ++ entry->edx &= boot_cpu_data.x86_power; ++ entry->eax = entry->ebx = entry->ecx = 0; ++ break; + case 0x80000008: { + unsigned g_phys_as = (entry->eax >> 16) & 0xff; + unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U); +@@ -467,7 +474,6 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, + case 3: /* Processor serial number */ + case 5: /* MONITOR/MWAIT */ + case 6: /* Thermal management */ +- case 0x80000007: /* Advanced power management */ + case 0xC0000002: + case 0xC0000003: + case 0xC0000004: +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index e0c859e1999a..06b37a671b12 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3009,6 +3009,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, + if (dbgregs->flags) + return -EINVAL; + ++ if (dbgregs->dr6 & ~0xffffffffull) ++ return -EINVAL; ++ if (dbgregs->dr7 & ~0xffffffffull) ++ return -EINVAL; ++ + memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db)); + vcpu->arch.dr6 = dbgregs->dr6; + vcpu->arch.dr7 = dbgregs->dr7; +diff --git a/drivers/base/module.c b/drivers/base/module.c +index db930d3ee312..2a215780eda2 100644 +--- a/drivers/base/module.c ++++ b/drivers/base/module.c +@@ -24,10 +24,12 @@ static char *make_driver_name(struct device_driver *drv) + + static void module_create_drivers_dir(struct module_kobject *mk) + { +- if (!mk || mk->drivers_dir) +- return; ++ static DEFINE_MUTEX(drivers_dir_mutex); + +- mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj); ++ mutex_lock(&drivers_dir_mutex); ++ if (mk && !mk->drivers_dir) ++ mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj); ++ mutex_unlock(&drivers_dir_mutex); + } + + void module_add_driver(struct module *mod, struct device_driver *drv) +diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c +index 8e5e0187506f..3ff21c3e9ab2 100644 +--- a/drivers/crypto/ux500/hash/hash_core.c ++++ b/drivers/crypto/ux500/hash/hash_core.c +@@ -797,7 +797,7 @@ static int hash_process_data(struct hash_device_data *device_data, + &device_data->state); + memmove(req_ctx->state.buffer, + device_data->state.buffer, +- HASH_BLOCK_SIZE / sizeof(u32)); ++ HASH_BLOCK_SIZE); + if (ret) { + dev_err(device_data->dev, + "%s: hash_resume_state() failed!\n", +@@ -848,7 +848,7 @@ static int hash_process_data(struct hash_device_data *device_data, + + memmove(device_data->state.buffer, + req_ctx->state.buffer, +- HASH_BLOCK_SIZE / sizeof(u32)); ++ HASH_BLOCK_SIZE); + if (ret) { + dev_err(device_data->dev, "%s: hash_save_state() failed!\n", + __func__); +diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c +index e5fde4382552..252e2fc83e8e 100644 +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -305,8 +305,6 @@ static struct device_type csrow_attr_type = { + * + */ + +-#define EDAC_NR_CHANNELS 6 +- + DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR, + channel_dimm_label_show, channel_dimm_label_store, 0); + DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR, +@@ -370,9 +368,6 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, + { + int err, chan; + +- if (csrow->nr_channels >= EDAC_NR_CHANNELS) +- return -ENODEV; +- + csrow->dev.type = &csrow_attr_type; + csrow->dev.bus = mci->bus; + device_initialize(&csrow->dev); +diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c +index 55e4920f967b..0cd5f767d861 100644 +--- a/drivers/hid/hid-elo.c ++++ b/drivers/hid/hid-elo.c +@@ -259,7 +259,7 @@ static void elo_remove(struct hid_device *hdev) + struct elo_priv *priv = hid_get_drvdata(hdev); + + hid_hw_stop(hdev); +- flush_workqueue(wq); ++ cancel_delayed_work_sync(&priv->work); + kfree(priv); + } + +diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c +index 2f1ddca6f2e0..700145b15088 100644 +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -516,13 +516,13 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, + goto inval; + } else if (uref->usage_index >= field->report_count) + goto inval; +- +- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && +- (uref_multi->num_values > HID_MAX_MULTI_USAGES || +- uref->usage_index + uref_multi->num_values > field->report_count)) +- goto inval; + } + ++ if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && ++ (uref_multi->num_values > HID_MAX_MULTI_USAGES || ++ uref->usage_index + uref_multi->num_values > field->report_count)) ++ goto inval; ++ + switch (cmd) { + case HIDIOCGUSAGE: + uref->value = field->value[uref->usage_index]; +diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c +index 890c23b3d714..f55d69500a5f 100644 +--- a/drivers/infiniband/hw/mlx4/ah.c ++++ b/drivers/infiniband/hw/mlx4/ah.c +@@ -65,6 +65,7 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr, + + ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24)); + ah->av.ib.g_slid = ah_attr->src_path_bits; ++ ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); + if (ah_attr->ah_flags & IB_AH_GRH) { + ah->av.ib.g_slid |= 0x80; + ah->av.ib.gid_index = ah_attr->grh.sgid_index; +@@ -82,7 +83,6 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr, + !(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support)) + --ah->av.ib.stat_rate; + } +- ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); + + return &ah->ibah; + } +diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c +index cad0e19b47a2..0b569da3c467 100644 +--- a/drivers/macintosh/rack-meter.c ++++ b/drivers/macintosh/rack-meter.c +@@ -225,6 +225,7 @@ static void rackmeter_do_timer(struct work_struct *work) + + total_idle_ticks = get_cpu_idle_time(cpu); + idle_ticks = (unsigned int) (total_idle_ticks - rcpu->prev_idle); ++ idle_ticks = min(idle_ticks, total_ticks); + rcpu->prev_idle = total_idle_ticks; + + /* We do a very dumb calculation to update the LEDs for now, +diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c +index 3b4a157714b1..b40ed32379ec 100644 +--- a/drivers/macintosh/therm_windtunnel.c ++++ b/drivers/macintosh/therm_windtunnel.c +@@ -408,6 +408,7 @@ static const struct i2c_device_id therm_windtunnel_id[] = { + { "therm_adm1030", adm1030 }, + { } + }; ++MODULE_DEVICE_TABLE(i2c, therm_windtunnel_id); + + static int + do_probe(struct i2c_client *cl, const struct i2c_device_id *id) +diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c +index 754ac8ef2484..4736df41f062 100644 +--- a/drivers/net/ethernet/atheros/alx/main.c ++++ b/drivers/net/ethernet/atheros/alx/main.c +@@ -86,9 +86,14 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp) + while (!cur_buf->skb && next != rxq->read_idx) { + struct alx_rfd *rfd = &rxq->rfd[cur]; + +- skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp); ++ skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size + 64, gfp); + if (!skb) + break; ++ ++ /* Workround for the HW RX DMA overflow issue */ ++ if (((unsigned long)skb->data & 0xfff) == 0xfc0) ++ skb_reserve(skb, 64); ++ + dma = dma_map_single(&alx->hw.pdev->dev, + skb->data, alx->rxbuf_size, + DMA_FROM_DEVICE); +diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c +index 151478a59e30..a8cbeed1968a 100644 +--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c ++++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c +@@ -4780,7 +4780,6 @@ static void ql_eeh_close(struct net_device *ndev) + } + + /* Disabling the timer */ +- del_timer_sync(&qdev->timer); + ql_cancel_all_work_sync(qdev); + + for (i = 0; i < qdev->rss_ring_count; i++) +@@ -4807,6 +4806,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + netif_device_detach(ndev); ++ del_timer_sync(&qdev->timer); + if (netif_running(ndev)) + ql_eeh_close(ndev); + pci_disable_device(pdev); +@@ -4814,6 +4814,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, + case pci_channel_io_perm_failure: + dev_err(&pdev->dev, + "%s: pci_channel_io_perm_failure.\n", __func__); ++ del_timer_sync(&qdev->timer); + ql_eeh_close(ndev); + set_bit(QL_EEH_FATAL, &qdev->flags); + return PCI_ERS_RESULT_DISCONNECT; +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index 6ee9665e20b2..a5802419381f 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -477,6 +477,13 @@ advance: + if (cdc_ncm_setup(ctx)) + goto error2; + ++ /* Some firmwares need a pause here or they will silently fail ++ * to set up the interface properly. This value was decided ++ * empirically on a Sierra Wireless MC7455 running 02.08.02.00 ++ * firmware. ++ */ ++ usleep_range(10000, 20000); ++ + /* configure data interface */ + temp = usb_set_interface(dev->udev, iface_no, data_altsetting); + if (temp) +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index c8e333306c4c..73790abf0c2a 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -1037,7 +1037,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + + /* Need Vxlan and inner Ethernet header to be present */ + if (!pskb_may_pull(skb, VXLAN_HLEN)) +- goto error; ++ goto drop; + + /* Return packets with reserved bits set */ + vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1); +@@ -1045,7 +1045,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) + (vxh->vx_vni & htonl(0xff))) { + netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n", + ntohl(vxh->vx_flags), ntohl(vxh->vx_vni)); +- goto error; ++ goto drop; + } + + if (iptunnel_pull_header(skb, VXLAN_HLEN, htons(ETH_P_TEB))) +@@ -1073,10 +1073,6 @@ drop: + /* Consume bad packet */ + kfree_skb(skb); + return 0; +- +-error: +- /* Return non vxlan pkt */ +- return 1; + } + + static void vxlan_rcv(struct vxlan_sock *vs, +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 38b8b7139ba3..38fa31d56ef9 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -1932,6 +1932,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, + if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || + !info->attrs[HWSIM_ATTR_FLAGS] || + !info->attrs[HWSIM_ATTR_COOKIE] || ++ !info->attrs[HWSIM_ATTR_SIGNAL] || + !info->attrs[HWSIM_ATTR_TX_INFO]) + goto out; + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index 1e480a898d28..36c3e71d54b5 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -25,6 +25,7 @@ + #include <linux/pci_hotplug.h> + #include <asm-generic/pci-bridge.h> + #include <asm/setup.h> ++#include <linux/aer.h> + #include "pci.h" + + const char *pci_power_names[] = { +@@ -1005,6 +1006,8 @@ void pci_restore_state(struct pci_dev *dev) + pci_restore_pcie_state(dev); + pci_restore_ats_state(dev); + ++ pci_cleanup_aer_error_status_regs(dev); ++ + pci_restore_config_space(dev); + + pci_restore_pcix_state(dev); +diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c +index 28d4c0a0d31a..382eacfd5636 100644 +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -74,6 +74,34 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); + ++int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) ++{ ++ int pos; ++ u32 status; ++ int port_type; ++ ++ if (!pci_is_pcie(dev)) ++ return -ENODEV; ++ ++ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); ++ if (!pos) ++ return -EIO; ++ ++ port_type = pci_pcie_type(dev); ++ if (port_type == PCI_EXP_TYPE_ROOT_PORT) { ++ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status); ++ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status); ++ } ++ ++ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); ++ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status); ++ ++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); ++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); ++ ++ return 0; ++} ++ + /** + * add_error_device - list device to be handled + * @e_info: pointer to error info +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 53b23ff577b4..4e415a85da29 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -10,6 +10,7 @@ + #include <linux/module.h> + #include <linux/cpumask.h> + #include <linux/pci-aspm.h> ++#include <linux/aer.h> + #include <asm-generic/pci-bridge.h> + #include "pci.h" + +@@ -1356,6 +1357,8 @@ static void pci_init_capabilities(struct pci_dev *dev) + + /* Enable ACS P2P upstream forwarding */ + pci_enable_acs(dev); ++ ++ pci_cleanup_aer_error_status_regs(dev); + } + + void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 2b01c88ad416..aeff39767588 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -540,66 +540,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost) + + static void __scsi_release_buffers(struct scsi_cmnd *, int); + +-/* +- * Function: scsi_end_request() +- * +- * Purpose: Post-processing of completed commands (usually invoked at end +- * of upper level post-processing and scsi_io_completion). +- * +- * Arguments: cmd - command that is complete. +- * error - 0 if I/O indicates success, < 0 for I/O error. +- * bytes - number of bytes of completed I/O +- * requeue - indicates whether we should requeue leftovers. +- * +- * Lock status: Assumed that lock is not held upon entry. +- * +- * Returns: cmd if requeue required, NULL otherwise. +- * +- * Notes: This is called for block device requests in order to +- * mark some number of sectors as complete. +- * +- * We are guaranteeing that the request queue will be goosed +- * at some point during this call. +- * Notes: If cmd was requeued, upon return it will be a stale pointer. +- */ +-static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error, +- int bytes, int requeue) +-{ +- struct request_queue *q = cmd->device->request_queue; +- struct request *req = cmd->request; +- +- /* +- * If there are blocks left over at the end, set up the command +- * to queue the remainder of them. +- */ +- if (blk_end_request(req, error, bytes)) { +- /* kill remainder if no retrys */ +- if (error && scsi_noretry_cmd(cmd)) +- blk_end_request_all(req, error); +- else { +- if (requeue) { +- /* +- * Bleah. Leftovers again. Stick the +- * leftovers in the front of the +- * queue, and goose the queue again. +- */ +- scsi_release_buffers(cmd); +- scsi_requeue_command(q, cmd); +- cmd = NULL; +- } +- return cmd; +- } +- } +- +- /* +- * This will goose the queue request function at the end, so we don't +- * need to worry about launching another command. +- */ +- __scsi_release_buffers(cmd, 0); +- scsi_next_command(cmd); +- return NULL; +-} +- + static inline unsigned int scsi_sgtable_index(unsigned short nents) + { + unsigned int index; +@@ -751,16 +691,9 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) + * + * Returns: Nothing + * +- * Notes: This function is matched in terms of capabilities to +- * the function that created the scatter-gather list. +- * In other words, if there are no bounce buffers +- * (the normal case for most drivers), we don't need +- * the logic to deal with cleaning up afterwards. +- * +- * We must call scsi_end_request(). This will finish off +- * the specified number of sectors. If we are done, the +- * command block will be released and the queue function +- * will be goosed. If we are not done then we have to ++ * Notes: We will finish off the specified number of sectors. If we ++ * are done, the command block will be released and the queue ++ * function will be goosed. If we are not done then we have to + * figure out what to do next: + * + * a) We can call scsi_requeue_command(). The request +@@ -769,7 +702,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) + * be used if we made forward progress, or if we want + * to switch from READ(10) to READ(6) for example. + * +- * b) We can call scsi_queue_insert(). The request will ++ * b) We can call __scsi_queue_insert(). The request will + * be put back on the queue and retried using the same + * command as before, possibly after a delay. + * +@@ -873,12 +806,28 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) + } + + /* +- * A number of bytes were successfully read. If there +- * are leftovers and there is some kind of error +- * (result != 0), retry the rest. ++ * special case: failed zero length commands always need to ++ * drop down into the retry code. Otherwise, if we finished ++ * all bytes in the request we are done now. + */ +- if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) +- return; ++ if (!(blk_rq_bytes(req) == 0 && error) && ++ !blk_end_request(req, error, good_bytes)) ++ goto next_command; ++ ++ /* ++ * Kill remainder if no retrys. ++ */ ++ if (error && scsi_noretry_cmd(cmd)) { ++ blk_end_request_all(req, error); ++ goto next_command; ++ } ++ ++ /* ++ * If there had been no error, but we have leftover bytes in the ++ * requeues just queue the command up again. ++ */ ++ if (result == 0) ++ goto requeue; + + error = __scsi_error_from_host_byte(cmd, result); + +@@ -1000,7 +949,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) + switch (action) { + case ACTION_FAIL: + /* Give up and fail the remainder of the request */ +- scsi_release_buffers(cmd); + if (!(req->cmd_flags & REQ_QUIET)) { + if (description) + scmd_printk(KERN_INFO, cmd, "%s\n", +@@ -1010,12 +958,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) + scsi_print_sense("", cmd); + scsi_print_command(cmd); + } +- if (blk_end_request_err(req, error)) +- scsi_requeue_command(q, cmd); +- else +- scsi_next_command(cmd); +- break; ++ if (!blk_end_request_err(req, error)) ++ goto next_command; ++ /*FALLTHRU*/ + case ACTION_REPREP: ++ requeue: + /* Unprep the request and put it back at the head of the queue. + * A new command will be prepared and issued. + */ +@@ -1031,6 +978,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) + __scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0); + break; + } ++ return; ++ ++next_command: ++ __scsi_release_buffers(cmd, 0); ++ scsi_next_command(cmd); + } + + static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, +diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c +index 054ec2c412a4..25073167bcc4 100644 +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -54,6 +54,7 @@ + * Default timeout + */ + #define SCSI_TIMEOUT (2*HZ) ++#define SCSI_REPORT_LUNS_TIMEOUT (30*HZ) + + /* + * Prefix values for the SCSI id's (stored in sysfs name field) +@@ -1447,7 +1448,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, + + result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, + lun_data, length, &sshdr, +- SCSI_TIMEOUT + 4 * HZ, 3, NULL); ++ SCSI_REPORT_LUNS_TIMEOUT, 3, NULL); + + SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" + " %s (try %d) result 0x%x\n", result +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index c076050cab47..a7b10c18759c 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -1106,10 +1106,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) + + static int proc_connectinfo(struct dev_state *ps, void __user *arg) + { +- struct usbdevfs_connectinfo ci = { +- .devnum = ps->dev->devnum, +- .slow = ps->dev->speed == USB_SPEED_LOW +- }; ++ struct usbdevfs_connectinfo ci; ++ ++ memset(&ci, 0, sizeof(ci)); ++ ci.devnum = ps->dev->devnum; ++ ci.slow = ps->dev->speed == USB_SPEED_LOW; + + if (copy_to_user(arg, &ci, sizeof(ci))) + return -EFAULT; +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 9596d4f3e71a..ba39d978583c 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -225,6 +225,9 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = { + /* Logitech Optical Mouse M90/M100 */ + { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Acer C120 LED Projector */ ++ { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM }, ++ + /* Blackmagic Design Intensity Shuttle */ + { USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM }, + +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index d73cda3591aa..7be2ad0a10f4 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -584,14 +584,13 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) + musb_writew(ep->regs, MUSB_TXCSR, 0); + + /* scrub all previous state, clearing toggle */ +- } else { +- csr = musb_readw(ep->regs, MUSB_RXCSR); +- if (csr & MUSB_RXCSR_RXPKTRDY) +- WARNING("rx%d, packet/%d ready?\n", ep->epnum, +- musb_readw(ep->regs, MUSB_RXCOUNT)); +- +- musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG); + } ++ csr = musb_readw(ep->regs, MUSB_RXCSR); ++ if (csr & MUSB_RXCSR_RXPKTRDY) ++ WARNING("rx%d, packet/%d ready?\n", ep->epnum, ++ musb_readw(ep->regs, MUSB_RXCOUNT)); ++ ++ musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG); + + /* target addr and (for multipoint) hub addr/port */ + if (musb->is_multipoint) { +@@ -951,9 +950,15 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep, + if (is_in) { + dma = is_dma_capable() ? ep->rx_channel : NULL; + +- /* clear nak timeout bit */ ++ /* ++ * Need to stop the transaction by clearing REQPKT first ++ * then the NAK Timeout bit ref MUSBMHDRC USB 2.0 HIGH-SPEED ++ * DUAL-ROLE CONTROLLER Programmer's Guide, section 9.2.2 ++ */ + rx_csr = musb_readw(epio, MUSB_RXCSR); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; ++ rx_csr &= ~MUSB_RXCSR_H_REQPKT; ++ musb_writew(epio, MUSB_RXCSR, rx_csr); + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); + +diff --git a/fs/dcache.c b/fs/dcache.c +index 40bf046884b1..9befdcea22fa 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1529,7 +1529,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) + struct dentry *dentry = __d_alloc(parent->d_sb, name); + if (!dentry) + return NULL; +- ++ dentry->d_flags |= DCACHE_RCUACCESS; + spin_lock(&parent->d_lock); + /* + * don't need child lock because it is not subject +@@ -2319,7 +2319,6 @@ static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b) + { + BUG_ON(!d_unhashed(entry)); + hlist_bl_lock(b); +- entry->d_flags |= DCACHE_RCUACCESS; + hlist_bl_add_head_rcu(&entry->d_hash, b); + hlist_bl_unlock(b); + } +@@ -2503,6 +2502,7 @@ static void __d_move(struct dentry * dentry, struct dentry * target) + + /* ... and switch the parents */ + if (IS_ROOT(dentry)) { ++ dentry->d_flags |= DCACHE_RCUACCESS; + dentry->d_parent = target->d_parent; + target->d_parent = target; + INIT_LIST_HEAD(&target->d_child); +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index f3fd66acae47..da02f7c16e0d 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -178,6 +178,19 @@ out: + return rc; + } + ++static int ecryptfs_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct file *lower_file = ecryptfs_file_to_lower(file); ++ /* ++ * Don't allow mmap on top of file systems that don't support it ++ * natively. If FILESYSTEM_MAX_STACK_DEPTH > 2 or ecryptfs ++ * allows recursive mounting, this will need to be extended. ++ */ ++ if (!lower_file->f_op->mmap) ++ return -ENODEV; ++ return generic_file_mmap(file, vma); ++} ++ + /** + * ecryptfs_open + * @inode: inode speciying file to open +@@ -353,7 +366,7 @@ const struct file_operations ecryptfs_main_fops = { + #ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, + #endif +- .mmap = generic_file_mmap, ++ .mmap = ecryptfs_mmap, + .open = ecryptfs_open, + .flush = ecryptfs_flush, + .release = ecryptfs_release, +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index cf6ede69a2e2..b9670301d7d3 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1483,9 +1483,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, + err = PTR_ERR(inode); + trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); + put_nfs_open_context(ctx); ++ d_drop(dentry); + switch (err) { + case -ENOENT: +- d_drop(dentry); + d_add(dentry, NULL); + break; + case -EISDIR: +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index ae85a71e5045..a94ec130003b 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -2569,12 +2569,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + call_close |= is_wronly; + else if (is_wronly) + calldata->arg.fmode |= FMODE_WRITE; ++ if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE)) ++ call_close |= is_rdwr; + } else if (is_rdwr) + calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; + +- if (calldata->arg.fmode == 0) +- call_close |= is_rdwr; +- + if (!nfs4_valid_open_stateid(state)) + call_close = 0; + spin_unlock(&state->owner->so_lock); +diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c +index b56eb6275744..c0d8fde3e6d9 100644 +--- a/fs/ubifs/file.c ++++ b/fs/ubifs/file.c +@@ -54,6 +54,7 @@ + #include <linux/mount.h> + #include <linux/namei.h> + #include <linux/slab.h> ++#include <linux/migrate.h> + + static int read_block(struct inode *inode, void *addr, unsigned int block, + struct ubifs_data_node *dn) +@@ -1423,6 +1424,26 @@ static int ubifs_set_page_dirty(struct page *page) + return ret; + } + ++#ifdef CONFIG_MIGRATION ++static int ubifs_migrate_page(struct address_space *mapping, ++ struct page *newpage, struct page *page, enum migrate_mode mode) ++{ ++ int rc; ++ ++ rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0); ++ if (rc != MIGRATEPAGE_SUCCESS) ++ return rc; ++ ++ if (PagePrivate(page)) { ++ ClearPagePrivate(page); ++ SetPagePrivate(newpage); ++ } ++ ++ migrate_page_copy(newpage, page); ++ return MIGRATEPAGE_SUCCESS; ++} ++#endif ++ + static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags) + { + /* +@@ -1559,6 +1580,9 @@ const struct address_space_operations ubifs_file_address_operations = { + .write_end = ubifs_write_end, + .invalidatepage = ubifs_invalidatepage, + .set_page_dirty = ubifs_set_page_dirty, ++#ifdef CONFIG_MIGRATION ++ .migratepage = ubifs_migrate_page, ++#endif + .releasepage = ubifs_releasepage, + }; + +diff --git a/include/linux/aer.h b/include/linux/aer.h +index 4dbaa7081530..1cbc28eb1f90 100644 +--- a/include/linux/aer.h ++++ b/include/linux/aer.h +@@ -38,6 +38,7 @@ struct aer_capability_regs { + int pci_enable_pcie_error_reporting(struct pci_dev *dev); + int pci_disable_pcie_error_reporting(struct pci_dev *dev); + int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); ++int pci_cleanup_aer_error_status_regs(struct pci_dev *dev); + #else + static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) + { +@@ -51,6 +52,10 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) + { + return -EINVAL; + } ++static inline int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) ++{ ++ return -EINVAL; ++} + #endif + + void cper_print_aer(struct pci_dev *dev, int cper_severity, +diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h +index dd49566315c6..1d24aa71f773 100644 +--- a/include/linux/netfilter/x_tables.h ++++ b/include/linux/netfilter/x_tables.h +@@ -239,11 +239,18 @@ extern void xt_unregister_match(struct xt_match *target); + extern int xt_register_matches(struct xt_match *match, unsigned int n); + extern void xt_unregister_matches(struct xt_match *match, unsigned int n); + ++int xt_check_entry_offsets(const void *base, const char *elems, ++ unsigned int target_offset, ++ unsigned int next_offset); ++ + extern int xt_check_match(struct xt_mtchk_param *, + unsigned int size, u_int8_t proto, bool inv_proto); + extern int xt_check_target(struct xt_tgchk_param *, + unsigned int size, u_int8_t proto, bool inv_proto); + ++void *xt_copy_counters_from_user(const void __user *user, unsigned int len, ++ struct xt_counters_info *info, bool compat); ++ + extern struct xt_table *xt_register_table(struct net *net, + const struct xt_table *table, + struct xt_table_info *bootstrap, +@@ -423,7 +430,7 @@ extern void xt_compat_init_offsets(u_int8_t af, unsigned int number); + extern int xt_compat_calc_jump(u_int8_t af, unsigned int offset); + + extern int xt_compat_match_offset(const struct xt_match *match); +-extern int xt_compat_match_from_user(struct xt_entry_match *m, ++extern void xt_compat_match_from_user(struct xt_entry_match *m, + void **dstptr, unsigned int *size); + extern int xt_compat_match_to_user(const struct xt_entry_match *m, + void __user **dstptr, unsigned int *size); +@@ -433,6 +440,9 @@ extern void xt_compat_target_from_user(struct xt_entry_target *t, + void **dstptr, unsigned int *size); + extern int xt_compat_target_to_user(const struct xt_entry_target *t, + void __user **dstptr, unsigned int *size); ++int xt_compat_check_entry_offsets(const void *base, const char *elems, ++ unsigned int target_offset, ++ unsigned int next_offset); + + #endif /* CONFIG_COMPAT */ + #endif /* _X_TABLES_H */ +diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h +index daec99af5d54..1c88b177cb9c 100644 +--- a/include/linux/usb/ehci_def.h ++++ b/include/linux/usb/ehci_def.h +@@ -178,11 +178,11 @@ struct ehci_regs { + * PORTSCx + */ + /* HOSTPC: offset 0x84 */ +- u32 hostpc[1]; /* HOSTPC extension */ ++ u32 hostpc[0]; /* HOSTPC extension */ + #define HOSTPC_PHCD (1<<22) /* Phy clock disable */ + #define HOSTPC_PSPD (3<<25) /* Port speed detection */ + +- u32 reserved5[16]; ++ u32 reserved5[17]; + + /* USBMODE_EX: offset 0xc8 */ + u32 usbmode_ex; /* USB Device mode extension */ +diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c +index aa149222cd8e..63903212933a 100644 +--- a/kernel/hrtimer.c ++++ b/kernel/hrtimer.c +@@ -349,6 +349,7 @@ u64 ktime_divns(const ktime_t kt, s64 div) + + return dclc; + } ++EXPORT_SYMBOL_GPL(ktime_divns); + #endif /* BITS_PER_LONG >= 64 */ + + /* +diff --git a/kernel/signal.c b/kernel/signal.c +index e99136208d7e..1a1b0e88c23d 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -3004,11 +3004,9 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) + * Nor can they impersonate a kill()/tgkill(), which adds source info. + */ + if ((info->si_code >= 0 || info->si_code == SI_TKILL) && +- (task_pid_vnr(current) != pid)) { +- /* We used to allow any < 0 si_code */ +- WARN_ON_ONCE(info->si_code < 0); ++ (task_pid_vnr(current) != pid)) + return -EPERM; +- } ++ + info->si_signo = sig; + + /* POSIX.1b doesn't mention process groups. */ +@@ -3053,12 +3051,10 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) + /* Not even root can pretend to send signals from the kernel. + * Nor can they impersonate a kill()/tgkill(), which adds source info. + */ +- if (((info->si_code >= 0 || info->si_code == SI_TKILL)) && +- (task_pid_vnr(current) != pid)) { +- /* We used to allow any < 0 si_code */ +- WARN_ON_ONCE(info->si_code < 0); ++ if ((info->si_code >= 0 || info->si_code == SI_TKILL) && ++ (task_pid_vnr(current) != pid)) + return -EPERM; +- } ++ + info->si_signo = sig; + + return do_send_specific(tgid, pid, sig, info); +diff --git a/mm/migrate.c b/mm/migrate.c +index 0c14c0e1bdd6..71a2533ca8f5 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -399,6 +399,7 @@ int migrate_page_move_mapping(struct address_space *mapping, + + return MIGRATEPAGE_SUCCESS; + } ++EXPORT_SYMBOL(migrate_page_move_mapping); + + /* + * The expected number of remaining references is the same as that +@@ -549,6 +550,7 @@ void migrate_page_copy(struct page *newpage, struct page *page) + if (PageWriteback(newpage)) + end_page_writeback(newpage); + } ++EXPORT_SYMBOL(migrate_page_copy); + + /************************************************************ + * Migration functions +diff --git a/mm/swap.c b/mm/swap.c +index 16e70ce1912a..a8e94391b2de 100644 +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -410,7 +410,7 @@ void rotate_reclaimable_page(struct page *page) + page_cache_get(page); + local_irq_save(flags); + pvec = &__get_cpu_var(lru_rotate_pvecs); +- if (!pagevec_add(pvec, page)) ++ if (!pagevec_add(pvec, page) || PageCompound(page)) + pagevec_move_tail(pvec); + local_irq_restore(flags); + } +@@ -466,7 +466,7 @@ void activate_page(struct page *page) + struct pagevec *pvec = &get_cpu_var(activate_page_pvecs); + + page_cache_get(page); +- if (!pagevec_add(pvec, page)) ++ if (!pagevec_add(pvec, page) || PageCompound(page)) + pagevec_lru_move_fn(pvec, __activate_page, NULL); + put_cpu_var(activate_page_pvecs); + } +@@ -564,9 +564,8 @@ static void __lru_cache_add(struct page *page) + struct pagevec *pvec = &get_cpu_var(lru_add_pvec); + + page_cache_get(page); +- if (!pagevec_space(pvec)) ++ if (!pagevec_add(pvec, page) || PageCompound(page)) + __pagevec_lru_add(pvec); +- pagevec_add(pvec, page); + put_cpu_var(lru_add_pvec); + } + +@@ -745,7 +744,7 @@ void deactivate_page(struct page *page) + if (likely(get_page_unless_zero(page))) { + struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs); + +- if (!pagevec_add(pvec, page)) ++ if (!pagevec_add(pvec, page) || PageCompound(page)) + pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL); + put_cpu_var(lru_deactivate_pvecs); + } +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index f2c104900163..91fed8147c39 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -449,8 +449,11 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, + if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, + &ip6h->saddr)) { + kfree_skb(skb); ++ br->has_ipv6_addr = 0; + return NULL; + } ++ ++ br->has_ipv6_addr = 1; + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + + hopopt = (u8 *)(ip6h + 1); +@@ -1776,6 +1779,7 @@ void br_multicast_init(struct net_bridge *br) + #if IS_ENABLED(CONFIG_IPV6) + br->ip6_querier.delay_time = 0; + #endif ++ br->has_ipv6_addr = 1; + + spin_lock_init(&br->multicast_lock); + setup_timer(&br->multicast_router_timer, +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index f02acd7c5472..8b7db15212b9 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -265,6 +265,7 @@ struct net_bridge + u8 multicast_disabled:1; + u8 multicast_querier:1; + u8 multicast_query_use_ifaddr:1; ++ u8 has_ipv6_addr:1; + + u32 hash_elasticity; + u32 hash_max; +@@ -512,10 +513,22 @@ static inline bool br_multicast_is_router(struct net_bridge *br) + + static inline bool + __br_multicast_querier_exists(struct net_bridge *br, +- struct bridge_mcast_querier *querier) +-{ ++ struct bridge_mcast_querier *querier, ++ const bool is_ipv6) ++{ ++ bool own_querier_enabled; ++ ++ if (br->multicast_querier) { ++ if (is_ipv6 && !br->has_ipv6_addr) ++ own_querier_enabled = false; ++ else ++ own_querier_enabled = true; ++ } else { ++ own_querier_enabled = false; ++ } ++ + return time_is_before_jiffies(querier->delay_time) && +- (br->multicast_querier || timer_pending(&querier->timer)); ++ (own_querier_enabled || timer_pending(&querier->timer)); + } + + static inline bool br_multicast_querier_exists(struct net_bridge *br, +@@ -523,10 +536,12 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br, + { + switch (eth->h_proto) { + case (htons(ETH_P_IP)): +- return __br_multicast_querier_exists(br, &br->ip4_querier); ++ return __br_multicast_querier_exists(br, ++ &br->ip4_querier, false); + #if IS_ENABLED(CONFIG_IPV6) + case (htons(ETH_P_IPV6)): +- return __br_multicast_querier_exists(br, &br->ip6_querier); ++ return __br_multicast_querier_exists(br, ++ &br->ip6_querier, true); + #endif + default: + return false; +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 2f8de5f9c032..dccda72bac62 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -881,8 +881,10 @@ static struct mfc_cache *ipmr_cache_alloc(void) + { + struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); + +- if (c) ++ if (c) { ++ c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; + c->mfc_un.res.minvif = MAXVIFS; ++ } + return c; + } + +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 456fc6efe05d..95a5f261fe8a 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -430,6 +430,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct arpt_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -452,6 +454,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct arpt_entry *) + (entry0 + newpos); +@@ -465,23 +469,6 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + return 1; + } + +-static inline int check_entry(const struct arpt_entry *e) +-{ +- const struct xt_entry_target *t; +- +- if (!arp_checkentry(&e->arp)) +- return -EINVAL; +- +- if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset) +- return -EINVAL; +- +- t = arpt_get_target_c(e); +- if (e->target_offset + t->u.target_size > e->next_offset) +- return -EINVAL; +- +- return 0; +-} +- + static inline int check_target(struct arpt_entry *e, const char *name) + { + struct xt_entry_target *t = arpt_get_target(e); +@@ -571,7 +558,11 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, + return -EINVAL; + } + +- err = check_entry(e); ++ if (!arp_checkentry(&e->arp)) ++ return -EINVAL; ++ ++ err = xt_check_entry_offsets(e, e->elems, e->target_offset, ++ e->next_offset); + if (err) + return err; + +@@ -675,10 +666,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, + } + } + +- if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { +- duprintf("Looping hook\n"); ++ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) + return -ELOOP; +- } + + /* Finally, each sanity check must pass */ + i = 0; +@@ -1071,6 +1060,9 @@ static int do_replace(struct net *net, const void __user *user, + /* overflow check */ + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; ++ if (tmp.num_counters == 0) ++ return -EINVAL; ++ + tmp.name[sizeof(tmp.name)-1] = 0; + + newinfo = xt_alloc_table_info(tmp.size); +@@ -1111,56 +1103,18 @@ static int do_add_counters(struct net *net, const void __user *user, + unsigned int i, curcpu; + struct xt_counters_info tmp; + struct xt_counters *paddc; +- unsigned int num_counters; +- const char *name; +- int size; +- void *ptmp; + struct xt_table *t; + const struct xt_table_info *private; + int ret = 0; + void *loc_cpu_entry; + struct arpt_entry *iter; + unsigned int addend; +-#ifdef CONFIG_COMPAT +- struct compat_xt_counters_info compat_tmp; +- +- if (compat) { +- ptmp = &compat_tmp; +- size = sizeof(struct compat_xt_counters_info); +- } else +-#endif +- { +- ptmp = &tmp; +- size = sizeof(struct xt_counters_info); +- } +- +- if (copy_from_user(ptmp, user, size) != 0) +- return -EFAULT; +- +-#ifdef CONFIG_COMPAT +- if (compat) { +- num_counters = compat_tmp.num_counters; +- name = compat_tmp.name; +- } else +-#endif +- { +- num_counters = tmp.num_counters; +- name = tmp.name; +- } + +- if (len != size + num_counters * sizeof(struct xt_counters)) +- return -EINVAL; ++ paddc = xt_copy_counters_from_user(user, len, &tmp, compat); ++ if (IS_ERR(paddc)) ++ return PTR_ERR(paddc); + +- paddc = vmalloc(len - size); +- if (!paddc) +- return -ENOMEM; +- +- if (copy_from_user(paddc, user + size, len - size) != 0) { +- ret = -EFAULT; +- goto free; +- } +- +- t = xt_find_table_lock(net, NFPROTO_ARP, name); ++ t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name); + if (IS_ERR_OR_NULL(t)) { + ret = t ? PTR_ERR(t) : -ENOENT; + goto free; +@@ -1168,7 +1122,7 @@ static int do_add_counters(struct net *net, const void __user *user, + + local_bh_disable(); + private = t->private; +- if (private->number != num_counters) { ++ if (private->number != tmp.num_counters) { + ret = -EINVAL; + goto unlock_up_free; + } +@@ -1194,6 +1148,18 @@ static int do_add_counters(struct net *net, const void __user *user, + } + + #ifdef CONFIG_COMPAT ++struct compat_arpt_replace { ++ char name[XT_TABLE_MAXNAMELEN]; ++ u32 valid_hooks; ++ u32 num_entries; ++ u32 size; ++ u32 hook_entry[NF_ARP_NUMHOOKS]; ++ u32 underflow[NF_ARP_NUMHOOKS]; ++ u32 num_counters; ++ compat_uptr_t counters; ++ struct compat_arpt_entry entries[0]; ++}; ++ + static inline void compat_release_entry(struct compat_arpt_entry *e) + { + struct xt_entry_target *t; +@@ -1202,20 +1168,17 @@ static inline void compat_release_entry(struct compat_arpt_entry *e) + module_put(t->u.kernel.target->me); + } + +-static inline int ++static int + check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, + struct xt_table_info *newinfo, + unsigned int *size, + const unsigned char *base, +- const unsigned char *limit, +- const unsigned int *hook_entries, +- const unsigned int *underflows, +- const char *name) ++ const unsigned char *limit) + { + struct xt_entry_target *t; + struct xt_target *target; + unsigned int entry_offset; +- int ret, off, h; ++ int ret, off; + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 || +@@ -1232,8 +1195,11 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, + return -EINVAL; + } + +- /* For purposes of check_entry casting the compat entry is fine */ +- ret = check_entry((struct arpt_entry *)e); ++ if (!arp_checkentry(&e->arp)) ++ return -EINVAL; ++ ++ ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset, ++ e->next_offset); + if (ret) + return ret; + +@@ -1257,17 +1223,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, + if (ret) + goto release_target; + +- /* Check hooks & underflows */ +- for (h = 0; h < NF_ARP_NUMHOOKS; h++) { +- if ((unsigned char *)e - base == hook_entries[h]) +- newinfo->hook_entry[h] = hook_entries[h]; +- if ((unsigned char *)e - base == underflows[h]) +- newinfo->underflow[h] = underflows[h]; +- } +- +- /* Clear counters and comefrom */ +- memset(&e->counters, 0, sizeof(e->counters)); +- e->comefrom = 0; + return 0; + + release_target: +@@ -1276,18 +1231,17 @@ out: + return ret; + } + +-static int ++static void + compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, +- unsigned int *size, const char *name, ++ unsigned int *size, + struct xt_table_info *newinfo, unsigned char *base) + { + struct xt_entry_target *t; + struct xt_target *target; + struct arpt_entry *de; + unsigned int origsize; +- int ret, h; ++ int h; + +- ret = 0; + origsize = *size; + de = (struct arpt_entry *)*dstptr; + memcpy(de, e, sizeof(struct arpt_entry)); +@@ -1308,144 +1262,81 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, + if ((unsigned char *)de - base < newinfo->underflow[h]) + newinfo->underflow[h] -= origsize - *size; + } +- return ret; + } + +-static int translate_compat_table(const char *name, +- unsigned int valid_hooks, +- struct xt_table_info **pinfo, ++static int translate_compat_table(struct xt_table_info **pinfo, + void **pentry0, +- unsigned int total_size, +- unsigned int number, +- unsigned int *hook_entries, +- unsigned int *underflows) ++ const struct compat_arpt_replace *compatr) + { + unsigned int i, j; + struct xt_table_info *newinfo, *info; + void *pos, *entry0, *entry1; + struct compat_arpt_entry *iter0; +- struct arpt_entry *iter1; ++ struct arpt_replace repl; + unsigned int size; + int ret = 0; + + info = *pinfo; + entry0 = *pentry0; +- size = total_size; +- info->number = number; +- +- /* Init all hooks to impossible value. */ +- for (i = 0; i < NF_ARP_NUMHOOKS; i++) { +- info->hook_entry[i] = 0xFFFFFFFF; +- info->underflow[i] = 0xFFFFFFFF; +- } ++ size = compatr->size; ++ info->number = compatr->num_entries; + + duprintf("translate_compat_table: size %u\n", info->size); + j = 0; + xt_compat_lock(NFPROTO_ARP); +- xt_compat_init_offsets(NFPROTO_ARP, number); ++ xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries); + /* Walk through entries, checking offsets. */ +- xt_entry_foreach(iter0, entry0, total_size) { ++ xt_entry_foreach(iter0, entry0, compatr->size) { + ret = check_compat_entry_size_and_hooks(iter0, info, &size, + entry0, +- entry0 + total_size, +- hook_entries, +- underflows, +- name); ++ entry0 + compatr->size); + if (ret != 0) + goto out_unlock; + ++j; + } + + ret = -EINVAL; +- if (j != number) { ++ if (j != compatr->num_entries) { + duprintf("translate_compat_table: %u not %u entries\n", +- j, number); ++ j, compatr->num_entries); + goto out_unlock; + } + +- /* Check hooks all assigned */ +- for (i = 0; i < NF_ARP_NUMHOOKS; i++) { +- /* Only hooks which are valid */ +- if (!(valid_hooks & (1 << i))) +- continue; +- if (info->hook_entry[i] == 0xFFFFFFFF) { +- duprintf("Invalid hook entry %u %u\n", +- i, hook_entries[i]); +- goto out_unlock; +- } +- if (info->underflow[i] == 0xFFFFFFFF) { +- duprintf("Invalid underflow %u %u\n", +- i, underflows[i]); +- goto out_unlock; +- } +- } +- + ret = -ENOMEM; + newinfo = xt_alloc_table_info(size); + if (!newinfo) + goto out_unlock; + +- newinfo->number = number; ++ newinfo->number = compatr->num_entries; + for (i = 0; i < NF_ARP_NUMHOOKS; i++) { + newinfo->hook_entry[i] = info->hook_entry[i]; + newinfo->underflow[i] = info->underflow[i]; + } + entry1 = newinfo->entries[raw_smp_processor_id()]; + pos = entry1; +- size = total_size; +- xt_entry_foreach(iter0, entry0, total_size) { +- ret = compat_copy_entry_from_user(iter0, &pos, &size, +- name, newinfo, entry1); +- if (ret != 0) +- break; +- } ++ size = compatr->size; ++ xt_entry_foreach(iter0, entry0, compatr->size) ++ compat_copy_entry_from_user(iter0, &pos, &size, ++ newinfo, entry1); ++ ++ /* all module references in entry0 are now gone */ ++ + xt_compat_flush_offsets(NFPROTO_ARP); + xt_compat_unlock(NFPROTO_ARP); +- if (ret) +- goto free_newinfo; + +- ret = -ELOOP; +- if (!mark_source_chains(newinfo, valid_hooks, entry1)) +- goto free_newinfo; ++ memcpy(&repl, compatr, sizeof(*compatr)); + +- i = 0; +- xt_entry_foreach(iter1, entry1, newinfo->size) { +- ret = check_target(iter1, name); +- if (ret != 0) +- break; +- ++i; +- if (strcmp(arpt_get_target(iter1)->u.user.name, +- XT_ERROR_TARGET) == 0) +- ++newinfo->stacksize; +- } +- if (ret) { +- /* +- * The first i matches need cleanup_entry (calls ->destroy) +- * because they had called ->check already. The other j-i +- * entries need only release. +- */ +- int skip = i; +- j -= i; +- xt_entry_foreach(iter0, entry0, newinfo->size) { +- if (skip-- > 0) +- continue; +- if (j-- == 0) +- break; +- compat_release_entry(iter0); +- } +- xt_entry_foreach(iter1, entry1, newinfo->size) { +- if (i-- == 0) +- break; +- cleanup_entry(iter1); +- } +- xt_free_table_info(newinfo); +- return ret; ++ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { ++ repl.hook_entry[i] = newinfo->hook_entry[i]; ++ repl.underflow[i] = newinfo->underflow[i]; + } + +- /* And one copy for every other CPU */ +- for_each_possible_cpu(i) +- if (newinfo->entries[i] && newinfo->entries[i] != entry1) +- memcpy(newinfo->entries[i], entry1, newinfo->size); ++ repl.num_counters = 0; ++ repl.counters = NULL; ++ repl.size = newinfo->size; ++ ret = translate_table(newinfo, entry1, &repl); ++ if (ret) ++ goto free_newinfo; + + *pinfo = newinfo; + *pentry0 = entry1; +@@ -1454,31 +1345,18 @@ static int translate_compat_table(const char *name, + + free_newinfo: + xt_free_table_info(newinfo); +-out: +- xt_entry_foreach(iter0, entry0, total_size) { ++ return ret; ++out_unlock: ++ xt_compat_flush_offsets(NFPROTO_ARP); ++ xt_compat_unlock(NFPROTO_ARP); ++ xt_entry_foreach(iter0, entry0, compatr->size) { + if (j-- == 0) + break; + compat_release_entry(iter0); + } + return ret; +-out_unlock: +- xt_compat_flush_offsets(NFPROTO_ARP); +- xt_compat_unlock(NFPROTO_ARP); +- goto out; + } + +-struct compat_arpt_replace { +- char name[XT_TABLE_MAXNAMELEN]; +- u32 valid_hooks; +- u32 num_entries; +- u32 size; +- u32 hook_entry[NF_ARP_NUMHOOKS]; +- u32 underflow[NF_ARP_NUMHOOKS]; +- u32 num_counters; +- compat_uptr_t counters; +- struct compat_arpt_entry entries[0]; +-}; +- + static int compat_do_replace(struct net *net, void __user *user, + unsigned int len) + { +@@ -1496,6 +1374,9 @@ static int compat_do_replace(struct net *net, void __user *user, + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; ++ if (tmp.num_counters == 0) ++ return -EINVAL; ++ + tmp.name[sizeof(tmp.name)-1] = 0; + + newinfo = xt_alloc_table_info(tmp.size); +@@ -1509,10 +1390,7 @@ static int compat_do_replace(struct net *net, void __user *user, + goto free_newinfo; + } + +- ret = translate_compat_table(tmp.name, tmp.valid_hooks, +- &newinfo, &loc_cpu_entry, tmp.size, +- tmp.num_entries, tmp.hook_entry, +- tmp.underflow); ++ ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp); + if (ret != 0) + goto free_newinfo; + +diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c +index a5bd3c8eee84..92c8f2727ee9 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -511,6 +511,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct ipt_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -532,6 +534,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ipt_entry *) + (entry0 + newpos); +@@ -559,25 +563,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) + } + + static int +-check_entry(const struct ipt_entry *e) +-{ +- const struct xt_entry_target *t; +- +- if (!ip_checkentry(&e->ip)) +- return -EINVAL; +- +- if (e->target_offset + sizeof(struct xt_entry_target) > +- e->next_offset) +- return -EINVAL; +- +- t = ipt_get_target_c(e); +- if (e->target_offset + t->u.target_size > e->next_offset) +- return -EINVAL; +- +- return 0; +-} +- +-static int + check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) + { + const struct ipt_ip *ip = par->entryinfo; +@@ -733,7 +718,11 @@ check_entry_size_and_hooks(struct ipt_entry *e, + return -EINVAL; + } + +- err = check_entry(e); ++ if (!ip_checkentry(&e->ip)) ++ return -EINVAL; ++ ++ err = xt_check_entry_offsets(e, e->elems, e->target_offset, ++ e->next_offset); + if (err) + return err; + +@@ -1257,6 +1246,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) + /* overflow check */ + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; ++ if (tmp.num_counters == 0) ++ return -EINVAL; ++ + tmp.name[sizeof(tmp.name)-1] = 0; + + newinfo = xt_alloc_table_info(tmp.size); +@@ -1298,56 +1290,18 @@ do_add_counters(struct net *net, const void __user *user, + unsigned int i, curcpu; + struct xt_counters_info tmp; + struct xt_counters *paddc; +- unsigned int num_counters; +- const char *name; +- int size; +- void *ptmp; + struct xt_table *t; + const struct xt_table_info *private; + int ret = 0; + void *loc_cpu_entry; + struct ipt_entry *iter; + unsigned int addend; +-#ifdef CONFIG_COMPAT +- struct compat_xt_counters_info compat_tmp; +- +- if (compat) { +- ptmp = &compat_tmp; +- size = sizeof(struct compat_xt_counters_info); +- } else +-#endif +- { +- ptmp = &tmp; +- size = sizeof(struct xt_counters_info); +- } +- +- if (copy_from_user(ptmp, user, size) != 0) +- return -EFAULT; + +-#ifdef CONFIG_COMPAT +- if (compat) { +- num_counters = compat_tmp.num_counters; +- name = compat_tmp.name; +- } else +-#endif +- { +- num_counters = tmp.num_counters; +- name = tmp.name; +- } +- +- if (len != size + num_counters * sizeof(struct xt_counters)) +- return -EINVAL; +- +- paddc = vmalloc(len - size); +- if (!paddc) +- return -ENOMEM; ++ paddc = xt_copy_counters_from_user(user, len, &tmp, compat); ++ if (IS_ERR(paddc)) ++ return PTR_ERR(paddc); + +- if (copy_from_user(paddc, user + size, len - size) != 0) { +- ret = -EFAULT; +- goto free; +- } +- +- t = xt_find_table_lock(net, AF_INET, name); ++ t = xt_find_table_lock(net, AF_INET, tmp.name); + if (IS_ERR_OR_NULL(t)) { + ret = t ? PTR_ERR(t) : -ENOENT; + goto free; +@@ -1355,7 +1309,7 @@ do_add_counters(struct net *net, const void __user *user, + + local_bh_disable(); + private = t->private; +- if (private->number != num_counters) { ++ if (private->number != tmp.num_counters) { + ret = -EINVAL; + goto unlock_up_free; + } +@@ -1434,7 +1388,6 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, + + static int + compat_find_calc_match(struct xt_entry_match *m, +- const char *name, + const struct ipt_ip *ip, + unsigned int hookmask, + int *size) +@@ -1470,17 +1423,14 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, + struct xt_table_info *newinfo, + unsigned int *size, + const unsigned char *base, +- const unsigned char *limit, +- const unsigned int *hook_entries, +- const unsigned int *underflows, +- const char *name) ++ const unsigned char *limit) + { + struct xt_entry_match *ematch; + struct xt_entry_target *t; + struct xt_target *target; + unsigned int entry_offset; + unsigned int j; +- int ret, off, h; ++ int ret, off; + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 || +@@ -1497,8 +1447,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, + return -EINVAL; + } + +- /* For purposes of check_entry casting the compat entry is fine */ +- ret = check_entry((struct ipt_entry *)e); ++ if (!ip_checkentry(&e->ip)) ++ return -EINVAL; ++ ++ ret = xt_compat_check_entry_offsets(e, e->elems, ++ e->target_offset, e->next_offset); + if (ret) + return ret; + +@@ -1506,8 +1459,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, + entry_offset = (void *)e - (void *)base; + j = 0; + xt_ematch_foreach(ematch, e) { +- ret = compat_find_calc_match(ematch, name, +- &e->ip, e->comefrom, &off); ++ ret = compat_find_calc_match(ematch, &e->ip, e->comefrom, ++ &off); + if (ret != 0) + goto release_matches; + ++j; +@@ -1530,17 +1483,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, + if (ret) + goto out; + +- /* Check hooks & underflows */ +- for (h = 0; h < NF_INET_NUMHOOKS; h++) { +- if ((unsigned char *)e - base == hook_entries[h]) +- newinfo->hook_entry[h] = hook_entries[h]; +- if ((unsigned char *)e - base == underflows[h]) +- newinfo->underflow[h] = underflows[h]; +- } +- +- /* Clear counters and comefrom */ +- memset(&e->counters, 0, sizeof(e->counters)); +- e->comefrom = 0; + return 0; + + out: +@@ -1554,19 +1496,18 @@ release_matches: + return ret; + } + +-static int ++static void + compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, +- unsigned int *size, const char *name, ++ unsigned int *size, + struct xt_table_info *newinfo, unsigned char *base) + { + struct xt_entry_target *t; + struct xt_target *target; + struct ipt_entry *de; + unsigned int origsize; +- int ret, h; ++ int h; + struct xt_entry_match *ematch; + +- ret = 0; + origsize = *size; + de = (struct ipt_entry *)*dstptr; + memcpy(de, e, sizeof(struct ipt_entry)); +@@ -1575,198 +1516,104 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, + *dstptr += sizeof(struct ipt_entry); + *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); + +- xt_ematch_foreach(ematch, e) { +- ret = xt_compat_match_from_user(ematch, dstptr, size); +- if (ret != 0) +- return ret; +- } ++ xt_ematch_foreach(ematch, e) ++ xt_compat_match_from_user(ematch, dstptr, size); ++ + de->target_offset = e->target_offset - (origsize - *size); + t = compat_ipt_get_target(e); + target = t->u.kernel.target; + xt_compat_target_from_user(t, dstptr, size); + + de->next_offset = e->next_offset - (origsize - *size); ++ + for (h = 0; h < NF_INET_NUMHOOKS; h++) { + if ((unsigned char *)de - base < newinfo->hook_entry[h]) + newinfo->hook_entry[h] -= origsize - *size; + if ((unsigned char *)de - base < newinfo->underflow[h]) + newinfo->underflow[h] -= origsize - *size; + } +- return ret; +-} +- +-static int +-compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) +-{ +- struct xt_entry_match *ematch; +- struct xt_mtchk_param mtpar; +- unsigned int j; +- int ret = 0; +- +- j = 0; +- mtpar.net = net; +- mtpar.table = name; +- mtpar.entryinfo = &e->ip; +- mtpar.hook_mask = e->comefrom; +- mtpar.family = NFPROTO_IPV4; +- xt_ematch_foreach(ematch, e) { +- ret = check_match(ematch, &mtpar); +- if (ret != 0) +- goto cleanup_matches; +- ++j; +- } +- +- ret = check_target(e, net, name); +- if (ret) +- goto cleanup_matches; +- return 0; +- +- cleanup_matches: +- xt_ematch_foreach(ematch, e) { +- if (j-- == 0) +- break; +- cleanup_match(ematch, net); +- } +- return ret; + } + + static int + translate_compat_table(struct net *net, +- const char *name, +- unsigned int valid_hooks, + struct xt_table_info **pinfo, + void **pentry0, +- unsigned int total_size, +- unsigned int number, +- unsigned int *hook_entries, +- unsigned int *underflows) ++ const struct compat_ipt_replace *compatr) + { + unsigned int i, j; + struct xt_table_info *newinfo, *info; + void *pos, *entry0, *entry1; + struct compat_ipt_entry *iter0; +- struct ipt_entry *iter1; ++ struct ipt_replace repl; + unsigned int size; + int ret; + + info = *pinfo; + entry0 = *pentry0; +- size = total_size; +- info->number = number; +- +- /* Init all hooks to impossible value. */ +- for (i = 0; i < NF_INET_NUMHOOKS; i++) { +- info->hook_entry[i] = 0xFFFFFFFF; +- info->underflow[i] = 0xFFFFFFFF; +- } ++ size = compatr->size; ++ info->number = compatr->num_entries; + + duprintf("translate_compat_table: size %u\n", info->size); + j = 0; + xt_compat_lock(AF_INET); +- xt_compat_init_offsets(AF_INET, number); ++ xt_compat_init_offsets(AF_INET, compatr->num_entries); + /* Walk through entries, checking offsets. */ +- xt_entry_foreach(iter0, entry0, total_size) { ++ xt_entry_foreach(iter0, entry0, compatr->size) { + ret = check_compat_entry_size_and_hooks(iter0, info, &size, + entry0, +- entry0 + total_size, +- hook_entries, +- underflows, +- name); ++ entry0 + compatr->size); + if (ret != 0) + goto out_unlock; + ++j; + } + + ret = -EINVAL; +- if (j != number) { ++ if (j != compatr->num_entries) { + duprintf("translate_compat_table: %u not %u entries\n", +- j, number); ++ j, compatr->num_entries); + goto out_unlock; + } + +- /* Check hooks all assigned */ +- for (i = 0; i < NF_INET_NUMHOOKS; i++) { +- /* Only hooks which are valid */ +- if (!(valid_hooks & (1 << i))) +- continue; +- if (info->hook_entry[i] == 0xFFFFFFFF) { +- duprintf("Invalid hook entry %u %u\n", +- i, hook_entries[i]); +- goto out_unlock; +- } +- if (info->underflow[i] == 0xFFFFFFFF) { +- duprintf("Invalid underflow %u %u\n", +- i, underflows[i]); +- goto out_unlock; +- } +- } +- + ret = -ENOMEM; + newinfo = xt_alloc_table_info(size); + if (!newinfo) + goto out_unlock; + +- newinfo->number = number; ++ newinfo->number = compatr->num_entries; + for (i = 0; i < NF_INET_NUMHOOKS; i++) { +- newinfo->hook_entry[i] = info->hook_entry[i]; +- newinfo->underflow[i] = info->underflow[i]; ++ newinfo->hook_entry[i] = compatr->hook_entry[i]; ++ newinfo->underflow[i] = compatr->underflow[i]; + } + entry1 = newinfo->entries[raw_smp_processor_id()]; + pos = entry1; +- size = total_size; +- xt_entry_foreach(iter0, entry0, total_size) { +- ret = compat_copy_entry_from_user(iter0, &pos, &size, +- name, newinfo, entry1); +- if (ret != 0) +- break; +- } ++ size = compatr->size; ++ xt_entry_foreach(iter0, entry0, compatr->size) ++ compat_copy_entry_from_user(iter0, &pos, &size, ++ newinfo, entry1); ++ ++ /* all module references in entry0 are now gone. ++ * entry1/newinfo contains a 64bit ruleset that looks exactly as ++ * generated by 64bit userspace. ++ * ++ * Call standard translate_table() to validate all hook_entrys, ++ * underflows, check for loops, etc. ++ */ + xt_compat_flush_offsets(AF_INET); + xt_compat_unlock(AF_INET); +- if (ret) +- goto free_newinfo; + +- ret = -ELOOP; +- if (!mark_source_chains(newinfo, valid_hooks, entry1)) +- goto free_newinfo; ++ memcpy(&repl, compatr, sizeof(*compatr)); + +- i = 0; +- xt_entry_foreach(iter1, entry1, newinfo->size) { +- ret = compat_check_entry(iter1, net, name); +- if (ret != 0) +- break; +- ++i; +- if (strcmp(ipt_get_target(iter1)->u.user.name, +- XT_ERROR_TARGET) == 0) +- ++newinfo->stacksize; +- } +- if (ret) { +- /* +- * The first i matches need cleanup_entry (calls ->destroy) +- * because they had called ->check already. The other j-i +- * entries need only release. +- */ +- int skip = i; +- j -= i; +- xt_entry_foreach(iter0, entry0, newinfo->size) { +- if (skip-- > 0) +- continue; +- if (j-- == 0) +- break; +- compat_release_entry(iter0); +- } +- xt_entry_foreach(iter1, entry1, newinfo->size) { +- if (i-- == 0) +- break; +- cleanup_entry(iter1, net); +- } +- xt_free_table_info(newinfo); +- return ret; ++ for (i = 0; i < NF_INET_NUMHOOKS; i++) { ++ repl.hook_entry[i] = newinfo->hook_entry[i]; ++ repl.underflow[i] = newinfo->underflow[i]; + } + +- /* And one copy for every other CPU */ +- for_each_possible_cpu(i) +- if (newinfo->entries[i] && newinfo->entries[i] != entry1) +- memcpy(newinfo->entries[i], entry1, newinfo->size); ++ repl.num_counters = 0; ++ repl.counters = NULL; ++ repl.size = newinfo->size; ++ ret = translate_table(net, newinfo, entry1, &repl); ++ if (ret) ++ goto free_newinfo; + + *pinfo = newinfo; + *pentry0 = entry1; +@@ -1775,17 +1622,16 @@ translate_compat_table(struct net *net, + + free_newinfo: + xt_free_table_info(newinfo); +-out: +- xt_entry_foreach(iter0, entry0, total_size) { ++ return ret; ++out_unlock: ++ xt_compat_flush_offsets(AF_INET); ++ xt_compat_unlock(AF_INET); ++ xt_entry_foreach(iter0, entry0, compatr->size) { + if (j-- == 0) + break; + compat_release_entry(iter0); + } + return ret; +-out_unlock: +- xt_compat_flush_offsets(AF_INET); +- xt_compat_unlock(AF_INET); +- goto out; + } + + static int +@@ -1805,6 +1651,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; ++ if (tmp.num_counters == 0) ++ return -EINVAL; ++ + tmp.name[sizeof(tmp.name)-1] = 0; + + newinfo = xt_alloc_table_info(tmp.size); +@@ -1819,10 +1668,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) + goto free_newinfo; + } + +- ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, +- &newinfo, &loc_cpu_entry, tmp.size, +- tmp.num_entries, tmp.hook_entry, +- tmp.underflow); ++ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); + if (ret != 0) + goto free_newinfo; + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index f904b644a40c..a5d71c65ea30 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1469,7 +1469,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) + + /* if we're overly short, let UDP handle it */ + encap_rcv = ACCESS_ONCE(up->encap_rcv); +- if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) { ++ if (encap_rcv != NULL) { + int ret; + + ret = encap_rcv(sk, skb); +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 8b144bf50189..f5f86850a305 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1018,19 +1018,12 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + bool can_sleep) + { + struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); +- int err; + + dst = ip6_sk_dst_check(sk, dst, fl6); ++ if (!dst) ++ dst = ip6_dst_lookup_flow(sk, fl6, final_dst, can_sleep); + +- err = ip6_dst_lookup_tail(sk, &dst, fl6); +- if (err) +- return ERR_PTR(err); +- if (final_dst) +- fl6->daddr = *final_dst; +- if (can_sleep) +- fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; +- +- return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); ++ return dst; + } + EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); + +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index 8b61288e5746..86d30e60242a 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -1076,6 +1076,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void) + struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); + if (c == NULL) + return NULL; ++ c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1; + c->mfc_un.res.minvif = MAXMIFS; + return c; + } +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index fb8a146abed8..e214222cd06f 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -521,6 +521,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct ip6t_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -542,6 +544,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ip6t_entry *) + (entry0 + newpos); +@@ -568,25 +572,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) + module_put(par.match->me); + } + +-static int +-check_entry(const struct ip6t_entry *e) +-{ +- const struct xt_entry_target *t; +- +- if (!ip6_checkentry(&e->ipv6)) +- return -EINVAL; +- +- if (e->target_offset + sizeof(struct xt_entry_target) > +- e->next_offset) +- return -EINVAL; +- +- t = ip6t_get_target_c(e); +- if (e->target_offset + t->u.target_size > e->next_offset) +- return -EINVAL; +- +- return 0; +-} +- + static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) + { + const struct ip6t_ip6 *ipv6 = par->entryinfo; +@@ -744,7 +729,11 @@ check_entry_size_and_hooks(struct ip6t_entry *e, + return -EINVAL; + } + +- err = check_entry(e); ++ if (!ip6_checkentry(&e->ipv6)) ++ return -EINVAL; ++ ++ err = xt_check_entry_offsets(e, e->elems, e->target_offset, ++ e->next_offset); + if (err) + return err; + +@@ -1267,6 +1256,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) + /* overflow check */ + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; ++ if (tmp.num_counters == 0) ++ return -EINVAL; ++ + tmp.name[sizeof(tmp.name)-1] = 0; + + newinfo = xt_alloc_table_info(tmp.size); +@@ -1308,56 +1300,17 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, + unsigned int i, curcpu; + struct xt_counters_info tmp; + struct xt_counters *paddc; +- unsigned int num_counters; +- char *name; +- int size; +- void *ptmp; + struct xt_table *t; + const struct xt_table_info *private; + int ret = 0; + const void *loc_cpu_entry; + struct ip6t_entry *iter; + unsigned int addend; +-#ifdef CONFIG_COMPAT +- struct compat_xt_counters_info compat_tmp; +- +- if (compat) { +- ptmp = &compat_tmp; +- size = sizeof(struct compat_xt_counters_info); +- } else +-#endif +- { +- ptmp = &tmp; +- size = sizeof(struct xt_counters_info); +- } +- +- if (copy_from_user(ptmp, user, size) != 0) +- return -EFAULT; +- +-#ifdef CONFIG_COMPAT +- if (compat) { +- num_counters = compat_tmp.num_counters; +- name = compat_tmp.name; +- } else +-#endif +- { +- num_counters = tmp.num_counters; +- name = tmp.name; +- } +- +- if (len != size + num_counters * sizeof(struct xt_counters)) +- return -EINVAL; + +- paddc = vmalloc(len - size); +- if (!paddc) +- return -ENOMEM; +- +- if (copy_from_user(paddc, user + size, len - size) != 0) { +- ret = -EFAULT; +- goto free; +- } +- +- t = xt_find_table_lock(net, AF_INET6, name); ++ paddc = xt_copy_counters_from_user(user, len, &tmp, compat); ++ if (IS_ERR(paddc)) ++ return PTR_ERR(paddc); ++ t = xt_find_table_lock(net, AF_INET6, tmp.name); + if (IS_ERR_OR_NULL(t)) { + ret = t ? PTR_ERR(t) : -ENOENT; + goto free; +@@ -1366,7 +1319,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, + + local_bh_disable(); + private = t->private; +- if (private->number != num_counters) { ++ if (private->number != tmp.num_counters) { + ret = -EINVAL; + goto unlock_up_free; + } +@@ -1446,7 +1399,6 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, + + static int + compat_find_calc_match(struct xt_entry_match *m, +- const char *name, + const struct ip6t_ip6 *ipv6, + unsigned int hookmask, + int *size) +@@ -1482,17 +1434,14 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, + struct xt_table_info *newinfo, + unsigned int *size, + const unsigned char *base, +- const unsigned char *limit, +- const unsigned int *hook_entries, +- const unsigned int *underflows, +- const char *name) ++ const unsigned char *limit) + { + struct xt_entry_match *ematch; + struct xt_entry_target *t; + struct xt_target *target; + unsigned int entry_offset; + unsigned int j; +- int ret, off, h; ++ int ret, off; + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 || +@@ -1509,8 +1458,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, + return -EINVAL; + } + +- /* For purposes of check_entry casting the compat entry is fine */ +- ret = check_entry((struct ip6t_entry *)e); ++ if (!ip6_checkentry(&e->ipv6)) ++ return -EINVAL; ++ ++ ret = xt_compat_check_entry_offsets(e, e->elems, ++ e->target_offset, e->next_offset); + if (ret) + return ret; + +@@ -1518,8 +1470,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, + entry_offset = (void *)e - (void *)base; + j = 0; + xt_ematch_foreach(ematch, e) { +- ret = compat_find_calc_match(ematch, name, +- &e->ipv6, e->comefrom, &off); ++ ret = compat_find_calc_match(ematch, &e->ipv6, e->comefrom, ++ &off); + if (ret != 0) + goto release_matches; + ++j; +@@ -1542,17 +1494,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, + if (ret) + goto out; + +- /* Check hooks & underflows */ +- for (h = 0; h < NF_INET_NUMHOOKS; h++) { +- if ((unsigned char *)e - base == hook_entries[h]) +- newinfo->hook_entry[h] = hook_entries[h]; +- if ((unsigned char *)e - base == underflows[h]) +- newinfo->underflow[h] = underflows[h]; +- } +- +- /* Clear counters and comefrom */ +- memset(&e->counters, 0, sizeof(e->counters)); +- e->comefrom = 0; + return 0; + + out: +@@ -1566,18 +1507,17 @@ release_matches: + return ret; + } + +-static int ++static void + compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, +- unsigned int *size, const char *name, ++ unsigned int *size, + struct xt_table_info *newinfo, unsigned char *base) + { + struct xt_entry_target *t; + struct ip6t_entry *de; + unsigned int origsize; +- int ret, h; ++ int h; + struct xt_entry_match *ematch; + +- ret = 0; + origsize = *size; + de = (struct ip6t_entry *)*dstptr; + memcpy(de, e, sizeof(struct ip6t_entry)); +@@ -1586,11 +1526,9 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, + *dstptr += sizeof(struct ip6t_entry); + *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); + +- xt_ematch_foreach(ematch, e) { +- ret = xt_compat_match_from_user(ematch, dstptr, size); +- if (ret != 0) +- return ret; +- } ++ xt_ematch_foreach(ematch, e) ++ xt_compat_match_from_user(ematch, dstptr, size); ++ + de->target_offset = e->target_offset - (origsize - *size); + t = compat_ip6t_get_target(e); + xt_compat_target_from_user(t, dstptr, size); +@@ -1602,181 +1540,82 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, + if ((unsigned char *)de - base < newinfo->underflow[h]) + newinfo->underflow[h] -= origsize - *size; + } +- return ret; +-} +- +-static int compat_check_entry(struct ip6t_entry *e, struct net *net, +- const char *name) +-{ +- unsigned int j; +- int ret = 0; +- struct xt_mtchk_param mtpar; +- struct xt_entry_match *ematch; +- +- j = 0; +- mtpar.net = net; +- mtpar.table = name; +- mtpar.entryinfo = &e->ipv6; +- mtpar.hook_mask = e->comefrom; +- mtpar.family = NFPROTO_IPV6; +- xt_ematch_foreach(ematch, e) { +- ret = check_match(ematch, &mtpar); +- if (ret != 0) +- goto cleanup_matches; +- ++j; +- } +- +- ret = check_target(e, net, name); +- if (ret) +- goto cleanup_matches; +- return 0; +- +- cleanup_matches: +- xt_ematch_foreach(ematch, e) { +- if (j-- == 0) +- break; +- cleanup_match(ematch, net); +- } +- return ret; + } + + static int + translate_compat_table(struct net *net, +- const char *name, +- unsigned int valid_hooks, + struct xt_table_info **pinfo, + void **pentry0, +- unsigned int total_size, +- unsigned int number, +- unsigned int *hook_entries, +- unsigned int *underflows) ++ const struct compat_ip6t_replace *compatr) + { + unsigned int i, j; + struct xt_table_info *newinfo, *info; + void *pos, *entry0, *entry1; + struct compat_ip6t_entry *iter0; +- struct ip6t_entry *iter1; ++ struct ip6t_replace repl; + unsigned int size; + int ret = 0; + + info = *pinfo; + entry0 = *pentry0; +- size = total_size; +- info->number = number; +- +- /* Init all hooks to impossible value. */ +- for (i = 0; i < NF_INET_NUMHOOKS; i++) { +- info->hook_entry[i] = 0xFFFFFFFF; +- info->underflow[i] = 0xFFFFFFFF; +- } ++ size = compatr->size; ++ info->number = compatr->num_entries; + + duprintf("translate_compat_table: size %u\n", info->size); + j = 0; + xt_compat_lock(AF_INET6); +- xt_compat_init_offsets(AF_INET6, number); ++ xt_compat_init_offsets(AF_INET6, compatr->num_entries); + /* Walk through entries, checking offsets. */ +- xt_entry_foreach(iter0, entry0, total_size) { ++ xt_entry_foreach(iter0, entry0, compatr->size) { + ret = check_compat_entry_size_and_hooks(iter0, info, &size, + entry0, +- entry0 + total_size, +- hook_entries, +- underflows, +- name); ++ entry0 + compatr->size); + if (ret != 0) + goto out_unlock; + ++j; + } + + ret = -EINVAL; +- if (j != number) { ++ if (j != compatr->num_entries) { + duprintf("translate_compat_table: %u not %u entries\n", +- j, number); ++ j, compatr->num_entries); + goto out_unlock; + } + +- /* Check hooks all assigned */ +- for (i = 0; i < NF_INET_NUMHOOKS; i++) { +- /* Only hooks which are valid */ +- if (!(valid_hooks & (1 << i))) +- continue; +- if (info->hook_entry[i] == 0xFFFFFFFF) { +- duprintf("Invalid hook entry %u %u\n", +- i, hook_entries[i]); +- goto out_unlock; +- } +- if (info->underflow[i] == 0xFFFFFFFF) { +- duprintf("Invalid underflow %u %u\n", +- i, underflows[i]); +- goto out_unlock; +- } +- } +- + ret = -ENOMEM; + newinfo = xt_alloc_table_info(size); + if (!newinfo) + goto out_unlock; + +- newinfo->number = number; ++ newinfo->number = compatr->num_entries; + for (i = 0; i < NF_INET_NUMHOOKS; i++) { +- newinfo->hook_entry[i] = info->hook_entry[i]; +- newinfo->underflow[i] = info->underflow[i]; ++ newinfo->hook_entry[i] = compatr->hook_entry[i]; ++ newinfo->underflow[i] = compatr->underflow[i]; + } + entry1 = newinfo->entries[raw_smp_processor_id()]; + pos = entry1; +- size = total_size; +- xt_entry_foreach(iter0, entry0, total_size) { +- ret = compat_copy_entry_from_user(iter0, &pos, &size, +- name, newinfo, entry1); +- if (ret != 0) +- break; +- } ++ size = compatr->size; ++ xt_entry_foreach(iter0, entry0, compatr->size) ++ compat_copy_entry_from_user(iter0, &pos, &size, ++ newinfo, entry1); ++ ++ /* all module references in entry0 are now gone. */ + xt_compat_flush_offsets(AF_INET6); + xt_compat_unlock(AF_INET6); +- if (ret) +- goto free_newinfo; + +- ret = -ELOOP; +- if (!mark_source_chains(newinfo, valid_hooks, entry1)) +- goto free_newinfo; ++ memcpy(&repl, compatr, sizeof(*compatr)); + +- i = 0; +- xt_entry_foreach(iter1, entry1, newinfo->size) { +- ret = compat_check_entry(iter1, net, name); +- if (ret != 0) +- break; +- ++i; +- if (strcmp(ip6t_get_target(iter1)->u.user.name, +- XT_ERROR_TARGET) == 0) +- ++newinfo->stacksize; +- } +- if (ret) { +- /* +- * The first i matches need cleanup_entry (calls ->destroy) +- * because they had called ->check already. The other j-i +- * entries need only release. +- */ +- int skip = i; +- j -= i; +- xt_entry_foreach(iter0, entry0, newinfo->size) { +- if (skip-- > 0) +- continue; +- if (j-- == 0) +- break; +- compat_release_entry(iter0); +- } +- xt_entry_foreach(iter1, entry1, newinfo->size) { +- if (i-- == 0) +- break; +- cleanup_entry(iter1, net); +- } +- xt_free_table_info(newinfo); +- return ret; ++ for (i = 0; i < NF_INET_NUMHOOKS; i++) { ++ repl.hook_entry[i] = newinfo->hook_entry[i]; ++ repl.underflow[i] = newinfo->underflow[i]; + } + +- /* And one copy for every other CPU */ +- for_each_possible_cpu(i) +- if (newinfo->entries[i] && newinfo->entries[i] != entry1) +- memcpy(newinfo->entries[i], entry1, newinfo->size); ++ repl.num_counters = 0; ++ repl.counters = NULL; ++ repl.size = newinfo->size; ++ ret = translate_table(net, newinfo, entry1, &repl); ++ if (ret) ++ goto free_newinfo; + + *pinfo = newinfo; + *pentry0 = entry1; +@@ -1785,17 +1624,16 @@ translate_compat_table(struct net *net, + + free_newinfo: + xt_free_table_info(newinfo); +-out: +- xt_entry_foreach(iter0, entry0, total_size) { ++ return ret; ++out_unlock: ++ xt_compat_flush_offsets(AF_INET6); ++ xt_compat_unlock(AF_INET6); ++ xt_entry_foreach(iter0, entry0, compatr->size) { + if (j-- == 0) + break; + compat_release_entry(iter0); + } + return ret; +-out_unlock: +- xt_compat_flush_offsets(AF_INET6); +- xt_compat_unlock(AF_INET6); +- goto out; + } + + static int +@@ -1815,6 +1653,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; ++ if (tmp.num_counters == 0) ++ return -EINVAL; ++ + tmp.name[sizeof(tmp.name)-1] = 0; + + newinfo = xt_alloc_table_info(tmp.size); +@@ -1829,10 +1670,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) + goto free_newinfo; + } + +- ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, +- &newinfo, &loc_cpu_entry, tmp.size, +- tmp.num_entries, tmp.hook_entry, +- tmp.underflow); ++ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp); + if (ret != 0) + goto free_newinfo; + +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index eb1fe0759752..a883776bcec8 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -529,13 +529,13 @@ static int ipip6_err(struct sk_buff *skb, u32 info) + + if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { + ipv4_update_pmtu(skb, dev_net(skb->dev), info, +- t->parms.link, 0, IPPROTO_IPV6, 0); ++ t->parms.link, 0, iph->protocol, 0); + err = 0; + goto out; + } + if (type == ICMP_REDIRECT) { + ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, +- IPPROTO_IPV6, 0); ++ iph->protocol, 0); + err = 0; + goto out; + } +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 7138ee87e07c..5ed4579f8212 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1776,7 +1776,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) + destp = ntohs(inet->inet_dport); + srcp = ntohs(inet->inet_sport); + +- if (icsk->icsk_pending == ICSK_TIME_RETRANS) { ++ if (icsk->icsk_pending == ICSK_TIME_RETRANS || ++ icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || ++ icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { + timer_active = 1; + timer_expires = icsk->icsk_timeout; + } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) { +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 26e1648ca228..b9188e157227 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -607,7 +607,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) + + /* if we're overly short, let UDP handle it */ + encap_rcv = ACCESS_ONCE(up->encap_rcv); +- if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) { ++ if (encap_rcv != NULL) { + int ret; + + ret = encap_rcv(sk, skb); +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 707ac61d63e5..67559f7a7832 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -160,6 +160,10 @@ void mesh_sta_cleanup(struct sta_info *sta) + del_timer_sync(&sta->plink_timer); + } + ++ /* make sure no readers can access nexthop sta from here on */ ++ mesh_path_flush_by_nexthop(sta); ++ synchronize_net(); ++ + if (changed) + ieee80211_mbss_info_change_notify(sdata, changed); + } +diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c +index 8b03028cca69..51c141b09dba 100644 +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -435,6 +435,47 @@ int xt_check_match(struct xt_mtchk_param *par, + } + EXPORT_SYMBOL_GPL(xt_check_match); + ++/** xt_check_entry_match - check that matches end before start of target ++ * ++ * @match: beginning of xt_entry_match ++ * @target: beginning of this rules target (alleged end of matches) ++ * @alignment: alignment requirement of match structures ++ * ++ * Validates that all matches add up to the beginning of the target, ++ * and that each match covers at least the base structure size. ++ * ++ * Return: 0 on success, negative errno on failure. ++ */ ++static int xt_check_entry_match(const char *match, const char *target, ++ const size_t alignment) ++{ ++ const struct xt_entry_match *pos; ++ int length = target - match; ++ ++ if (length == 0) /* no matches */ ++ return 0; ++ ++ pos = (struct xt_entry_match *)match; ++ do { ++ if ((unsigned long)pos % alignment) ++ return -EINVAL; ++ ++ if (length < (int)sizeof(struct xt_entry_match)) ++ return -EINVAL; ++ ++ if (pos->u.match_size < sizeof(struct xt_entry_match)) ++ return -EINVAL; ++ ++ if (pos->u.match_size > length) ++ return -EINVAL; ++ ++ length -= pos->u.match_size; ++ pos = ((void *)((char *)(pos) + (pos)->u.match_size)); ++ } while (length > 0); ++ ++ return 0; ++} ++ + #ifdef CONFIG_COMPAT + int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta) + { +@@ -504,13 +545,14 @@ int xt_compat_match_offset(const struct xt_match *match) + } + EXPORT_SYMBOL_GPL(xt_compat_match_offset); + +-int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, +- unsigned int *size) ++void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, ++ unsigned int *size) + { + const struct xt_match *match = m->u.kernel.match; + struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; + int pad, off = xt_compat_match_offset(match); + u_int16_t msize = cm->u.user.match_size; ++ char name[sizeof(m->u.user.name)]; + + m = *dstptr; + memcpy(m, cm, sizeof(*cm)); +@@ -524,10 +566,12 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, + + msize += off; + m->u.user.match_size = msize; ++ strlcpy(name, match->name, sizeof(name)); ++ module_put(match->me); ++ strncpy(m->u.user.name, name, sizeof(m->u.user.name)); + + *size += off; + *dstptr += msize; +- return 0; + } + EXPORT_SYMBOL_GPL(xt_compat_match_from_user); + +@@ -558,8 +602,125 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, + return 0; + } + EXPORT_SYMBOL_GPL(xt_compat_match_to_user); ++ ++/* non-compat version may have padding after verdict */ ++struct compat_xt_standard_target { ++ struct compat_xt_entry_target t; ++ compat_uint_t verdict; ++}; ++ ++int xt_compat_check_entry_offsets(const void *base, const char *elems, ++ unsigned int target_offset, ++ unsigned int next_offset) ++{ ++ long size_of_base_struct = elems - (const char *)base; ++ const struct compat_xt_entry_target *t; ++ const char *e = base; ++ ++ if (target_offset < size_of_base_struct) ++ return -EINVAL; ++ ++ if (target_offset + sizeof(*t) > next_offset) ++ return -EINVAL; ++ ++ t = (void *)(e + target_offset); ++ if (t->u.target_size < sizeof(*t)) ++ return -EINVAL; ++ ++ if (target_offset + t->u.target_size > next_offset) ++ return -EINVAL; ++ ++ if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && ++ COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset) ++ return -EINVAL; ++ ++ /* compat_xt_entry match has less strict aligment requirements, ++ * otherwise they are identical. In case of padding differences ++ * we need to add compat version of xt_check_entry_match. ++ */ ++ BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match)); ++ ++ return xt_check_entry_match(elems, base + target_offset, ++ __alignof__(struct compat_xt_entry_match)); ++} ++EXPORT_SYMBOL(xt_compat_check_entry_offsets); + #endif /* CONFIG_COMPAT */ + ++/** ++ * xt_check_entry_offsets - validate arp/ip/ip6t_entry ++ * ++ * @base: pointer to arp/ip/ip6t_entry ++ * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems ++ * @target_offset: the arp/ip/ip6_t->target_offset ++ * @next_offset: the arp/ip/ip6_t->next_offset ++ * ++ * validates that target_offset and next_offset are sane and that all ++ * match sizes (if any) align with the target offset. ++ * ++ * This function does not validate the targets or matches themselves, it ++ * only tests that all the offsets and sizes are correct, that all ++ * match structures are aligned, and that the last structure ends where ++ * the target structure begins. ++ * ++ * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version. ++ * ++ * The arp/ip/ip6t_entry structure @base must have passed following tests: ++ * - it must point to a valid memory location ++ * - base to base + next_offset must be accessible, i.e. not exceed allocated ++ * length. ++ * ++ * A well-formed entry looks like this: ++ * ++ * ip(6)t_entry match [mtdata] match [mtdata] target [tgdata] ip(6)t_entry ++ * e->elems[]-----' | | ++ * matchsize | | ++ * matchsize | | ++ * | | ++ * target_offset---------------------------------' | ++ * next_offset---------------------------------------------------' ++ * ++ * elems[]: flexible array member at end of ip(6)/arpt_entry struct. ++ * This is where matches (if any) and the target reside. ++ * target_offset: beginning of target. ++ * next_offset: start of the next rule; also: size of this rule. ++ * Since targets have a minimum size, target_offset + minlen <= next_offset. ++ * ++ * Every match stores its size, sum of sizes must not exceed target_offset. ++ * ++ * Return: 0 on success, negative errno on failure. ++ */ ++int xt_check_entry_offsets(const void *base, ++ const char *elems, ++ unsigned int target_offset, ++ unsigned int next_offset) ++{ ++ long size_of_base_struct = elems - (const char *)base; ++ const struct xt_entry_target *t; ++ const char *e = base; ++ ++ /* target start is within the ip/ip6/arpt_entry struct */ ++ if (target_offset < size_of_base_struct) ++ return -EINVAL; ++ ++ if (target_offset + sizeof(*t) > next_offset) ++ return -EINVAL; ++ ++ t = (void *)(e + target_offset); ++ if (t->u.target_size < sizeof(*t)) ++ return -EINVAL; ++ ++ if (target_offset + t->u.target_size > next_offset) ++ return -EINVAL; ++ ++ if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 && ++ XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset) ++ return -EINVAL; ++ ++ return xt_check_entry_match(elems, base + target_offset, ++ __alignof__(struct xt_entry_match)); ++} ++EXPORT_SYMBOL(xt_check_entry_offsets); ++ + int xt_check_target(struct xt_tgchk_param *par, + unsigned int size, u_int8_t proto, bool inv_proto) + { +@@ -610,6 +771,80 @@ int xt_check_target(struct xt_tgchk_param *par, + } + EXPORT_SYMBOL_GPL(xt_check_target); + ++/** ++ * xt_copy_counters_from_user - copy counters and metadata from userspace ++ * ++ * @user: src pointer to userspace memory ++ * @len: alleged size of userspace memory ++ * @info: where to store the xt_counters_info metadata ++ * @compat: true if we setsockopt call is done by 32bit task on 64bit kernel ++ * ++ * Copies counter meta data from @user and stores it in @info. ++ * ++ * vmallocs memory to hold the counters, then copies the counter data ++ * from @user to the new memory and returns a pointer to it. ++ * ++ * If @compat is true, @info gets converted automatically to the 64bit ++ * representation. ++ * ++ * The metadata associated with the counters is stored in @info. ++ * ++ * Return: returns pointer that caller has to test via IS_ERR(). ++ * If IS_ERR is false, caller has to vfree the pointer. ++ */ ++void *xt_copy_counters_from_user(const void __user *user, unsigned int len, ++ struct xt_counters_info *info, bool compat) ++{ ++ void *mem; ++ u64 size; ++ ++#ifdef CONFIG_COMPAT ++ if (compat) { ++ /* structures only differ in size due to alignment */ ++ struct compat_xt_counters_info compat_tmp; ++ ++ if (len <= sizeof(compat_tmp)) ++ return ERR_PTR(-EINVAL); ++ ++ len -= sizeof(compat_tmp); ++ if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0) ++ return ERR_PTR(-EFAULT); ++ ++ strlcpy(info->name, compat_tmp.name, sizeof(info->name)); ++ info->num_counters = compat_tmp.num_counters; ++ user += sizeof(compat_tmp); ++ } else ++#endif ++ { ++ if (len <= sizeof(*info)) ++ return ERR_PTR(-EINVAL); ++ ++ len -= sizeof(*info); ++ if (copy_from_user(info, user, sizeof(*info)) != 0) ++ return ERR_PTR(-EFAULT); ++ ++ info->name[sizeof(info->name) - 1] = '\0'; ++ user += sizeof(*info); ++ } ++ ++ size = sizeof(struct xt_counters); ++ size *= info->num_counters; ++ ++ if (size != (u64)len) ++ return ERR_PTR(-EINVAL); ++ ++ mem = vmalloc(len); ++ if (!mem) ++ return ERR_PTR(-ENOMEM); ++ ++ if (copy_from_user(mem, user, len) == 0) ++ return mem; ++ ++ vfree(mem); ++ return ERR_PTR(-EFAULT); ++} ++EXPORT_SYMBOL_GPL(xt_copy_counters_from_user); ++ + #ifdef CONFIG_COMPAT + int xt_compat_target_offset(const struct xt_target *target) + { +@@ -625,6 +860,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, + struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; + int pad, off = xt_compat_target_offset(target); + u_int16_t tsize = ct->u.user.target_size; ++ char name[sizeof(t->u.user.name)]; + + t = *dstptr; + memcpy(t, ct, sizeof(*ct)); +@@ -638,6 +874,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, + + tsize += off; + t->u.user.target_size = tsize; ++ strlcpy(name, target->name, sizeof(name)); ++ module_put(target->me); ++ strncpy(t->u.user.name, name, sizeof(t->u.user.name)); + + *size += off; + *dstptr += tsize; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 10805856dfba..bb04abe72d76 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2658,6 +2658,7 @@ static int netlink_dump(struct sock *sk) + struct netlink_callback *cb; + struct sk_buff *skb = NULL; + struct nlmsghdr *nlh; ++ struct module *module; + int len, err = -ENOBUFS; + int alloc_size; + +@@ -2707,9 +2708,11 @@ static int netlink_dump(struct sock *sk) + cb->done(cb); + + nlk->cb_running = false; ++ module = cb->module; ++ skb = cb->skb; + mutex_unlock(nlk->cb_mutex); +- module_put(cb->module); +- consume_skb(cb->skb); ++ module_put(module); ++ consume_skb(skb); + return 0; + + errout_skb: +diff --git a/net/rds/recv.c b/net/rds/recv.c +index de339b24ca14..917f36af8d37 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -544,5 +544,7 @@ void rds_inc_info_copy(struct rds_incoming *inc, + minfo.fport = inc->i_hdr.h_dport; + } + ++ minfo.flags = 0; ++ + rds_info_copy(iter, &minfo, sizeof(minfo)); + } +diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c +index 87dd619fb2e9..1c9a505b7019 100644 +--- a/net/wireless/wext-core.c ++++ b/net/wireless/wext-core.c +@@ -954,8 +954,29 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, + return private(dev, iwr, cmd, info, handler); + } + /* Old driver API : call driver ioctl handler */ +- if (dev->netdev_ops->ndo_do_ioctl) +- return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); ++ if (dev->netdev_ops->ndo_do_ioctl) { ++#ifdef CONFIG_COMPAT ++ if (info->flags & IW_REQUEST_FLAG_COMPAT) { ++ int ret = 0; ++ struct iwreq iwr_lcl; ++ struct compat_iw_point *iwp_compat = (void *) &iwr->u.data; ++ ++ memcpy(&iwr_lcl, iwr, sizeof(struct iwreq)); ++ iwr_lcl.u.data.pointer = compat_ptr(iwp_compat->pointer); ++ iwr_lcl.u.data.length = iwp_compat->length; ++ iwr_lcl.u.data.flags = iwp_compat->flags; ++ ++ ret = dev->netdev_ops->ndo_do_ioctl(dev, (void *) &iwr_lcl, cmd); ++ ++ iwp_compat->pointer = ptr_to_compat(iwr_lcl.u.data.pointer); ++ iwp_compat->length = iwr_lcl.u.data.length; ++ iwp_compat->flags = iwr_lcl.u.data.flags; ++ ++ return ret; ++ } else ++#endif ++ return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); ++ } + return -EOPNOTSUPP; + } + +diff --git a/security/keys/key.c b/security/keys/key.c +index 8fb7c7bd4657..6595b2dd89fe 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -580,7 +580,7 @@ int key_reject_and_link(struct key *key, + + mutex_unlock(&key_construction_mutex); + +- if (keyring) ++ if (keyring && link_ret == 0) + __key_link_end(keyring, key->type, prealloc); + + /* wake up anyone waiting for a key to be constructed */ +diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c +index 3f2b4b7f2ec9..a20650d28844 100644 +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -501,7 +501,7 @@ static int snd_compress_check_input(struct snd_compr_params *params) + { + /* first let's check the buffer parameter's */ + if (params->buffer.fragment_size == 0 || +- params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) ++ params->buffer.fragments > INT_MAX / params->buffer.fragment_size) + return -EINVAL; + + /* now codec parameters */ +diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c +index 14d483d6b3b0..327bbf797c6c 100644 +--- a/sound/core/hrtimer.c ++++ b/sound/core/hrtimer.c +@@ -38,37 +38,53 @@ static unsigned int resolution; + struct snd_hrtimer { + struct snd_timer *timer; + struct hrtimer hrt; +- atomic_t running; ++ bool in_callback; + }; + + static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) + { + struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); + struct snd_timer *t = stime->timer; +- unsigned long oruns; +- +- if (!atomic_read(&stime->running)) +- return HRTIMER_NORESTART; +- +- oruns = hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); +- snd_timer_interrupt(stime->timer, t->sticks * oruns); ++ ktime_t delta; ++ unsigned long ticks; ++ enum hrtimer_restart ret = HRTIMER_NORESTART; ++ ++ spin_lock(&t->lock); ++ if (!t->running) ++ goto out; /* fast path */ ++ stime->in_callback = true; ++ ticks = t->sticks; ++ spin_unlock(&t->lock); ++ ++ /* calculate the drift */ ++ delta = ktime_sub(hrt->base->get_time(), hrtimer_get_expires(hrt)); ++ if (delta.tv64 > 0) ++ ticks += ktime_divns(delta, ticks * resolution); ++ ++ snd_timer_interrupt(stime->timer, ticks); ++ ++ spin_lock(&t->lock); ++ if (t->running) { ++ hrtimer_add_expires_ns(hrt, t->sticks * resolution); ++ ret = HRTIMER_RESTART; ++ } + +- if (!atomic_read(&stime->running)) +- return HRTIMER_NORESTART; +- return HRTIMER_RESTART; ++ stime->in_callback = false; ++ out: ++ spin_unlock(&t->lock); ++ return ret; + } + + static int snd_hrtimer_open(struct snd_timer *t) + { + struct snd_hrtimer *stime; + +- stime = kmalloc(sizeof(*stime), GFP_KERNEL); ++ stime = kzalloc(sizeof(*stime), GFP_KERNEL); + if (!stime) + return -ENOMEM; + hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + stime->timer = t; + stime->hrt.function = snd_hrtimer_callback; +- atomic_set(&stime->running, 0); + t->private_data = stime; + return 0; + } +@@ -78,6 +94,11 @@ static int snd_hrtimer_close(struct snd_timer *t) + struct snd_hrtimer *stime = t->private_data; + + if (stime) { ++ spin_lock_irq(&t->lock); ++ t->running = 0; /* just to be sure */ ++ stime->in_callback = 1; /* skip start/stop */ ++ spin_unlock_irq(&t->lock); ++ + hrtimer_cancel(&stime->hrt); + kfree(stime); + t->private_data = NULL; +@@ -89,18 +110,19 @@ static int snd_hrtimer_start(struct snd_timer *t) + { + struct snd_hrtimer *stime = t->private_data; + +- atomic_set(&stime->running, 0); +- hrtimer_try_to_cancel(&stime->hrt); ++ if (stime->in_callback) ++ return 0; + hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), + HRTIMER_MODE_REL); +- atomic_set(&stime->running, 1); + return 0; + } + + static int snd_hrtimer_stop(struct snd_timer *t) + { + struct snd_hrtimer *stime = t->private_data; +- atomic_set(&stime->running, 0); ++ ++ if (stime->in_callback) ++ return 0; + hrtimer_try_to_cancel(&stime->hrt); + return 0; + } +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 10463beae4bb..1902ec0d4487 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1218,6 +1218,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, + tu->tstamp = *tstamp; + if ((tu->filter & (1 << event)) == 0 || !tu->tread) + return; ++ memset(&r1, 0, sizeof(r1)); + r1.event = event; + r1.tstamp = *tstamp; + r1.val = resolution; +@@ -1252,6 +1253,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, + } + if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && + tu->last_resolution != resolution) { ++ memset(&r1, 0, sizeof(r1)); + r1.event = SNDRV_TIMER_EVENT_RESOLUTION; + r1.tstamp = tstamp; + r1.val = resolution; +@@ -1717,6 +1719,7 @@ static int snd_timer_user_params(struct file *file, + if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { + if (tu->tread) { + struct snd_timer_tread tread; ++ memset(&tread, 0, sizeof(tread)); + tread.event = SNDRV_TIMER_EVENT_EARLY; + tread.tstamp.tv_sec = 0; + tread.tstamp.tv_nsec = 0; |