public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/hardened-patchset:master commit in: 4.6.4/, 4.6.3/
@ 2016-07-12 18:56 Anthony G. Basile
  0 siblings, 0 replies; only message in thread
From: Anthony G. Basile @ 2016-07-12 18:56 UTC (permalink / raw
  To: gentoo-commits

commit:     e541c2b69dd1103c5b8377a64ea8cb82d646558c
Author:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
AuthorDate: Tue Jul 12 18:59:29 2016 +0000
Commit:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
CommitDate: Tue Jul 12 18:59:29 2016 +0000
URL:        https://gitweb.gentoo.org/proj/hardened-patchset.git/commit/?id=e541c2b6

grsecurity-3.1-4.6.4-201607112205

 4.6.3/1002_linux-4.6.3.patch                       | 4713 --------------------
 {4.6.3 => 4.6.4}/0000_README                       |    6 +-
 .../4420_grsecurity-3.1-4.6.4-201607112205.patch   |  182 +-
 {4.6.3 => 4.6.4}/4425_grsec_remove_EI_PAX.patch    |    0
 {4.6.3 => 4.6.4}/4427_force_XATTR_PAX_tmpfs.patch  |    0
 .../4430_grsec-remove-localversion-grsec.patch     |    0
 {4.6.3 => 4.6.4}/4435_grsec-mute-warnings.patch    |    0
 .../4440_grsec-remove-protected-paths.patch        |    0
 .../4450_grsec-kconfig-default-gids.patch          |    0
 .../4465_selinux-avc_audit-log-curr_ip.patch       |    0
 {4.6.3 => 4.6.4}/4470_disable-compat_vdso.patch    |    0
 {4.6.3 => 4.6.4}/4475_emutramp_default_on.patch    |    0
 12 files changed, 152 insertions(+), 4749 deletions(-)

diff --git a/4.6.3/1002_linux-4.6.3.patch b/4.6.3/1002_linux-4.6.3.patch
deleted file mode 100644
index f999198..0000000
--- a/4.6.3/1002_linux-4.6.3.patch
+++ /dev/null
@@ -1,4713 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 93068c2..c62b531 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 6
--SUBLEVEL = 2
-+SUBLEVEL = 3
- EXTRAVERSION =
- NAME = Charred Weasel
- 
-diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
-index ef9119f..4d93758 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/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
-index 24ed037..83d48a5 100644
---- a/arch/arm64/include/asm/elf.h
-+++ b/arch/arm64/include/asm/elf.h
-@@ -160,14 +160,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
- #define STACK_RND_MASK			(0x3ffff >> (PAGE_SHIFT - 12))
- #endif
- 
--#ifdef CONFIG_COMPAT
--
- #ifdef __AARCH64EB__
- #define COMPAT_ELF_PLATFORM		("v8b")
- #else
- #define COMPAT_ELF_PLATFORM		("v8l")
- #endif
- 
-+#ifdef CONFIG_COMPAT
-+
- #define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
- 
- /* AArch32 registers. */
-diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
-index f0c3fb7..2d2d7cb 100644
---- a/arch/arm64/kernel/cpuinfo.c
-+++ b/arch/arm64/kernel/cpuinfo.c
-@@ -22,6 +22,8 @@
- 
- #include <linux/bitops.h>
- #include <linux/bug.h>
-+#include <linux/compat.h>
-+#include <linux/elf.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/personality.h>
-@@ -104,6 +106,7 @@ static const char *const compat_hwcap2_str[] = {
- static int c_show(struct seq_file *m, void *v)
- {
- 	int i, j;
-+	bool compat = personality(current->personality) == PER_LINUX32;
- 
- 	for_each_online_cpu(i) {
- 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
-@@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
- 		 * "processor".  Give glibc what it expects.
- 		 */
- 		seq_printf(m, "processor\t: %d\n", i);
-+		if (compat)
-+			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
-+				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
- 
- 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
- 			   loops_per_jiffy / (500000UL/HZ),
-@@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
- 		 * software which does already (at least for 32-bit).
- 		 */
- 		seq_puts(m, "Features\t:");
--		if (personality(current->personality) == PER_LINUX32) {
-+		if (compat) {
- #ifdef CONFIG_COMPAT
- 			for (j = 0; compat_hwcap_str[j]; j++)
- 				if (compat_elf_hwcap & (1 << j))
-diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
-index fff7cd4..3129df9 100644
---- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
-+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
-@@ -190,12 +190,11 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
- 			if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
- 				continue;
- 
--			if (cpu_if->vgic_elrsr & (1 << i)) {
-+			if (cpu_if->vgic_elrsr & (1 << i))
- 				cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
--				continue;
--			}
-+			else
-+				cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
- 
--			cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
- 			__gic_v3_set_lr(0, i);
- 		}
- 
-diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
-index 3ae4a28..10b79e9 100644
---- a/arch/arm64/mm/fault.c
-+++ b/arch/arm64/mm/fault.c
-@@ -109,7 +109,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
- 	 * PTE_RDONLY is cleared by default in the asm below, so set it in
- 	 * back if necessary (read-only or clean PTE).
- 	 */
--	if (!pte_write(entry) || !dirty)
-+	if (!pte_write(entry) || !pte_sw_dirty(entry))
- 		pte_val(entry) |= PTE_RDONLY;
- 
- 	/*
-diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
-index d7c0acb..8d49614 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 f5f4c66..166d863 100644
---- a/arch/powerpc/include/asm/reg.h
-+++ b/arch/powerpc/include/asm/reg.h
-@@ -715,7 +715,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
-@@ -752,13 +752,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
- #define SPRN_TACR	888
- #define SPRN_TCSCR	889
- #define SPRN_CSIGR	890
-diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
-index da51925..ccd2037 100644
---- a/arch/powerpc/kernel/prom_init.c
-+++ b/arch/powerpc/kernel/prom_init.c
-@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = {
- 	W(0xffff0000), W(0x003e0000),	/* POWER6 */
- 	W(0xffff0000), W(0x003f0000),	/* POWER7 */
- 	W(0xffff0000), W(0x004b0000),	/* POWER8E */
-+	W(0xffff0000), W(0x004c0000),   /* POWER8NVL */
- 	W(0xffff0000), W(0x004d0000),	/* POWER8 */
- 	W(0xffffffff), W(0x0f000004),	/* all 2.07-compliant */
- 	W(0xffffffff), W(0x0f000003),	/* all 2.06-compliant */
-diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
-index 7635b1c..f4acba2 100644
---- a/arch/powerpc/mm/hash_utils_64.c
-+++ b/arch/powerpc/mm/hash_utils_64.c
-@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = {
- 	},
- };
- 
-+/*
-+ * 'R' and 'C' update notes:
-+ *  - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
-+ *     create writeable HPTEs without C set, because the hcall H_PROTECT
-+ *     that we use in that case will not update C
-+ *  - The above is however not a problem, because we also don't do that
-+ *     fancy "no flush" variant of eviction and we use H_REMOVE which will
-+ *     do the right thing and thus we don't have the race I described earlier
-+ *
-+ *    - Under bare metal,  we do have the race, so we need R and C set
-+ *    - We make sure R is always set and never lost
-+ *    - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping
-+ */
- unsigned long htab_convert_pte_flags(unsigned long pteflags)
- {
- 	unsigned long rflags = 0;
-@@ -180,9 +193,14 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
- 			rflags |= 0x1;
- 	}
- 	/*
--	 * Always add "C" bit for perf. Memory coherence is always enabled
-+	 * We can't allow hardware to update hpte bits. Hence always
-+	 * set 'R' bit and set 'C' if it is a write fault
-+	 * Memory coherence is always enabled
- 	 */
--	rflags |=  HPTE_R_C | HPTE_R_M;
-+	rflags |=  HPTE_R_R | HPTE_R_M;
-+
-+	if (pteflags & _PAGE_DIRTY)
-+		rflags |= HPTE_R_C;
- 	/*
- 	 * Add in WIG bits
- 	 */
-diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
-index ac3ffd9..405baaf 100644
---- a/arch/powerpc/platforms/pseries/eeh_pseries.c
-+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
-@@ -615,29 +615,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_warn("%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/s390/net/bpf_jit.h b/arch/s390/net/bpf_jit.h
-index f010c93..fda605d 100644
---- a/arch/s390/net/bpf_jit.h
-+++ b/arch/s390/net/bpf_jit.h
-@@ -37,7 +37,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
-  *	      |		      |     |
-  *	      +---------------+     |
-  *	      | 8 byte skbp   |     |
-- * R15+170 -> +---------------+     |
-+ * R15+176 -> +---------------+     |
-  *	      | 8 byte hlen   |     |
-  * R15+168 -> +---------------+     |
-  *	      | 4 byte align  |     |
-@@ -58,7 +58,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
- #define STK_OFF		(STK_SPACE - STK_160_UNUSED)
- #define STK_OFF_TMP	160	/* Offset of tmp buffer on stack */
- #define STK_OFF_HLEN	168	/* Offset of SKB header length on stack */
--#define STK_OFF_SKBP	170	/* Offset of SKB pointer on stack */
-+#define STK_OFF_SKBP	176	/* Offset of SKB pointer on stack */
- 
- #define STK_OFF_R6	(160 - 11 * 8)	/* Offset of r6 on stack */
- #define STK_OFF_TCCNT	(160 - 12 * 8)	/* Offset of tail_call_cnt on stack */
-diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
-index 3c0bfc1..2662fcc 100644
---- a/arch/s390/net/bpf_jit_comp.c
-+++ b/arch/s390/net/bpf_jit_comp.c
-@@ -45,7 +45,7 @@ struct bpf_jit {
- 	int labels[1];		/* Labels for local jumps */
- };
- 
--#define BPF_SIZE_MAX	0x7ffff	/* Max size for program (20 bit signed displ) */
-+#define BPF_SIZE_MAX	0xffff	/* Max size for program (16 bit branches) */
- 
- #define SEEN_SKB	1	/* skb access */
- #define SEEN_MEM	2	/* use mem[] for temporary storage */
-@@ -446,7 +446,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit)
- 		emit_load_skb_data_hlen(jit);
- 	if (jit->seen & SEEN_SKB_CHANGE)
- 		/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
--		EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
-+		EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
- 			      STK_OFF_SKBP);
- }
- 
-diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h
-index 10e9dab..f0700cf 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/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
-index f089cfa..5a189bf 100644
---- a/arch/sparc/include/asm/pgtable_64.h
-+++ b/arch/sparc/include/asm/pgtable_64.h
-@@ -375,7 +375,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
- #define pgprot_noncached pgprot_noncached
- 
- #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
--static inline pte_t pte_mkhuge(pte_t pte)
-+static inline unsigned long __pte_huge_mask(void)
- {
- 	unsigned long mask;
- 
-@@ -390,8 +390,19 @@ static inline pte_t pte_mkhuge(pte_t pte)
- 	: "=r" (mask)
- 	: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
- 
--	return __pte(pte_val(pte) | mask);
-+	return mask;
-+}
-+
-+static inline pte_t pte_mkhuge(pte_t pte)
-+{
-+	return __pte(pte_val(pte) | __pte_huge_mask());
-+}
-+
-+static inline bool is_hugetlb_pte(pte_t pte)
-+{
-+	return !!(pte_val(pte) & __pte_huge_mask());
- }
-+
- #ifdef CONFIG_TRANSPARENT_HUGEPAGE
- static inline pmd_t pmd_mkhuge(pmd_t pmd)
- {
-@@ -403,6 +414,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
- 	return __pmd(pte_val(pte));
- }
- #endif
-+#else
-+static inline bool is_hugetlb_pte(pte_t pte)
-+{
-+	return false;
-+}
- #endif
- 
- static inline pte_t pte_mkdirty(pte_t pte)
-@@ -858,6 +874,19 @@ static inline unsigned long pud_pfn(pud_t pud)
- void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
- 		   pte_t *ptep, pte_t orig, int fullmm);
- 
-+static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
-+				pte_t *ptep, pte_t orig, int fullmm)
-+{
-+	/* It is more efficient to let flush_tlb_kernel_range()
-+	 * handle init_mm tlb flushes.
-+	 *
-+	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
-+	 *             and SUN4V pte layout, so this inline test is fine.
-+	 */
-+	if (likely(mm != &init_mm) && pte_accessible(mm, orig))
-+		tlb_batch_add(mm, vaddr, ptep, orig, fullmm);
-+}
-+
- #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
- static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
- 					    unsigned long addr,
-@@ -874,15 +903,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
- 	pte_t orig = *ptep;
- 
- 	*ptep = pte;
--
--	/* It is more efficient to let flush_tlb_kernel_range()
--	 * handle init_mm tlb flushes.
--	 *
--	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
--	 *             and SUN4V pte layout, so this inline test is fine.
--	 */
--	if (likely(mm != &init_mm) && pte_accessible(mm, orig))
--		tlb_batch_add(mm, addr, ptep, orig, fullmm);
-+	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm);
- }
- 
- #define set_pte_at(mm,addr,ptep,pte)	\
-diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
-index dea1cfa..a8e192e 100644
---- a/arch/sparc/include/asm/tlbflush_64.h
-+++ b/arch/sparc/include/asm/tlbflush_64.h
-@@ -8,6 +8,7 @@
- #define TLB_BATCH_NR	192
- 
- struct tlb_batch {
-+	bool huge;
- 	struct mm_struct *mm;
- 	unsigned long tlb_nr;
- 	unsigned long active;
-@@ -16,7 +17,7 @@ struct tlb_batch {
- 
- void flush_tsb_kernel_range(unsigned long start, unsigned long end);
- void flush_tsb_user(struct tlb_batch *tb);
--void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
-+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge);
- 
- /* TLB flush operations. */
- 
-diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h
-index 71b5a67..781b9f1 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 7cf9c6e..fdb1332 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/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
-index d08bdaf..216948c 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)
--
- #ifdef CONFIG_CONTEXT_TRACKING
- # define SCHEDULE_USER schedule_user
- #else
-@@ -242,52 +238,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 3c25241..ebd0bfe 100644
---- a/arch/sparc/kernel/signal32.c
-+++ b/arch/sparc/kernel/signal32.c
-@@ -138,12 +138,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 int pc, npc;
- 	sigset_t set;
- 	compat_sigset_t seta;
-@@ -158,11 +170,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;
- 
-@@ -227,7 +244,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;
-@@ -242,11 +259,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;
- 
-@@ -307,14 +329,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 52aa5e4..c3c12ef 100644
---- a/arch/sparc/kernel/signal_32.c
-+++ b/arch/sparc/kernel/signal_32.c
-@@ -60,10 +60,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;
-@@ -77,10 +89,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);
-@@ -127,7 +142,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;
-@@ -135,8 +150,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);
-@@ -178,15 +198,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 39aaec1..5ee930c 100644
---- a/arch/sparc/kernel/signal_64.c
-+++ b/arch/sparc/kernel/signal_64.c
-@@ -234,6 +234,17 @@ do_sigsegv:
- 	goto out;
- }
- 
-+/* 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;
-@@ -246,8 +257,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;
-@@ -261,10 +272,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;
-@@ -308,14 +325,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 0f6eebe..e5fe8ce 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 387834a..36aadcb 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/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S
-new file mode 100644
-index 0000000..5604a2b
---- /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/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
-index 4977800..ba52e64 100644
---- a/arch/sparc/mm/hugetlbpage.c
-+++ b/arch/sparc/mm/hugetlbpage.c
-@@ -176,17 +176,31 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
- 		     pte_t *ptep, pte_t entry)
- {
- 	int i;
-+	pte_t orig[2];
-+	unsigned long nptes;
- 
- 	if (!pte_present(*ptep) && pte_present(entry))
- 		mm->context.huge_pte_count++;
- 
- 	addr &= HPAGE_MASK;
--	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
--		set_pte_at(mm, addr, ptep, entry);
-+
-+	nptes = 1 << HUGETLB_PAGE_ORDER;
-+	orig[0] = *ptep;
-+	orig[1] = *(ptep + nptes / 2);
-+	for (i = 0; i < nptes; i++) {
-+		*ptep = entry;
- 		ptep++;
- 		addr += PAGE_SIZE;
- 		pte_val(entry) += PAGE_SIZE;
- 	}
-+
-+	/* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
-+	addr -= REAL_HPAGE_SIZE;
-+	ptep -= nptes / 2;
-+	maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0);
-+	addr -= REAL_HPAGE_SIZE;
-+	ptep -= nptes / 2;
-+	maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0);
- }
- 
- pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
-@@ -194,19 +208,28 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
- {
- 	pte_t entry;
- 	int i;
-+	unsigned long nptes;
- 
- 	entry = *ptep;
- 	if (pte_present(entry))
- 		mm->context.huge_pte_count--;
- 
- 	addr &= HPAGE_MASK;
--
--	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
--		pte_clear(mm, addr, ptep);
-+	nptes = 1 << HUGETLB_PAGE_ORDER;
-+	for (i = 0; i < nptes; i++) {
-+		*ptep = __pte(0UL);
- 		addr += PAGE_SIZE;
- 		ptep++;
- 	}
- 
-+	/* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
-+	addr -= REAL_HPAGE_SIZE;
-+	ptep -= nptes / 2;
-+	maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
-+	addr -= REAL_HPAGE_SIZE;
-+	ptep -= nptes / 2;
-+	maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
-+
- 	return entry;
- }
- 
-diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
-index 09e8388..14bb0d5 100644
---- a/arch/sparc/mm/init_64.c
-+++ b/arch/sparc/mm/init_64.c
-@@ -324,18 +324,6 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde
- 	tsb_insert(tsb, tag, tte);
- }
- 
--#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
--static inline bool is_hugetlb_pte(pte_t pte)
--{
--	if ((tlb_type == hypervisor &&
--	     (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
--	    (tlb_type != hypervisor &&
--	     (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U))
--		return true;
--	return false;
--}
--#endif
--
- void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
- {
- 	struct mm_struct *mm;
-@@ -2836,9 +2824,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;
-@@ -2857,9 +2846,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/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
-index 9df2190..f81cd97 100644
---- a/arch/sparc/mm/tlb.c
-+++ b/arch/sparc/mm/tlb.c
-@@ -67,7 +67,7 @@ void arch_leave_lazy_mmu_mode(void)
- }
- 
- static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
--			      bool exec)
-+			      bool exec, bool huge)
- {
- 	struct tlb_batch *tb = &get_cpu_var(tlb_batch);
- 	unsigned long nr;
-@@ -84,13 +84,21 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
- 	}
- 
- 	if (!tb->active) {
--		flush_tsb_user_page(mm, vaddr);
-+		flush_tsb_user_page(mm, vaddr, huge);
- 		global_flush_tlb_page(mm, vaddr);
- 		goto out;
- 	}
- 
--	if (nr == 0)
-+	if (nr == 0) {
- 		tb->mm = mm;
-+		tb->huge = huge;
-+	}
-+
-+	if (tb->huge != huge) {
-+		flush_tlb_pending();
-+		tb->huge = huge;
-+		nr = 0;
-+	}
- 
- 	tb->vaddrs[nr] = vaddr;
- 	tb->tlb_nr = ++nr;
-@@ -104,6 +112,8 @@ out:
- void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
- 		   pte_t *ptep, pte_t orig, int fullmm)
- {
-+	bool huge = is_hugetlb_pte(orig);
-+
- 	if (tlb_type != hypervisor &&
- 	    pte_dirty(orig)) {
- 		unsigned long paddr, pfn = pte_pfn(orig);
-@@ -129,7 +139,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
- 
- no_cache_flush:
- 	if (!fullmm)
--		tlb_batch_add_one(mm, vaddr, pte_exec(orig));
-+		tlb_batch_add_one(mm, vaddr, pte_exec(orig), huge);
- }
- 
- #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-@@ -145,7 +155,7 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr,
- 		if (pte_val(*pte) & _PAGE_VALID) {
- 			bool exec = pte_exec(*pte);
- 
--			tlb_batch_add_one(mm, vaddr, exec);
-+			tlb_batch_add_one(mm, vaddr, exec, false);
- 		}
- 		pte++;
- 		vaddr += PAGE_SIZE;
-@@ -185,8 +195,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
- 			pte_t orig_pte = __pte(pmd_val(orig));
- 			bool exec = pte_exec(orig_pte);
- 
--			tlb_batch_add_one(mm, addr, exec);
--			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec);
-+			tlb_batch_add_one(mm, addr, exec, true);
-+			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec,
-+					true);
- 		} else {
- 			tlb_batch_pmd_scan(mm, addr, orig);
- 		}
-diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
-index a065766..a0604a4 100644
---- a/arch/sparc/mm/tsb.c
-+++ b/arch/sparc/mm/tsb.c
-@@ -76,14 +76,15 @@ void flush_tsb_user(struct tlb_batch *tb)
- 
- 	spin_lock_irqsave(&mm->context.lock, flags);
- 
--	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
--	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
--	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
--		base = __pa(base);
--	__flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
--
-+	if (!tb->huge) {
-+		base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
-+		nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
-+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-+			base = __pa(base);
-+		__flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
-+	}
- #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
--	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
-+	if (tb->huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
- 		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
- 		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
- 		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-@@ -94,20 +95,21 @@ void flush_tsb_user(struct tlb_batch *tb)
- 	spin_unlock_irqrestore(&mm->context.lock, flags);
- }
- 
--void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
-+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge)
- {
- 	unsigned long nentries, base, flags;
- 
- 	spin_lock_irqsave(&mm->context.lock, flags);
- 
--	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
--	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
--	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
--		base = __pa(base);
--	__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
--
-+	if (!huge) {
-+		base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
-+		nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
-+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-+			base = __pa(base);
-+		__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
-+	}
- #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
--	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
-+	if (huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
- 		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
- 		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
- 		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
-index 06cbe25..87bd6b6 100644
---- a/arch/x86/kernel/traps.c
-+++ b/arch/x86/kernel/traps.c
-@@ -95,6 +95,12 @@ static inline void cond_local_irq_disable(struct pt_regs *regs)
- 		local_irq_disable();
- }
- 
-+/*
-+ * In IST context, we explicitly disable preemption.  This serves two
-+ * purposes: it makes it much less likely that we would accidentally
-+ * schedule in IST context and it will force a warning if we somehow
-+ * manage to schedule by accident.
-+ */
- void ist_enter(struct pt_regs *regs)
- {
- 	if (user_mode(regs)) {
-@@ -109,13 +115,7 @@ void ist_enter(struct pt_regs *regs)
- 		rcu_nmi_enter();
- 	}
- 
--	/*
--	 * We are atomic because we're on the IST stack; or we're on
--	 * x86_32, in which case we still shouldn't schedule; or we're
--	 * on x86_64 and entered from user mode, in which case we're
--	 * still atomic unless ist_begin_non_atomic is called.
--	 */
--	preempt_count_add(HARDIRQ_OFFSET);
-+	preempt_disable();
- 
- 	/* This code is a bit fragile.  Test it. */
- 	RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
-@@ -123,7 +123,7 @@ void ist_enter(struct pt_regs *regs)
- 
- void ist_exit(struct pt_regs *regs)
- {
--	preempt_count_sub(HARDIRQ_OFFSET);
-+	preempt_enable_no_resched();
- 
- 	if (!user_mode(regs))
- 		rcu_nmi_exit();
-@@ -154,7 +154,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
- 	BUG_ON((unsigned long)(current_top_of_stack() -
- 			       current_stack_pointer()) >= THREAD_SIZE);
- 
--	preempt_count_sub(HARDIRQ_OFFSET);
-+	preempt_enable_no_resched();
- }
- 
- /**
-@@ -164,7 +164,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
-  */
- void ist_end_non_atomic(void)
- {
--	preempt_count_add(HARDIRQ_OFFSET);
-+	preempt_disable();
- }
- 
- static nokprobe_inline int
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index 9b7798c..6b9701b 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -3032,6 +3032,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));
- 	kvm_update_dr0123(vcpu);
- 	vcpu->arch.dr6 = dbgregs->dr6;
-diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
-index 91a7e04..477cbf39 100644
---- a/crypto/asymmetric_keys/Kconfig
-+++ b/crypto/asymmetric_keys/Kconfig
-@@ -13,6 +13,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
- 	tristate "Asymmetric public-key crypto algorithm subtype"
- 	select MPILIB
- 	select CRYPTO_HASH_INFO
-+	select CRYPTO_AKCIPHER
- 	help
- 	  This option provides support for asymmetric public key type handling.
- 	  If signature generation and/or verification are to be used,
-diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
-index 52c7395..0d0d452 100644
---- a/drivers/crypto/ccp/ccp-crypto-aes-xts.c
-+++ b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
-@@ -122,6 +122,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
- 	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
- 	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
- 	unsigned int unit;
-+	u32 unit_size;
- 	int ret;
- 
- 	if (!ctx->u.aes.key_len)
-@@ -133,11 +134,17 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
- 	if (!req->info)
- 		return -EINVAL;
- 
--	for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
--		if (!(req->nbytes & (unit_size_map[unit].size - 1)))
--			break;
-+	unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
-+	if (req->nbytes <= unit_size_map[0].size) {
-+		for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
-+			if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
-+				unit_size = unit_size_map[unit].value;
-+				break;
-+			}
-+		}
-+	}
- 
--	if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
-+	if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
- 	    (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
- 		/* Use the fallback to process the request for any
- 		 * unsupported unit sizes or key sizes
-@@ -158,7 +165,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
- 	rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
- 	rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
- 					   : CCP_AES_ACTION_DECRYPT;
--	rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
-+	rctx->cmd.u.xts.unit_size = unit_size;
- 	rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
- 	rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
- 	rctx->cmd.u.xts.iv = &rctx->iv_sg;
-diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
-index 2fd38d5..3c5e832 100644
---- a/drivers/gpio/gpio-bcm-kona.c
-+++ b/drivers/gpio/gpio-bcm-kona.c
-@@ -546,11 +546,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
- 	/* disable interrupts and clear status */
- 	for (i = 0; i < kona_gpio->num_bank; i++) {
- 		/* Unlock the entire bank first */
--		bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
-+		bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
- 		writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
- 		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
- 		/* Now re-lock the bank */
--		bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
-+		bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
- 	}
- }
- 
-diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
-index 66d3d24..e72794e 100644
---- a/drivers/gpio/gpio-zynq.c
-+++ b/drivers/gpio/gpio-zynq.c
-@@ -709,11 +709,17 @@ static int zynq_gpio_probe(struct platform_device *pdev)
- 		dev_err(&pdev->dev, "input clock not found.\n");
- 		return PTR_ERR(gpio->clk);
- 	}
-+	ret = clk_prepare_enable(gpio->clk);
-+	if (ret) {
-+		dev_err(&pdev->dev, "Unable to enable clock.\n");
-+		return ret;
-+	}
- 
-+	pm_runtime_set_active(&pdev->dev);
- 	pm_runtime_enable(&pdev->dev);
- 	ret = pm_runtime_get_sync(&pdev->dev);
- 	if (ret < 0)
--		return ret;
-+		goto err_pm_dis;
- 
- 	/* report a bug if gpio chip registration fails */
- 	ret = gpiochip_add_data(chip, gpio);
-@@ -745,6 +751,9 @@ err_rm_gpiochip:
- 	gpiochip_remove(chip);
- err_pm_put:
- 	pm_runtime_put(&pdev->dev);
-+err_pm_dis:
-+	pm_runtime_disable(&pdev->dev);
-+	clk_disable_unprepare(gpio->clk);
- 
- 	return ret;
- }
-diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index b747c76..cf3e712 100644
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -438,7 +438,6 @@ static void gpiodevice_release(struct device *dev)
- {
- 	struct gpio_device *gdev = dev_get_drvdata(dev);
- 
--	cdev_del(&gdev->chrdev);
- 	list_del(&gdev->list);
- 	ida_simple_remove(&gpio_ida, gdev->id);
- 	kfree(gdev->label);
-@@ -471,7 +470,6 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
- 
- 	/* From this point, the .release() function cleans up gpio_device */
- 	gdev->dev.release = gpiodevice_release;
--	get_device(&gdev->dev);
- 	pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
- 		 __func__, gdev->base, gdev->base + gdev->ngpio - 1,
- 		 dev_name(&gdev->dev), gdev->chip->label ? : "generic");
-@@ -742,6 +740,8 @@ void gpiochip_remove(struct gpio_chip *chip)
- 	 * be removed, else it will be dangling until the last user is
- 	 * gone.
- 	 */
-+	cdev_del(&gdev->chrdev);
-+	device_del(&gdev->dev);
- 	put_device(&gdev->dev);
- }
- EXPORT_SYMBOL_GPL(gpiochip_remove);
-@@ -841,7 +841,7 @@ struct gpio_chip *gpiochip_find(void *data,
- 
- 	spin_lock_irqsave(&gpio_lock, flags);
- 	list_for_each_entry(gdev, &gpio_devices, list)
--		if (match(gdev->chip, data))
-+		if (gdev->chip && match(gdev->chip, data))
- 			break;
- 
- 	/* No match? */
-@@ -1339,10 +1339,13 @@ done:
- /*
-  * This descriptor validation needs to be inserted verbatim into each
-  * function taking a descriptor, so we need to use a preprocessor
-- * macro to avoid endless duplication.
-+ * macro to avoid endless duplication. If the desc is NULL it is an
-+ * optional GPIO and calls should just bail out.
-  */
- #define VALIDATE_DESC(desc) do { \
--	if (!desc || !desc->gdev) { \
-+	if (!desc) \
-+		return 0; \
-+	if (!desc->gdev) { \
- 		pr_warn("%s: invalid GPIO\n", __func__); \
- 		return -EINVAL; \
- 	} \
-@@ -1353,7 +1356,9 @@ done:
- 	} } while (0)
- 
- #define VALIDATE_DESC_VOID(desc) do { \
--	if (!desc || !desc->gdev) { \
-+	if (!desc) \
-+		return; \
-+	if (!desc->gdev) { \
- 		pr_warn("%s: invalid GPIO\n", __func__); \
- 		return; \
- 	} \
-@@ -2001,7 +2006,14 @@ int gpiod_to_irq(const struct gpio_desc *desc)
- 	struct gpio_chip	*chip;
- 	int			offset;
- 
--	VALIDATE_DESC(desc);
-+	/*
-+	 * Cannot VALIDATE_DESC() here as gpiod_to_irq() consumer semantics
-+	 * requires this function to not return zero on an invalid descriptor
-+	 * but rather a negative error number.
-+	 */
-+	if (!desc || !desc->gdev || !desc->gdev->chip)
-+		return -EINVAL;
-+
- 	chip = desc->gdev->chip;
- 	offset = gpio_chip_hwgpio(desc);
- 	return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
-diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
-index e08f962..f30de80 100644
---- a/drivers/gpu/drm/drm_crtc.c
-+++ b/drivers/gpu/drm/drm_crtc.c
-@@ -3434,6 +3434,24 @@ int drm_mode_addfb2(struct drm_device *dev,
- 	return 0;
- }
- 
-+struct drm_mode_rmfb_work {
-+	struct work_struct work;
-+	struct list_head fbs;
-+};
-+
-+static void drm_mode_rmfb_work_fn(struct work_struct *w)
-+{
-+	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
-+
-+	while (!list_empty(&arg->fbs)) {
-+		struct drm_framebuffer *fb =
-+			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
-+
-+		list_del_init(&fb->filp_head);
-+		drm_framebuffer_remove(fb);
-+	}
-+}
-+
- /**
-  * drm_mode_rmfb - remove an FB from the configuration
-  * @dev: drm device for the ioctl
-@@ -3474,7 +3492,25 @@ int drm_mode_rmfb(struct drm_device *dev,
- 	mutex_unlock(&dev->mode_config.fb_lock);
- 	mutex_unlock(&file_priv->fbs_lock);
- 
--	drm_framebuffer_unreference(fb);
-+	/*
-+	 * we now own the reference that was stored in the fbs list
-+	 *
-+	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
-+	 * so run this in a separate stack as there's no way to correctly
-+	 * handle this after the fb is already removed from the lookup table.
-+	 */
-+	if (atomic_read(&fb->refcount.refcount) > 1) {
-+		struct drm_mode_rmfb_work arg;
-+
-+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
-+		INIT_LIST_HEAD(&arg.fbs);
-+		list_add_tail(&fb->filp_head, &arg.fbs);
-+
-+		schedule_work(&arg.work);
-+		flush_work(&arg.work);
-+		destroy_work_on_stack(&arg.work);
-+	} else
-+		drm_framebuffer_unreference(fb);
- 
- 	return 0;
- 
-@@ -3627,7 +3663,6 @@ out_err1:
- 	return ret;
- }
- 
--
- /**
-  * drm_fb_release - remove and free the FBs on this file
-  * @priv: drm file for the ioctl
-@@ -3642,6 +3677,9 @@ out_err1:
- void drm_fb_release(struct drm_file *priv)
- {
- 	struct drm_framebuffer *fb, *tfb;
-+	struct drm_mode_rmfb_work arg;
-+
-+	INIT_LIST_HEAD(&arg.fbs);
- 
- 	/*
- 	 * When the file gets released that means no one else can access the fb
-@@ -3654,10 +3692,22 @@ void drm_fb_release(struct drm_file *priv)
- 	 * at it any more.
- 	 */
- 	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
--		list_del_init(&fb->filp_head);
-+		if (atomic_read(&fb->refcount.refcount) > 1) {
-+			list_move_tail(&fb->filp_head, &arg.fbs);
-+		} else {
-+			list_del_init(&fb->filp_head);
- 
--		/* This drops the fpriv->fbs reference. */
--		drm_framebuffer_unreference(fb);
-+			/* This drops the fpriv->fbs reference. */
-+			drm_framebuffer_unreference(fb);
-+		}
-+	}
-+
-+	if (!list_empty(&arg.fbs)) {
-+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
-+
-+		schedule_work(&arg.work);
-+		flush_work(&arg.work);
-+		destroy_work_on_stack(&arg.work);
- 	}
- }
- 
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index 1c21220..d1a46ef 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -1829,7 +1829,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
- 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
- 	disable_rpm_wakeref_asserts(dev_priv);
- 
--	do {
-+	for (;;) {
- 		master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
- 		iir = I915_READ(VLV_IIR);
- 
-@@ -1857,7 +1857,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
- 
- 		I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
- 		POSTING_READ(GEN8_MASTER_IRQ);
--	} while (0);
-+	}
- 
- 	enable_rpm_wakeref_asserts(dev_priv);
- 
-diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h
-index 8fc93c5..d02c424 100644
---- a/drivers/net/ethernet/atheros/alx/alx.h
-+++ b/drivers/net/ethernet/atheros/alx/alx.h
-@@ -96,6 +96,10 @@ struct alx_priv {
- 	unsigned int rx_ringsz;
- 	unsigned int rxbuf_size;
- 
-+	struct page  *rx_page;
-+	unsigned int rx_page_offset;
-+	unsigned int rx_frag_size;
-+
- 	struct napi_struct napi;
- 	struct alx_tx_queue txq;
- 	struct alx_rx_queue rxq;
-diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
-index 55b118e..8611811 100644
---- a/drivers/net/ethernet/atheros/alx/main.c
-+++ b/drivers/net/ethernet/atheros/alx/main.c
-@@ -70,6 +70,35 @@ static void alx_free_txbuf(struct alx_priv *alx, int entry)
- 	}
- }
- 
-+static struct sk_buff *alx_alloc_skb(struct alx_priv *alx, gfp_t gfp)
-+{
-+	struct sk_buff *skb;
-+	struct page *page;
-+
-+	if (alx->rx_frag_size > PAGE_SIZE)
-+		return __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
-+
-+	page = alx->rx_page;
-+	if (!page) {
-+		alx->rx_page = page = alloc_page(gfp);
-+		if (unlikely(!page))
-+			return NULL;
-+		alx->rx_page_offset = 0;
-+	}
-+
-+	skb = build_skb(page_address(page) + alx->rx_page_offset,
-+			alx->rx_frag_size);
-+	if (likely(skb)) {
-+		alx->rx_page_offset += alx->rx_frag_size;
-+		if (alx->rx_page_offset >= PAGE_SIZE)
-+			alx->rx_page = NULL;
-+		else
-+			get_page(page);
-+	}
-+	return skb;
-+}
-+
-+
- static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
- {
- 	struct alx_rx_queue *rxq = &alx->rxq;
-@@ -86,7 +115,7 @@ 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 = alx_alloc_skb(alx, gfp);
- 		if (!skb)
- 			break;
- 		dma = dma_map_single(&alx->hw.pdev->dev,
-@@ -124,6 +153,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
- 		alx_write_mem16(&alx->hw, ALX_RFD_PIDX, cur);
- 	}
- 
-+
- 	return count;
- }
- 
-@@ -592,6 +622,11 @@ static void alx_free_rings(struct alx_priv *alx)
- 	kfree(alx->txq.bufs);
- 	kfree(alx->rxq.bufs);
- 
-+	if (alx->rx_page) {
-+		put_page(alx->rx_page);
-+		alx->rx_page = NULL;
-+	}
-+
- 	dma_free_coherent(&alx->hw.pdev->dev,
- 			  alx->descmem.size,
- 			  alx->descmem.virt,
-@@ -646,6 +681,7 @@ static int alx_request_irq(struct alx_priv *alx)
- 				  alx->dev->name, alx);
- 		if (!err)
- 			goto out;
-+
- 		/* fall back to legacy interrupt */
- 		pci_disable_msi(alx->hw.pdev);
- 	}
-@@ -689,6 +725,7 @@ static int alx_init_sw(struct alx_priv *alx)
- 	struct pci_dev *pdev = alx->hw.pdev;
- 	struct alx_hw *hw = &alx->hw;
- 	int err;
-+	unsigned int head_size;
- 
- 	err = alx_identify_hw(alx);
- 	if (err) {
-@@ -704,7 +741,12 @@ static int alx_init_sw(struct alx_priv *alx)
- 
- 	hw->smb_timer = 400;
- 	hw->mtu = alx->dev->mtu;
-+
- 	alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
-+	head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) +
-+		    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-+	alx->rx_frag_size = roundup_pow_of_two(head_size);
-+
- 	alx->tx_ringsz = 256;
- 	alx->rx_ringsz = 512;
- 	hw->imt = 200;
-@@ -806,6 +848,7 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
- {
- 	struct alx_priv *alx = netdev_priv(netdev);
- 	int max_frame = ALX_MAX_FRAME_LEN(mtu);
-+	unsigned int head_size;
- 
- 	if ((max_frame < ALX_MIN_FRAME_SIZE) ||
- 	    (max_frame > ALX_MAX_FRAME_SIZE))
-@@ -817,6 +860,9 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
- 	netdev->mtu = mtu;
- 	alx->hw.mtu = mtu;
- 	alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
-+	head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) +
-+		    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-+	alx->rx_frag_size = roundup_pow_of_two(head_size);
- 	netdev_update_features(netdev);
- 	if (netif_running(netdev))
- 		alx_reinit(alx);
-diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c
-index 085f912..06f0317 100644
---- a/drivers/net/ethernet/ezchip/nps_enet.c
-+++ b/drivers/net/ethernet/ezchip/nps_enet.c
-@@ -205,8 +205,10 @@ static int nps_enet_poll(struct napi_struct *napi, int budget)
- 		 * re-adding ourselves to the poll list.
- 		 */
- 
--		if (priv->tx_skb && !tx_ctrl_ct)
-+		if (priv->tx_skb && !tx_ctrl_ct) {
-+			nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0);
- 			napi_reschedule(napi);
-+		}
- 	}
- 
- 	return work_done;
-diff --git a/drivers/net/ethernet/marvell/mvneta_bm.c b/drivers/net/ethernet/marvell/mvneta_bm.c
-index 01fccec..466939f 100644
---- a/drivers/net/ethernet/marvell/mvneta_bm.c
-+++ b/drivers/net/ethernet/marvell/mvneta_bm.c
-@@ -189,6 +189,7 @@ struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
- 			SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- 		hwbm_pool->construct = mvneta_bm_construct;
- 		hwbm_pool->priv = new_pool;
-+		spin_lock_init(&hwbm_pool->lock);
- 
- 		/* Create new pool */
- 		err = mvneta_bm_pool_create(priv, new_pool);
-diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
-index 0e758bc..1ca7963 100644
---- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
-+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
-@@ -2727,7 +2727,7 @@ static int ofdpa_port_obj_fib4_add(struct rocker_port *rocker_port,
- 
- 	return ofdpa_port_fib_ipv4(ofdpa_port, trans,
- 				   htonl(fib4->dst), fib4->dst_len,
--				   &fib4->fi, fib4->tb_id, 0);
-+				   fib4->fi, fib4->tb_id, 0);
- }
- 
- static int ofdpa_port_obj_fib4_del(struct rocker_port *rocker_port,
-@@ -2737,7 +2737,7 @@ static int ofdpa_port_obj_fib4_del(struct rocker_port *rocker_port,
- 
- 	return ofdpa_port_fib_ipv4(ofdpa_port, NULL,
- 				   htonl(fib4->dst), fib4->dst_len,
--				   &fib4->fi, fib4->tb_id,
-+				   fib4->fi, fib4->tb_id,
- 				   OFDPA_OP_FLAG_REMOVE);
- }
- 
-diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
-index 1681084..1f30912 100644
---- a/drivers/net/ethernet/sfc/ef10.c
-+++ b/drivers/net/ethernet/sfc/ef10.c
-@@ -619,6 +619,17 @@ fail:
- 	return rc;
- }
- 
-+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
-+{
-+	struct efx_channel *channel;
-+	struct efx_tx_queue *tx_queue;
-+
-+	/* All our existing PIO buffers went away */
-+	efx_for_each_channel(channel, efx)
-+		efx_for_each_channel_tx_queue(tx_queue, channel)
-+			tx_queue->piobuf = NULL;
-+}
-+
- #else /* !EFX_USE_PIO */
- 
- static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
-@@ -635,6 +646,10 @@ static void efx_ef10_free_piobufs(struct efx_nic *efx)
- {
- }
- 
-+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
-+{
-+}
-+
- #endif /* EFX_USE_PIO */
- 
- static void efx_ef10_remove(struct efx_nic *efx)
-@@ -1018,6 +1033,7 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx)
- 	nic_data->must_realloc_vis = true;
- 	nic_data->must_restore_filters = true;
- 	nic_data->must_restore_piobufs = true;
-+	efx_ef10_forget_old_piobufs(efx);
- 	nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
- 
- 	/* Driver-created vswitches and vports must be re-created */
-diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
-index 06704ca..8683a21 100644
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
-@@ -209,7 +209,7 @@ int stmmac_mdio_register(struct net_device *ndev)
- 		return -ENOMEM;
- 
- 	if (mdio_bus_data->irqs)
--		memcpy(new_bus->irq, mdio_bus_data, sizeof(new_bus->irq));
-+		memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));
- 
- #ifdef CONFIG_OF
- 	if (priv->device->of_node)
-diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
-index 7b0a644..9fcb489 100644
---- a/drivers/net/geneve.c
-+++ b/drivers/net/geneve.c
-@@ -336,15 +336,15 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
- 
- 	/* Need Geneve and inner Ethernet header to be present */
- 	if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))
--		goto error;
-+		goto drop;
- 
- 	/* Return packets with reserved bits set */
- 	geneveh = geneve_hdr(skb);
- 	if (unlikely(geneveh->ver != GENEVE_VER))
--		goto error;
-+		goto drop;
- 
- 	if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
--		goto error;
-+		goto drop;
- 
- 	gs = rcu_dereference_sk_user_data(sk);
- 	if (!gs)
-@@ -367,10 +367,6 @@ drop:
- 	/* Consume bad packet */
- 	kfree_skb(skb);
- 	return 0;
--
--error:
--	/* Let the UDP layer deal with the skb */
--	return 1;
- }
- 
- static struct socket *geneve_create_sock(struct net *net, bool ipv6,
-diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
-index 92eaab95..9e803bb 100644
---- a/drivers/net/macsec.c
-+++ b/drivers/net/macsec.c
-@@ -1645,7 +1645,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
- 	if (tb_sa[MACSEC_SA_ATTR_ACTIVE])
- 		rx_sa->active = !!nla_get_u8(tb_sa[MACSEC_SA_ATTR_ACTIVE]);
- 
--	nla_memcpy(rx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEY], MACSEC_KEYID_LEN);
-+	nla_memcpy(rx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN);
- 	rx_sa->sc = rx_sc;
- 	rcu_assign_pointer(rx_sc->sa[assoc_num], rx_sa);
- 
-@@ -1784,7 +1784,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
- 		return -ENOMEM;
- 	}
- 
--	nla_memcpy(tx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEY], MACSEC_KEYID_LEN);
-+	nla_memcpy(tx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN);
- 
- 	spin_lock_bh(&tx_sa->lock);
- 	tx_sa->next_pn = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]);
-diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
-index a0f64cb..2ace126 100644
---- a/drivers/net/team/team.c
-+++ b/drivers/net/team/team.c
-@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team,
- #define TEAM_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
- 				 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
- 
--static void __team_compute_features(struct team *team)
-+static void ___team_compute_features(struct team *team)
- {
- 	struct team_port *port;
- 	u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
-@@ -1021,15 +1021,20 @@ static void __team_compute_features(struct team *team)
- 	team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
- 	if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
- 		team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
-+}
- 
-+static void __team_compute_features(struct team *team)
-+{
-+	___team_compute_features(team);
- 	netdev_change_features(team->dev);
- }
- 
- static void team_compute_features(struct team *team)
- {
- 	mutex_lock(&team->lock);
--	__team_compute_features(team);
-+	___team_compute_features(team);
- 	mutex_unlock(&team->lock);
-+	netdev_change_features(team->dev);
- }
- 
- static int team_port_enter(struct team *team, struct team_port *port)
-diff --git a/drivers/net/tun.c b/drivers/net/tun.c
-index 2c9e45f5..dda4905 100644
---- a/drivers/net/tun.c
-+++ b/drivers/net/tun.c
-@@ -568,11 +568,13 @@ static void tun_detach_all(struct net_device *dev)
- 	for (i = 0; i < n; i++) {
- 		tfile = rtnl_dereference(tun->tfiles[i]);
- 		BUG_ON(!tfile);
-+		tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
- 		tfile->socket.sk->sk_data_ready(tfile->socket.sk);
- 		RCU_INIT_POINTER(tfile->tun, NULL);
- 		--tun->numqueues;
- 	}
- 	list_for_each_entry(tfile, &tun->disabled, next) {
-+		tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
- 		tfile->socket.sk->sk_data_ready(tfile->socket.sk);
- 		RCU_INIT_POINTER(tfile->tun, NULL);
- 	}
-@@ -628,6 +630,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte
- 			goto out;
- 	}
- 	tfile->queue_index = tun->numqueues;
-+	tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN;
- 	rcu_assign_pointer(tfile->tun, tun);
- 	rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
- 	tun->numqueues++;
-@@ -1425,9 +1428,6 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
- 	if (!iov_iter_count(to))
- 		return 0;
- 
--	if (tun->dev->reg_state != NETREG_REGISTERED)
--		return -EIO;
--
- 	/* Read frames from queue */
- 	skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0,
- 				  &peeked, &off, &err);
-diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
-index 8ac261a..7e29b55 100644
---- a/drivers/net/vxlan.c
-+++ b/drivers/net/vxlan.c
-@@ -1262,7 +1262,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
- 
- 	/* Need Vxlan and inner Ethernet header to be present */
- 	if (!pskb_may_pull(skb, VXLAN_HLEN))
--		return 1;
-+		goto drop;
- 
- 	unparsed = *vxlan_hdr(skb);
- 	/* VNI flag always required to be set */
-@@ -1271,7 +1271,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
- 			   ntohl(vxlan_hdr(skb)->vx_flags),
- 			   ntohl(vxlan_hdr(skb)->vx_vni));
- 		/* Return non vxlan pkt */
--		return 1;
-+		goto drop;
- 	}
- 	unparsed.vx_flags &= ~VXLAN_HF_VNI;
- 	unparsed.vx_vni &= ~VXLAN_VNI_MASK;
-@@ -2959,6 +2959,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
- 	if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL])
- 		conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL;
- 
-+	if (tb[IFLA_MTU])
-+		conf.mtu = nla_get_u32(tb[IFLA_MTU]);
-+
- 	err = vxlan_dev_configure(src_net, dev, &conf);
- 	switch (err) {
- 	case -ENODEV:
-diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
-index f700908..0e537fd 100644
---- a/drivers/perf/arm_pmu.c
-+++ b/drivers/perf/arm_pmu.c
-@@ -987,9 +987,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
- 
- 	armpmu_init(pmu);
- 
--	if (!__oprofile_cpu_pmu)
--		__oprofile_cpu_pmu = pmu;
--
- 	pmu->plat_device = pdev;
- 
- 	if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
-@@ -1025,6 +1022,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
- 	if (ret)
- 		goto out_destroy;
- 
-+	if (!__oprofile_cpu_pmu)
-+		__oprofile_cpu_pmu = pmu;
-+
- 	pr_info("enabled with %s PMU driver, %d counters available\n",
- 			pmu->name, pmu->num_events);
- 
-diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
-index 6ab8c3c..fba2dd9 100644
---- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
-+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
-@@ -1256,9 +1256,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
- 	const struct mtk_desc_pin *pin;
- 
- 	chained_irq_enter(chip, desc);
--	for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
-+	for (eint_num = 0;
-+	     eint_num < pctl->devdata->ap_num;
-+	     eint_num += 32, reg += 4) {
- 		status = readl(reg);
--		reg += 4;
- 		while (status) {
- 			offset = __ffs(status);
- 			index = eint_num + offset;
-diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
-index 3408578..ff41c31 100644
---- a/drivers/scsi/scsi_devinfo.c
-+++ b/drivers/scsi/scsi_devinfo.c
-@@ -230,6 +230,7 @@ static struct {
- 	{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
- 	{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
- 	{"Promise", "", NULL, BLIST_SPARSELUN},
-+	{"QEMU", "QEMU CD-ROM", NULL, BLIST_SKIP_VPD_PAGES},
- 	{"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
- 	{"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
- 	{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
-diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
-index 8106515..f704d02 100644
---- a/drivers/scsi/scsi_lib.c
-+++ b/drivers/scsi/scsi_lib.c
-@@ -911,9 +911,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
- 	}
- 
- 	/*
--	 * If we finished all bytes in the request we are done now.
-+	 * 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(req, error, good_bytes, 0))
-+	if (!(blk_rq_bytes(req) == 0 && error) &&
-+	    !scsi_end_request(req, error, good_bytes, 0))
- 		return;
- 
- 	/*
-diff --git a/fs/dcache.c b/fs/dcache.c
-index d5ecc6e..44008e3 100644
---- a/fs/dcache.c
-+++ b/fs/dcache.c
-@@ -1619,7 +1619,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
-@@ -2338,7 +2338,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);
- }
-@@ -2637,6 +2636,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
- 	/* ... and switch them in the tree */
- 	if (IS_ROOT(dentry)) {
- 		/* splicing a tree */
-+		dentry->d_flags |= DCACHE_RCUACCESS;
- 		dentry->d_parent = target->d_parent;
- 		target->d_parent = target;
- 		list_del_init(&target->d_child);
-diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
-index 866bb18..e818f5a 100644
---- a/fs/ecryptfs/kthread.c
-+++ b/fs/ecryptfs/kthread.c
-@@ -25,6 +25,7 @@
- #include <linux/slab.h>
- #include <linux/wait.h>
- #include <linux/mount.h>
-+#include <linux/file.h>
- #include "ecryptfs_kernel.h"
- 
- struct ecryptfs_open_req {
-@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
- 	flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
- 	(*lower_file) = dentry_open(&req.path, flags, cred);
- 	if (!IS_ERR(*lower_file))
--		goto out;
-+		goto have_file;
- 	if ((flags & O_ACCMODE) == O_RDONLY) {
- 		rc = PTR_ERR((*lower_file));
- 		goto out;
-@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file,
- 	mutex_unlock(&ecryptfs_kthread_ctl.mux);
- 	wake_up(&ecryptfs_kthread_ctl.wait);
- 	wait_for_completion(&req.done);
--	if (IS_ERR(*lower_file))
-+	if (IS_ERR(*lower_file)) {
- 		rc = PTR_ERR(*lower_file);
-+		goto out;
-+	}
-+have_file:
-+	if ((*lower_file)->f_op->mmap == NULL) {
-+		fput(*lower_file);
-+		*lower_file = NULL;
-+		rc = -EMEDIUMTYPE;
-+	}
- out:
- 	return rc;
- }
-diff --git a/fs/proc/root.c b/fs/proc/root.c
-index 361ab4e..ec649c9 100644
---- a/fs/proc/root.c
-+++ b/fs/proc/root.c
-@@ -121,6 +121,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
- 	if (IS_ERR(sb))
- 		return ERR_CAST(sb);
- 
-+	/*
-+	 * procfs isn't actually a stacking filesystem; however, there is
-+	 * too much magic going on inside it to permit stacking things on
-+	 * top of it
-+	 */
-+	sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
-+
- 	if (!proc_parse_options(options, ns)) {
- 		deactivate_locked_super(sb);
- 		return ERR_PTR(-EINVAL);
-diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
-index d5d798b..e984250 100644
---- a/include/linux/irqchip/arm-gic-v3.h
-+++ b/include/linux/irqchip/arm-gic-v3.h
-@@ -301,7 +301,7 @@
- #define ICC_SGI1R_AFFINITY_1_SHIFT	16
- #define ICC_SGI1R_AFFINITY_1_MASK	(0xff << ICC_SGI1R_AFFINITY_1_SHIFT)
- #define ICC_SGI1R_SGI_ID_SHIFT		24
--#define ICC_SGI1R_SGI_ID_MASK		(0xff << ICC_SGI1R_SGI_ID_SHIFT)
-+#define ICC_SGI1R_SGI_ID_MASK		(0xfULL << ICC_SGI1R_SGI_ID_SHIFT)
- #define ICC_SGI1R_AFFINITY_2_SHIFT	32
- #define ICC_SGI1R_AFFINITY_2_MASK	(0xffULL << ICC_SGI1R_AFFINITY_1_SHIFT)
- #define ICC_SGI1R_IRQ_ROUTING_MODE_BIT	40
-diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
-index 80a305b..4dd9306 100644
---- a/include/linux/netfilter/x_tables.h
-+++ b/include/linux/netfilter/x_tables.h
-@@ -242,11 +242,18 @@ void xt_unregister_match(struct xt_match *target);
- int xt_register_matches(struct xt_match *match, unsigned int n);
- 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);
-+
- int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto,
- 		   bool inv_proto);
- 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);
-+
- struct xt_table *xt_register_table(struct net *net,
- 				   const struct xt_table *table,
- 				   struct xt_table_info *bootstrap,
-@@ -480,7 +487,7 @@ void xt_compat_init_offsets(u_int8_t af, unsigned int number);
- int xt_compat_calc_jump(u_int8_t af, unsigned int offset);
- 
- int xt_compat_match_offset(const struct xt_match *match);
--int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
-+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
- 			      unsigned int *size);
- int xt_compat_match_to_user(const struct xt_entry_match *m,
- 			    void __user **dstptr, unsigned int *size);
-@@ -490,6 +497,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
- 				unsigned int *size);
- 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/net/switchdev.h b/include/net/switchdev.h
-index 51d77b2..985619a 100644
---- a/include/net/switchdev.h
-+++ b/include/net/switchdev.h
-@@ -97,7 +97,7 @@ struct switchdev_obj_ipv4_fib {
- 	struct switchdev_obj obj;
- 	u32 dst;
- 	int dst_len;
--	struct fib_info fi;
-+	struct fib_info *fi;
- 	u8 tos;
- 	u8 type;
- 	u32 nlflags;
-diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h
-index d5e38c7..e4f048e 100644
---- a/include/uapi/linux/libc-compat.h
-+++ b/include/uapi/linux/libc-compat.h
-@@ -52,7 +52,7 @@
- #if defined(__GLIBC__)
- 
- /* Coordinate with glibc net/if.h header. */
--#if defined(_NET_IF_H)
-+#if defined(_NET_IF_H) && defined(__USE_MISC)
- 
- /* GLIBC headers included first so don't define anything
-  * that would already be defined. */
-diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
-index 8f94ca1..b2aefa2 100644
---- a/kernel/bpf/inode.c
-+++ b/kernel/bpf/inode.c
-@@ -378,7 +378,7 @@ static int bpf_fill_super(struct super_block *sb, void *data, int silent)
- static struct dentry *bpf_mount(struct file_system_type *type, int flags,
- 				const char *dev_name, void *data)
- {
--	return mount_ns(type, flags, current->nsproxy->mnt_ns, bpf_fill_super);
-+	return mount_nodev(type, flags, data, bpf_fill_super);
- }
- 
- static struct file_system_type bpf_fs_type = {
-@@ -386,7 +386,6 @@ static struct file_system_type bpf_fs_type = {
- 	.name		= "bpf",
- 	.mount		= bpf_mount,
- 	.kill_sb	= kill_litter_super,
--	.fs_flags	= FS_USERNS_MOUNT,
- };
- 
- MODULE_ALIAS_FS("bpf");
-diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index d1f7149..11546a6 100644
---- a/kernel/sched/core.c
-+++ b/kernel/sched/core.c
-@@ -3047,7 +3047,8 @@ static noinline void __schedule_bug(struct task_struct *prev)
- static inline void schedule_debug(struct task_struct *prev)
- {
- #ifdef CONFIG_SCHED_STACK_END_CHECK
--	BUG_ON(task_stack_end_corrupted(prev));
-+	if (task_stack_end_corrupted(prev))
-+		panic("corrupted stack end detected inside scheduler\n");
- #endif
- 
- 	if (unlikely(in_atomic_preempt_off())) {
-diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
-index 3e4ffb3..d028941 100644
---- a/kernel/trace/bpf_trace.c
-+++ b/kernel/trace/bpf_trace.c
-@@ -194,7 +194,7 @@ static u64 bpf_perf_event_read(u64 r1, u64 index, u64 r3, u64 r4, u64 r5)
- 	if (unlikely(index >= array->map.max_entries))
- 		return -E2BIG;
- 
--	file = (struct file *)array->ptrs[index];
-+	file = READ_ONCE(array->ptrs[index]);
- 	if (unlikely(!file))
- 		return -ENOENT;
- 
-@@ -238,7 +238,7 @@ static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 index, u64 r4, u64 size)
- 	if (unlikely(index >= array->map.max_entries))
- 		return -E2BIG;
- 
--	file = (struct file *)array->ptrs[index];
-+	file = READ_ONCE(array->ptrs[index]);
- 	if (unlikely(!file))
- 		return -ENOENT;
- 
-diff --git a/mm/memcontrol.c b/mm/memcontrol.c
-index fe787f5..a2e79b8 100644
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -2877,6 +2877,7 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
- 	 * ordering is imposed by list_lru_node->lock taken by
- 	 * memcg_drain_all_list_lrus().
- 	 */
-+	rcu_read_lock(); /* can be called from css_free w/o cgroup_mutex */
- 	css_for_each_descendant_pre(css, &memcg->css) {
- 		child = mem_cgroup_from_css(css);
- 		BUG_ON(child->kmemcg_id != kmemcg_id);
-@@ -2884,6 +2885,8 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
- 		if (!memcg->use_hierarchy)
- 			break;
- 	}
-+	rcu_read_unlock();
-+
- 	memcg_drain_all_list_lrus(kmemcg_id, parent->kmemcg_id);
- 
- 	memcg_free_cache_id(kmemcg_id);
-diff --git a/mm/swap_state.c b/mm/swap_state.c
-index 366ce35..1155a68 100644
---- a/mm/swap_state.c
-+++ b/mm/swap_state.c
-@@ -252,7 +252,10 @@ static inline void free_swap_cache(struct page *page)
- void free_page_and_swap_cache(struct page *page)
- {
- 	free_swap_cache(page);
--	put_page(page);
-+	if (is_huge_zero_page(page))
-+		put_huge_zero_page();
-+	else
-+		put_page(page);
- }
- 
- /*
-diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
-index dcea4f4..c18080a 100644
---- a/net/bridge/br_fdb.c
-+++ b/net/bridge/br_fdb.c
-@@ -279,6 +279,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
- 	 * change from under us.
- 	 */
- 	list_for_each_entry(v, &vg->vlan_list, vlist) {
-+		if (!br_vlan_should_use(v))
-+			continue;
- 		f = __br_fdb_get(br, br->dev->dev_addr, v->vid);
- 		if (f && f->is_local && !f->dst)
- 			fdb_delete_local(br, NULL, f);
-diff --git a/net/core/hwbm.c b/net/core/hwbm.c
-index 941c284..2cab489 100644
---- a/net/core/hwbm.c
-+++ b/net/core/hwbm.c
-@@ -55,18 +55,21 @@ int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
- 	spin_lock_irqsave(&bm_pool->lock, flags);
- 	if (bm_pool->buf_num == bm_pool->size) {
- 		pr_warn("pool already filled\n");
-+		spin_unlock_irqrestore(&bm_pool->lock, flags);
- 		return bm_pool->buf_num;
- 	}
- 
- 	if (buf_num + bm_pool->buf_num > bm_pool->size) {
- 		pr_warn("cannot allocate %d buffers for pool\n",
- 			buf_num);
-+		spin_unlock_irqrestore(&bm_pool->lock, flags);
- 		return 0;
- 	}
- 
- 	if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {
- 		pr_warn("Adding %d buffers to the %d current buffers will overflow\n",
- 			buf_num,  bm_pool->buf_num);
-+		spin_unlock_irqrestore(&bm_pool->lock, flags);
- 		return 0;
- 	}
- 
-diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
-index 9e48199..7ad0e56 100644
---- a/net/ipv4/af_inet.c
-+++ b/net/ipv4/af_inet.c
-@@ -1660,6 +1660,14 @@ static __net_init int inet_init_net(struct net *net)
- 	 */
- 	net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1);
- 	net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0);
-+
-+	/* Default values for sysctl-controlled parameters.
-+	 * We set them here, in case sysctl is not compiled.
-+	 */
-+	net->ipv4.sysctl_ip_default_ttl = IPDEFTTL;
-+	net->ipv4.sysctl_ip_dynaddr = 0;
-+	net->ipv4.sysctl_ip_early_demux = 1;
-+
- 	return 0;
- }
- 
-diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
-index 4133b0f..85d60c6 100644
---- a/net/ipv4/netfilter/arp_tables.c
-+++ b/net/ipv4/netfilter/arp_tables.c
-@@ -367,6 +367,18 @@ static inline bool unconditional(const struct arpt_entry *e)
- 	       memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
- }
- 
-+static bool find_jump_target(const struct xt_table_info *t,
-+			     const struct arpt_entry *target)
-+{
-+	struct arpt_entry *iter;
-+
-+	xt_entry_foreach(iter, t->entries, t->size) {
-+		 if (iter == target)
-+			return true;
-+	}
-+	return false;
-+}
-+
- /* Figures out from what hook each rule can be called: returns 0 if
-  * there are loops.  Puts hook bitmask in comefrom.
-  */
-@@ -439,6 +451,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 {
-@@ -458,9 +472,15 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
- 					/* This a jump; chase it. */
- 					duprintf("Jump rule %u -> %u\n",
- 						 pos, newpos);
-+					e = (struct arpt_entry *)
-+						(entry0 + newpos);
-+					if (!find_jump_target(newinfo, e))
-+						return 0;
- 				} else {
- 					/* ... this is a fallthru */
- 					newpos = pos + e->next_offset;
-+					if (newpos >= newinfo->size)
-+						return 0;
- 				}
- 				e = (struct arpt_entry *)
- 					(entry0 + newpos);
-@@ -474,23 +494,6 @@ next:
- 	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);
-@@ -586,7 +589,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;
- 
-@@ -691,10 +698,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;
-@@ -1126,55 +1131,17 @@ static int do_add_counters(struct net *net, const void __user *user,
- 	unsigned int i;
- 	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;
- 	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);
--	}
-+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
-+	if (IS_ERR(paddc))
-+		return PTR_ERR(paddc);
- 
--	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, 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;
-@@ -1182,7 +1149,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;
- 	}
-@@ -1209,6 +1176,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;
-@@ -1217,20 +1196,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 ||
-@@ -1247,8 +1223,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;
- 
-@@ -1272,17 +1251,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:
-@@ -1291,18 +1259,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));
-@@ -1323,148 +1290,82 @@ 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;
- 	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) {
--		iter1->counters.pcnt = xt_percpu_counter_alloc();
--		if (IS_ERR_VALUE(iter1->counters.pcnt)) {
--			ret = -ENOMEM;
--			break;
--		}
--
--		ret = check_target(iter1, name);
--		if (ret != 0) {
--			xt_percpu_counter_free(iter1->counters.pcnt);
--			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];
- 	}
- 
-+	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;
- 	xt_free_table_info(info);
-@@ -1472,31 +1373,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)
- {
-@@ -1529,10 +1417,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 631c100..0984ea3 100644
---- a/net/ipv4/netfilter/ip_tables.c
-+++ b/net/ipv4/netfilter/ip_tables.c
-@@ -443,6 +443,18 @@ ipt_do_table(struct sk_buff *skb,
- #endif
- }
- 
-+static bool find_jump_target(const struct xt_table_info *t,
-+			     const struct ipt_entry *target)
-+{
-+	struct ipt_entry *iter;
-+
-+	xt_entry_foreach(iter, t->entries, t->size) {
-+		 if (iter == target)
-+			return true;
-+	}
-+	return false;
-+}
-+
- /* Figures out from what hook each rule can be called: returns 0 if
-    there are loops.  Puts hook bitmask in comefrom. */
- static int
-@@ -520,6 +532,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 {
-@@ -538,9 +552,15 @@ mark_source_chains(const struct xt_table_info *newinfo,
- 					/* This a jump; chase it. */
- 					duprintf("Jump rule %u -> %u\n",
- 						 pos, newpos);
-+					e = (struct ipt_entry *)
-+						(entry0 + newpos);
-+					if (!find_jump_target(newinfo, e))
-+						return 0;
- 				} else {
- 					/* ... this is a fallthru */
- 					newpos = pos + e->next_offset;
-+					if (newpos >= newinfo->size)
-+						return 0;
- 				}
- 				e = (struct ipt_entry *)
- 					(entry0 + newpos);
-@@ -568,25 +588,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;
-@@ -750,7 +751,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;
- 
-@@ -1309,55 +1314,17 @@ do_add_counters(struct net *net, const void __user *user,
- 	unsigned int i;
- 	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;
- 	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;
--	}
-+	paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
-+	if (IS_ERR(paddc))
-+		return PTR_ERR(paddc);
- 
--	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_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;
-@@ -1365,7 +1332,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;
- 	}
-@@ -1444,7 +1411,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,
- 		       int *size)
- {
-@@ -1479,17 +1445,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 ||
-@@ -1506,8 +1469,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;
- 
-@@ -1515,7 +1481,7 @@ 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, &off);
-+		ret = compat_find_calc_match(ematch, &e->ip, &off);
- 		if (ret != 0)
- 			goto release_matches;
- 		++j;
-@@ -1538,17 +1504,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:
-@@ -1562,19 +1517,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));
-@@ -1583,201 +1537,105 @@ 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;
--
--	e->counters.pcnt = xt_percpu_counter_alloc();
--	if (IS_ERR_VALUE(e->counters.pcnt))
--		return -ENOMEM;
--
--	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);
--	}
--
--	xt_percpu_counter_free(e->counters.pcnt);
--
--	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;
- 	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];
- 	}
- 
-+	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;
- 	xt_free_table_info(info);
-@@ -1785,17 +1643,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
-@@ -1831,10 +1688,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/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
-index 1e1fe60..03112a3 100644
---- a/net/ipv4/sysctl_net_ipv4.c
-+++ b/net/ipv4/sysctl_net_ipv4.c
-@@ -988,10 +988,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
- 	if (!net->ipv4.sysctl_local_reserved_ports)
- 		goto err_ports;
- 
--	net->ipv4.sysctl_ip_default_ttl = IPDEFTTL;
--	net->ipv4.sysctl_ip_dynaddr = 0;
--	net->ipv4.sysctl_ip_early_demux = 1;
--
- 	return 0;
- 
- err_ports:
-diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
-index a2e7f55..e9853df 100644
---- a/net/ipv4/udp.c
-+++ b/net/ipv4/udp.c
-@@ -1616,7 +1616,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) {
-+		if (encap_rcv) {
- 			int ret;
- 
- 			/* Verify checksum before giving to encap */
-diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index bc972e7..da88de8 100644
---- a/net/ipv6/ip6_output.c
-+++ b/net/ipv6/ip6_output.c
-@@ -1071,17 +1071,12 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
- 					 const struct in6_addr *final_dst)
- {
- 	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);
- 
--	err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6);
--	if (err)
--		return ERR_PTR(err);
--	if (final_dst)
--		fl6->daddr = *final_dst;
--
--	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/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
-index 86b67b7..9021b43 100644
---- a/net/ipv6/netfilter/ip6_tables.c
-+++ b/net/ipv6/netfilter/ip6_tables.c
-@@ -455,6 +455,18 @@ ip6t_do_table(struct sk_buff *skb,
- #endif
- }
- 
-+static bool find_jump_target(const struct xt_table_info *t,
-+			     const struct ip6t_entry *target)
-+{
-+	struct ip6t_entry *iter;
-+
-+	xt_entry_foreach(iter, t->entries, t->size) {
-+		 if (iter == target)
-+			return true;
-+	}
-+	return false;
-+}
-+
- /* Figures out from what hook each rule can be called: returns 0 if
-    there are loops.  Puts hook bitmask in comefrom. */
- static int
-@@ -532,6 +544,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 {
-@@ -550,9 +564,15 @@ mark_source_chains(const struct xt_table_info *newinfo,
- 					/* This a jump; chase it. */
- 					duprintf("Jump rule %u -> %u\n",
- 						 pos, newpos);
-+					e = (struct ip6t_entry *)
-+						(entry0 + newpos);
-+					if (!find_jump_target(newinfo, e))
-+						return 0;
- 				} else {
- 					/* ... this is a fallthru */
- 					newpos = pos + e->next_offset;
-+					if (newpos >= newinfo->size)
-+						return 0;
- 				}
- 				e = (struct ip6t_entry *)
- 					(entry0 + newpos);
-@@ -579,25 +599,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;
-@@ -762,7 +763,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;
- 
-@@ -1321,55 +1326,16 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
- 	unsigned int i;
- 	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;
- 	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;
-@@ -1377,7 +1343,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;
- 	}
-@@ -1456,7 +1422,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,
- 		       int *size)
- {
-@@ -1491,17 +1456,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 ||
-@@ -1518,8 +1480,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;
- 
-@@ -1527,7 +1492,7 @@ 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, &off);
-+		ret = compat_find_calc_match(ematch, &e->ipv6, &off);
- 		if (ret != 0)
- 			goto release_matches;
- 		++j;
-@@ -1550,17 +1515,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:
-@@ -1574,18 +1528,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));
-@@ -1594,11 +1547,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);
-@@ -1610,183 +1561,83 @@ 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;
--
--	e->counters.pcnt = xt_percpu_counter_alloc();
--	if (IS_ERR_VALUE(e->counters.pcnt))
--		return -ENOMEM;
--	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);
--	}
--
--	xt_percpu_counter_free(e->counters.pcnt);
--
--	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;
- 	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];
- 	}
- 
-+	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;
- 	xt_free_table_info(info);
-@@ -1794,17 +1645,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
-@@ -1840,10 +1690,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/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
-index f443c6b..f6d7516 100644
---- a/net/ipv6/tcp_ipv6.c
-+++ b/net/ipv6/tcp_ipv6.c
-@@ -1717,7 +1717,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 6bc5c66..f96831d9 100644
---- a/net/ipv6/udp.c
-+++ b/net/ipv6/udp.c
-@@ -653,7 +653,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) {
-+		if (encap_rcv) {
- 			int ret;
- 
- 			/* Verify checksum before giving to encap */
-diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
-index 6edfa99..1e40dac 100644
---- a/net/l2tp/l2tp_core.c
-+++ b/net/l2tp/l2tp_core.c
-@@ -1581,7 +1581,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
- 	/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
- 	tunnel->encap = encap;
- 	if (encap == L2TP_ENCAPTYPE_UDP) {
--		struct udp_tunnel_sock_cfg udp_cfg;
-+		struct udp_tunnel_sock_cfg udp_cfg = { };
- 
- 		udp_cfg.sk_user_data = tunnel;
- 		udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
-diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
-index 582c9cf..2675d58 100644
---- a/net/netfilter/x_tables.c
-+++ b/net/netfilter/x_tables.c
-@@ -416,6 +416,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)
- {
-@@ -485,13 +526,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));
-@@ -505,10 +547,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);
- 
-@@ -539,8 +583,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)
- {
-@@ -591,6 +752,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)
- {
-@@ -606,6 +841,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));
-@@ -619,6 +855,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 330ebd6..f48e3b3 100644
---- a/net/netlink/af_netlink.c
-+++ b/net/netlink/af_netlink.c
-@@ -2059,6 +2059,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_min_size;
- 	int alloc_size;
-@@ -2134,9 +2135,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/switchdev/switchdev.c b/net/switchdev/switchdev.c
-index b7e01d8..59658b2 100644
---- a/net/switchdev/switchdev.c
-+++ b/net/switchdev/switchdev.c
-@@ -1188,6 +1188,7 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
- 		.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
- 		.dst = dst,
- 		.dst_len = dst_len,
-+		.fi = fi,
- 		.tos = tos,
- 		.type = type,
- 		.nlflags = nlflags,
-@@ -1196,8 +1197,6 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
- 	struct net_device *dev;
- 	int err = 0;
- 
--	memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
--
- 	/* Don't offload route if using custom ip rules or if
- 	 * IPv4 FIB offloading has been disabled completely.
- 	 */
-@@ -1242,6 +1241,7 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
- 		.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
- 		.dst = dst,
- 		.dst_len = dst_len,
-+		.fi = fi,
- 		.tos = tos,
- 		.type = type,
- 		.nlflags = 0,
-@@ -1250,8 +1250,6 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
- 	struct net_device *dev;
- 	int err = 0;
- 
--	memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
--
- 	if (!(fi->fib_flags & RTNH_F_OFFLOAD))
- 		return 0;
- 
-diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
-index d7d050f..4dfc5c1 100644
---- a/net/tipc/netlink_compat.c
-+++ b/net/tipc/netlink_compat.c
-@@ -802,7 +802,7 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg,
- 		goto out;
- 
- 	tipc_tlv_sprintf(msg->rep, "%-10u %s",
--			 nla_get_u32(publ[TIPC_NLA_PUBL_REF]),
-+			 nla_get_u32(publ[TIPC_NLA_PUBL_KEY]),
- 			 scope_str[nla_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]);
- out:
- 	tipc_tlv_sprintf(msg->rep, "\n");
-diff --git a/net/tipc/socket.c b/net/tipc/socket.c
-index 3eeb50a..5f80d3f 100644
---- a/net/tipc/socket.c
-+++ b/net/tipc/socket.c
-@@ -2807,6 +2807,9 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
- 		if (err)
- 			return err;
- 
-+		if (!attrs[TIPC_NLA_SOCK])
-+			return -EINVAL;
-+
- 		err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
- 				       attrs[TIPC_NLA_SOCK],
- 				       tipc_nl_sock_policy);
-diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
-index b50ee5d..c753211 100644
---- a/net/wireless/wext-core.c
-+++ b/net/wireless/wext-core.c
-@@ -955,8 +955,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/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
-index 9a0d144..94089fc 100644
---- a/sound/pci/hda/hda_intel.c
-+++ b/sound/pci/hda/hda_intel.c
-@@ -365,8 +365,11 @@ enum {
- 
- #define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
- #define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
-+#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171)
-+#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
- #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
--#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
-+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
-+			IS_KBL(pci) || IS_KBL_LP(pci)
- 
- static char *driver_short_names[] = {
- 	[AZX_DRIVER_ICH] = "HDA Intel",
-@@ -2181,6 +2184,12 @@ static const struct pci_device_id azx_ids[] = {
- 	/* Sunrise Point-LP */
- 	{ PCI_DEVICE(0x8086, 0x9d70),
- 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
-+	/* Kabylake */
-+	{ PCI_DEVICE(0x8086, 0xa171),
-+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
-+	/* Kabylake-LP */
-+	{ PCI_DEVICE(0x8086, 0x9d71),
-+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
- 	/* Broxton-P(Apollolake) */
- 	{ PCI_DEVICE(0x8086, 0x5a98),
- 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
-diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
-index d53c25e..0fe18ed 100644
---- a/sound/pci/hda/patch_realtek.c
-+++ b/sound/pci/hda/patch_realtek.c
-@@ -346,6 +346,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
- 	case 0x10ec0234:
- 	case 0x10ec0274:
- 	case 0x10ec0294:
-+	case 0x10ec0700:
-+	case 0x10ec0701:
-+	case 0x10ec0703:
- 		alc_update_coef_idx(codec, 0x10, 1<<15, 0);
- 		break;
- 	case 0x10ec0662:
-@@ -2655,6 +2658,7 @@ enum {
- 	ALC269_TYPE_ALC256,
- 	ALC269_TYPE_ALC225,
- 	ALC269_TYPE_ALC294,
-+	ALC269_TYPE_ALC700,
- };
- 
- /*
-@@ -2686,6 +2690,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
- 	case ALC269_TYPE_ALC256:
- 	case ALC269_TYPE_ALC225:
- 	case ALC269_TYPE_ALC294:
-+	case ALC269_TYPE_ALC700:
- 		ssids = alc269_ssids;
- 		break;
- 	default:
-@@ -3618,13 +3623,20 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
- static void alc_headset_mode_unplugged(struct hda_codec *codec)
- {
- 	static struct coef_fw coef0255[] = {
--		WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
- 		WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
- 		UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
- 		WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
- 		WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
- 		{}
- 	};
-+	static struct coef_fw coef0255_1[] = {
-+		WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
-+		{}
-+	};
-+	static struct coef_fw coef0256[] = {
-+		WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
-+		{}
-+	};
- 	static struct coef_fw coef0233[] = {
- 		WRITE_COEF(0x1b, 0x0c0b),
- 		WRITE_COEF(0x45, 0xc429),
-@@ -3677,7 +3689,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
- 
- 	switch (codec->core.vendor_id) {
- 	case 0x10ec0255:
-+		alc_process_coef_fw(codec, coef0255_1);
-+		alc_process_coef_fw(codec, coef0255);
-+		break;
- 	case 0x10ec0256:
-+		alc_process_coef_fw(codec, coef0256);
- 		alc_process_coef_fw(codec, coef0255);
- 		break;
- 	case 0x10ec0233:
-@@ -3896,6 +3912,12 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
- 		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
- 		{}
- 	};
-+	static struct coef_fw coef0256[] = {
-+		WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
-+		WRITE_COEF(0x1b, 0x0c6b),
-+		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
-+		{}
-+	};
- 	static struct coef_fw coef0233[] = {
- 		WRITE_COEF(0x45, 0xd429),
- 		WRITE_COEF(0x1b, 0x0c2b),
-@@ -3936,9 +3958,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
- 
- 	switch (codec->core.vendor_id) {
- 	case 0x10ec0255:
--	case 0x10ec0256:
- 		alc_process_coef_fw(codec, coef0255);
- 		break;
-+	case 0x10ec0256:
-+		alc_process_coef_fw(codec, coef0256);
-+		break;
- 	case 0x10ec0233:
- 	case 0x10ec0283:
- 		alc_process_coef_fw(codec, coef0233);
-@@ -3978,6 +4002,12 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
- 		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
- 		{}
- 	};
-+	static struct coef_fw coef0256[] = {
-+		WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
-+		WRITE_COEF(0x1b, 0x0c6b),
-+		WRITE_COEFEX(0x57, 0x03, 0x8ea6),
-+		{}
-+	};
- 	static struct coef_fw coef0233[] = {
- 		WRITE_COEF(0x45, 0xe429),
- 		WRITE_COEF(0x1b, 0x0c2b),
-@@ -4018,9 +4048,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
- 
- 	switch (codec->core.vendor_id) {
- 	case 0x10ec0255:
--	case 0x10ec0256:
- 		alc_process_coef_fw(codec, coef0255);
- 		break;
-+	case 0x10ec0256:
-+		alc_process_coef_fw(codec, coef0256);
-+		break;
- 	case 0x10ec0233:
- 	case 0x10ec0283:
- 		alc_process_coef_fw(codec, coef0233);
-@@ -4266,7 +4298,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
- static void alc255_set_default_jack_type(struct hda_codec *codec)
- {
- 	/* Set to iphone type */
--	static struct coef_fw fw[] = {
-+	static struct coef_fw alc255fw[] = {
- 		WRITE_COEF(0x1b, 0x880b),
- 		WRITE_COEF(0x45, 0xd089),
- 		WRITE_COEF(0x1b, 0x080b),
-@@ -4274,7 +4306,22 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
- 		WRITE_COEF(0x1b, 0x0c0b),
- 		{}
- 	};
--	alc_process_coef_fw(codec, fw);
-+	static struct coef_fw alc256fw[] = {
-+		WRITE_COEF(0x1b, 0x884b),
-+		WRITE_COEF(0x45, 0xd089),
-+		WRITE_COEF(0x1b, 0x084b),
-+		WRITE_COEF(0x46, 0x0004),
-+		WRITE_COEF(0x1b, 0x0c4b),
-+		{}
-+	};
-+	switch (codec->core.vendor_id) {
-+	case 0x10ec0255:
-+		alc_process_coef_fw(codec, alc255fw);
-+		break;
-+	case 0x10ec0256:
-+		alc_process_coef_fw(codec, alc256fw);
-+		break;
-+	}
- 	msleep(30);
- }
- 
-@@ -5587,6 +5634,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
- 	SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
- 	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
- 	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
-+	SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
- 	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
- 	SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
- 	SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
-@@ -5775,6 +5823,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
- 		{0x12, 0x90a60180},
- 		{0x14, 0x90170130},
- 		{0x21, 0x02211040}),
-+	SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5565", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
-+		{0x12, 0x90a60180},
-+		{0x14, 0x90170120},
-+		{0x21, 0x02211030}),
- 	SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- 		{0x12, 0x90a60160},
- 		{0x14, 0x90170120},
-@@ -6053,6 +6105,14 @@ static int patch_alc269(struct hda_codec *codec)
- 	case 0x10ec0294:
- 		spec->codec_variant = ALC269_TYPE_ALC294;
- 		break;
-+	case 0x10ec0700:
-+	case 0x10ec0701:
-+	case 0x10ec0703:
-+		spec->codec_variant = ALC269_TYPE_ALC700;
-+		spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
-+		alc_update_coef_idx(codec, 0x4a, 0, 1 << 15); /* Combo jack auto trigger control */
-+		break;
-+
- 	}
- 
- 	if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
-@@ -7008,6 +7068,9 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
- 	HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
- 	HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
- 	HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
-+	HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
-+	HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
-+	HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
- 	HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc882),
- 	HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
- 	HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
-diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
-index 674bdf8..501849a 100644
---- a/virt/kvm/arm/hyp/vgic-v2-sr.c
-+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
-@@ -93,12 +93,11 @@ static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
- 		if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
- 			continue;
- 
--		if (cpu_if->vgic_elrsr & (1UL << i)) {
-+		if (cpu_if->vgic_elrsr & (1UL << i))
- 			cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
--			continue;
--		}
-+		else
-+			cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
- 
--		cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
- 		writel_relaxed(0, base + GICH_LR0 + (i * 4));
- 	}
- }
-diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
-index fe84e1a..8db197b 100644
---- a/virt/kvm/irqchip.c
-+++ b/virt/kvm/irqchip.c
-@@ -40,7 +40,7 @@ int kvm_irq_map_gsi(struct kvm *kvm,
- 
- 	irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
- 					lockdep_is_held(&kvm->irq_lock));
--	if (gsi < irq_rt->nr_rt_entries) {
-+	if (irq_rt && gsi < irq_rt->nr_rt_entries) {
- 		hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
- 			entries[n] = *e;
- 			++n;

diff --git a/4.6.3/0000_README b/4.6.4/0000_README
similarity index 92%
rename from 4.6.3/0000_README
rename to 4.6.4/0000_README
index 585f483..55247f8 100644
--- a/4.6.3/0000_README
+++ b/4.6.4/0000_README
@@ -2,11 +2,7 @@ README
 -----------------------------------------------------------------------------
 Individual Patch Descriptions:
 -----------------------------------------------------------------------------
-Patch:	1002_linux-4.6.3.patch
-From:	http://www.kernel.org
-Desc:	Linux 4.6.3
-
-Patch:	4420_grsecurity-3.1-4.6.3-201607070721.patch
+Patch:	4420_grsecurity-3.1-4.6.4-201607112205.patch
 From:	http://www.grsecurity.net
 Desc:	hardened-sources base patch from upstream grsecurity
 

diff --git a/4.6.3/4420_grsecurity-3.1-4.6.3-201607070721.patch b/4.6.4/4420_grsecurity-3.1-4.6.4-201607112205.patch
similarity index 99%
rename from 4.6.3/4420_grsecurity-3.1-4.6.3-201607070721.patch
rename to 4.6.4/4420_grsecurity-3.1-4.6.4-201607112205.patch
index b3964cb..95ffa2d 100644
--- a/4.6.3/4420_grsecurity-3.1-4.6.3-201607070721.patch
+++ b/4.6.4/4420_grsecurity-3.1-4.6.4-201607112205.patch
@@ -420,7 +420,7 @@ index fcddfd5..71afd6b 100644
  
  A toggle value indicating if modules are allowed to be loaded
 diff --git a/Makefile b/Makefile
-index c62b531..e158b54 100644
+index cd37442..4c8e887 100644
 --- a/Makefile
 +++ b/Makefile
 @@ -298,7 +298,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@@ -39799,10 +39799,10 @@ index 7921251..ba86330 100644
  static void cryptd_queue_worker(struct work_struct *work);
  
 diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
-index 43fe85f..215a174 100644
+index 7097a33..e946ace 100644
 --- a/crypto/crypto_user.c
 +++ b/crypto/crypto_user.c
-@@ -504,7 +504,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+@@ -505,7 +505,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  			dump_alloc += CRYPTO_REPORT_MAXSIZE;
  
  		{
@@ -42021,7 +42021,7 @@ index 92d6fc0..e4e1e27 100644
  }
  
 diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
-index 7a1cf7e..538f666 100644
+index 7a1cf7e..0330e12 100644
 --- a/drivers/block/drbd/drbd_int.h
 +++ b/drivers/block/drbd/drbd_int.h
 @@ -382,7 +382,7 @@ struct drbd_epoch {
@@ -42033,6 +42033,17 @@ index 7a1cf7e..538f666 100644
  	atomic_t active;     /* increased on every req. added, and dec on every finished. */
  	unsigned long flags;
  };
+@@ -586,8 +586,8 @@ struct drbd_md {
+ 	u32 flags;
+ 	u32 md_size_sect;
+ 
+-	s32 al_offset;	/* signed relative sector offset to activity log */
+-	s32 bm_offset;	/* signed relative sector offset to bitmap */
++	s32 al_offset __intentional_overflow(0);	/* signed relative sector offset to activity log */
++	s32 bm_offset __intentional_overflow(0);	/* signed relative sector offset to bitmap */
+ 
+ 	/* cached value of bdev->disk_conf->meta_dev_idx (see below) */
+ 	s32 meta_dev_idx;
 @@ -951,7 +951,7 @@ struct drbd_device {
  	unsigned int al_tr_number;
  	int al_tr_cycle;
@@ -70517,7 +70528,7 @@ index 1e7e139..c2031dd 100644
  
  /*
 diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
-index 06dc215..543c5aa 100644
+index 06dc215..543c5aaa 100644
 --- a/drivers/scsi/bfa/bfa_fcs.h
 +++ b/drivers/scsi/bfa/bfa_fcs.h
 @@ -67,8 +67,10 @@ struct bfa_fcs_s;
@@ -78569,7 +78580,7 @@ index a7de8e8..e1ef134 100644
  	spin_lock_init(&uhci->lock);
  	setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
 diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
-index 48672fa..9245081 100644
+index c10972f..7a2d5db5 100644
 --- a/drivers/usb/host/xhci-pci.c
 +++ b/drivers/usb/host/xhci-pci.c
 @@ -32,7 +32,7 @@
@@ -78582,10 +78593,10 @@ index 48672fa..9245081 100644
  /* Device for a quirk */
  #define PCI_VENDOR_ID_FRESCO_LOGIC	0x1b73
 diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
-index 99b4ff4..83b36b4 100644
+index 8b5b2ac..052a44e 100644
 --- a/drivers/usb/host/xhci-ring.c
 +++ b/drivers/usb/host/xhci-ring.c
-@@ -1861,9 +1861,9 @@ td_cleanup:
+@@ -1878,9 +1878,9 @@ td_cleanup:
  	 * unsigned).  Play it safe and say we didn't transfer anything.
  	 */
  	if (urb->actual_length > urb->transfer_buffer_length) {
@@ -78597,7 +78608,7 @@ index 99b4ff4..83b36b4 100644
  		urb->actual_length = 0;
  		if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
  			*status = -EREMOTEIO;
-@@ -1942,10 +1942,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+@@ -1959,10 +1959,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
  		return finish_td(xhci, td, event_trb, event, ep, status, false);
  	case COMP_STOP:
  		/* Did we stop at data stage? */
@@ -78617,7 +78628,7 @@ index 99b4ff4..83b36b4 100644
  		/* fall through */
  	case COMP_STOP_INVAL:
  		return finish_td(xhci, td, event_trb, event, ep, status, false);
-@@ -1959,12 +1964,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+@@ -1976,12 +1981,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
  		/* else fall through */
  	case COMP_STALL:
  		/* Did we transfer part of the data (middle) phase? */
@@ -78639,7 +78650,7 @@ index 99b4ff4..83b36b4 100644
  			td->urb->actual_length = 0;
  
  		return finish_td(xhci, td, event_trb, event, ep, status, false);
-@@ -1997,9 +2005,12 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+@@ -2014,9 +2022,12 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
  			 * the last TRB.
  			 */
  			td->urb_length_set = true;
@@ -78655,7 +78666,7 @@ index 99b4ff4..83b36b4 100644
  			xhci_dbg(xhci, "Waiting for status "
  					"stage event\n");
  			return 0;
-@@ -2194,11 +2205,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+@@ -2211,11 +2222,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
  	/* Fast path - was this the last TRB in the TD for this URB? */
  	} else if (event_trb == td->last_trb) {
  		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
@@ -78668,7 +78679,7 @@ index 99b4ff4..83b36b4 100644
  				xhci_warn(xhci, "HC gave bad length "
  						"of %d bytes left\n",
  					  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
-@@ -2207,7 +2214,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+@@ -2224,7 +2231,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
  					*status = -EREMOTEIO;
  				else
  					*status = 0;
@@ -78681,10 +78692,10 @@ index 99b4ff4..83b36b4 100644
  			if (*status == -EINPROGRESS) {
  				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
 diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
-index 9e71c96..f9b2333 100644
+index 3272805..a3f7895 100644
 --- a/drivers/usb/host/xhci.c
 +++ b/drivers/usb/host/xhci.c
-@@ -4875,7 +4875,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+@@ -4878,7 +4878,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
  	int			retval;
  
  	/* Accept arbitrarily long scatter-gather lists */
@@ -98514,6 +98525,39 @@ index 8580831..36166e5 100644
  	retval = sysfs_create_mount_point(kernel_kobj, "debug");
  	if (retval)
  		return retval;
+diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
+index f024040..27794b1 100644
+--- a/fs/ecryptfs/file.c
++++ b/fs/ecryptfs/file.c
+@@ -169,6 +169,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
+@@ -403,7 +416,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/ecryptfs/inode.c b/fs/ecryptfs/inode.c
 index 224b49e..980370c 100644
 --- a/fs/ecryptfs/inode.c
@@ -133239,7 +133283,7 @@ index f3f302f..a001305 100644
  /* Helper routines for sys_msgsnd and sys_msgrcv */
  extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
 diff --git a/include/linux/net.h b/include/linux/net.h
-index f840d77..f7a95d98 100644
+index 9d90efe6..55eeb64 100644
 --- a/include/linux/net.h
 +++ b/include/linux/net.h
 @@ -195,7 +195,7 @@ struct net_proto_family {
@@ -135063,7 +135107,7 @@ index c441407..f487b83 100644
  /*
   * Callback to arch code if there's nosmp or maxcpus=0 on the
 diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
-index 4018b48..68baf26 100644
+index a0596ca0..6c9245f 100644
 --- a/include/linux/sock_diag.h
 +++ b/include/linux/sock_diag.h
 @@ -16,7 +16,7 @@ struct sock_diag_handler {
@@ -139598,7 +139642,7 @@ index 2a20c0d..3eb7d03 100644
  #ifdef CONFIG_MODULE_UNLOAD
  		{
 diff --git a/kernel/events/core.c b/kernel/events/core.c
-index c0ded24..9a8ef89 100644
+index a69c90c..9344bfe 100644
 --- a/kernel/events/core.c
 +++ b/kernel/events/core.c
 @@ -350,8 +350,15 @@ static struct srcu_struct pmus_srcu;
@@ -154052,7 +154096,7 @@ index 3937b1b..b18d1cb 100644
  			fle->object = flo;
  		else
 diff --git a/net/core/neighbour.c b/net/core/neighbour.c
-index f18ae91..f033693 100644
+index 769cece..425d3bd 100644
 --- a/net/core/neighbour.c
 +++ b/net/core/neighbour.c
 @@ -860,7 +860,7 @@ static void neigh_probe(struct neighbour *neigh)
@@ -154118,7 +154162,7 @@ index f18ae91..f033693 100644
  	    nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
  		goto nla_put_failure;
  
-@@ -2870,7 +2870,7 @@ static int proc_unres_qlen(struct ctl_table *ctl, int write,
+@@ -2874,7 +2874,7 @@ static int proc_unres_qlen(struct ctl_table *ctl, int write,
  			   void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	int size, ret;
@@ -154127,7 +154171,7 @@ index f18ae91..f033693 100644
  
  	tmp.extra1 = &zero;
  	tmp.extra2 = &unres_qlen_max;
-@@ -2932,7 +2932,7 @@ static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
+@@ -2936,7 +2936,7 @@ static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
  					   void __user *buffer,
  					   size_t *lenp, loff_t *ppos)
  {
@@ -157090,7 +157134,7 @@ index 6f32944..03cad65 100644
  	table = kmemdup(ipv6_route_table_template,
  			sizeof(ipv6_route_table_template),
 diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
-index 8338430..602490e 100644
+index 6c53e4e..6e83866 100644
 --- a/net/ipv6/sit.c
 +++ b/net/ipv6/sit.c
 @@ -74,7 +74,7 @@ static void ipip6_tunnel_setup(struct net_device *dev);
@@ -184835,10 +184879,10 @@ index 0000000..00c7430
 +}
 diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data
 new file mode 100644
-index 0000000..bdcfd9a
+index 0000000..e6b58b6
 --- /dev/null
 +++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data
-@@ -0,0 +1,21989 @@
+@@ -0,0 +1,21990 @@
 +enable_so_recv_ctrl_pipe_us_data_0 recv_ctrl_pipe us_data 0 0 NULL
 +enable_so___earlyonly_bootmem_alloc_fndecl_3 __earlyonly_bootmem_alloc fndecl 2-3-4 3 NULL
 +enable_so_v9fs_xattr_get_acl_fndecl_4 v9fs_xattr_get_acl fndecl 5 4 NULL
@@ -184976,6 +185020,7 @@ index 0000000..bdcfd9a
 +enable_so_fcp_resid_bnx2fc_cmd_412 fcp_resid bnx2fc_cmd 0 412 NULL
 +enable_so_base_cbuf_417 base cbuf 0 417 NULL
 +enable_so_mp_config_acpi_gsi_fndecl_419 mp_config_acpi_gsi fndecl 2 419 NULL
++enable_so_apparmor_setprocattr_fndecl_421 apparmor_setprocattr fndecl 4 421 NULL
 +enable_so_fat_short2uni_fndecl_423 fat_short2uni fndecl 0 423 NULL
 +enable_so_vol_reg_size_tas571x_chip_426 vol_reg_size tas571x_chip 0 426 NULL
 +enable_so_status_netdev_desc_430 status netdev_desc 0 430 NULL
@@ -212148,7 +212193,7 @@ index f72f48f..769a657 100755
  # Find all available archs
  find_all_archs()
 diff --git a/security/Kconfig b/security/Kconfig
-index e452378..e634654 100644
+index e4523789..e634654 100644
 --- a/security/Kconfig
 +++ b/security/Kconfig
 @@ -4,6 +4,994 @@
@@ -213184,7 +213229,7 @@ index c28b0f2..3b9fee0 100644
  
  	struct dentry *dents[AAFS_NS_SIZEOF];
 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
-index dec607c..37fe357 100644
+index dec607c..53d479f 100644
 --- a/security/apparmor/lsm.c
 +++ b/security/apparmor/lsm.c
 @@ -176,7 +176,7 @@ static int common_perm_dir_dentry(int op, struct path *dir,
@@ -213216,7 +213261,82 @@ index dec607c..37fe357 100644
  		struct path_cond cond = { d_backing_inode(old_dentry)->i_uid,
  					  d_backing_inode(old_dentry)->i_mode
  		};
-@@ -677,11 +677,11 @@ static const struct kernel_param_ops param_ops_aalockpolicy = {
+@@ -523,34 +523,34 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
+ {
+ 	struct common_audit_data sa;
+ 	struct apparmor_audit_data aad = {0,};
+-	char *command, *args = value;
++	char *command, *largs = NULL, *args = value;
+ 	size_t arg_size;
+ 	int error;
+ 
+ 	if (size == 0)
+ 		return -EINVAL;
+-	/* args points to a PAGE_SIZE buffer, AppArmor requires that
+-	 * the buffer must be null terminated or have size <= PAGE_SIZE -1
+-	 * so that AppArmor can null terminate them
+-	 */
+-	if (args[size - 1] != '\0') {
+-		if (size == PAGE_SIZE)
+-			return -EINVAL;
+-		args[size] = '\0';
+-	}
+-
+ 	/* task can only write its own attributes */
+ 	if (current != task)
+ 		return -EACCES;
+ 
+-	args = value;
++	/* AppArmor requires that the buffer must be null terminated atm */
++	if (args[size - 1] != '\0') {
++		/* null terminate */
++		largs = args = kmalloc(size + 1, GFP_KERNEL);
++		if (!args)
++			return -ENOMEM;
++		memcpy(args, value, size);
++		args[size] = '\0';
++	}
++
++	error = -EINVAL;
+ 	args = strim(args);
+ 	command = strsep(&args, " ");
+ 	if (!args)
+-		return -EINVAL;
++		goto out;
+ 	args = skip_spaces(args);
+ 	if (!*args)
+-		return -EINVAL;
++		goto out;
+ 
+ 	arg_size = size - (args - (char *) value);
+ 	if (strcmp(name, "current") == 0) {
+@@ -576,10 +576,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
+ 			goto fail;
+ 	} else
+ 		/* only support the "current" and "exec" process attributes */
+-		return -EINVAL;
++		goto fail;
+ 
+ 	if (!error)
+ 		error = size;
++out:
++	kfree(largs);
+ 	return error;
+ 
+ fail:
+@@ -588,9 +590,9 @@ fail:
+ 	aad.profile = aa_current_profile();
+ 	aad.op = OP_SETPROCATTR;
+ 	aad.info = name;
+-	aad.error = -EINVAL;
++	aad.error = error = -EINVAL;
+ 	aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
+-	return -EINVAL;
++	goto out;
+ }
+ 
+ static int apparmor_task_setrlimit(struct task_struct *task,
+@@ -677,11 +679,11 @@ static const struct kernel_param_ops param_ops_aalockpolicy = {
  	.get = param_get_aalockpolicy
  };
  
@@ -213232,7 +213352,7 @@ index dec607c..37fe357 100644
  
  /* Flag values, also controllable via /sys/module/apparmor/parameters
   * We define special types as we want to do additional mediation.
-@@ -791,7 +791,7 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp)
+@@ -791,7 +793,7 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp)
  	return param_get_uint(buffer, kp);
  }
  
@@ -213241,7 +213361,7 @@ index dec607c..37fe357 100644
  {
  	if (!capable(CAP_MAC_ADMIN))
  		return -EPERM;
-@@ -802,7 +802,7 @@ static int param_get_audit(char *buffer, struct kernel_param *kp)
+@@ -802,7 +804,7 @@ static int param_get_audit(char *buffer, struct kernel_param *kp)
  	return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
  }
  
@@ -213250,7 +213370,7 @@ index dec607c..37fe357 100644
  {
  	int i;
  	if (!capable(CAP_MAC_ADMIN))
-@@ -824,7 +824,7 @@ static int param_set_audit(const char *val, struct kernel_param *kp)
+@@ -824,7 +826,7 @@ static int param_set_audit(const char *val, struct kernel_param *kp)
  	return -EINVAL;
  }
  
@@ -213259,7 +213379,7 @@ index dec607c..37fe357 100644
  {
  	if (!capable(CAP_MAC_ADMIN))
  		return -EPERM;
-@@ -835,7 +835,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
+@@ -835,7 +837,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
  	return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
  }
  

diff --git a/4.6.3/4425_grsec_remove_EI_PAX.patch b/4.6.4/4425_grsec_remove_EI_PAX.patch
similarity index 100%
rename from 4.6.3/4425_grsec_remove_EI_PAX.patch
rename to 4.6.4/4425_grsec_remove_EI_PAX.patch

diff --git a/4.6.3/4427_force_XATTR_PAX_tmpfs.patch b/4.6.4/4427_force_XATTR_PAX_tmpfs.patch
similarity index 100%
rename from 4.6.3/4427_force_XATTR_PAX_tmpfs.patch
rename to 4.6.4/4427_force_XATTR_PAX_tmpfs.patch

diff --git a/4.6.3/4430_grsec-remove-localversion-grsec.patch b/4.6.4/4430_grsec-remove-localversion-grsec.patch
similarity index 100%
rename from 4.6.3/4430_grsec-remove-localversion-grsec.patch
rename to 4.6.4/4430_grsec-remove-localversion-grsec.patch

diff --git a/4.6.3/4435_grsec-mute-warnings.patch b/4.6.4/4435_grsec-mute-warnings.patch
similarity index 100%
rename from 4.6.3/4435_grsec-mute-warnings.patch
rename to 4.6.4/4435_grsec-mute-warnings.patch

diff --git a/4.6.3/4440_grsec-remove-protected-paths.patch b/4.6.4/4440_grsec-remove-protected-paths.patch
similarity index 100%
rename from 4.6.3/4440_grsec-remove-protected-paths.patch
rename to 4.6.4/4440_grsec-remove-protected-paths.patch

diff --git a/4.6.3/4450_grsec-kconfig-default-gids.patch b/4.6.4/4450_grsec-kconfig-default-gids.patch
similarity index 100%
rename from 4.6.3/4450_grsec-kconfig-default-gids.patch
rename to 4.6.4/4450_grsec-kconfig-default-gids.patch

diff --git a/4.6.3/4465_selinux-avc_audit-log-curr_ip.patch b/4.6.4/4465_selinux-avc_audit-log-curr_ip.patch
similarity index 100%
rename from 4.6.3/4465_selinux-avc_audit-log-curr_ip.patch
rename to 4.6.4/4465_selinux-avc_audit-log-curr_ip.patch

diff --git a/4.6.3/4470_disable-compat_vdso.patch b/4.6.4/4470_disable-compat_vdso.patch
similarity index 100%
rename from 4.6.3/4470_disable-compat_vdso.patch
rename to 4.6.4/4470_disable-compat_vdso.patch

diff --git a/4.6.3/4475_emutramp_default_on.patch b/4.6.4/4475_emutramp_default_on.patch
similarity index 100%
rename from 4.6.3/4475_emutramp_default_on.patch
rename to 4.6.4/4475_emutramp_default_on.patch


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2016-07-12 18:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-12 18:56 [gentoo-commits] proj/hardened-patchset:master commit in: 4.6.4/, 4.6.3/ Anthony G. Basile

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox