diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-08-18 09:41:29 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-08-18 09:41:57 +0000 |
commit | ba36cab5846d9ab6df02301972a275c0381d3c6d (patch) | |
tree | f4206487b0febd847fd91581f2626f8f2062bd1e | |
parent | ba7ad8d83adf824e0fc70456ddcb3fe70d771b6c (diff) | |
download | aports-ba36cab5846d9ab6df02301972a275c0381d3c6d.tar.bz2 aports-ba36cab5846d9ab6df02301972a275c0381d3c6d.tar.xz |
main/linux-grsec: upgrade to 3.10.7
-rw-r--r-- | main/linux-grsec/APKBUILD | 7 | ||||
-rw-r--r-- | main/linux-grsec/grsecurity-2.9.1-3.10.7-201308171249.patch (renamed from main/linux-grsec/grsecurity-2.9.1-3.10.5-201308052154.patch) | 4366 | ||||
-rw-r--r-- | main/linux-grsec/net-ip_gre-fix-ipgre_header-to-return-correct-offset.patch | 45 |
3 files changed, 3681 insertions, 737 deletions
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD index 310c684356..aedc828204 100644 --- a/main/linux-grsec/APKBUILD +++ b/main/linux-grsec/APKBUILD @@ -2,12 +2,12 @@ _flavor=grsec pkgname=linux-${_flavor} -pkgver=3.10.5 +pkgver=3.10.7 case $pkgver in *.*.*) _kernver=${pkgver%.*};; *.*) _kernver=${pkgver};; esac -pkgrel=1 +pkgrel=0 pkgdesc="Linux kernel with grsecurity" url=http://grsecurity.net depends="mkinitfs linux-firmware" @@ -17,7 +17,7 @@ _config=${config:-kernelconfig.${CARCH}} install= source="http://ftp.kernel.org/pub/linux/kernel/v3.x/linux-$_kernver.tar.xz http://ftp.kernel.org/pub/linux/kernel/v3.x/patch-$pkgver.xz - grsecurity-2.9.1-3.10.5-201308052154.patch + grsecurity-2.9.1-3.10.7-201308171249.patch 0001-net-inform-NETDEV_CHANGE-callbacks-which-flags-were-.patch 0002-arp-flush-arp-cache-on-IFF_NOARP-change.patch @@ -25,7 +25,6 @@ source="http://ftp.kernel.org/pub/linux/kernel/v3.x/linux-$_kernver.tar.xz 0004-ipv4-rate-limit-updating-of-next-hop-exceptions-with.patch 0005-ipv4-use-separate-genid-for-next-hop-exceptions.patch 0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch - net-ip_gre-fix-ipgre_header-to-return-correct-offset.patch kernelconfig.x86 kernelconfig.x86_64 diff --git a/main/linux-grsec/grsecurity-2.9.1-3.10.5-201308052154.patch b/main/linux-grsec/grsecurity-2.9.1-3.10.7-201308171249.patch index f2633c140b..9a72c3e12c 100644 --- a/main/linux-grsec/grsecurity-2.9.1-3.10.5-201308052154.patch +++ b/main/linux-grsec/grsecurity-2.9.1-3.10.7-201308171249.patch @@ -229,7 +229,7 @@ index b89a739..79768fb 100644 +zconf.lex.c zoffset.h diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index 2fe6e76..df58221 100644 +index 2fe6e76..889ee23 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -976,6 +976,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. @@ -243,7 +243,18 @@ index 2fe6e76..df58221 100644 hashdist= [KNL,NUMA] Large hashes allocated during boot are distributed across NUMA nodes. Defaults on for 64-bit NUMA, off otherwise. -@@ -2195,6 +2199,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted. +@@ -1928,6 +1932,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + noexec=on: enable non-executable mappings (default) + noexec=off: disable non-executable mappings + ++ nopcid [X86-64] ++ Disable PCID (Process-Context IDentifier) even if it ++ is supported by the processor. ++ + nosmap [X86] + Disable SMAP (Supervisor Mode Access Prevention) + even if it is supported by processor. +@@ -2195,6 +2203,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted. the specified number of seconds. This is to be used if your oopses keep scrolling off the screen. @@ -263,11 +274,14 @@ index 2fe6e76..df58221 100644 + from the first 4GB of memory as the bootmem allocator + passes the memory pages to the buddy allocator. + ++ pax_weakuderef [X86-64] enables the weaker but faster form of UDEREF ++ when the processor supports PCID. ++ pcbit= [HW,ISDN] pcd. [PARIDE] diff --git a/Makefile b/Makefile -index f8349d0..563a504 100644 +index 33e36ab..31f1dc8 100644 --- a/Makefile +++ b/Makefile @@ -241,8 +241,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -815,7 +829,7 @@ index 0c4132d..88f0d53 100644 /* Allow reads even for write-only mappings */ if (!(vma->vm_flags & (VM_READ | VM_WRITE))) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 136f263..f471277 100644 +index 18a9f5e..ca910b7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1766,7 +1766,7 @@ config ALIGNMENT_TRAP @@ -1628,7 +1642,7 @@ index 6ddbe44..b5e38b1 100644 static inline void set_domain(unsigned val) { } static inline void modify_domain(unsigned dom, unsigned type) { } diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h -index 38050b1..9d90e8b 100644 +index 56211f2..17e8a25 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -116,7 +116,14 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); @@ -1647,7 +1661,7 @@ index 38050b1..9d90e8b 100644 /* When the program starts, a1 contains a pointer to a function to be registered with atexit, as per the SVR4 ABI. A value of 0 means we -@@ -126,8 +133,4 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); +@@ -126,10 +133,6 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); extern void elf_set_personality(const struct elf32_hdr *); #define SET_PERSONALITY(ex) elf_set_personality(&(ex)) @@ -1655,7 +1669,9 @@ index 38050b1..9d90e8b 100644 -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - - #endif + #ifdef CONFIG_MMU + #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 + struct linux_binprm; diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h index de53547..52b9a28 100644 --- a/arch/arm/include/asm/fncpy.h @@ -1788,7 +1804,7 @@ index 12f71a1..04e063c 100644 #ifdef CONFIG_OUTER_CACHE diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h -index 812a494..71fc0b6 100644 +index cbdc7a2..32f44fe 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -114,7 +114,7 @@ struct cpu_user_fns { @@ -1898,17 +1914,19 @@ index 5cfba15..f415e1a 100644 #define PTE_EXT_AP0 (_AT(pteval_t, 1) << 4) #define PTE_EXT_AP1 (_AT(pteval_t, 2) << 4) diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h -index f97ee02..07f1be5 100644 +index f97ee02..cc9fe9e 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h -@@ -125,6 +125,7 @@ - #define L_PTE_XN (_AT(pteval_t, 1) << 9) +@@ -126,6 +126,9 @@ #define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ #define L_PTE_NONE (_AT(pteval_t, 1) << 11) -+#define L_PTE_PXN (_AT(pteval_t, 1) << 12) /* v7*/ ++/* Two-level page tables only have PXN in the PGD, not in the PTE. */ ++#define L_PTE_PXN (_AT(pteval_t, 0)) ++ /* * These are the memory types, defined to be compatible with + * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index 18f5cef..25b8f43 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -2057,22 +2075,6 @@ index f3628fb..a0672dd 100644 #ifndef MULTI_CPU extern void cpu_proc_init(void); -diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h -index 06e7d50..8a8e251 100644 ---- a/arch/arm/include/asm/processor.h -+++ b/arch/arm/include/asm/processor.h -@@ -65,9 +65,8 @@ struct thread_struct { - regs->ARM_cpsr |= PSR_ENDSTATE; \ - regs->ARM_pc = pc & ~1; /* pc */ \ - regs->ARM_sp = sp; /* sp */ \ -- regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ -- regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ -- regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ -+ /* r2 (envp), r1 (argv), r0 (argc) */ \ -+ (void)copy_from_user(®s->ARM_r0, (const char __user *)stack, 3 * sizeof(unsigned long)); \ - nommu_start_thread(regs); \ - }) - diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h index ce0dbe7..c085b6f 100644 --- a/arch/arm/include/asm/psci.h @@ -2100,7 +2102,7 @@ index d3a22be..3a69ad5 100644 /* * set platform specific SMP operations diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h -index 1995d1a..76693a2 100644 +index f00b569..aa5bb41 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -77,9 +77,9 @@ struct thread_info { @@ -2129,7 +2131,7 @@ index 1995d1a..76693a2 100644 #define TIF_USING_IWMMXT 17 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 20 -@@ -166,10 +170,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, +@@ -165,10 +169,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) @@ -2142,8 +2144,35 @@ index 1995d1a..76693a2 100644 /* * Change these and you break ASM code in entry-common.S +diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h +index bdf2b84..aa9b4ac 100644 +--- a/arch/arm/include/asm/tlb.h ++++ b/arch/arm/include/asm/tlb.h +@@ -43,6 +43,7 @@ struct mmu_gather { + struct mm_struct *mm; + unsigned int fullmm; + struct vm_area_struct *vma; ++ unsigned long start, end; + unsigned long range_start; + unsigned long range_end; + unsigned int nr; +@@ -107,10 +108,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb) + } + + static inline void +-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) ++tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) + { + tlb->mm = mm; +- tlb->fullmm = fullmm; ++ tlb->fullmm = !(start | (end+1)); ++ tlb->start = start; ++ tlb->end = end; + tlb->vma = NULL; + tlb->max = ARRAY_SIZE(tlb->local); + tlb->pages = tlb->local; diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h -index 7e1f760..d42d7f8 100644 +index 7e1f760..de33b13 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -18,6 +18,7 @@ @@ -2154,7 +2183,7 @@ index 7e1f760..d42d7f8 100644 #define VERIFY_READ 0 #define VERIFY_WRITE 1 -@@ -63,11 +64,35 @@ extern int __put_user_bad(void); +@@ -63,11 +64,38 @@ extern int __put_user_bad(void); static inline void set_fs(mm_segment_t fs) { current_thread_info()->addr_limit = fs; @@ -2164,6 +2193,9 @@ index 7e1f760..d42d7f8 100644 #define segment_eq(a,b) ((a) == (b)) ++#define __HAVE_ARCH_PAX_OPEN_USERLAND ++#define __HAVE_ARCH_PAX_CLOSE_USERLAND ++ +static inline void pax_open_userland(void) +{ + @@ -2191,7 +2223,7 @@ index 7e1f760..d42d7f8 100644 #define __addr_ok(addr) ({ \ unsigned long flag; \ __asm__("cmp %2, %0; movlo %0, #0" \ -@@ -143,8 +168,12 @@ extern int __get_user_4(void *); +@@ -143,8 +171,12 @@ extern int __get_user_4(void *); #define get_user(x,p) \ ({ \ @@ -2205,7 +2237,7 @@ index 7e1f760..d42d7f8 100644 }) extern int __put_user_1(void *, unsigned int); -@@ -188,8 +217,12 @@ extern int __put_user_8(void *, unsigned long long); +@@ -188,8 +220,12 @@ extern int __put_user_8(void *, unsigned long long); #define put_user(x,p) \ ({ \ @@ -2219,7 +2251,7 @@ index 7e1f760..d42d7f8 100644 }) #else /* CONFIG_MMU */ -@@ -230,13 +263,17 @@ static inline void set_fs(mm_segment_t fs) +@@ -230,13 +266,17 @@ static inline void set_fs(mm_segment_t fs) #define __get_user(x,ptr) \ ({ \ long __gu_err = 0; \ @@ -2237,7 +2269,7 @@ index 7e1f760..d42d7f8 100644 (void) 0; \ }) -@@ -312,13 +349,17 @@ do { \ +@@ -312,13 +352,17 @@ do { \ #define __put_user(x,ptr) \ ({ \ long __pu_err = 0; \ @@ -2255,7 +2287,7 @@ index 7e1f760..d42d7f8 100644 (void) 0; \ }) -@@ -418,11 +459,44 @@ do { \ +@@ -418,11 +462,44 @@ do { \ #ifdef CONFIG_MMU @@ -2303,7 +2335,7 @@ index 7e1f760..d42d7f8 100644 #else #define __copy_from_user(to,from,n) (memcpy(to, (void __force *)from, n), 0) #define __copy_to_user(to,from,n) (memcpy((void __force *)to, from, n), 0) -@@ -431,6 +505,9 @@ extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned l +@@ -431,6 +508,9 @@ extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned l static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { @@ -2313,7 +2345,7 @@ index 7e1f760..d42d7f8 100644 if (access_ok(VERIFY_READ, from, n)) n = __copy_from_user(to, from, n); else /* security hole - plug it */ -@@ -440,6 +517,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u +@@ -440,6 +520,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { @@ -2363,7 +2395,7 @@ index 60d3b73..e5a0f22 100644 EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S -index 582b405..a78366b 100644 +index d43c7e5..257c050 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -47,6 +47,87 @@ @@ -2505,7 +2537,17 @@ index 582b405..a78366b 100644 sub sp, sp, #S_FRAME_SIZE ARM( stmib sp, {r1 - r12} ) THUMB( stmia sp, {r0 - r12} ) -@@ -414,7 +511,9 @@ __und_usr: +@@ -357,7 +454,8 @@ ENDPROC(__pabt_svc) + .endm + + .macro kuser_cmpxchg_check +-#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) ++#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ ++ !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) + #ifndef CONFIG_MMU + #warning "NPTL on non MMU needs fixing" + #else +@@ -414,7 +512,9 @@ __und_usr: tst r3, #PSR_T_BIT @ Thumb mode? bne __und_usr_thumb sub r4, r2, #4 @ ARM instr at LR - 4 @@ -2515,7 +2557,7 @@ index 582b405..a78366b 100644 #ifdef CONFIG_CPU_ENDIAN_BE8 rev r0, r0 @ little endian instruction #endif -@@ -449,10 +548,14 @@ __und_usr_thumb: +@@ -449,10 +549,14 @@ __und_usr_thumb: */ .arch armv6t2 #endif @@ -2530,7 +2572,7 @@ index 582b405..a78366b 100644 add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 str r2, [sp, #S_PC] @ it's a 2x16bit instr, update orr r0, r0, r5, lsl #16 -@@ -481,7 +584,8 @@ ENDPROC(__und_usr) +@@ -481,7 +585,8 @@ ENDPROC(__und_usr) */ .pushsection .fixup, "ax" .align 2 @@ -2540,7 +2582,7 @@ index 582b405..a78366b 100644 .popsection .pushsection __ex_table,"a" .long 1b, 4b -@@ -690,7 +794,7 @@ ENTRY(__switch_to) +@@ -690,7 +795,7 @@ ENTRY(__switch_to) THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack THUMB( str sp, [ip], #4 ) THUMB( str lr, [ip], #4 ) @@ -2549,7 +2591,7 @@ index 582b405..a78366b 100644 ldr r6, [r2, #TI_CPU_DOMAIN] #endif set_tls r3, r4, r5 -@@ -699,7 +803,7 @@ ENTRY(__switch_to) +@@ -699,7 +804,7 @@ ENTRY(__switch_to) ldr r8, =__stack_chk_guard ldr r7, [r7, #TSK_STACK_CANARY] #endif @@ -2719,19 +2761,32 @@ index 160f337..db67ee4 100644 ldrd r0, r1, [sp, #S_LR] @ calling lr and pc clrex @ clear the exclusive monitor diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c -index 2adda11..7fbe958 100644 +index 25442f4..d4948fc 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c -@@ -82,7 +82,9 @@ void set_fiq_handler(void *start, unsigned int length) - #if defined(CONFIG_CPU_USE_DOMAINS) - memcpy((void *)0xffff001c, start, length); - #else +@@ -84,17 +84,16 @@ int show_fiq_list(struct seq_file *p, int prec) + + void set_fiq_handler(void *start, unsigned int length) + { +-#if defined(CONFIG_CPU_USE_DOMAINS) +- void *base = (void *)0xffff0000; +-#else + void *base = vectors_page; +-#endif + unsigned offset = FIQ_OFFSET; + + pax_open_kernel(); - memcpy(vectors_page + 0x1c, start, length); + memcpy(base + offset, start, length); + pax_close_kernel(); - #endif - flush_icache_range(0xffff001c, 0xffff001c + length); - if (!vectors_high()) ++ ++ if (!cache_is_vipt_nonaliasing()) ++ flush_icache_range(base + offset, offset + length); + flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); +- if (!vectors_high()) +- flush_icache_range(offset, offset + length); + } + + int claim_fiq(struct fiq_handler *f) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 8bac553..caee108 100644 --- a/arch/arm/kernel/head.S @@ -2833,6 +2888,34 @@ index 07314af..c46655c 100644 flush_icache_range((uintptr_t)(addr), (uintptr_t)(addr) + size); +diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c +index d9f5cd4..e186ee1 100644 +--- a/arch/arm/kernel/perf_event.c ++++ b/arch/arm/kernel/perf_event.c +@@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map) + static int + armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) + { +- int mapping = (*event_map)[config]; ++ int mapping; ++ ++ if (config >= PERF_COUNT_HW_MAX) ++ return -EINVAL; ++ ++ mapping = (*event_map)[config]; + return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; + } + +@@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events, + struct arm_pmu *armpmu = to_arm_pmu(event->pmu); + struct pmu *leader_pmu = event->group_leader->pmu; + ++ if (is_software_event(event)) ++ return 1; ++ + if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) + return 1; + diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 1f2740e..b36e225 100644 --- a/arch/arm/kernel/perf_event_cpu.c @@ -2847,10 +2930,10 @@ index 1f2740e..b36e225 100644 }; diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 6e8931c..82ec6a5 100644 +index 5bc2615..4f1a0c2 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c -@@ -28,7 +28,6 @@ +@@ -28,10 +28,10 @@ #include <linux/tick.h> #include <linux/utsname.h> #include <linux/uaccess.h> @@ -2858,7 +2941,11 @@ index 6e8931c..82ec6a5 100644 #include <linux/hw_breakpoint.h> #include <linux/cpuidle.h> #include <linux/leds.h> -@@ -223,6 +222,7 @@ void machine_power_off(void) ++#include <linux/random.h> + + #include <asm/cacheflush.h> + #include <asm/idmap.h> +@@ -223,6 +223,7 @@ void machine_power_off(void) if (pm_power_off) pm_power_off(); @@ -2866,7 +2953,7 @@ index 6e8931c..82ec6a5 100644 } /* -@@ -236,7 +236,7 @@ void machine_power_off(void) +@@ -236,7 +237,7 @@ void machine_power_off(void) * executing pre-reset code, and using RAM that the primary CPU's code wishes * to use. Implementing such co-ordination would be essentially impossible. */ @@ -2875,18 +2962,18 @@ index 6e8931c..82ec6a5 100644 { smp_send_stop(); -@@ -258,8 +258,8 @@ void __show_regs(struct pt_regs *regs) +@@ -258,8 +259,8 @@ void __show_regs(struct pt_regs *regs) show_regs_print_info(KERN_DEFAULT); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - print_symbol("LR is at %s\n", regs->ARM_lr); -+ printk("PC is at %pA\n", instruction_pointer(regs)); -+ printk("LR is at %pA\n", regs->ARM_lr); ++ printk("PC is at %pA\n", (void *)instruction_pointer(regs)); ++ printk("LR is at %pA\n", (void *)regs->ARM_lr); printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" "sp : %08lx ip : %08lx fp : %08lx\n", regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, -@@ -426,12 +426,6 @@ unsigned long get_wchan(struct task_struct *p) +@@ -426,12 +427,6 @@ unsigned long get_wchan(struct task_struct *p) return 0; } @@ -2897,23 +2984,70 @@ index 6e8931c..82ec6a5 100644 -} - #ifdef CONFIG_MMU + #ifdef CONFIG_KUSER_HELPERS /* - * The vectors page is always readable from user space for the -@@ -441,12 +435,12 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) - static struct vm_area_struct gate_vma = { - .vm_start = 0xffff0000, - .vm_end = 0xffff0000 + PAGE_SIZE, -- .vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC, -+ .vm_flags = VM_NONE, - }; +@@ -447,7 +442,7 @@ static struct vm_area_struct gate_vma = { static int __init gate_vma_init(void) { - gate_vma.vm_page_prot = PAGE_READONLY_EXEC; -+ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); ++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); return 0; } arch_initcall(gate_vma_init); +@@ -466,48 +461,23 @@ int in_gate_area_no_mm(unsigned long addr) + { + return in_gate_area(NULL, addr); + } +-#define is_gate_vma(vma) ((vma) = &gate_vma) ++#define is_gate_vma(vma) ((vma) == &gate_vma) + #else + #define is_gate_vma(vma) 0 + #endif + + const char *arch_vma_name(struct vm_area_struct *vma) + { +- return is_gate_vma(vma) ? "[vectors]" : +- (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ? +- "[sigpage]" : NULL; ++ return is_gate_vma(vma) ? "[vectors]" : NULL; + } + +-static struct page *signal_page; +-extern struct page *get_signal_page(void); +- + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) + { + struct mm_struct *mm = current->mm; +- unsigned long addr; +- int ret; +- +- if (!signal_page) +- signal_page = get_signal_page(); +- if (!signal_page) +- return -ENOMEM; + + down_write(&mm->mmap_sem); +- addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); +- if (IS_ERR_VALUE(addr)) { +- ret = addr; +- goto up_fail; +- } +- +- ret = install_special_mapping(mm, addr, PAGE_SIZE, +- VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, +- &signal_page); +- +- if (ret == 0) +- mm->context.sigpage = addr; +- +- up_fail: ++ mm->context.sigpage = (PAGE_OFFSET + (get_random_int() % 0x3FFEFFE0)) & 0xFFFFFFFC; + up_write(&mm->mmap_sem); +- return ret; ++ return 0; + } + #endif diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c index 3653164..d83e55d 100644 --- a/arch/arm/kernel/psci.c @@ -3010,39 +3144,62 @@ index b4b1d39..efdc9be 100644 #ifdef MULTI_TLB cpu_tlb = *list->tlb; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c -index 296786b..a8d4dd5 100644 +index 5a42c12..a2bb7c6 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c -@@ -396,22 +396,14 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, - __put_user(sigreturn_codes[idx+1], rc+1)) - return 1; - -- if (cpsr & MODE32_BIT) { -- /* -- * 32-bit code can use the new high-page -- * signal return code support. -- */ -- retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; -- } else { -- /* -- * Ensure that the instruction cache sees -- * the return code written onto the stack. -- */ -- flush_icache_range((unsigned long)rc, -- (unsigned long)(rc + 2)); -+ /* -+ * Ensure that the instruction cache sees -+ * the return code written onto the stack. -+ */ -+ flush_icache_range((unsigned long)rc, -+ (unsigned long)(rc + 2)); - -- retcode = ((unsigned long)rc) + thumb; -- } -+ retcode = ((unsigned long)rc) + thumb; - } +@@ -45,8 +45,6 @@ static const unsigned long sigreturn_codes[7] = { + MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, + }; - regs->ARM_r0 = map_sig(ksig->sig); +-static unsigned long signal_return_offset; +- + #ifdef CONFIG_CRUNCH + static int preserve_crunch_context(struct crunch_sigframe __user *frame) + { +@@ -406,8 +404,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, + * except when the MPU has protected the vectors + * page from PL0 + */ +- retcode = mm->context.sigpage + signal_return_offset + +- (idx << 2) + thumb; ++ retcode = mm->context.sigpage + (idx << 2) + thumb; + } else + #endif + { +@@ -611,33 +608,3 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) + } while (thread_flags & _TIF_WORK_MASK); + return 0; + } +- +-struct page *get_signal_page(void) +-{ +- unsigned long ptr; +- unsigned offset; +- struct page *page; +- void *addr; +- +- page = alloc_pages(GFP_KERNEL, 0); +- +- if (!page) +- return NULL; +- +- addr = page_address(page); +- +- /* Give the signal return code some randomness */ +- offset = 0x200 + (get_random_int() & 0x7fc); +- signal_return_offset = offset; +- +- /* +- * Copy signal return handlers into the vector page, and +- * set sigreturn to be a pointer to these. +- */ +- memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes)); +- +- ptr = (unsigned long)addr + offset; +- flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); +- +- return page; +-} diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 5919eb4..b5d6dfe 100644 --- a/arch/arm/kernel/smp.c @@ -3057,10 +3214,10 @@ index 5919eb4..b5d6dfe 100644 void __init smp_set_ops(struct smp_operations *ops) { diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c -index 18b32e8..b0c8dca 100644 +index 6b9567e..b8af2d6 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c -@@ -57,7 +57,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long); +@@ -55,7 +55,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long); void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS @@ -3069,7 +3226,7 @@ index 18b32e8..b0c8dca 100644 #else printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); #endif -@@ -259,6 +259,8 @@ static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; +@@ -257,6 +257,8 @@ static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; static int die_owner = -1; static unsigned int die_nest_count; @@ -3078,7 +3235,7 @@ index 18b32e8..b0c8dca 100644 static unsigned long oops_begin(void) { int cpu; -@@ -301,6 +303,9 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) +@@ -299,6 +301,9 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); @@ -3088,7 +3245,7 @@ index 18b32e8..b0c8dca 100644 if (signr) do_exit(signr); } -@@ -594,7 +599,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) +@@ -592,7 +597,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) * The user helper at 0xffff0fe0 must be used instead. * (see entry-armv.S for details) */ @@ -3098,18 +3255,10 @@ index 18b32e8..b0c8dca 100644 } return 0; -@@ -834,13 +841,10 @@ void __init early_trap_init(void *vectors_base) - */ - kuser_get_tls_init(vectors); +@@ -848,5 +855,9 @@ void __init early_trap_init(void *vectors_base) + kuser_init(vectors_base); -- /* -- * Copy signal return handlers into the vector page, and -- * set sigreturn to be a pointer to these. -- */ -- memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), -- sigreturn_codes, sizeof(sigreturn_codes)); -- - flush_icache_range(vectors, vectors + PAGE_SIZE); + flush_icache_range(vectors, vectors + PAGE_SIZE * 2); - modify_domain(DOMAIN_USER, DOMAIN_CLIENT); + +#ifndef CONFIG_PAX_MEMORY_UDEREF @@ -3118,7 +3267,7 @@ index 18b32e8..b0c8dca 100644 + } diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S -index a871b8e..123b00a 100644 +index 33f2ea3..0b91824 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -8,7 +8,11 @@ @@ -3166,7 +3315,7 @@ index a871b8e..123b00a 100644 #ifndef CONFIG_XIP_KERNEL . = ALIGN(PAGE_SIZE); -@@ -207,6 +220,11 @@ SECTIONS +@@ -224,6 +237,11 @@ SECTIONS . = PAGE_OFFSET + TEXT_OFFSET; #else __init_end = .; @@ -3539,10 +3688,10 @@ index cad3ca86..1d79e0f 100644 extern void ux500_cpu_die(unsigned int cpu); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index 35955b5..b475042 100644 +index 2950082..d0f0782 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig -@@ -432,7 +432,7 @@ config CPU_32v5 +@@ -436,7 +436,7 @@ config CPU_32v5 config CPU_32v6 bool @@ -3551,7 +3700,7 @@ index 35955b5..b475042 100644 select TLS_REG_EMUL if !CPU_32v6K && !MMU config CPU_32v6K -@@ -581,6 +581,7 @@ config CPU_CP15_MPU +@@ -585,6 +585,7 @@ config CPU_CP15_MPU config CPU_USE_DOMAINS bool @@ -3559,6 +3708,23 @@ index 35955b5..b475042 100644 help This option enables or disables the use of domain switching via the set_fs() function. +@@ -780,6 +781,7 @@ config NEED_KUSER_HELPERS + config KUSER_HELPERS + bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS + default y ++ depends on !(CPU_V6 || CPU_V6K || CPU_V7) + help + Warning: disabling this option may break user programs. + +@@ -790,7 +792,7 @@ config KUSER_HELPERS + run on ARMv4 through to ARMv7 without modification. + + However, the fixed address nature of these helpers can be used +- by ROP (return orientated programming) authors when creating ++ by ROP (Return Oriented Programming) authors when creating + exploits. + + If all of the binaries and libraries which run on your platform diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 6f4585b..7b6f52b 100644 --- a/arch/arm/mm/alignment.c @@ -3625,7 +3791,7 @@ index 6f4585b..7b6f52b 100644 goto fault; \ } while (0) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c -index 5dbf13f..1a60561 100644 +index 5dbf13f..ee1ec24 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -25,6 +25,7 @@ @@ -3728,11 +3894,29 @@ index 5dbf13f..1a60561 100644 printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); -@@ -575,9 +637,49 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) +@@ -569,15 +631,67 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs * + ifsr_info[nr].name = name; + } + ++asmlinkage int sys_sigreturn(struct pt_regs *regs); ++asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); ++ + asmlinkage void __exception + do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) + { const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); struct siginfo info; + if (user_mode(regs)) { ++ unsigned long sigpage = current->mm->context.sigpage; ++ ++ if (sigpage <= addr && addr < sigpage + 7*4) { ++ if (addr < sigpage + 3*4) ++ sys_sigreturn(regs); ++ else ++ sys_rt_sigreturn(regs); ++ return; ++ } + if (addr == 0xffff0fe0UL) { + /* + * PaX: __kuser_get_tls emulation @@ -3997,7 +4181,7 @@ index 10062ce..8695745 100644 mm->unmap_area = arch_unmap_area_topdown; } diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c -index 4d409e6..f375351 100644 +index daf336f..4e6392c 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -36,6 +36,22 @@ @@ -4064,7 +4248,7 @@ index 4d409e6..f375351 100644 .domain = DOMAIN_KERNEL, }, #endif -@@ -277,36 +301,65 @@ static struct mem_type mem_types[] = { +@@ -277,36 +301,54 @@ static struct mem_type mem_types[] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_RDONLY, .prot_l1 = PMD_TYPE_TABLE, @@ -4072,21 +4256,8 @@ index 4d409e6..f375351 100644 + .domain = DOMAIN_VECTORS, }, [MT_HIGH_VECTORS] = { -- .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | -- L_PTE_USER | L_PTE_RDONLY, -+ /* we always want the vector page to be noaccess for userland on archs with -+ XN where we can enforce some reasonable measure of security -+ therefore, when kernexec is disabled, instead of L_PTE_USER | L_PTE_RDONLY -+ which turns into supervisor rwx, userland rx, we instead omit that entirely, -+ leaving it as supervisor rwx only -+ */ -+#ifdef CONFIG_PAX_KERNEXEC -+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_RDONLY, -+#elif __LINUX_ARM_ARCH__ >= 6 -+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, -+#else -+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_USER | L_PTE_RDONLY, -+#endif + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_USER | L_PTE_RDONLY, .prot_l1 = PMD_TYPE_TABLE, - .domain = DOMAIN_USER, + .domain = DOMAIN_VECTORS, @@ -4140,7 +4311,7 @@ index 4d409e6..f375351 100644 .domain = DOMAIN_KERNEL, }, [MT_MEMORY_ITCM] = { -@@ -316,10 +369,10 @@ static struct mem_type mem_types[] = { +@@ -316,10 +358,10 @@ static struct mem_type mem_types[] = { }, [MT_MEMORY_SO] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | @@ -4153,7 +4324,7 @@ index 4d409e6..f375351 100644 .domain = DOMAIN_KERNEL, }, [MT_MEMORY_DMA_READY] = { -@@ -405,9 +458,35 @@ static void __init build_mem_type_table(void) +@@ -405,9 +447,35 @@ static void __init build_mem_type_table(void) * to prevent speculative instruction fetches. */ mem_types[MT_DEVICE].prot_sect |= PMD_SECT_XN; @@ -4189,7 +4360,7 @@ index 4d409e6..f375351 100644 } if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { /* -@@ -468,6 +547,9 @@ static void __init build_mem_type_table(void) +@@ -468,6 +536,9 @@ static void __init build_mem_type_table(void) * from SVC mode and no access from userspace. */ mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; @@ -4199,7 +4370,7 @@ index 4d409e6..f375351 100644 mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; #endif -@@ -485,11 +567,17 @@ static void __init build_mem_type_table(void) +@@ -485,11 +556,17 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; @@ -4221,7 +4392,7 @@ index 4d409e6..f375351 100644 } } -@@ -500,15 +588,20 @@ static void __init build_mem_type_table(void) +@@ -500,15 +577,20 @@ static void __init build_mem_type_table(void) if (cpu_arch >= CPU_ARCH_ARMv6) { if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { /* Non-cacheable Normal is XCB = 001 */ @@ -4245,7 +4416,7 @@ index 4d409e6..f375351 100644 } #ifdef CONFIG_ARM_LPAE -@@ -524,6 +617,8 @@ static void __init build_mem_type_table(void) +@@ -524,6 +606,8 @@ static void __init build_mem_type_table(void) vecs_pgprot |= PTE_EXT_AF; #endif @@ -4254,7 +4425,7 @@ index 4d409e6..f375351 100644 for (i = 0; i < 16; i++) { pteval_t v = pgprot_val(protection_map[i]); protection_map[i] = __pgprot(v | user_pgprot); -@@ -541,10 +636,15 @@ static void __init build_mem_type_table(void) +@@ -541,10 +625,15 @@ static void __init build_mem_type_table(void) mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; @@ -4273,12 +4444,12 @@ index 4d409e6..f375351 100644 mem_types[MT_ROM].prot_sect |= cp->pmd; switch (cp->pmd) { -@@ -1166,18 +1266,15 @@ void __init arm_mm_memblock_reserve(void) +@@ -1166,18 +1255,15 @@ void __init arm_mm_memblock_reserve(void) * called function. This means you can't use any function or debugging * method which may touch any device, otherwise the kernel _will_ crash. */ + -+static char vectors[PAGE_SIZE] __read_only __aligned(PAGE_SIZE); ++static char vectors[PAGE_SIZE * 2] __read_only __aligned(PAGE_SIZE); + static void __init devicemaps_init(struct machine_desc *mdesc) { @@ -4289,14 +4460,14 @@ index 4d409e6..f375351 100644 - /* - * Allocate the vector page early. - */ -- vectors = early_alloc(PAGE_SIZE); +- vectors = early_alloc(PAGE_SIZE * 2); - - early_trap_init(vectors); + early_trap_init(&vectors); for (addr = VMALLOC_START; addr; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); -@@ -1217,7 +1314,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) +@@ -1217,7 +1303,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) * location (0xffff0000). If we aren't using high-vectors, also * create a mapping at the low-vectors virtual address. */ @@ -4304,8 +4475,8 @@ index 4d409e6..f375351 100644 + map.pfn = __phys_to_pfn(virt_to_phys(&vectors)); map.virtual = 0xffff0000; map.length = PAGE_SIZE; - map.type = MT_HIGH_VECTORS; -@@ -1275,8 +1372,39 @@ static void __init map_lowmem(void) + #ifdef CONFIG_KUSER_HELPERS +@@ -1287,8 +1373,39 @@ static void __init map_lowmem(void) map.pfn = __phys_to_pfn(start); map.virtual = __phys_to_virt(start); map.length = end - start; @@ -4346,20 +4517,6 @@ index 4d409e6..f375351 100644 create_mapping(&map); } } -diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S -index 9704097..3e36dde 100644 ---- a/arch/arm/mm/proc-v7-2level.S -+++ b/arch/arm/mm/proc-v7-2level.S -@@ -99,6 +99,9 @@ ENTRY(cpu_v7_set_pte_ext) - tst r1, #L_PTE_XN - orrne r3, r3, #PTE_EXT_XN - -+ tst r1, #L_PTE_PXN -+ orrne r3, r3, #PTE_EXT_PXN -+ - tst r1, #L_PTE_YOUNG - tstne r1, #L_PTE_VALID - #ifndef CONFIG_CPU_USE_DOMAINS diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index a5bc92d..0bb4730 100644 --- a/arch/arm/plat-omap/sram.c @@ -4386,6 +4543,33 @@ index ce6d763..cfea917 100644 extern void *samsung_dmadev_get_ops(void); extern void *s3c_dma_get_ops(void); +diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h +index 654f096..5546653 100644 +--- a/arch/arm64/include/asm/tlb.h ++++ b/arch/arm64/include/asm/tlb.h +@@ -35,6 +35,7 @@ struct mmu_gather { + struct mm_struct *mm; + unsigned int fullmm; + struct vm_area_struct *vma; ++ unsigned long start, end; + unsigned long range_start; + unsigned long range_end; + unsigned int nr; +@@ -97,10 +98,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb) + } + + static inline void +-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) ++tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) + { + tlb->mm = mm; +- tlb->fullmm = fullmm; ++ tlb->fullmm = !(start | (end+1)); ++ tlb->start = start; ++ tlb->end = end; + tlb->vma = NULL; + tlb->max = ARRAY_SIZE(tlb->local); + tlb->pages = tlb->local; diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index f4726dc..39ed646 100644 --- a/arch/arm64/kernel/debug-monitors.c @@ -4795,6 +4979,45 @@ index 54ff557..70c88b7 100644 } static __always_inline void __ticket_spin_unlock_wait(arch_spinlock_t *lock) +diff --git a/arch/ia64/include/asm/tlb.h b/arch/ia64/include/asm/tlb.h +index ef3a9de..bc5efc7 100644 +--- a/arch/ia64/include/asm/tlb.h ++++ b/arch/ia64/include/asm/tlb.h +@@ -22,7 +22,7 @@ + * unmapping a portion of the virtual address space, these hooks are called according to + * the following template: + * +- * tlb <- tlb_gather_mmu(mm, full_mm_flush); // start unmap for address space MM ++ * tlb <- tlb_gather_mmu(mm, start, end); // start unmap for address space MM + * { + * for each vma that needs a shootdown do { + * tlb_start_vma(tlb, vma); +@@ -58,6 +58,7 @@ struct mmu_gather { + unsigned int max; + unsigned char fullmm; /* non-zero means full mm flush */ + unsigned char need_flush; /* really unmapped some PTEs? */ ++ unsigned long start, end; + unsigned long start_addr; + unsigned long end_addr; + struct page **pages; +@@ -155,13 +156,15 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb) + + + static inline void +-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) ++tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) + { + tlb->mm = mm; + tlb->max = ARRAY_SIZE(tlb->local); + tlb->pages = tlb->local; + tlb->nr = 0; +- tlb->fullmm = full_mm_flush; ++ tlb->fullmm = !(start | (end+1)); ++ tlb->start = start; ++ tlb->end = end; + tlb->start_addr = ~0UL; + } + diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h index 449c8c0..18965fb 100644 --- a/arch/ia64/include/asm/uaccess.h @@ -5329,6 +5552,97 @@ index c1f6afa..38cc6e9 100644 +#define arch_align_stack(x) ((x) & ~0xfUL) #endif /* _ASM_EXEC_H */ +diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h +index d44622c..64990d2 100644 +--- a/arch/mips/include/asm/local.h ++++ b/arch/mips/include/asm/local.h +@@ -12,15 +12,25 @@ typedef struct + atomic_long_t a; + } local_t; + ++typedef struct { ++ atomic_long_unchecked_t a; ++} local_unchecked_t; ++ + #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } + + #define local_read(l) atomic_long_read(&(l)->a) ++#define local_read_unchecked(l) atomic_long_read_unchecked(&(l)->a) + #define local_set(l, i) atomic_long_set(&(l)->a, (i)) ++#define local_set_unchecked(l, i) atomic_long_set_unchecked(&(l)->a, (i)) + + #define local_add(i, l) atomic_long_add((i), (&(l)->a)) ++#define local_add_unchecked(i, l) atomic_long_add_unchecked((i), (&(l)->a)) + #define local_sub(i, l) atomic_long_sub((i), (&(l)->a)) ++#define local_sub_unchecked(i, l) atomic_long_sub_unchecked((i), (&(l)->a)) + #define local_inc(l) atomic_long_inc(&(l)->a) ++#define local_inc_unchecked(l) atomic_long_inc_unchecked(&(l)->a) + #define local_dec(l) atomic_long_dec(&(l)->a) ++#define local_dec_unchecked(l) atomic_long_dec_unchecked(&(l)->a) + + /* + * Same as above, but return the result value +@@ -70,6 +80,51 @@ static __inline__ long local_add_return(long i, local_t * l) + return result; + } + ++static __inline__ long local_add_return_unchecked(long i, local_unchecked_t * l) ++{ ++ unsigned long result; ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ unsigned long temp; ++ ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1:" __LL "%1, %2 # local_add_return \n" ++ " addu %0, %1, %3 \n" ++ __SC "%0, %2 \n" ++ " beqzl %0, 1b \n" ++ " addu %0, %1, %3 \n" ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) ++ : "Ir" (i), "m" (l->a.counter) ++ : "memory"); ++ } else if (kernel_uses_llsc) { ++ unsigned long temp; ++ ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1:" __LL "%1, %2 # local_add_return \n" ++ " addu %0, %1, %3 \n" ++ __SC "%0, %2 \n" ++ " beqz %0, 1b \n" ++ " addu %0, %1, %3 \n" ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) ++ : "Ir" (i), "m" (l->a.counter) ++ : "memory"); ++ } else { ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ result = l->a.counter; ++ result += i; ++ l->a.counter = result; ++ local_irq_restore(flags); ++ } ++ ++ return result; ++} ++ + static __inline__ long local_sub_return(long i, local_t * l) + { + unsigned long result; +@@ -117,6 +172,8 @@ static __inline__ long local_sub_return(long i, local_t * l) + + #define local_cmpxchg(l, o, n) \ + ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) ++#define local_cmpxchg_unchecked(l, o, n) \ ++ ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) + #define local_xchg(l, n) (atomic_long_xchg((&(l)->a), (n))) + + /** diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index f59552f..3abe9b9 100644 --- a/arch/mips/include/asm/page.h @@ -5528,7 +5842,7 @@ index 74f485d..47d2c38 100644 and t0, t1, t0 bnez t0, trace_a_syscall diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c -index 0fead53..a2c0fb5 100644 +index 0fead53..eeb00a6 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -27,6 +27,23 @@ @@ -5555,6 +5869,21 @@ index 0fead53..a2c0fb5 100644 /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate +@@ -196,6 +213,14 @@ bad_area: + bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ + if (user_mode(regs)) { ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (cpu_has_rixi && (mm->pax_flags & MF_PAX_PAGEEXEC) && !write && address == instruction_pointer(regs)) { ++ pax_report_fault(regs, (void *)address, (void *)user_stack_pointer(regs)); ++ do_group_exit(SIGKILL); ++ } ++#endif ++ + tsk->thread.cp0_badvaddr = address; + tsk->thread.error_code = write; + #if 0 diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index 7e5fe27..9656513 100644 --- a/arch/mips/mm/mmap.c @@ -6442,7 +6771,7 @@ index 4aad413..85d86bf 100644 #define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */ #define _PAGE_WRITETHRU 0x040 /* W: cache write-through */ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h -index 362142b..8b22c1b 100644 +index e1fb161..2290d1d 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -234,6 +234,7 @@ @@ -6454,7 +6783,7 @@ index 362142b..8b22c1b 100644 #define DSISR_ISSTORE 0x02000000 /* access was a store */ #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h -index ffbaabe..eabe843 100644 +index 48cfc85..891382f 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -50,7 +50,7 @@ struct smp_ops_t { @@ -6695,10 +7024,10 @@ index 645170a..6cf0271 100644 ld r4,_DAR(r1) bl .bad_page_fault diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S -index 4e00d22..b26abcc 100644 +index 902ca3c..e942155 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S -@@ -1356,10 +1356,10 @@ handle_page_fault: +@@ -1357,10 +1357,10 @@ handle_page_fault: 11: ld r4,_DAR(r1) ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD @@ -6744,10 +7073,10 @@ index 2e3200c..72095ce 100644 /* Find this entry, or if that fails, the next avail. entry */ while (entry->jump[0]) { diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c -index 076d124..6cb2cbf 100644 +index 7baa27b..f6b394a 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c -@@ -874,8 +874,8 @@ void show_regs(struct pt_regs * regs) +@@ -884,8 +884,8 @@ void show_regs(struct pt_regs * regs) * Lookup NIP late so we have the best change of getting the * above info out without failing */ @@ -6758,7 +7087,7 @@ index 076d124..6cb2cbf 100644 #endif #ifdef CONFIG_PPC_TRANSACTIONAL_MEM printk("PACATMSCRATCH [%llx]\n", get_paca()->tm_scratch); -@@ -1335,10 +1335,10 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) +@@ -1345,10 +1345,10 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) newsp = stack[0]; ip = stack[STACK_FRAME_LR_SAVE]; if (!firstframe || ip != lr) { @@ -6771,7 +7100,7 @@ index 076d124..6cb2cbf 100644 (void *)current->ret_stack[curr_frame].ret); curr_frame--; } -@@ -1358,7 +1358,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) +@@ -1368,7 +1368,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) struct pt_regs *regs = (struct pt_regs *) (sp + STACK_FRAME_OVERHEAD); lr = regs->link; @@ -6780,7 +7109,7 @@ index 076d124..6cb2cbf 100644 regs->trap, (void *)regs->nip, (void *)lr); firstframe = 1; } -@@ -1394,58 +1394,3 @@ void notrace __ppc64_runlatch_off(void) +@@ -1404,58 +1404,3 @@ void notrace __ppc64_runlatch_off(void) mtspr(SPRN_CTRLT, ctrl); } #endif /* CONFIG_PPC64 */ @@ -6918,10 +7247,10 @@ index e68a845..8b140e6 100644 }; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c -index e4f205a..8bfffb8 100644 +index 88929b1..bece8f8 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c -@@ -143,6 +143,8 @@ static unsigned __kprobes long oops_begin(struct pt_regs *regs) +@@ -141,6 +141,8 @@ static unsigned __kprobes long oops_begin(struct pt_regs *regs) return flags; } @@ -6930,7 +7259,7 @@ index e4f205a..8bfffb8 100644 static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) { -@@ -192,6 +194,9 @@ static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, +@@ -190,6 +192,9 @@ static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); @@ -7157,10 +7486,10 @@ index e779642..e5bb889 100644 }; diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c -index 2859a1f..74f9a6e 100644 +index cafad40..9cbc0fc 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c -@@ -919,7 +919,7 @@ static void __init *careful_zallocation(int nid, unsigned long size, +@@ -920,7 +920,7 @@ static void __init *careful_zallocation(int nid, unsigned long size, return ret; } @@ -7316,6 +7645,34 @@ index c4a93d6..4d2a9b4 100644 +#define arch_align_stack(x) ((x) & ~0xfUL) #endif /* __ASM_EXEC_H */ +diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h +index b75d7d6..6d6d92b 100644 +--- a/arch/s390/include/asm/tlb.h ++++ b/arch/s390/include/asm/tlb.h +@@ -32,6 +32,7 @@ struct mmu_gather { + struct mm_struct *mm; + struct mmu_table_batch *batch; + unsigned int fullmm; ++ unsigned long start, end; + }; + + struct mmu_table_batch { +@@ -48,10 +49,13 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table); + + static inline void tlb_gather_mmu(struct mmu_gather *tlb, + struct mm_struct *mm, +- unsigned int full_mm_flush) ++ unsigned long start, ++ unsigned long end) + { + tlb->mm = mm; +- tlb->fullmm = full_mm_flush; ++ tlb->start = start; ++ tlb->end = end; ++ tlb->fullmm = !(start | (end+1)); + tlb->batch = NULL; + if (tlb->fullmm) + __tlb_flush_mm(mm); diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 9c33ed4..e40cbef 100644 --- a/arch/s390/include/asm/uaccess.h @@ -7584,6 +7941,25 @@ index ef9e555..331bd29 100644 #define __read_mostly __attribute__((__section__(".data..read_mostly"))) +diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h +index e61d43d..362192e 100644 +--- a/arch/sh/include/asm/tlb.h ++++ b/arch/sh/include/asm/tlb.h +@@ -36,10 +36,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) + } + + static inline void +-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) ++tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) + { + tlb->mm = mm; +- tlb->fullmm = full_mm_flush; ++ tlb->start = start; ++ tlb->end = end; ++ tlb->fullmm = !(start | (end+1)); + + init_tlb_gather(tlb); + } diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 03f2b55..b0270327 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -9956,10 +10332,20 @@ index 5062ff3..e0b75f3 100644 * load/store/atomic was a write or not, it only says that there * was no match. So in such a case we (carefully) read the diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c -index d2b5944..bd813f2 100644 +index d2b5944..d878f3c 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c -@@ -38,7 +38,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, +@@ -28,7 +28,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, + unsigned long addr, + unsigned long len, + unsigned long pgoff, +- unsigned long flags) ++ unsigned long flags, ++ unsigned long offset) + { + unsigned long task_size = TASK_SIZE; + struct vm_unmapped_area_info info; +@@ -38,15 +39,22 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, info.flags = 0; info.length = len; @@ -9968,7 +10354,9 @@ index d2b5944..bd813f2 100644 info.high_limit = min(task_size, VA_EXCLUDE_START); info.align_mask = PAGE_MASK & ~HPAGE_MASK; info.align_offset = 0; -@@ -47,6 +47,12 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, ++ info.threadstack_offset = offset; + addr = vm_unmapped_area(&info); + if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) { VM_BUG_ON(addr != -ENOMEM); info.low_limit = VA_EXCLUDE_END; @@ -9981,7 +10369,25 @@ index d2b5944..bd813f2 100644 info.high_limit = task_size; addr = vm_unmapped_area(&info); } -@@ -85,6 +91,12 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -58,7 +66,8 @@ static unsigned long + hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, + const unsigned long pgoff, +- const unsigned long flags) ++ const unsigned long flags, ++ const unsigned long offset) + { + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; +@@ -73,6 +82,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + info.high_limit = mm->mmap_base; + info.align_mask = PAGE_MASK & ~HPAGE_MASK; + info.align_offset = 0; ++ info.threadstack_offset = offset; + addr = vm_unmapped_area(&info); + + /* +@@ -85,6 +95,12 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; @@ -9994,7 +10400,7 @@ index d2b5944..bd813f2 100644 info.high_limit = STACK_TOP32; addr = vm_unmapped_area(&info); } -@@ -99,6 +111,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, +@@ -99,6 +115,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long task_size = TASK_SIZE; @@ -10002,7 +10408,7 @@ index d2b5944..bd813f2 100644 if (test_thread_flag(TIF_32BIT)) task_size = STACK_TOP32; -@@ -114,11 +127,14 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, +@@ -114,19 +131,22 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, return addr; } @@ -10019,6 +10425,16 @@ index d2b5944..bd813f2 100644 return addr; } if (mm->get_unmapped_area == arch_get_unmapped_area) + return hugetlb_get_unmapped_area_bottomup(file, addr, len, +- pgoff, flags); ++ pgoff, flags, offset); + else + return hugetlb_get_unmapped_area_topdown(file, addr, len, +- pgoff, flags); ++ pgoff, flags, offset); + } + + pte_t *huge_pte_alloc(struct mm_struct *mm, diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h index f4500c6..889656c 100644 --- a/arch/tile/include/asm/atomic_64.h @@ -10179,6 +10595,25 @@ index 0032f92..cd151e0 100644 #ifdef CONFIG_64BIT #define set_pud(pudptr, pudval) set_64bit((u64 *) (pudptr), pud_val(pudval)) +diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h +index 4febacd..29b0301 100644 +--- a/arch/um/include/asm/tlb.h ++++ b/arch/um/include/asm/tlb.h +@@ -45,10 +45,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) + } + + static inline void +-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush) ++tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) + { + tlb->mm = mm; +- tlb->fullmm = full_mm_flush; ++ tlb->start = start; ++ tlb->end = end; ++ tlb->fullmm = !(start | (end+1)); + + init_tlb_gather(tlb); + } diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index bbcef52..6a2a483 100644 --- a/arch/um/kernel/process.c @@ -10958,6 +11393,57 @@ index 477e9d7..3ab339f 100644 ret ENDPROC(aesni_xts_crypt8) +diff --git a/arch/x86/crypto/blowfish-avx2-asm_64.S b/arch/x86/crypto/blowfish-avx2-asm_64.S +index 784452e..46982c7 100644 +--- a/arch/x86/crypto/blowfish-avx2-asm_64.S ++++ b/arch/x86/crypto/blowfish-avx2-asm_64.S +@@ -221,6 +221,7 @@ __blowfish_enc_blk32: + + write_block(RXl, RXr); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(__blowfish_enc_blk32) + +@@ -250,6 +251,7 @@ __blowfish_dec_blk32: + + write_block(RXl, RXr); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(__blowfish_dec_blk32) + +@@ -284,6 +286,7 @@ ENTRY(blowfish_ecb_enc_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(blowfish_ecb_enc_32way) + +@@ -318,6 +321,7 @@ ENTRY(blowfish_ecb_dec_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(blowfish_ecb_dec_32way) + +@@ -365,6 +369,7 @@ ENTRY(blowfish_cbc_dec_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(blowfish_cbc_dec_32way) + +@@ -445,5 +450,6 @@ ENTRY(blowfish_ctr_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(blowfish_ctr_32way) diff --git a/arch/x86/crypto/blowfish-x86_64-asm_64.S b/arch/x86/crypto/blowfish-x86_64-asm_64.S index 246c670..4d1ed00 100644 --- a/arch/x86/crypto/blowfish-x86_64-asm_64.S @@ -11013,6 +11499,174 @@ index 246c670..4d1ed00 100644 + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_dec_blk_4way) +diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S +index ce71f92..2dd5b1e 100644 +--- a/arch/x86/crypto/camellia-aesni-avx-asm_64.S ++++ b/arch/x86/crypto/camellia-aesni-avx-asm_64.S +@@ -16,6 +16,7 @@ + */ + + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + #define CAMELLIA_TABLE_BYTE_LEN 272 + +@@ -191,6 +192,7 @@ roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd: + roundsm16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, + %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, + %rcx, (%r9)); ++ pax_force_retaddr_bts + ret; + ENDPROC(roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd) + +@@ -199,6 +201,7 @@ roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab: + roundsm16(%xmm4, %xmm5, %xmm6, %xmm7, %xmm0, %xmm1, %xmm2, %xmm3, + %xmm12, %xmm13, %xmm14, %xmm15, %xmm8, %xmm9, %xmm10, %xmm11, + %rax, (%r9)); ++ pax_force_retaddr_bts + ret; + ENDPROC(roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) + +@@ -780,6 +783,7 @@ __camellia_enc_blk16: + %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, + %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax)); + ++ pax_force_retaddr_bts + ret; + + .align 8 +@@ -865,6 +869,7 @@ __camellia_dec_blk16: + %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, + %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax)); + ++ pax_force_retaddr_bts + ret; + + .align 8 +@@ -904,6 +909,7 @@ ENTRY(camellia_ecb_enc_16way) + %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, + %xmm8, %rsi); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_ecb_enc_16way) + +@@ -932,6 +938,7 @@ ENTRY(camellia_ecb_dec_16way) + %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, + %xmm8, %rsi); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_ecb_dec_16way) + +@@ -981,6 +988,7 @@ ENTRY(camellia_cbc_dec_16way) + %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, + %xmm8, %rsi); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_cbc_dec_16way) + +@@ -1092,6 +1100,7 @@ ENTRY(camellia_ctr_16way) + %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, + %xmm8, %rsi); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_ctr_16way) + +@@ -1234,6 +1243,7 @@ camellia_xts_crypt_16way: + %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, + %xmm8, %rsi); + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_xts_crypt_16way) + +diff --git a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S +index 91a1878..bcf340a 100644 +--- a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S ++++ b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S +@@ -11,6 +11,7 @@ + */ + + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + #define CAMELLIA_TABLE_BYTE_LEN 272 + +@@ -212,6 +213,7 @@ roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd: + roundsm32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, + %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, + %rcx, (%r9)); ++ pax_force_retaddr_bts + ret; + ENDPROC(roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd) + +@@ -220,6 +222,7 @@ roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab: + roundsm32(%ymm4, %ymm5, %ymm6, %ymm7, %ymm0, %ymm1, %ymm2, %ymm3, + %ymm12, %ymm13, %ymm14, %ymm15, %ymm8, %ymm9, %ymm10, %ymm11, + %rax, (%r9)); ++ pax_force_retaddr_bts + ret; + ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) + +@@ -802,6 +805,7 @@ __camellia_enc_blk32: + %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, + %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax)); + ++ pax_force_retaddr_bts + ret; + + .align 8 +@@ -887,6 +891,7 @@ __camellia_dec_blk32: + %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, + %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax)); + ++ pax_force_retaddr_bts + ret; + + .align 8 +@@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_ecb_enc_32way) + +@@ -962,6 +968,7 @@ ENTRY(camellia_ecb_dec_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_ecb_dec_32way) + +@@ -1028,6 +1035,7 @@ ENTRY(camellia_cbc_dec_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_cbc_dec_32way) + +@@ -1166,6 +1174,7 @@ ENTRY(camellia_ctr_32way) + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_ctr_32way) + +@@ -1331,6 +1340,7 @@ camellia_xts_crypt_32way: + + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(camellia_xts_crypt_32way) + diff --git a/arch/x86/crypto/camellia-x86_64-asm_64.S b/arch/x86/crypto/camellia-x86_64-asm_64.S index 310319c..ce174a4 100644 --- a/arch/x86/crypto/camellia-x86_64-asm_64.S @@ -11205,6 +11859,69 @@ index e3531f8..18ded3a 100644 + pax_force_retaddr ret; ENDPROC(cast6_xts_dec_8way) +diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S +index dbc4339..3d868c5 100644 +--- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S ++++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S +@@ -45,6 +45,7 @@ + + #include <asm/inst.h> + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction + +@@ -312,6 +313,7 @@ do_return: + popq %rsi + popq %rdi + popq %rbx ++ pax_force_retaddr 0, 1 + ret + + ################################################################ +diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S +index 586f41a..d02851e 100644 +--- a/arch/x86/crypto/ghash-clmulni-intel_asm.S ++++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S +@@ -18,6 +18,7 @@ + + #include <linux/linkage.h> + #include <asm/inst.h> ++#include <asm/alternative-asm.h> + + .data + +@@ -93,6 +94,7 @@ __clmul_gf128mul_ble: + psrlq $1, T2 + pxor T2, T1 + pxor T1, DATA ++ pax_force_retaddr + ret + ENDPROC(__clmul_gf128mul_ble) + +@@ -105,6 +107,7 @@ ENTRY(clmul_ghash_mul) + call __clmul_gf128mul_ble + PSHUFB_XMM BSWAP DATA + movups DATA, (%rdi) ++ pax_force_retaddr + ret + ENDPROC(clmul_ghash_mul) + +@@ -132,6 +135,7 @@ ENTRY(clmul_ghash_update) + PSHUFB_XMM BSWAP DATA + movups DATA, (%rdi) + .Lupdate_just_ret: ++ pax_force_retaddr + ret + ENDPROC(clmul_ghash_update) + +@@ -157,5 +161,6 @@ ENTRY(clmul_ghash_setkey) + pand .Lpoly, %xmm1 + pxor %xmm1, %xmm0 + movups %xmm0, (%rdi) ++ pax_force_retaddr + ret + ENDPROC(clmul_ghash_setkey) diff --git a/arch/x86/crypto/salsa20-x86_64-asm_64.S b/arch/x86/crypto/salsa20-x86_64-asm_64.S index 9279e0b..9270820 100644 --- a/arch/x86/crypto/salsa20-x86_64-asm_64.S @@ -11313,6 +12030,81 @@ index 2f202f4..d9164d6 100644 + pax_force_retaddr ret; ENDPROC(serpent_xts_dec_8way_avx) +diff --git a/arch/x86/crypto/serpent-avx2-asm_64.S b/arch/x86/crypto/serpent-avx2-asm_64.S +index b222085..abd483c 100644 +--- a/arch/x86/crypto/serpent-avx2-asm_64.S ++++ b/arch/x86/crypto/serpent-avx2-asm_64.S +@@ -15,6 +15,7 @@ + */ + + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + #include "glue_helper-asm-avx2.S" + + .file "serpent-avx2-asm_64.S" +@@ -610,6 +611,7 @@ __serpent_enc_blk16: + write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2); + write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2); + ++ pax_force_retaddr + ret; + ENDPROC(__serpent_enc_blk16) + +@@ -664,6 +666,7 @@ __serpent_dec_blk16: + write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2); + write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2); + ++ pax_force_retaddr + ret; + ENDPROC(__serpent_dec_blk16) + +@@ -684,6 +687,7 @@ ENTRY(serpent_ecb_enc_16way) + + vzeroupper; + ++ pax_force_retaddr + ret; + ENDPROC(serpent_ecb_enc_16way) + +@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way) + + vzeroupper; + ++ pax_force_retaddr + ret; + ENDPROC(serpent_ecb_dec_16way) + +@@ -725,6 +730,7 @@ ENTRY(serpent_cbc_dec_16way) + + vzeroupper; + ++ pax_force_retaddr + ret; + ENDPROC(serpent_cbc_dec_16way) + +@@ -748,6 +754,7 @@ ENTRY(serpent_ctr_16way) + + vzeroupper; + ++ pax_force_retaddr + ret; + ENDPROC(serpent_ctr_16way) + +@@ -772,6 +779,7 @@ ENTRY(serpent_xts_enc_16way) + + vzeroupper; + ++ pax_force_retaddr + ret; + ENDPROC(serpent_xts_enc_16way) + +@@ -796,5 +804,6 @@ ENTRY(serpent_xts_dec_16way) + + vzeroupper; + ++ pax_force_retaddr + ret; + ENDPROC(serpent_xts_dec_16way) diff --git a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S index acc066c..1559cc4 100644 --- a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S @@ -11367,6 +12159,126 @@ index a410950..3356d42 100644 ret ENDPROC(\name) +diff --git a/arch/x86/crypto/sha256-avx-asm.S b/arch/x86/crypto/sha256-avx-asm.S +index 642f156..4ab07b9 100644 +--- a/arch/x86/crypto/sha256-avx-asm.S ++++ b/arch/x86/crypto/sha256-avx-asm.S +@@ -49,6 +49,7 @@ + + #ifdef CONFIG_AS_AVX + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + ## assume buffers not aligned + #define VMOVDQ vmovdqu +@@ -460,6 +461,7 @@ done_hash: + popq %r13 + popq %rbp + popq %rbx ++ pax_force_retaddr 0, 1 + ret + ENDPROC(sha256_transform_avx) + +diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S +index 9e86944..2e7f95a 100644 +--- a/arch/x86/crypto/sha256-avx2-asm.S ++++ b/arch/x86/crypto/sha256-avx2-asm.S +@@ -50,6 +50,7 @@ + + #ifdef CONFIG_AS_AVX2 + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + ## assume buffers not aligned + #define VMOVDQ vmovdqu +@@ -720,6 +721,7 @@ done_hash: + popq %r12 + popq %rbp + popq %rbx ++ pax_force_retaddr 0, 1 + ret + ENDPROC(sha256_transform_rorx) + +diff --git a/arch/x86/crypto/sha256-ssse3-asm.S b/arch/x86/crypto/sha256-ssse3-asm.S +index f833b74..c36ed14 100644 +--- a/arch/x86/crypto/sha256-ssse3-asm.S ++++ b/arch/x86/crypto/sha256-ssse3-asm.S +@@ -47,6 +47,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + ## assume buffers not aligned + #define MOVDQ movdqu +@@ -471,6 +472,7 @@ done_hash: + popq %rbp + popq %rbx + ++ pax_force_retaddr 0, 1 + ret + ENDPROC(sha256_transform_ssse3) + +diff --git a/arch/x86/crypto/sha512-avx-asm.S b/arch/x86/crypto/sha512-avx-asm.S +index 974dde9..4533d34 100644 +--- a/arch/x86/crypto/sha512-avx-asm.S ++++ b/arch/x86/crypto/sha512-avx-asm.S +@@ -49,6 +49,7 @@ + + #ifdef CONFIG_AS_AVX + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + .text + +@@ -364,6 +365,7 @@ updateblock: + mov frame_RSPSAVE(%rsp), %rsp + + nowork: ++ pax_force_retaddr 0, 1 + ret + ENDPROC(sha512_transform_avx) + +diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S +index 568b961..061ef1d 100644 +--- a/arch/x86/crypto/sha512-avx2-asm.S ++++ b/arch/x86/crypto/sha512-avx2-asm.S +@@ -51,6 +51,7 @@ + + #ifdef CONFIG_AS_AVX2 + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + .text + +@@ -678,6 +679,7 @@ done_hash: + + # Restore Stack Pointer + mov frame_RSPSAVE(%rsp), %rsp ++ pax_force_retaddr 0, 1 + ret + ENDPROC(sha512_transform_rorx) + +diff --git a/arch/x86/crypto/sha512-ssse3-asm.S b/arch/x86/crypto/sha512-ssse3-asm.S +index fb56855..e23914f 100644 +--- a/arch/x86/crypto/sha512-ssse3-asm.S ++++ b/arch/x86/crypto/sha512-ssse3-asm.S +@@ -48,6 +48,7 @@ + ######################################################################## + + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + + .text + +@@ -363,6 +364,7 @@ updateblock: + mov frame_RSPSAVE(%rsp), %rsp + + nowork: ++ pax_force_retaddr 0, 1 + ret + ENDPROC(sha512_transform_ssse3) + diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S index 0505813..63b1d00 100644 --- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S @@ -11442,6 +12354,74 @@ index 0505813..63b1d00 100644 + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_xts_dec_8way) +diff --git a/arch/x86/crypto/twofish-avx2-asm_64.S b/arch/x86/crypto/twofish-avx2-asm_64.S +index e1a83b9..33006b9 100644 +--- a/arch/x86/crypto/twofish-avx2-asm_64.S ++++ b/arch/x86/crypto/twofish-avx2-asm_64.S +@@ -11,6 +11,7 @@ + */ + + #include <linux/linkage.h> ++#include <asm/alternative-asm.h> + #include "glue_helper-asm-avx2.S" + + .file "twofish-avx2-asm_64.S" +@@ -422,6 +423,7 @@ __twofish_enc_blk16: + outunpack_enc16(RA, RB, RC, RD); + write_blocks16(RA, RB, RC, RD); + ++ pax_force_retaddr_bts + ret; + ENDPROC(__twofish_enc_blk16) + +@@ -454,6 +456,7 @@ __twofish_dec_blk16: + outunpack_dec16(RA, RB, RC, RD); + write_blocks16(RA, RB, RC, RD); + ++ pax_force_retaddr_bts + ret; + ENDPROC(__twofish_dec_blk16) + +@@ -476,6 +479,7 @@ ENTRY(twofish_ecb_enc_16way) + popq %r12; + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(twofish_ecb_enc_16way) + +@@ -498,6 +502,7 @@ ENTRY(twofish_ecb_dec_16way) + popq %r12; + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(twofish_ecb_dec_16way) + +@@ -521,6 +526,7 @@ ENTRY(twofish_cbc_dec_16way) + popq %r12; + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(twofish_cbc_dec_16way) + +@@ -546,6 +552,7 @@ ENTRY(twofish_ctr_16way) + popq %r12; + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(twofish_ctr_16way) + +@@ -574,6 +581,7 @@ twofish_xts_crypt_16way: + popq %r12; + vzeroupper; + ++ pax_force_retaddr 0, 1 + ret; + ENDPROC(twofish_xts_crypt_16way) + diff --git a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S index 1c3b7ce..b365c5e 100644 --- a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S @@ -11518,7 +12498,7 @@ index 52ff81c..98af645 100644 set_fs(KERNEL_DS); has_dumped = 1; diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c -index cf1a471..3bc4cf8 100644 +index cf1a471..5ba2673 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -340,7 +340,7 @@ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, @@ -11548,7 +12528,12 @@ index cf1a471..3bc4cf8 100644 }; frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate); -@@ -463,16 +463,18 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, +@@ -459,20 +459,22 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); +- err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp); ++ __compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); if (ksig->ka.sa.sa_flags & SA_RESTORER) restorer = ksig->ka.sa.sa_restorer; @@ -11571,7 +12556,7 @@ index cf1a471..3bc4cf8 100644 err |= copy_siginfo_to_user32(&frame->info, &ksig->info); diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S -index 474dc1b..24aaa3e 100644 +index 474dc1b..9297c58 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -15,8 +15,10 @@ @@ -11631,7 +12616,7 @@ index 474dc1b..24aaa3e 100644 movl %ebp,%ebp /* zero extension */ pushq_cfi $__USER32_DS /*CFI_REL_OFFSET ss,0*/ -@@ -135,24 +157,44 @@ ENTRY(ia32_sysenter_target) +@@ -135,24 +157,49 @@ ENTRY(ia32_sysenter_target) CFI_REL_OFFSET rsp,0 pushfq_cfi /*CFI_REL_OFFSET rflags,0*/ @@ -11665,8 +12650,8 @@ index 474dc1b..24aaa3e 100644 32bit zero extended */ + +#ifdef CONFIG_PAX_MEMORY_UDEREF -+ mov pax_user_shadow_base,%r11 -+ add %r11,%rbp ++ addq pax_user_shadow_base,%rbp ++ ASM_PAX_OPEN_USERLAND +#endif + ASM_STAC @@ -11675,13 +12660,18 @@ index 474dc1b..24aaa3e 100644 ASM_CLAC - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ ASM_PAX_CLOSE_USERLAND ++#endif ++ + GET_THREAD_INFO(%r11) + orl $TS_COMPAT,TI_status(%r11) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r11) CFI_REMEMBER_STATE jnz sysenter_tracesys cmpq $(IA32_NR_syscalls-1),%rax -@@ -162,12 +204,15 @@ sysenter_do_call: +@@ -162,12 +209,15 @@ sysenter_do_call: sysenter_dispatch: call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) @@ -11699,7 +12689,7 @@ index 474dc1b..24aaa3e 100644 /* clear IF, that popfq doesn't enable interrupts early */ andl $~0x200,EFLAGS-R11(%rsp) movl RIP-R11(%rsp),%edx /* User %eip */ -@@ -193,6 +238,9 @@ sysexit_from_sys_call: +@@ -193,6 +243,9 @@ sysexit_from_sys_call: movl %eax,%esi /* 2nd arg: syscall number */ movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ call __audit_syscall_entry @@ -11709,7 +12699,7 @@ index 474dc1b..24aaa3e 100644 movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys -@@ -204,7 +252,7 @@ sysexit_from_sys_call: +@@ -204,7 +257,7 @@ sysexit_from_sys_call: .endm .macro auditsys_exit exit @@ -11718,7 +12708,7 @@ index 474dc1b..24aaa3e 100644 jnz ia32_ret_from_sys_call TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) -@@ -215,11 +263,12 @@ sysexit_from_sys_call: +@@ -215,11 +268,12 @@ sysexit_from_sys_call: 1: setbe %al /* 1 if error, 0 if not */ movzbl %al,%edi /* zero-extend that into %edi */ call __audit_syscall_exit @@ -11732,7 +12722,7 @@ index 474dc1b..24aaa3e 100644 jz \exit CLEAR_RREGS -ARGOFFSET jmp int_with_check -@@ -237,7 +286,7 @@ sysexit_audit: +@@ -237,7 +291,7 @@ sysexit_audit: sysenter_tracesys: #ifdef CONFIG_AUDITSYSCALL @@ -11741,7 +12731,7 @@ index 474dc1b..24aaa3e 100644 jz sysenter_auditsys #endif SAVE_REST -@@ -249,6 +298,9 @@ sysenter_tracesys: +@@ -249,6 +303,9 @@ sysenter_tracesys: RESTORE_REST cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ @@ -11751,7 +12741,7 @@ index 474dc1b..24aaa3e 100644 jmp sysenter_do_call CFI_ENDPROC ENDPROC(ia32_sysenter_target) -@@ -276,19 +328,25 @@ ENDPROC(ia32_sysenter_target) +@@ -276,19 +333,25 @@ ENDPROC(ia32_sysenter_target) ENTRY(ia32_cstar_target) CFI_STARTPROC32 simple CFI_SIGNAL_FRAME @@ -11779,14 +12769,15 @@ index 474dc1b..24aaa3e 100644 movl %eax,%eax /* zero extension */ movq %rax,ORIG_RAX-ARGOFFSET(%rsp) movq %rcx,RIP-ARGOFFSET(%rsp) -@@ -304,12 +362,19 @@ ENTRY(ia32_cstar_target) +@@ -304,12 +367,25 @@ ENTRY(ia32_cstar_target) /* no need to do an access_ok check here because r8 has been 32bit zero extended */ /* hardware stack frame is complete now */ + +#ifdef CONFIG_PAX_MEMORY_UDEREF -+ mov pax_user_shadow_base,%r11 -+ add %r11,%r8 ++ ASM_PAX_OPEN_USERLAND ++ movq pax_user_shadow_base,%r8 ++ addq RSP-ARGOFFSET(%rsp),%r8 +#endif + ASM_STAC @@ -11795,13 +12786,18 @@ index 474dc1b..24aaa3e 100644 ASM_CLAC - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ ASM_PAX_CLOSE_USERLAND ++#endif ++ + GET_THREAD_INFO(%r11) + orl $TS_COMPAT,TI_status(%r11) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r11) CFI_REMEMBER_STATE jnz cstar_tracesys cmpq $IA32_NR_syscalls-1,%rax -@@ -319,12 +384,15 @@ cstar_do_call: +@@ -319,12 +395,15 @@ cstar_do_call: cstar_dispatch: call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) @@ -11819,7 +12815,7 @@ index 474dc1b..24aaa3e 100644 RESTORE_ARGS 0,-ARG_SKIP,0,0,0 movl RIP-ARGOFFSET(%rsp),%ecx CFI_REGISTER rip,rcx -@@ -352,7 +420,7 @@ sysretl_audit: +@@ -352,7 +431,7 @@ sysretl_audit: cstar_tracesys: #ifdef CONFIG_AUDITSYSCALL @@ -11828,7 +12824,7 @@ index 474dc1b..24aaa3e 100644 jz cstar_auditsys #endif xchgl %r9d,%ebp -@@ -366,6 +434,9 @@ cstar_tracesys: +@@ -366,11 +445,19 @@ cstar_tracesys: xchgl %ebp,%r9d cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ @@ -11838,7 +12834,17 @@ index 474dc1b..24aaa3e 100644 jmp cstar_do_call END(ia32_cstar_target) -@@ -407,19 +478,26 @@ ENTRY(ia32_syscall) + ia32_badarg: + ASM_CLAC ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ ASM_PAX_CLOSE_USERLAND ++#endif ++ + movq $-EFAULT,%rax + jmp ia32_sysret + CFI_ENDPROC +@@ -407,19 +494,26 @@ ENTRY(ia32_syscall) CFI_REL_OFFSET rip,RIP-RIP PARAVIRT_ADJUST_EXCEPTION_FRAME SWAPGS @@ -11872,7 +12878,7 @@ index 474dc1b..24aaa3e 100644 jnz ia32_tracesys cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys -@@ -442,6 +520,9 @@ ia32_tracesys: +@@ -442,6 +536,9 @@ ia32_tracesys: RESTORE_REST cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ @@ -13109,9 +14115,18 @@ index 59c6c40..5e0b22c 100644 struct compat_timespec { compat_time_t tv_sec; diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h -index e99ac27..e89e28c 100644 +index e99ac27..10d834e 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h +@@ -203,7 +203,7 @@ + #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ + #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ + #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ +- ++#define X86_FEATURE_STRONGUDEREF (8*32+31) /* PaX PCID based strong UDEREF */ + + /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ + #define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ @@ -211,7 +211,7 @@ #define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */ #define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision */ @@ -13121,7 +14136,15 @@ index e99ac27..e89e28c 100644 #define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */ #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */ #define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */ -@@ -394,7 +394,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) +@@ -353,6 +353,7 @@ extern const char * const x86_power_flags[32]; + #undef cpu_has_centaur_mcr + #define cpu_has_centaur_mcr 0 + ++#define cpu_has_pcid boot_cpu_has(X86_FEATURE_PCID) + #endif /* CONFIG_X86_64 */ + + #if __GNUC__ >= 4 +@@ -394,7 +395,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) ".section .discard,\"aw\",@progbits\n" " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ ".previous\n" @@ -13444,12 +14467,14 @@ index 75ce3f4..882e801 100644 #endif /* _ASM_X86_EMERGENCY_RESTART_H */ diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h -index e25cc33..425d099 100644 +index e25cc33..7d3ec01 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h -@@ -127,7 +127,9 @@ static inline void sanitize_i387_state(struct task_struct *tsk) +@@ -126,8 +126,11 @@ static inline void sanitize_i387_state(struct task_struct *tsk) + #define user_insn(insn, output, input...) \ ({ \ int err; \ ++ pax_open_userland(); \ asm volatile(ASM_STAC "\n" \ - "1:" #insn "\n\t" \ + "1:" \ @@ -13458,7 +14483,15 @@ index e25cc33..425d099 100644 "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "3: movl $-1,%[err]\n" \ -@@ -300,7 +302,7 @@ static inline int restore_fpu_checking(struct task_struct *tsk) +@@ -136,6 +139,7 @@ static inline void sanitize_i387_state(struct task_struct *tsk) + _ASM_EXTABLE(1b, 3b) \ + : [err] "=r" (err), output \ + : "0"(0), input); \ ++ pax_close_userland(); \ + err; \ + }) + +@@ -300,7 +304,7 @@ static inline int restore_fpu_checking(struct task_struct *tsk) "emms\n\t" /* clear stack tags */ "fildl %P[addr]", /* set F?P to defined value */ X86_FEATURE_FXSAVE_LEAK, @@ -13468,7 +14501,7 @@ index e25cc33..425d099 100644 return fpu_restore_checking(&tsk->thread.fpu); } diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h -index be27ba1..8f13ff9 100644 +index be27ba1..04a8801 100644 --- a/arch/x86/include/asm/futex.h +++ b/arch/x86/include/asm/futex.h @@ -12,6 +12,7 @@ @@ -13507,8 +14540,11 @@ index be27ba1..8f13ff9 100644 : "r" (oparg), "i" (-EFAULT), "1" (0)) static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) -@@ -59,10 +61,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) +@@ -57,12 +59,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + pagefault_disable(); + ++ pax_open_userland(); switch (op) { case FUTEX_OP_SET: - __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); @@ -13520,9 +14556,19 @@ index be27ba1..8f13ff9 100644 uaddr, oparg); break; case FUTEX_OP_OR: -@@ -116,14 +118,14 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +@@ -77,6 +80,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + default: + ret = -ENOSYS; + } ++ pax_close_userland(); + + pagefault_enable(); + +@@ -115,18 +119,20 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; ++ pax_open_userland(); asm volatile("\t" ASM_STAC "\n" - "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n" + "1:\t" LOCK_PREFIX __copyuser_seg"cmpxchgl %4, %2\n" @@ -13537,6 +14583,10 @@ index be27ba1..8f13ff9 100644 : "i" (-EFAULT), "r" (newval), "1" (oldval) : "memory" ); ++ pax_close_userland(); + + *uval = oldval; + return ret; diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 1da97ef..9c2ebff 100644 --- a/arch/x86/include/asm/hw_irq.h @@ -13923,29 +14973,31 @@ index 5f55e69..e20bfb1 100644 #ifdef CONFIG_SMP diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h -index cdbf367..adb37ac 100644 +index cdbf367..4c73c9e 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h -@@ -24,6 +24,18 @@ void destroy_context(struct mm_struct *mm); +@@ -24,6 +24,20 @@ void destroy_context(struct mm_struct *mm); static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) -+ unsigned int i; -+ pgd_t *pgd; ++ if (!(static_cpu_has(X86_FEATURE_PCID))) { ++ unsigned int i; ++ pgd_t *pgd; + -+ pax_open_kernel(); -+ pgd = get_cpu_pgd(smp_processor_id()); -+ for (i = USER_PGD_PTRS; i < 2 * USER_PGD_PTRS; ++i) -+ set_pgd_batched(pgd+i, native_make_pgd(0)); -+ pax_close_kernel(); ++ pax_open_kernel(); ++ pgd = get_cpu_pgd(smp_processor_id(), kernel); ++ for (i = USER_PGD_PTRS; i < 2 * USER_PGD_PTRS; ++i) ++ set_pgd_batched(pgd+i, native_make_pgd(0)); ++ pax_close_kernel(); ++ } +#endif + #ifdef CONFIG_SMP if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); -@@ -34,16 +46,30 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, +@@ -34,16 +48,55 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { unsigned cpu = smp_processor_id(); @@ -13966,17 +15018,42 @@ index cdbf367..adb37ac 100644 /* Re-load page tables */ +#ifdef CONFIG_PAX_PER_CPU_PGD + pax_open_kernel(); -+ __clone_user_pgds(get_cpu_pgd(cpu), next->pgd); -+ __shadow_user_pgds(get_cpu_pgd(cpu) + USER_PGD_PTRS, next->pgd); ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ if (static_cpu_has(X86_FEATURE_PCID)) ++ __clone_user_pgds(get_cpu_pgd(cpu, user), next->pgd); ++ else ++#endif ++ ++ __clone_user_pgds(get_cpu_pgd(cpu, kernel), next->pgd); ++ __shadow_user_pgds(get_cpu_pgd(cpu, kernel) + USER_PGD_PTRS, next->pgd); + pax_close_kernel(); -+ load_cr3(get_cpu_pgd(cpu)); ++ BUG_ON((__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL) != (read_cr3() & __PHYSICAL_MASK) && (__pa(get_cpu_pgd(cpu, user)) | PCID_USER) != (read_cr3() & __PHYSICAL_MASK)); ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ if (static_cpu_has(X86_FEATURE_PCID)) { ++ if (static_cpu_has(X86_FEATURE_INVPCID)) { ++ unsigned long descriptor[2]; ++ descriptor[0] = PCID_USER; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_CONTEXT) : "memory"); ++ } else { ++ write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER); ++ if (static_cpu_has(X86_FEATURE_STRONGUDEREF)) ++ write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); ++ else ++ write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL); ++ } ++ } else ++#endif ++ ++ load_cr3(get_cpu_pgd(cpu, kernel)); +#else load_cr3(next->pgd); +#endif /* stop flush ipis for the previous mm */ cpumask_clear_cpu(cpu, mm_cpumask(prev)); -@@ -53,9 +79,38 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, +@@ -53,9 +106,63 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, */ if (unlikely(prev->context.ldt != next->context.ldt)) load_LDT_nolock(&next->context); @@ -14006,17 +15083,42 @@ index cdbf367..adb37ac 100644 + +#ifdef CONFIG_PAX_PER_CPU_PGD + pax_open_kernel(); -+ __clone_user_pgds(get_cpu_pgd(cpu), next->pgd); -+ __shadow_user_pgds(get_cpu_pgd(cpu) + USER_PGD_PTRS, next->pgd); ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ if (static_cpu_has(X86_FEATURE_PCID)) ++ __clone_user_pgds(get_cpu_pgd(cpu, user), next->pgd); ++ else ++#endif ++ ++ __clone_user_pgds(get_cpu_pgd(cpu, kernel), next->pgd); ++ __shadow_user_pgds(get_cpu_pgd(cpu, kernel) + USER_PGD_PTRS, next->pgd); + pax_close_kernel(); -+ load_cr3(get_cpu_pgd(cpu)); ++ BUG_ON((__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL) != (read_cr3() & __PHYSICAL_MASK) && (__pa(get_cpu_pgd(cpu, user)) | PCID_USER) != (read_cr3() & __PHYSICAL_MASK)); ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ if (static_cpu_has(X86_FEATURE_PCID)) { ++ if (static_cpu_has(X86_FEATURE_INVPCID)) { ++ unsigned long descriptor[2]; ++ descriptor[0] = PCID_USER; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_CONTEXT) : "memory"); ++ } else { ++ write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER); ++ if (static_cpu_has(X86_FEATURE_STRONGUDEREF)) ++ write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); ++ else ++ write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL); ++ } ++ } else ++#endif ++ ++ load_cr3(get_cpu_pgd(cpu, kernel)); +#endif + +#ifdef CONFIG_SMP this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next); -@@ -64,11 +119,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, +@@ -64,11 +171,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, * tlb flush IPI delivery. We must reload CR3 * to make sure to use no freed page tables. */ @@ -14381,7 +15483,7 @@ index 4cc9f2b..5fd9226 100644 /* diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h -index 1e67223..dd6e7ea 100644 +index 1e67223..92a9585 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -44,6 +44,7 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); @@ -14487,23 +15589,24 @@ index 1e67223..dd6e7ea 100644 } static inline pte_t pte_mkdirty(pte_t pte) -@@ -394,6 +459,15 @@ pte_t *populate_extra_pte(unsigned long vaddr); +@@ -394,6 +459,16 @@ pte_t *populate_extra_pte(unsigned long vaddr); #endif #ifndef __ASSEMBLY__ + +#ifdef CONFIG_PAX_PER_CPU_PGD -+extern pgd_t cpu_pgd[NR_CPUS][PTRS_PER_PGD]; -+static inline pgd_t *get_cpu_pgd(unsigned int cpu) ++extern pgd_t cpu_pgd[NR_CPUS][2][PTRS_PER_PGD]; ++enum cpu_pgd_type {kernel = 0, user = 1}; ++static inline pgd_t *get_cpu_pgd(unsigned int cpu, enum cpu_pgd_type type) +{ -+ return cpu_pgd[cpu]; ++ return cpu_pgd[cpu][type]; +} +#endif + #include <linux/mm_types.h> #include <linux/log2.h> -@@ -529,7 +603,7 @@ static inline unsigned long pud_page_vaddr(pud_t pud) +@@ -529,7 +604,7 @@ static inline unsigned long pud_page_vaddr(pud_t pud) * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ @@ -14512,7 +15615,7 @@ index 1e67223..dd6e7ea 100644 /* Find an entry in the second-level page table.. */ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) -@@ -569,7 +643,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) +@@ -569,7 +644,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ @@ -14521,7 +15624,7 @@ index 1e67223..dd6e7ea 100644 /* to find an entry in a page-table-directory. */ static inline unsigned long pud_index(unsigned long address) -@@ -584,7 +658,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) +@@ -584,7 +659,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) static inline int pgd_bad(pgd_t pgd) { @@ -14530,7 +15633,7 @@ index 1e67223..dd6e7ea 100644 } static inline int pgd_none(pgd_t pgd) -@@ -607,7 +681,12 @@ static inline int pgd_none(pgd_t pgd) +@@ -607,7 +682,12 @@ static inline int pgd_none(pgd_t pgd) * pgd_offset() returns a (pgd_t *) * pgd_index() is used get the offset into the pgd page's array of pgd_t's; */ @@ -14538,13 +15641,13 @@ index 1e67223..dd6e7ea 100644 +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) + +#ifdef CONFIG_PAX_PER_CPU_PGD -+#define pgd_offset_cpu(cpu, address) (get_cpu_pgd(cpu) + pgd_index(address)) ++#define pgd_offset_cpu(cpu, type, address) (get_cpu_pgd(cpu, type) + pgd_index(address)) +#endif + /* * a shortcut which implies the use of the kernel's pgd, instead * of a process's -@@ -618,6 +697,22 @@ static inline int pgd_none(pgd_t pgd) +@@ -618,6 +698,23 @@ static inline int pgd_none(pgd_t pgd) #define KERNEL_PGD_BOUNDARY pgd_index(PAGE_OFFSET) #define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY) @@ -14559,6 +15662,7 @@ index 1e67223..dd6e7ea 100644 +#define pax_user_shadow_base pax_user_shadow_base(%rip) +#else +extern unsigned long pax_user_shadow_base; ++extern pgdval_t clone_pgd_mask; +#endif +#endif + @@ -14567,7 +15671,7 @@ index 1e67223..dd6e7ea 100644 #ifndef __ASSEMBLY__ extern int direct_gbpages; -@@ -784,11 +879,24 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, +@@ -784,11 +881,24 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, * dst and src can be on the same page, but the range must not overlap, * and must not cross a page boundary. */ @@ -14859,10 +15963,33 @@ index e642300..0ef8f31 100644 #define pgprot_writecombine pgprot_writecombine extern pgprot_t pgprot_writecombine(pgprot_t prot); diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index 22224b3..4080dab 100644 +index 22224b3..c5d8d7d 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h -@@ -282,7 +282,7 @@ struct tss_struct { +@@ -198,9 +198,21 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, + : "memory"); + } + ++/* invpcid (%rdx),%rax */ ++#define __ASM_INVPCID ".byte 0x66,0x0f,0x38,0x82,0x02" ++ ++#define INVPCID_SINGLE_ADDRESS 0UL ++#define INVPCID_SINGLE_CONTEXT 1UL ++#define INVPCID_ALL_GLOBAL 2UL ++#define INVPCID_ALL_MONGLOBAL 3UL ++ ++#define PCID_KERNEL 0UL ++#define PCID_USER 1UL ++#define PCID_NOFLUSH (1UL << 63) ++ + static inline void load_cr3(pgd_t *pgdir) + { +- write_cr3(__pa(pgdir)); ++ write_cr3(__pa(pgdir) | PCID_KERNEL); + } + + #ifdef CONFIG_X86_32 +@@ -282,7 +294,7 @@ struct tss_struct { } ____cacheline_aligned; @@ -14871,7 +15998,15 @@ index 22224b3..4080dab 100644 /* * Save the original ist values for checking stack pointers during debugging -@@ -823,11 +823,18 @@ static inline void spin_lock_prefetch(const void *x) +@@ -452,6 +464,7 @@ struct thread_struct { + unsigned short ds; + unsigned short fsindex; + unsigned short gsindex; ++ unsigned short ss; + #endif + #ifdef CONFIG_X86_32 + unsigned long ip; +@@ -823,11 +836,18 @@ static inline void spin_lock_prefetch(const void *x) */ #define TASK_SIZE PAGE_OFFSET #define TASK_SIZE_MAX TASK_SIZE @@ -14892,7 +16027,7 @@ index 22224b3..4080dab 100644 .vm86_info = NULL, \ .sysenter_cs = __KERNEL_CS, \ .io_bitmap_ptr = NULL, \ -@@ -841,7 +848,7 @@ static inline void spin_lock_prefetch(const void *x) +@@ -841,7 +861,7 @@ static inline void spin_lock_prefetch(const void *x) */ #define INIT_TSS { \ .x86_tss = { \ @@ -14901,7 +16036,7 @@ index 22224b3..4080dab 100644 .ss0 = __KERNEL_DS, \ .ss1 = __KERNEL_CS, \ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \ -@@ -852,11 +859,7 @@ static inline void spin_lock_prefetch(const void *x) +@@ -852,11 +872,7 @@ static inline void spin_lock_prefetch(const void *x) extern unsigned long thread_saved_pc(struct task_struct *tsk); #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long)) @@ -14914,7 +16049,7 @@ index 22224b3..4080dab 100644 /* * The below -8 is to reserve 8 bytes on top of the ring0 stack. -@@ -871,7 +874,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); +@@ -871,7 +887,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); #define task_pt_regs(task) \ ({ \ struct pt_regs *__regs__; \ @@ -14923,7 +16058,7 @@ index 22224b3..4080dab 100644 __regs__ - 1; \ }) -@@ -881,13 +884,13 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); +@@ -881,13 +897,13 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); /* * User space process size. 47bits minus one guard page. */ @@ -14939,7 +16074,7 @@ index 22224b3..4080dab 100644 #define TASK_SIZE (test_thread_flag(TIF_ADDR32) ? \ IA32_PAGE_OFFSET : TASK_SIZE_MAX) -@@ -898,11 +901,11 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); +@@ -898,11 +914,11 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); #define STACK_TOP_MAX TASK_SIZE_MAX #define INIT_THREAD { \ @@ -14953,7 +16088,7 @@ index 22224b3..4080dab 100644 } /* -@@ -930,6 +933,10 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, +@@ -930,6 +946,10 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, */ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) @@ -14964,7 +16099,17 @@ index 22224b3..4080dab 100644 #define KSTK_EIP(task) (task_pt_regs(task)->ip) /* Get/set a process' ability to use the timestamp counter instruction */ -@@ -970,7 +977,7 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, +@@ -942,7 +962,8 @@ extern int set_tsc_mode(unsigned int val); + extern u16 amd_get_nb_id(int cpu); + + struct aperfmperf { +- u64 aperf, mperf; ++ u64 aperf __intentional_overflow(0); ++ u64 mperf __intentional_overflow(0); + }; + + static inline void get_aperfmperf(struct aperfmperf *am) +@@ -970,7 +991,7 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, return ratio; } @@ -14973,7 +16118,7 @@ index 22224b3..4080dab 100644 extern void free_init_pages(char *what, unsigned long begin, unsigned long end); void default_idle(void); -@@ -980,6 +987,6 @@ bool xen_set_default_idle(void); +@@ -980,6 +1001,6 @@ bool xen_set_default_idle(void); #define xen_set_default_idle 0 #endif @@ -15221,7 +16366,7 @@ index cad82c9..2e5c5c1 100644 #endif /* __KERNEL__ */ diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h -index c48a950..c6d7468 100644 +index c48a950..bc40804 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h @@ -64,10 +64,15 @@ @@ -15282,15 +16427,32 @@ index c48a950..c6d7468 100644 #define GDT_ENTRY_TSS 8 /* needs two entries */ #define GDT_ENTRY_LDT 10 /* needs two entries */ #define GDT_ENTRY_TLS_MIN 12 -@@ -185,6 +200,7 @@ +@@ -173,6 +188,8 @@ + #define GDT_ENTRY_PER_CPU 15 /* Abused to load per CPU data from limit */ + #define __PER_CPU_SEG (GDT_ENTRY_PER_CPU * 8 + 3) + ++#define GDT_ENTRY_UDEREF_KERNEL_DS 16 ++ + /* TLS indexes for 64bit - hardcoded in arch_prctl */ + #define FS_TLS 0 + #define GS_TLS 1 +@@ -180,12 +197,14 @@ + #define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3) + #define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) + +-#define GDT_ENTRIES 16 ++#define GDT_ENTRIES 17 + #endif #define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8) +#define __KERNEXEC_KERNEL_CS (GDT_ENTRY_KERNEXEC_KERNEL_CS*8) #define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8) ++#define __UDEREF_KERNEL_DS (GDT_ENTRY_UDEREF_KERNEL_DS*8) #define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3) #define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3) -@@ -265,7 +281,7 @@ static inline unsigned long get_limit(unsigned long segment) + #ifndef CONFIG_PARAVIRT +@@ -265,7 +284,7 @@ static inline unsigned long get_limit(unsigned long segment) { unsigned long __limit; asm("lsll %1,%0" : "=r" (__limit) : "r" (segment)); @@ -15299,6 +16461,99 @@ index c48a950..c6d7468 100644 } #endif /* !__ASSEMBLY__ */ +diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h +index 8d3120f..352b440 100644 +--- a/arch/x86/include/asm/smap.h ++++ b/arch/x86/include/asm/smap.h +@@ -25,11 +25,40 @@ + + #include <asm/alternative-asm.h> + ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++#define ASM_PAX_OPEN_USERLAND \ ++ 661: jmp 663f; \ ++ .pushsection .altinstr_replacement, "a" ; \ ++ 662: pushq %rax; nop; \ ++ .popsection ; \ ++ .pushsection .altinstructions, "a" ; \ ++ altinstruction_entry 661b, 662b, X86_FEATURE_STRONGUDEREF, 2, 2;\ ++ .popsection ; \ ++ call __pax_open_userland; \ ++ popq %rax; \ ++ 663: ++ ++#define ASM_PAX_CLOSE_USERLAND \ ++ 661: jmp 663f; \ ++ .pushsection .altinstr_replacement, "a" ; \ ++ 662: pushq %rax; nop; \ ++ .popsection; \ ++ .pushsection .altinstructions, "a" ; \ ++ altinstruction_entry 661b, 662b, X86_FEATURE_STRONGUDEREF, 2, 2;\ ++ .popsection; \ ++ call __pax_close_userland; \ ++ popq %rax; \ ++ 663: ++#else ++#define ASM_PAX_OPEN_USERLAND ++#define ASM_PAX_CLOSE_USERLAND ++#endif ++ + #ifdef CONFIG_X86_SMAP + + #define ASM_CLAC \ + 661: ASM_NOP3 ; \ +- .pushsection .altinstr_replacement, "ax" ; \ ++ .pushsection .altinstr_replacement, "a" ; \ + 662: __ASM_CLAC ; \ + .popsection ; \ + .pushsection .altinstructions, "a" ; \ +@@ -38,7 +67,7 @@ + + #define ASM_STAC \ + 661: ASM_NOP3 ; \ +- .pushsection .altinstr_replacement, "ax" ; \ ++ .pushsection .altinstr_replacement, "a" ; \ + 662: __ASM_STAC ; \ + .popsection ; \ + .pushsection .altinstructions, "a" ; \ +@@ -56,6 +85,37 @@ + + #include <asm/alternative.h> + ++#define __HAVE_ARCH_PAX_OPEN_USERLAND ++#define __HAVE_ARCH_PAX_CLOSE_USERLAND ++ ++extern void __pax_open_userland(void); ++static __always_inline unsigned long pax_open_userland(void) ++{ ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ asm volatile(ALTERNATIVE(ASM_NOP5, "call %P[open]", X86_FEATURE_STRONGUDEREF) ++ : ++ : [open] "i" (__pax_open_userland) ++ : "memory", "rax"); ++#endif ++ ++ return 0; ++} ++ ++extern void __pax_close_userland(void); ++static __always_inline unsigned long pax_close_userland(void) ++{ ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ asm volatile(ALTERNATIVE(ASM_NOP5, "call %P[close]", X86_FEATURE_STRONGUDEREF) ++ : ++ : [close] "i" (__pax_close_userland) ++ : "memory", "rax"); ++#endif ++ ++ return 0; ++} ++ + #ifdef CONFIG_X86_SMAP + + static __always_inline void clac(void) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index b073aae..39f9bdd 100644 --- a/arch/x86/include/asm/smp.h @@ -15704,8 +16959,94 @@ index a1df6e8..e002940 100644 + #endif #endif /* _ASM_X86_THREAD_INFO_H */ +diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h +index 50a7fc0..d00c622 100644 +--- a/arch/x86/include/asm/tlbflush.h ++++ b/arch/x86/include/asm/tlbflush.h +@@ -17,18 +17,39 @@ + + static inline void __native_flush_tlb(void) + { +- native_write_cr3(native_read_cr3()); ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ if (static_cpu_has(X86_FEATURE_PCID)) { ++ unsigned int cpu = raw_get_cpu(); ++ ++ if (static_cpu_has(X86_FEATURE_INVPCID)) { ++ unsigned long descriptor[2]; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_MONGLOBAL) : "memory"); ++ } else { ++ native_write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER); ++ native_write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL); ++ } ++ raw_put_cpu_no_resched(); ++ } else ++#endif ++ ++ native_write_cr3(native_read_cr3()); + } + + static inline void __native_flush_tlb_global_irq_disabled(void) + { +- unsigned long cr4; ++ if (static_cpu_has(X86_FEATURE_INVPCID)) { ++ unsigned long descriptor[2]; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_GLOBAL) : "memory"); ++ } else { ++ unsigned long cr4; + +- cr4 = native_read_cr4(); +- /* clear PGE */ +- native_write_cr4(cr4 & ~X86_CR4_PGE); +- /* write old PGE again and flush TLBs */ +- native_write_cr4(cr4); ++ cr4 = native_read_cr4(); ++ /* clear PGE */ ++ native_write_cr4(cr4 & ~X86_CR4_PGE); ++ /* write old PGE again and flush TLBs */ ++ native_write_cr4(cr4); ++ } + } + + static inline void __native_flush_tlb_global(void) +@@ -49,7 +70,33 @@ static inline void __native_flush_tlb_global(void) + + static inline void __native_flush_tlb_single(unsigned long addr) + { +- asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); ++ ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ if (static_cpu_has(X86_FEATURE_PCID) && addr < TASK_SIZE_MAX) { ++ unsigned int cpu = raw_get_cpu(); ++ ++ if (static_cpu_has(X86_FEATURE_INVPCID)) { ++ unsigned long descriptor[2]; ++ descriptor[0] = PCID_USER; ++ descriptor[1] = addr; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_ADDRESS) : "memory"); ++ if (!static_cpu_has(X86_FEATURE_STRONGUDEREF)) { ++ descriptor[0] = PCID_KERNEL; ++ descriptor[1] = addr + pax_user_shadow_base; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_ADDRESS) : "memory"); ++ } ++ } else { ++ native_write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER | PCID_NOFLUSH); ++ asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); ++ native_write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); ++ if (!static_cpu_has(X86_FEATURE_STRONGUDEREF)) ++ asm volatile("invlpg (%0)" ::"r" (addr + pax_user_shadow_base) : "memory"); ++ } ++ raw_put_cpu_no_resched(); ++ } else ++#endif ++ ++ asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); + } + + static inline void __flush_tlb_all(void) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h -index 5ee2687..70d5895 100644 +index 5ee2687..74590b9 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -7,6 +7,7 @@ @@ -15765,7 +17106,20 @@ index 5ee2687..70d5895 100644 /* * The exception table consists of pairs of addresses relative to the -@@ -176,13 +207,21 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) +@@ -165,10 +196,12 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) + register __inttype(*(ptr)) __val_gu asm("%edx"); \ + __chk_user_ptr(ptr); \ + might_fault(); \ ++ pax_open_userland(); \ + asm volatile("call __get_user_%P3" \ + : "=a" (__ret_gu), "=r" (__val_gu) \ + : "0" (ptr), "i" (sizeof(*(ptr)))); \ + (x) = (__typeof__(*(ptr))) __val_gu; \ ++ pax_close_userland(); \ + __ret_gu; \ + }) + +@@ -176,13 +209,21 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) asm volatile("call __put_user_" #size : "=a" (__ret_pu) \ : "0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") @@ -15790,7 +17144,7 @@ index 5ee2687..70d5895 100644 "3: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "4: movl %3,%0\n" \ -@@ -195,8 +234,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) +@@ -195,8 +236,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) #define __put_user_asm_ex_u64(x, addr) \ asm volatile(ASM_STAC "\n" \ @@ -15801,34 +17155,50 @@ index 5ee2687..70d5895 100644 "3: " ASM_CLAC "\n" \ _ASM_EXTABLE_EX(1b, 2b) \ _ASM_EXTABLE_EX(2b, 3b) \ -@@ -246,7 +285,7 @@ extern void __put_user_8(void); +@@ -246,7 +287,8 @@ extern void __put_user_8(void); __typeof__(*(ptr)) __pu_val; \ __chk_user_ptr(ptr); \ might_fault(); \ - __pu_val = x; \ + __pu_val = (x); \ ++ pax_open_userland(); \ switch (sizeof(*(ptr))) { \ case 1: \ __put_user_x(1, __pu_val, ptr, __ret_pu); \ -@@ -345,7 +384,7 @@ do { \ +@@ -264,6 +306,7 @@ extern void __put_user_8(void); + __put_user_x(X, __pu_val, ptr, __ret_pu); \ + break; \ + } \ ++ pax_close_userland(); \ + __ret_pu; \ + }) + +@@ -344,8 +387,10 @@ do { \ + } while (0) #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \ ++do { \ ++ pax_open_userland(); \ asm volatile(ASM_STAC "\n" \ - "1: mov"itype" %2,%"rtype"1\n" \ + "1: "__copyuser_seg"mov"itype" %2,%"rtype"1\n"\ "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "3: mov %3,%0\n" \ -@@ -353,7 +392,7 @@ do { \ +@@ -353,8 +398,10 @@ do { \ " jmp 2b\n" \ ".previous\n" \ _ASM_EXTABLE(1b, 3b) \ - : "=r" (err), ltype(x) \ +- : "m" (__m(addr)), "i" (errret), "0" (err)) + : "=r" (err), ltype (x) \ - : "m" (__m(addr)), "i" (errret), "0" (err)) ++ : "m" (__m(addr)), "i" (errret), "0" (err)); \ ++ pax_close_userland(); \ ++} while (0) #define __get_user_size_ex(x, ptr, size) \ -@@ -378,7 +417,7 @@ do { \ + do { \ +@@ -378,7 +425,7 @@ do { \ } while (0) #define __get_user_asm_ex(x, addr, itype, rtype, ltype) \ @@ -15837,7 +17207,7 @@ index 5ee2687..70d5895 100644 "2:\n" \ _ASM_EXTABLE_EX(1b, 2b) \ : ltype(x) : "m" (__m(addr))) -@@ -395,13 +434,24 @@ do { \ +@@ -395,13 +442,24 @@ do { \ int __gu_err; \ unsigned long __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \ @@ -15864,21 +17234,26 @@ index 5ee2687..70d5895 100644 /* * Tell gcc we read from memory instead of writing: this is because -@@ -410,7 +460,7 @@ struct __large_struct { unsigned long buf[100]; }; +@@ -409,8 +467,10 @@ struct __large_struct { unsigned long buf[100]; }; + * aliasing issues. */ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ ++do { \ ++ pax_open_userland(); \ asm volatile(ASM_STAC "\n" \ - "1: mov"itype" %"rtype"1,%2\n" \ + "1: "__copyuser_seg"mov"itype" %"rtype"1,%2\n"\ "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "3: mov %3,%0\n" \ -@@ -418,10 +468,10 @@ struct __large_struct { unsigned long buf[100]; }; +@@ -418,10 +478,12 @@ struct __large_struct { unsigned long buf[100]; }; ".previous\n" \ _ASM_EXTABLE(1b, 3b) \ : "=r"(err) \ - : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) -+ : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err)) ++ : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err));\ ++ pax_close_userland(); \ ++} while (0) #define __put_user_asm_ex(x, addr, itype, rtype, ltype) \ - asm volatile("1: mov"itype" %"rtype"0,%1\n" \ @@ -15886,7 +17261,21 @@ index 5ee2687..70d5895 100644 "2:\n" \ _ASM_EXTABLE_EX(1b, 2b) \ : : ltype(x), "m" (__m(addr))) -@@ -460,8 +510,12 @@ struct __large_struct { unsigned long buf[100]; }; +@@ -431,11 +493,13 @@ struct __large_struct { unsigned long buf[100]; }; + */ + #define uaccess_try do { \ + current_thread_info()->uaccess_err = 0; \ ++ pax_open_userland(); \ + stac(); \ + barrier(); + + #define uaccess_catch(err) \ + clac(); \ ++ pax_close_userland(); \ + (err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \ + } while (0) + +@@ -460,8 +524,12 @@ struct __large_struct { unsigned long buf[100]; }; * On error, the variable @x is set to zero. */ @@ -15899,7 +17288,7 @@ index 5ee2687..70d5895 100644 /** * __put_user: - Write a simple value into user space, with less checking. -@@ -483,8 +537,12 @@ struct __large_struct { unsigned long buf[100]; }; +@@ -483,8 +551,12 @@ struct __large_struct { unsigned long buf[100]; }; * Returns zero on success, or -EFAULT on error. */ @@ -15912,7 +17301,7 @@ index 5ee2687..70d5895 100644 #define __get_user_unaligned __get_user #define __put_user_unaligned __put_user -@@ -502,7 +560,7 @@ struct __large_struct { unsigned long buf[100]; }; +@@ -502,7 +574,7 @@ struct __large_struct { unsigned long buf[100]; }; #define get_user_ex(x, ptr) do { \ unsigned long __gue_val; \ __get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr)))); \ @@ -15921,7 +17310,7 @@ index 5ee2687..70d5895 100644 } while (0) #define put_user_try uaccess_try -@@ -519,8 +577,8 @@ strncpy_from_user(char *dst, const char __user *src, long count); +@@ -519,8 +591,8 @@ strncpy_from_user(char *dst, const char __user *src, long count); extern __must_check long strlen_user(const char __user *str); extern __must_check long strnlen_user(const char __user *str, long n); @@ -16567,12 +17956,14 @@ index d8d9922..bf6cecb 100644 extern struct x86_init_ops x86_init; extern struct x86_cpuinit_ops x86_cpuinit; diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h -index 0415cda..b43d877 100644 +index 0415cda..3b22adc 100644 --- a/arch/x86/include/asm/xsave.h +++ b/arch/x86/include/asm/xsave.h -@@ -71,7 +71,9 @@ static inline int xsave_user(struct xsave_struct __user *buf) +@@ -70,8 +70,11 @@ static inline int xsave_user(struct xsave_struct __user *buf) + if (unlikely(err)) return -EFAULT; ++ pax_open_userland(); __asm__ __volatile__(ASM_STAC "\n" - "1: .byte " REX_PREFIX "0x0f,0xae,0x27\n" + "1:" @@ -16581,7 +17972,14 @@ index 0415cda..b43d877 100644 "2: " ASM_CLAC "\n" ".section .fixup,\"ax\"\n" "3: movl $-1,%[err]\n" -@@ -87,12 +89,14 @@ static inline int xsave_user(struct xsave_struct __user *buf) +@@ -81,18 +84,22 @@ static inline int xsave_user(struct xsave_struct __user *buf) + : [err] "=r" (err) + : "D" (buf), "a" (-1), "d" (-1), "0" (0) + : "memory"); ++ pax_close_userland(); + return err; + } + static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) { int err; @@ -16590,6 +17988,7 @@ index 0415cda..b43d877 100644 u32 lmask = mask; u32 hmask = mask >> 32; ++ pax_open_userland(); __asm__ __volatile__(ASM_STAC "\n" - "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n" + "1:" @@ -16598,6 +17997,14 @@ index 0415cda..b43d877 100644 "2: " ASM_CLAC "\n" ".section .fixup,\"ax\"\n" "3: movl $-1,%[err]\n" +@@ -102,6 +109,7 @@ static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) + : [err] "=r" (err) + : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0) + : "memory"); /* memory required? */ ++ pax_close_userland(); + return err; + } + diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h index bbae024..e1528f9 100644 --- a/arch/x86/include/uapi/asm/e820.h @@ -17197,7 +18604,7 @@ index 5013a48..0782c53 100644 if (c->x86_model == 3 && c->x86_mask == 0) size = 64; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c -index 22018f7..bc6f5e3 100644 +index 22018f7..a5883af 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -88,60 +88,6 @@ static const struct cpu_dev __cpuinitconst default_cpu = { @@ -17261,7 +18668,48 @@ index 22018f7..bc6f5e3 100644 static int __init x86_xsave_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_XSAVE); -@@ -386,7 +332,7 @@ void switch_to_new_gdt(int cpu) +@@ -288,6 +234,40 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c) + set_in_cr4(X86_CR4_SMAP); + } + ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++static __init int setup_disable_pcid(char *arg) ++{ ++ setup_clear_cpu_cap(X86_FEATURE_PCID); ++ if (clone_pgd_mask != ~(pgdval_t)0UL) ++ pax_user_shadow_base = 1UL << TASK_SIZE_MAX_SHIFT; ++ return 1; ++} ++__setup("nopcid", setup_disable_pcid); ++ ++static void setup_pcid(struct cpuinfo_x86 *c) ++{ ++ if (cpu_has(c, X86_FEATURE_PCID)) ++ printk("PAX: PCID detected\n"); ++ ++ if (cpu_has(c, X86_FEATURE_INVPCID)) ++ printk("PAX: INVPCID detected\n"); ++ ++ if (cpu_has(c, X86_FEATURE_PCID)) { ++ set_in_cr4(X86_CR4_PCIDE); ++ clone_pgd_mask = ~(pgdval_t)0UL; ++ if (pax_user_shadow_base) ++ printk("PAX: weak UDEREF enabled\n"); ++ else { ++ set_cpu_cap(c, X86_FEATURE_STRONGUDEREF); ++ printk("PAX: strong UDEREF enabled\n"); ++ } ++ } else if (pax_user_shadow_base) ++ printk("PAX: slow and weak UDEREF enabled\n"); ++ else ++ printk("PAX: UDEREF disabled\n"); ++} ++#endif ++ + /* + * Some CPU features depend on higher CPUID levels, which may not always + * be available due to CPUID level capping or broken virtualization +@@ -386,7 +366,7 @@ void switch_to_new_gdt(int cpu) { struct desc_ptr gdt_descr; @@ -17270,7 +18718,18 @@ index 22018f7..bc6f5e3 100644 gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); /* Reload the per-cpu base */ -@@ -882,6 +828,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) +@@ -874,6 +854,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) + setup_smep(c); + setup_smap(c); + ++#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) ++ setup_pcid(c); ++#endif ++ + /* + * The vendor-specific functions might have changed features. + * Now we do "generic changes." +@@ -882,6 +866,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Filter out anything that depends on CPUID levels we don't have */ filter_cpuid_features(c, true); @@ -17281,7 +18740,7 @@ index 22018f7..bc6f5e3 100644 /* If the model name is still unset, do table lookup. */ if (!c->x86_model_id[0]) { const char *p; -@@ -1069,10 +1019,12 @@ static __init int setup_disablecpuid(char *arg) +@@ -1069,10 +1057,12 @@ static __init int setup_disablecpuid(char *arg) } __setup("clearcpuid=", setup_disablecpuid); @@ -17296,7 +18755,7 @@ index 22018f7..bc6f5e3 100644 DEFINE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union) __aligned(PAGE_SIZE); -@@ -1086,7 +1038,7 @@ DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned = +@@ -1086,7 +1076,7 @@ DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned = EXPORT_PER_CPU_SYMBOL(current_task); DEFINE_PER_CPU(unsigned long, kernel_stack) = @@ -17305,7 +18764,7 @@ index 22018f7..bc6f5e3 100644 EXPORT_PER_CPU_SYMBOL(kernel_stack); DEFINE_PER_CPU(char *, irq_stack_ptr) = -@@ -1231,7 +1183,7 @@ void __cpuinit cpu_init(void) +@@ -1231,7 +1221,7 @@ void __cpuinit cpu_init(void) load_ucode_ap(); cpu = stack_smp_processor_id(); @@ -17314,7 +18773,7 @@ index 22018f7..bc6f5e3 100644 oist = &per_cpu(orig_ist, cpu); #ifdef CONFIG_NUMA -@@ -1257,7 +1209,7 @@ void __cpuinit cpu_init(void) +@@ -1257,7 +1247,7 @@ void __cpuinit cpu_init(void) switch_to_new_gdt(cpu); loadsegment(fs, 0); @@ -17323,7 +18782,7 @@ index 22018f7..bc6f5e3 100644 memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); syscall_init(); -@@ -1266,7 +1218,6 @@ void __cpuinit cpu_init(void) +@@ -1266,7 +1256,6 @@ void __cpuinit cpu_init(void) wrmsrl(MSR_KERNEL_GS_BASE, 0); barrier(); @@ -17331,7 +18790,7 @@ index 22018f7..bc6f5e3 100644 enable_x2apic(); /* -@@ -1318,7 +1269,7 @@ void __cpuinit cpu_init(void) +@@ -1318,7 +1307,7 @@ void __cpuinit cpu_init(void) { int cpu = smp_processor_id(); struct task_struct *curr = current; @@ -18233,7 +19692,7 @@ index d15f575..d692043 100644 #include <asm/processor.h> #include <asm/fcntl.h> diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S -index 8f3e2de..caecc4e 100644 +index 8f3e2de..6b71e39 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -177,13 +177,153 @@ @@ -18743,6 +20202,15 @@ index 8f3e2de..caecc4e 100644 ENTRY(simd_coprocessor_error) RING0_INT_FRAME +@@ -826,7 +1065,7 @@ ENTRY(simd_coprocessor_error) + .section .altinstructions,"a" + altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f + .previous +-.section .altinstr_replacement,"ax" ++.section .altinstr_replacement,"a" + 663: pushl $do_simd_coprocessor_error + 664: + .previous @@ -835,7 +1074,7 @@ ENTRY(simd_coprocessor_error) #endif jmp error_code @@ -18993,7 +20461,7 @@ index 8f3e2de..caecc4e 100644 /* diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S -index 7272089..6204f9c5 100644 +index 7272089..833fdf8 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -59,6 +59,8 @@ @@ -19080,7 +20548,7 @@ index 7272089..6204f9c5 100644 #endif -@@ -284,6 +293,309 @@ ENTRY(native_usergs_sysret64) +@@ -284,6 +293,427 @@ ENTRY(native_usergs_sysret64) ENDPROC(native_usergs_sysret64) #endif /* CONFIG_PARAVIRT */ @@ -19100,18 +20568,19 @@ index 7272089..6204f9c5 100644 + + .macro pax_enter_kernel + pax_set_fptr_mask -+#ifdef CONFIG_PAX_KERNEXEC ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + call pax_enter_kernel +#endif + .endm + + .macro pax_exit_kernel -+#ifdef CONFIG_PAX_KERNEXEC ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + call pax_exit_kernel +#endif ++ + .endm + -+#ifdef CONFIG_PAX_KERNEXEC ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) +ENTRY(pax_enter_kernel) + pushq %rdi + @@ -19119,6 +20588,7 @@ index 7272089..6204f9c5 100644 + PV_SAVE_REGS(CLBR_RDI) +#endif + ++#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_RDI + bts $16,%rdi + jnc 3f @@ -19126,6 +20596,32 @@ index 7272089..6204f9c5 100644 + cmp $__KERNEL_CS,%edi + jnz 2f +1: ++#endif ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ 661: jmp 111f ++ .pushsection .altinstr_replacement, "a" ++ 662: ASM_NOP2 ++ .popsection ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 ++ .popsection ++ GET_CR3_INTO_RDI ++ cmp $0,%dil ++ jnz 112f ++ mov $__KERNEL_DS,%edi ++ mov %edi,%ss ++ jmp 111f ++112: cmp $1,%dil ++ jz 113f ++ ud2 ++113: sub $4097,%rdi ++ bts $63,%rdi ++ SET_RDI_INTO_CR3 ++ mov $__UDEREF_KERNEL_DS,%edi ++ mov %edi,%ss ++111: ++#endif + +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI) @@ -19135,10 +20631,12 @@ index 7272089..6204f9c5 100644 + pax_force_retaddr + retq + ++#ifdef CONFIG_PAX_KERNEXEC +2: ljmpq __KERNEL_CS,1b +3: ljmpq __KERNEXEC_KERNEL_CS,4f +4: SET_RDI_INTO_CR0 + jmp 1b ++#endif +ENDPROC(pax_enter_kernel) + +ENTRY(pax_exit_kernel) @@ -19148,6 +20646,7 @@ index 7272089..6204f9c5 100644 + PV_SAVE_REGS(CLBR_RDI) +#endif + ++#ifdef CONFIG_PAX_KERNEXEC + mov %cs,%rdi + cmp $__KERNEXEC_KERNEL_CS,%edi + jz 2f @@ -19155,6 +20654,30 @@ index 7272089..6204f9c5 100644 + bts $16,%rdi + jnc 4f +1: ++#endif ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ 661: jmp 111f ++ .pushsection .altinstr_replacement, "a" ++ 662: ASM_NOP2 ++ .popsection ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 ++ .popsection ++ mov %ss,%edi ++ cmp $__UDEREF_KERNEL_DS,%edi ++ jnz 111f ++ GET_CR3_INTO_RDI ++ cmp $0,%dil ++ jz 112f ++ ud2 ++112: add $4097,%rdi ++ bts $63,%rdi ++ SET_RDI_INTO_CR3 ++ mov $__KERNEL_DS,%edi ++ mov %edi,%ss ++111: ++#endif + +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI); @@ -19164,6 +20687,7 @@ index 7272089..6204f9c5 100644 + pax_force_retaddr + retq + ++#ifdef CONFIG_PAX_KERNEXEC +2: GET_CR0_INTO_RDI + btr $16,%rdi + jnc 4f @@ -19172,6 +20696,7 @@ index 7272089..6204f9c5 100644 + jmp 1b +4: ud2 + jmp 4b ++#endif +ENDPROC(pax_exit_kernel) +#endif + @@ -19204,6 +20729,21 @@ index 7272089..6204f9c5 100644 + PV_SAVE_REGS(CLBR_RDI) +#endif + ++ 661: jmp 111f ++ .pushsection .altinstr_replacement, "a" ++ 662: ASM_NOP2 ++ .popsection ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 ++ .popsection ++ GET_CR3_INTO_RDI ++ cmp $1,%dil ++ jnz 3f ++ sub $4097,%rdi ++ bts $63,%rdi ++ jmp 2f ++111: ++ + GET_CR3_INTO_RDI + mov %rdi,%rbx + add $__START_KERNEL_map,%rbx @@ -19232,17 +20772,14 @@ index 7272089..6204f9c5 100644 + i = i + 1 + .endr + -+#ifdef CONFIG_PARAVIRT -+2: -+#endif -+ SET_RDI_INTO_CR3 -+ +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_RDI + bts $16,%rdi + SET_RDI_INTO_CR0 +#endif + ++2: SET_RDI_INTO_CR3 ++ +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI) +#endif @@ -19251,6 +20788,7 @@ index 7272089..6204f9c5 100644 + popq %rdi + pax_force_retaddr + retq ++3: ud2 +ENDPROC(pax_enter_kernel_user) + +ENTRY(pax_exit_kernel_user) @@ -19261,14 +20799,21 @@ index 7272089..6204f9c5 100644 + PV_SAVE_REGS(CLBR_RDI) +#endif + -+#ifdef CONFIG_PAX_KERNEXEC -+ GET_CR0_INTO_RDI -+ btr $16,%rdi -+ jnc 3f -+ SET_RDI_INTO_CR0 -+#endif -+ + GET_CR3_INTO_RDI ++ 661: jmp 1f ++ .pushsection .altinstr_replacement, "a" ++ 662: ASM_NOP2 ++ .popsection ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 ++ .popsection ++ cmp $0,%dil ++ jnz 3f ++ add $4097,%rdi ++ bts $63,%rdi ++ SET_RDI_INTO_CR3 ++ jmp 2f ++1: + mov %rdi,%rbx + add $__START_KERNEL_map,%rbx + sub phys_base(%rip),%rbx @@ -19276,6 +20821,7 @@ index 7272089..6204f9c5 100644 +#ifdef CONFIG_PARAVIRT + cmpl $0, pv_info+PARAVIRT_enabled + jz 1f ++ pushq %rdi + i = 0 + .rept USER_PGD_PTRS + mov i*8(%rbx),%rsi @@ -19284,18 +20830,27 @@ index 7272089..6204f9c5 100644 + call PARA_INDIRECT(pv_mmu_ops+PV_MMU_set_pgd_batched) + i = i + 1 + .endr ++ popq %rdi + jmp 2f +1: +#endif + ++#ifdef CONFIG_PAX_KERNEXEC ++ GET_CR0_INTO_RDI ++ btr $16,%rdi ++ jnc 3f ++ SET_RDI_INTO_CR0 ++#endif ++ + i = 0 + .rept USER_PGD_PTRS + movb $0x67,i*8(%rbx) + i = i + 1 + .endr ++2: + +#ifdef CONFIG_PARAVIRT -+2: PV_RESTORE_REGS(CLBR_RDI) ++ PV_RESTORE_REGS(CLBR_RDI) +#endif + + popq %rbx @@ -19303,7 +20858,6 @@ index 7272089..6204f9c5 100644 + pax_force_retaddr + retq +3: ud2 -+ jmp 3b +ENDPROC(pax_exit_kernel_user) +#endif + @@ -19318,6 +20872,26 @@ index 7272089..6204f9c5 100644 + or $2,%ebx +110: +#endif ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ 661: jmp 111f ++ .pushsection .altinstr_replacement, "a" ++ 662: ASM_NOP2 ++ .popsection ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 ++ .popsection ++ GET_CR3_INTO_RDI ++ cmp $0,%dil ++ jz 111f ++ sub $4097,%rdi ++ or $4,%ebx ++ bts $63,%rdi ++ SET_RDI_INTO_CR3 ++ mov $__UDEREF_KERNEL_DS,%edi ++ mov %edi,%ss ++111: ++#endif + .endm + + .macro pax_exit_kernel_nmi @@ -19329,6 +20903,18 @@ index 7272089..6204f9c5 100644 + SET_RDI_INTO_CR0 +110: +#endif ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ btr $2,%ebx ++ jnc 111f ++ GET_CR3_INTO_RDI ++ add $4097,%rdi ++ bts $63,%rdi ++ SET_RDI_INTO_CR3 ++ mov $__KERNEL_DS,%edi ++ mov %edi,%ss ++111: ++#endif + .endm + + .macro pax_erase_kstack @@ -19390,7 +20976,7 @@ index 7272089..6204f9c5 100644 .macro TRACE_IRQS_IRETQ offset=ARGOFFSET #ifdef CONFIG_TRACE_IRQFLAGS -@@ -375,8 +687,8 @@ ENDPROC(native_usergs_sysret64) +@@ -375,8 +805,8 @@ ENDPROC(native_usergs_sysret64) .endm .macro UNFAKE_STACK_FRAME @@ -19401,7 +20987,7 @@ index 7272089..6204f9c5 100644 .endm /* -@@ -463,7 +775,7 @@ ENDPROC(native_usergs_sysret64) +@@ -463,7 +893,7 @@ ENDPROC(native_usergs_sysret64) movq %rsp, %rsi leaq -RBP(%rsp),%rdi /* arg1 for handler */ @@ -19410,7 +20996,7 @@ index 7272089..6204f9c5 100644 je 1f SWAPGS /* -@@ -498,9 +810,10 @@ ENTRY(save_rest) +@@ -498,9 +928,10 @@ ENTRY(save_rest) movq_cfi r15, R15+16 movq %r11, 8(%rsp) /* return address */ FIXUP_TOP_OF_STACK %r11, 16 @@ -19422,7 +21008,7 @@ index 7272089..6204f9c5 100644 /* save complete stack frame */ .pushsection .kprobes.text, "ax" -@@ -529,9 +842,10 @@ ENTRY(save_paranoid) +@@ -529,9 +960,10 @@ ENTRY(save_paranoid) js 1f /* negative -> in kernel */ SWAPGS xorl %ebx,%ebx @@ -19435,7 +21021,7 @@ index 7272089..6204f9c5 100644 .popsection /* -@@ -553,7 +867,7 @@ ENTRY(ret_from_fork) +@@ -553,7 +985,7 @@ ENTRY(ret_from_fork) RESTORE_REST @@ -19444,7 +21030,7 @@ index 7272089..6204f9c5 100644 jz 1f testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET -@@ -571,7 +885,7 @@ ENTRY(ret_from_fork) +@@ -571,7 +1003,7 @@ ENTRY(ret_from_fork) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC @@ -19453,7 +21039,7 @@ index 7272089..6204f9c5 100644 /* * System call entry. Up to 6 arguments in registers are supported. -@@ -608,7 +922,7 @@ END(ret_from_fork) +@@ -608,7 +1040,7 @@ END(ret_from_fork) ENTRY(system_call) CFI_STARTPROC simple CFI_SIGNAL_FRAME @@ -19462,7 +21048,7 @@ index 7272089..6204f9c5 100644 CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ SWAPGS_UNSAFE_STACK -@@ -621,16 +935,23 @@ GLOBAL(system_call_after_swapgs) +@@ -621,16 +1053,23 @@ GLOBAL(system_call_after_swapgs) movq %rsp,PER_CPU_VAR(old_rsp) movq PER_CPU_VAR(kernel_stack),%rsp @@ -19488,7 +21074,7 @@ index 7272089..6204f9c5 100644 jnz tracesys system_call_fastpath: #if __SYSCALL_MASK == ~0 -@@ -640,7 +961,7 @@ system_call_fastpath: +@@ -640,7 +1079,7 @@ system_call_fastpath: cmpl $__NR_syscall_max,%eax #endif ja badsys @@ -19497,7 +21083,7 @@ index 7272089..6204f9c5 100644 call *sys_call_table(,%rax,8) # XXX: rip relative movq %rax,RAX-ARGOFFSET(%rsp) /* -@@ -654,10 +975,13 @@ sysret_check: +@@ -654,10 +1093,13 @@ sysret_check: LOCKDEP_SYS_EXIT DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF @@ -19512,7 +21098,7 @@ index 7272089..6204f9c5 100644 /* * sysretq will re-enable interrupts: */ -@@ -709,14 +1033,18 @@ badsys: +@@ -709,14 +1151,18 @@ badsys: * jump back to the normal fast path. */ auditsys: @@ -19532,7 +21118,7 @@ index 7272089..6204f9c5 100644 jmp system_call_fastpath /* -@@ -737,7 +1065,7 @@ sysret_audit: +@@ -737,7 +1183,7 @@ sysret_audit: /* Do syscall tracing */ tracesys: #ifdef CONFIG_AUDITSYSCALL @@ -19541,7 +21127,7 @@ index 7272089..6204f9c5 100644 jz auditsys #endif SAVE_REST -@@ -745,12 +1073,16 @@ tracesys: +@@ -745,12 +1191,16 @@ tracesys: FIXUP_TOP_OF_STACK %rdi movq %rsp,%rdi call syscall_trace_enter @@ -19558,7 +21144,7 @@ index 7272089..6204f9c5 100644 RESTORE_REST #if __SYSCALL_MASK == ~0 cmpq $__NR_syscall_max,%rax -@@ -759,7 +1091,7 @@ tracesys: +@@ -759,7 +1209,7 @@ tracesys: cmpl $__NR_syscall_max,%eax #endif ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */ @@ -19567,7 +21153,7 @@ index 7272089..6204f9c5 100644 call *sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) /* Use IRET because user could have changed frame */ -@@ -780,7 +1112,9 @@ GLOBAL(int_with_check) +@@ -780,7 +1230,9 @@ GLOBAL(int_with_check) andl %edi,%edx jnz int_careful andl $~TS_COMPAT,TI_status(%rcx) @@ -19578,7 +21164,7 @@ index 7272089..6204f9c5 100644 /* Either reschedule or signal or syscall exit tracking needed. */ /* First do a reschedule test. */ -@@ -826,7 +1160,7 @@ int_restore_rest: +@@ -826,7 +1278,7 @@ int_restore_rest: TRACE_IRQS_OFF jmp int_with_check CFI_ENDPROC @@ -19587,7 +21173,7 @@ index 7272089..6204f9c5 100644 .macro FORK_LIKE func ENTRY(stub_\func) -@@ -839,9 +1173,10 @@ ENTRY(stub_\func) +@@ -839,9 +1291,10 @@ ENTRY(stub_\func) DEFAULT_FRAME 0 8 /* offset 8: return address */ call sys_\func RESTORE_TOP_OF_STACK %r11, 8 @@ -19599,7 +21185,7 @@ index 7272089..6204f9c5 100644 .endm .macro FIXED_FRAME label,func -@@ -851,9 +1186,10 @@ ENTRY(\label) +@@ -851,9 +1304,10 @@ ENTRY(\label) FIXUP_TOP_OF_STACK %r11, 8-ARGOFFSET call \func RESTORE_TOP_OF_STACK %r11, 8-ARGOFFSET @@ -19611,7 +21197,7 @@ index 7272089..6204f9c5 100644 .endm FORK_LIKE clone -@@ -870,9 +1206,10 @@ ENTRY(ptregscall_common) +@@ -870,9 +1324,10 @@ ENTRY(ptregscall_common) movq_cfi_restore R12+8, r12 movq_cfi_restore RBP+8, rbp movq_cfi_restore RBX+8, rbx @@ -19623,7 +21209,7 @@ index 7272089..6204f9c5 100644 ENTRY(stub_execve) CFI_STARTPROC -@@ -885,7 +1222,7 @@ ENTRY(stub_execve) +@@ -885,7 +1340,7 @@ ENTRY(stub_execve) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC @@ -19632,7 +21218,7 @@ index 7272089..6204f9c5 100644 /* * sigreturn is special because it needs to restore all registers on return. -@@ -902,7 +1239,7 @@ ENTRY(stub_rt_sigreturn) +@@ -902,7 +1357,7 @@ ENTRY(stub_rt_sigreturn) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC @@ -19641,7 +21227,7 @@ index 7272089..6204f9c5 100644 #ifdef CONFIG_X86_X32_ABI ENTRY(stub_x32_rt_sigreturn) -@@ -916,7 +1253,7 @@ ENTRY(stub_x32_rt_sigreturn) +@@ -916,7 +1371,7 @@ ENTRY(stub_x32_rt_sigreturn) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC @@ -19650,7 +21236,7 @@ index 7272089..6204f9c5 100644 ENTRY(stub_x32_execve) CFI_STARTPROC -@@ -930,7 +1267,7 @@ ENTRY(stub_x32_execve) +@@ -930,7 +1385,7 @@ ENTRY(stub_x32_execve) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC @@ -19659,7 +21245,7 @@ index 7272089..6204f9c5 100644 #endif -@@ -967,7 +1304,7 @@ vector=vector+1 +@@ -967,7 +1422,7 @@ vector=vector+1 2: jmp common_interrupt .endr CFI_ENDPROC @@ -19668,7 +21254,7 @@ index 7272089..6204f9c5 100644 .previous END(interrupt) -@@ -987,6 +1324,16 @@ END(interrupt) +@@ -987,6 +1442,16 @@ END(interrupt) subq $ORIG_RAX-RBP, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP SAVE_ARGS_IRQ @@ -19685,7 +21271,7 @@ index 7272089..6204f9c5 100644 call \func .endm -@@ -1019,7 +1366,7 @@ ret_from_intr: +@@ -1019,7 +1484,7 @@ ret_from_intr: exit_intr: GET_THREAD_INFO(%rcx) @@ -19694,7 +21280,7 @@ index 7272089..6204f9c5 100644 je retint_kernel /* Interrupt came from user space */ -@@ -1041,12 +1388,16 @@ retint_swapgs: /* return to user-space */ +@@ -1041,12 +1506,16 @@ retint_swapgs: /* return to user-space */ * The iretq could re-enable interrupts: */ DISABLE_INTERRUPTS(CLBR_ANY) @@ -19711,7 +21297,7 @@ index 7272089..6204f9c5 100644 /* * The iretq could re-enable interrupts: */ -@@ -1129,7 +1480,7 @@ ENTRY(retint_kernel) +@@ -1129,7 +1598,7 @@ ENTRY(retint_kernel) #endif CFI_ENDPROC @@ -19720,7 +21306,7 @@ index 7272089..6204f9c5 100644 /* * End of kprobes section */ -@@ -1147,7 +1498,7 @@ ENTRY(\sym) +@@ -1147,7 +1616,7 @@ ENTRY(\sym) interrupt \do_sym jmp ret_from_intr CFI_ENDPROC @@ -19729,7 +21315,7 @@ index 7272089..6204f9c5 100644 .endm #ifdef CONFIG_SMP -@@ -1208,12 +1559,22 @@ ENTRY(\sym) +@@ -1208,12 +1677,22 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call error_entry DEFAULT_FRAME 0 @@ -19753,7 +21339,7 @@ index 7272089..6204f9c5 100644 .endm .macro paranoidzeroentry sym do_sym -@@ -1226,15 +1587,25 @@ ENTRY(\sym) +@@ -1226,15 +1705,25 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call save_paranoid TRACE_IRQS_OFF @@ -19781,7 +21367,7 @@ index 7272089..6204f9c5 100644 .macro paranoidzeroentry_ist sym do_sym ist ENTRY(\sym) INTR_FRAME -@@ -1245,14 +1616,30 @@ ENTRY(\sym) +@@ -1245,14 +1734,30 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call save_paranoid TRACE_IRQS_OFF_DEBUG @@ -19813,7 +21399,7 @@ index 7272089..6204f9c5 100644 .endm .macro errorentry sym do_sym -@@ -1264,13 +1651,23 @@ ENTRY(\sym) +@@ -1264,13 +1769,23 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call error_entry DEFAULT_FRAME 0 @@ -19838,7 +21424,7 @@ index 7272089..6204f9c5 100644 .endm /* error code is on the stack already */ -@@ -1284,13 +1681,23 @@ ENTRY(\sym) +@@ -1284,13 +1799,23 @@ ENTRY(\sym) call save_paranoid DEFAULT_FRAME 0 TRACE_IRQS_OFF @@ -19863,7 +21449,7 @@ index 7272089..6204f9c5 100644 .endm zeroentry divide_error do_divide_error -@@ -1320,9 +1727,10 @@ gs_change: +@@ -1320,9 +1845,10 @@ gs_change: 2: mfence /* workaround */ SWAPGS popfq_cfi @@ -19875,7 +21461,7 @@ index 7272089..6204f9c5 100644 _ASM_EXTABLE(gs_change,bad_gs) .section .fixup,"ax" -@@ -1350,9 +1758,10 @@ ENTRY(call_softirq) +@@ -1350,9 +1876,10 @@ ENTRY(call_softirq) CFI_DEF_CFA_REGISTER rsp CFI_ADJUST_CFA_OFFSET -8 decl PER_CPU_VAR(irq_count) @@ -19887,7 +21473,7 @@ index 7272089..6204f9c5 100644 #ifdef CONFIG_XEN zeroentry xen_hypervisor_callback xen_do_hypervisor_callback -@@ -1390,7 +1799,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) +@@ -1390,7 +1917,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) decl PER_CPU_VAR(irq_count) jmp error_exit CFI_ENDPROC @@ -19896,7 +21482,7 @@ index 7272089..6204f9c5 100644 /* * Hypervisor uses this for application faults while it executes. -@@ -1449,7 +1858,7 @@ ENTRY(xen_failsafe_callback) +@@ -1449,7 +1976,7 @@ ENTRY(xen_failsafe_callback) SAVE_ALL jmp error_exit CFI_ENDPROC @@ -19905,7 +21491,7 @@ index 7272089..6204f9c5 100644 apicinterrupt HYPERVISOR_CALLBACK_VECTOR \ xen_hvm_callback_vector xen_evtchn_do_upcall -@@ -1501,18 +1910,33 @@ ENTRY(paranoid_exit) +@@ -1501,18 +2028,33 @@ ENTRY(paranoid_exit) DEFAULT_FRAME DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF_DEBUG @@ -19941,7 +21527,7 @@ index 7272089..6204f9c5 100644 jmp irq_return paranoid_userspace: GET_THREAD_INFO(%rcx) -@@ -1541,7 +1965,7 @@ paranoid_schedule: +@@ -1541,7 +2083,7 @@ paranoid_schedule: TRACE_IRQS_OFF jmp paranoid_userspace CFI_ENDPROC @@ -19950,7 +21536,7 @@ index 7272089..6204f9c5 100644 /* * Exception entry point. This expects an error code/orig_rax on the stack. -@@ -1568,12 +1992,13 @@ ENTRY(error_entry) +@@ -1568,12 +2110,13 @@ ENTRY(error_entry) movq_cfi r14, R14+8 movq_cfi r15, R15+8 xorl %ebx,%ebx @@ -19965,7 +21551,7 @@ index 7272089..6204f9c5 100644 ret /* -@@ -1600,7 +2025,7 @@ bstep_iret: +@@ -1600,7 +2143,7 @@ bstep_iret: movq %rcx,RIP+8(%rsp) jmp error_swapgs CFI_ENDPROC @@ -19974,7 +21560,7 @@ index 7272089..6204f9c5 100644 /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */ -@@ -1611,7 +2036,7 @@ ENTRY(error_exit) +@@ -1611,7 +2154,7 @@ ENTRY(error_exit) DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF GET_THREAD_INFO(%rcx) @@ -19983,7 +21569,7 @@ index 7272089..6204f9c5 100644 jne retint_kernel LOCKDEP_SYS_EXIT_IRQ movl TI_flags(%rcx),%edx -@@ -1620,7 +2045,7 @@ ENTRY(error_exit) +@@ -1620,7 +2163,7 @@ ENTRY(error_exit) jnz retint_careful jmp retint_swapgs CFI_ENDPROC @@ -19992,7 +21578,7 @@ index 7272089..6204f9c5 100644 /* * Test if a given stack is an NMI stack or not. -@@ -1678,9 +2103,11 @@ ENTRY(nmi) +@@ -1678,9 +2221,11 @@ ENTRY(nmi) * If %cs was not the kernel segment, then the NMI triggered in user * space, which means it is definitely not nested. */ @@ -20005,7 +21591,7 @@ index 7272089..6204f9c5 100644 /* * Check the special variable on the stack to see if NMIs are * executing. -@@ -1714,8 +2141,7 @@ nested_nmi: +@@ -1714,8 +2259,7 @@ nested_nmi: 1: /* Set up the interrupted NMIs stack to jump to repeat_nmi */ @@ -20015,7 +21601,7 @@ index 7272089..6204f9c5 100644 CFI_ADJUST_CFA_OFFSET 1*8 leaq -10*8(%rsp), %rdx pushq_cfi $__KERNEL_DS -@@ -1733,6 +2159,7 @@ nested_nmi_out: +@@ -1733,6 +2277,7 @@ nested_nmi_out: CFI_RESTORE rdx /* No need to check faults here */ @@ -20023,7 +21609,7 @@ index 7272089..6204f9c5 100644 INTERRUPT_RETURN CFI_RESTORE_STATE -@@ -1849,6 +2276,8 @@ end_repeat_nmi: +@@ -1849,6 +2394,8 @@ end_repeat_nmi: */ movq %cr2, %r12 @@ -20032,7 +21618,7 @@ index 7272089..6204f9c5 100644 /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */ movq %rsp,%rdi movq $-1,%rsi -@@ -1861,26 +2290,31 @@ end_repeat_nmi: +@@ -1861,26 +2408,31 @@ end_repeat_nmi: movq %r12, %cr2 1: @@ -20188,7 +21774,7 @@ index 55b6761..a6456fc 100644 init_level4_pgt[511] = early_level4_pgt[511]; diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S -index 73afd11..d1670f5 100644 +index 73afd11..0ef46f2 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -26,6 +26,12 @@ @@ -20509,7 +22095,7 @@ index 73afd11..d1670f5 100644 + +#ifdef CONFIG_PAX_PER_CPU_PGD +ENTRY(cpu_pgd) -+ .rept NR_CPUS ++ .rept 2*NR_CPUS + .fill 4,8,0 + .endr +#endif @@ -20620,7 +22206,7 @@ index 73afd11..d1670f5 100644 + .fill PAGE_SIZE_asm - GDT_SIZE,1,0 + .endr diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S -index a836860..bdeb7a5 100644 +index a836860..1b5c665 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -20,6 +20,8 @@ @@ -20755,7 +22341,7 @@ index a836860..bdeb7a5 100644 +#ifdef CONFIG_PAX_PER_CPU_PGD +NEXT_PAGE(cpu_pgd) -+ .rept NR_CPUS ++ .rept 2*NR_CPUS + .fill 512,8,0 + .endr +#endif @@ -20800,7 +22386,7 @@ index a836860..bdeb7a5 100644 NEXT_PAGE(level2_kernel_pgt) /* * 512 MB kernel mapping. We spend a full page on this pagetable -@@ -488,39 +544,64 @@ NEXT_PAGE(level2_kernel_pgt) +@@ -488,39 +544,70 @@ NEXT_PAGE(level2_kernel_pgt) KERNEL_IMAGE_SIZE/PMD_SIZE) NEXT_PAGE(level2_fixmap_pgt) @@ -20843,6 +22429,12 @@ index a836860..bdeb7a5 100644 + .quad 0x0000f40000000000 /* node/CPU stored in limit */ + /* asm/segment.h:GDT_ENTRIES must match this */ + ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ .quad 0x00cf93000000ffff /* __UDEREF_KERNEL_DS */ ++#else ++ .quad 0x0 /* unused */ ++#endif ++ + /* zero the remaining page */ + .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0 + .endr @@ -20906,7 +22498,7 @@ index 0fa6912..37fce70 100644 +EXPORT_SYMBOL(__LOAD_PHYSICAL_ADDR); +#endif diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c -index cb33909..1163b40 100644 +index f7ea30d..6318acc 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -51,7 +51,7 @@ static inline bool interrupted_kernel_fpu_idle(void) @@ -22278,7 +23870,7 @@ index 7305f7d..22f73d6 100644 } - diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c -index 355ae06..4530766 100644 +index 355ae06..560fbbe 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -151,10 +151,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, @@ -22294,7 +23886,16 @@ index 355ae06..4530766 100644 set_tsk_thread_flag(p, TIF_FORK); p->fpu_counter = 0; p->thread.io_bitmap_ptr = NULL; -@@ -273,7 +274,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) +@@ -165,6 +166,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, + p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; + savesegment(es, p->thread.es); + savesegment(ds, p->thread.ds); ++ savesegment(ss, p->thread.ss); ++ BUG_ON(p->thread.ss == __UDEREF_KERNEL_DS); + memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); + + if (unlikely(p->flags & PF_KTHREAD)) { +@@ -273,7 +276,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) struct thread_struct *prev = &prev_p->thread; struct thread_struct *next = &next_p->thread; int cpu = smp_processor_id(); @@ -22303,7 +23904,17 @@ index 355ae06..4530766 100644 unsigned fsindex, gsindex; fpu_switch_t fpu; -@@ -355,10 +356,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) +@@ -296,6 +299,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + if (unlikely(next->ds | prev->ds)) + loadsegment(ds, next->ds); + ++ savesegment(ss, prev->ss); ++ if (unlikely(next->ss != prev->ss)) ++ loadsegment(ss, next->ss); + + /* We must save %fs and %gs before load_TLS() because + * %fs and %gs may be cleared by load_TLS(). +@@ -355,10 +361,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) prev->usersp = this_cpu_read(old_rsp); this_cpu_write(old_rsp, next->usersp); this_cpu_write(current_task, next_p); @@ -22316,7 +23927,7 @@ index 355ae06..4530766 100644 /* * Now maybe reload the debug registers and handle I/O bitmaps -@@ -427,12 +427,11 @@ unsigned long get_wchan(struct task_struct *p) +@@ -427,12 +432,11 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); @@ -22637,7 +24248,7 @@ index f2bb9c9..bed145d7 100644 1: diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 56f7fcf..fa229f4 100644 +index 56f7fcf..3b88ad1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -110,6 +110,7 @@ @@ -22648,7 +24259,23 @@ index 56f7fcf..fa229f4 100644 /* * max_low_pfn_mapped: highest direct mapped pfn under 4GB -@@ -444,7 +445,7 @@ static void __init parse_setup_data(void) +@@ -205,10 +206,12 @@ EXPORT_SYMBOL(boot_cpu_data); + #endif + + +-#if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64) +-unsigned long mmu_cr4_features; ++#ifdef CONFIG_X86_64 ++unsigned long mmu_cr4_features __read_only = X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE; ++#elif defined(CONFIG_X86_PAE) ++unsigned long mmu_cr4_features __read_only = X86_CR4_PAE; + #else +-unsigned long mmu_cr4_features = X86_CR4_PAE; ++unsigned long mmu_cr4_features __read_only; + #endif + + /* Boot loader ID and version as integers, for the benefit of proc_dointvec */ +@@ -444,7 +447,7 @@ static void __init parse_setup_data(void) switch (data->type) { case SETUP_E820_EXT: @@ -22657,7 +24284,7 @@ index 56f7fcf..fa229f4 100644 break; case SETUP_DTB: add_dtb(pa_data); -@@ -771,7 +772,7 @@ static void __init trim_bios_range(void) +@@ -771,7 +774,7 @@ static void __init trim_bios_range(void) * area (640->1Mb) as ram even though it is not. * take them out. */ @@ -22666,7 +24293,7 @@ index 56f7fcf..fa229f4 100644 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } -@@ -779,7 +780,7 @@ static void __init trim_bios_range(void) +@@ -779,7 +782,7 @@ static void __init trim_bios_range(void) /* called before trim_bios_range() to spare extra sanitize */ static void __init e820_add_kernel_range(void) { @@ -22675,7 +24302,7 @@ index 56f7fcf..fa229f4 100644 u64 size = __pa_symbol(_end) - start; /* -@@ -841,8 +842,12 @@ static void __init trim_low_memory_range(void) +@@ -841,8 +844,12 @@ static void __init trim_low_memory_range(void) void __init setup_arch(char **cmdline_p) { @@ -22688,7 +24315,7 @@ index 56f7fcf..fa229f4 100644 early_reserve_initrd(); -@@ -934,14 +939,14 @@ void __init setup_arch(char **cmdline_p) +@@ -934,14 +941,14 @@ void __init setup_arch(char **cmdline_p) if (!boot_params.hdr.root_flags) root_mountflags &= ~MS_RDONLY; @@ -22785,7 +24412,7 @@ index 5cdff03..80fa283 100644 * Up to this point, the boot CPU has been using .init.data * area. Reload any changed state for the boot CPU. diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c -index 6956299..f20beae 100644 +index 6956299..18126ec4 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -196,7 +196,7 @@ static unsigned long align_sigframe(unsigned long sp) @@ -22818,8 +24445,12 @@ index 6956299..f20beae 100644 if (err) return -EFAULT; -@@ -367,7 +367,10 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, - err |= __save_altstack(&frame->uc.uc_stack, regs->sp); +@@ -364,10 +364,13 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); +- err |= __save_altstack(&frame->uc.uc_stack, regs->sp); ++ __save_altstack_ex(&frame->uc.uc_stack, regs->sp); /* Set up to return from userspace. */ - restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); @@ -22839,6 +24470,15 @@ index 6956299..f20beae 100644 } put_user_catch(err); err |= copy_siginfo_to_user(&frame->info, &ksig->info); +@@ -429,7 +432,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, + else + put_user_ex(0, &frame->uc.uc_flags); + put_user_ex(0, &frame->uc.uc_link); +- err |= __save_altstack(&frame->uc.uc_stack, regs->sp); ++ __save_altstack_ex(&frame->uc.uc_stack, regs->sp); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ @@ -615,7 +618,12 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) { int usig = signr_convert(ksig->sig); @@ -22876,10 +24516,35 @@ index 48d2b7d..90d328a 100644 .smp_prepare_cpus = native_smp_prepare_cpus, .smp_cpus_done = native_smp_cpus_done, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c -index bfd348e..4816ad8 100644 +index bfd348e..f0c1bf2 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c -@@ -748,6 +748,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) +@@ -251,14 +251,18 @@ notrace static void __cpuinit start_secondary(void *unused) + + enable_start_cpu0 = 0; + +-#ifdef CONFIG_X86_32 +- /* switch away from the initial page table */ +- load_cr3(swapper_pg_dir); +- __flush_tlb_all(); +-#endif +- + /* otherwise gcc will move up smp_processor_id before the cpu_init */ + barrier(); ++ ++ /* switch away from the initial page table */ ++#ifdef CONFIG_PAX_PER_CPU_PGD ++ load_cr3(get_cpu_pgd(smp_processor_id(), kernel)); ++ __flush_tlb_all(); ++#elif defined(CONFIG_X86_32) ++ load_cr3(swapper_pg_dir); ++ __flush_tlb_all(); ++#endif ++ + /* + * Check TSC synchronization with the BP: + */ +@@ -748,6 +752,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) idle->thread.sp = (unsigned long) (((struct pt_regs *) (THREAD_SIZE + task_stack_page(idle))) - 1); per_cpu(current_task, cpu) = idle; @@ -22887,7 +24552,7 @@ index bfd348e..4816ad8 100644 #ifdef CONFIG_X86_32 /* Stack for startup_32 can be just as for start_secondary onwards */ -@@ -755,11 +756,13 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) +@@ -755,11 +760,13 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) #else clear_tsk_thread_flag(idle, TIF_FORK); initial_gs = per_cpu_offset(cpu); @@ -22904,12 +24569,15 @@ index bfd348e..4816ad8 100644 initial_code = (unsigned long)start_secondary; stack_start = idle->thread.sp; -@@ -908,6 +911,15 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) +@@ -908,6 +915,18 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) /* the FPU context is blank, nobody can own it */ __cpu_disable_lazy_restore(cpu); +#ifdef CONFIG_PAX_PER_CPU_PGD -+ clone_pgd_range(get_cpu_pgd(cpu) + KERNEL_PGD_BOUNDARY, ++ clone_pgd_range(get_cpu_pgd(cpu, kernel) + KERNEL_PGD_BOUNDARY, ++ swapper_pg_dir + KERNEL_PGD_BOUNDARY, ++ KERNEL_PGD_PTRS); ++ clone_pgd_range(get_cpu_pgd(cpu, user) + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); +#endif @@ -25213,27 +26881,43 @@ index 176cca6..1166c50 100644 .byte (copy_page_rep - copy_page) - (2f - 1b) /* offset */ 2: diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S -index a30ca15..d25fab6 100644 +index a30ca15..6b3f4e1 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S -@@ -18,6 +18,7 @@ +@@ -18,31 +18,7 @@ #include <asm/alternative-asm.h> #include <asm/asm.h> #include <asm/smap.h> +- +-/* +- * By placing feature2 after feature1 in altinstructions section, we logically +- * implement: +- * If CPU has feature2, jmp to alt2 is used +- * else if CPU has feature1, jmp to alt1 is used +- * else jmp to orig is used. +- */ +- .macro ALTERNATIVE_JUMP feature1,feature2,orig,alt1,alt2 +-0: +- .byte 0xe9 /* 32bit jump */ +- .long \orig-1f /* by default jump to orig */ +-1: +- .section .altinstr_replacement,"ax" +-2: .byte 0xe9 /* near jump with 32bit immediate */ +- .long \alt1-1b /* offset */ /* or alternatively to alt1 */ +-3: .byte 0xe9 /* near jump with 32bit immediate */ +- .long \alt2-1b /* offset */ /* or alternatively to alt2 */ +- .previous +- +- .section .altinstructions,"a" +- altinstruction_entry 0b,2b,\feature1,5,5 +- altinstruction_entry 0b,3b,\feature2,5,5 +- .previous +- .endm +#include <asm/pgtable.h> - /* - * By placing feature2 after feature1 in altinstructions section, we logically -@@ -31,7 +32,7 @@ - .byte 0xe9 /* 32bit jump */ - .long \orig-1f /* by default jump to orig */ - 1: -- .section .altinstr_replacement,"ax" -+ .section .altinstr_replacement,"a" - 2: .byte 0xe9 /* near jump with 32bit immediate */ - .long \alt1-1b /* offset */ /* or alternatively to alt1 */ - 3: .byte 0xe9 /* near jump with 32bit immediate */ -@@ -70,47 +71,20 @@ + .macro ALIGN_DESTINATION + #ifdef FIX_ALIGNMENT +@@ -70,52 +46,6 @@ #endif .endm @@ -25267,24 +26951,34 @@ index a30ca15..d25fab6 100644 - CFI_ENDPROC -ENDPROC(_copy_from_user) - - .section .fixup,"ax" - /* must zero dest */ - ENTRY(bad_from_user) - bad_from_user: +- .section .fixup,"ax" +- /* must zero dest */ +-ENTRY(bad_from_user) +-bad_from_user: +- CFI_STARTPROC +- movl %edx,%ecx +- xorl %eax,%eax +- rep +- stosb +-bad_to_user: +- movl %edx,%eax +- ret +- CFI_ENDPROC +-ENDPROC(bad_from_user) +- .previous +- + /* + * copy_user_generic_unrolled - memory copy with exception handling. + * This version is for CPUs like P4 that don't have efficient micro +@@ -131,6 +61,7 @@ ENDPROC(bad_from_user) + */ + ENTRY(copy_user_generic_unrolled) CFI_STARTPROC -+ testl %edx,%edx -+ js bad_to_user - movl %edx,%ecx - xorl %eax,%eax - rep - stosb - bad_to_user: - movl %edx,%eax -+ pax_force_retaddr - ret - CFI_ENDPROC - ENDPROC(bad_from_user) -@@ -141,19 +115,19 @@ ENTRY(copy_user_generic_unrolled) ++ ASM_PAX_OPEN_USERLAND + ASM_STAC + cmpl $8,%edx + jb 20f /* less then 8 bytes, go to byte copy loop */ +@@ -141,19 +72,19 @@ ENTRY(copy_user_generic_unrolled) jz 17f 1: movq (%rsi),%r8 2: movq 1*8(%rsi),%r9 @@ -25308,32 +27002,51 @@ index a30ca15..d25fab6 100644 16: movq %r11,7*8(%rdi) leaq 64(%rsi),%rsi leaq 64(%rdi),%rdi -@@ -180,6 +154,7 @@ ENTRY(copy_user_generic_unrolled) +@@ -180,6 +111,8 @@ ENTRY(copy_user_generic_unrolled) jnz 21b 23: xor %eax,%eax ASM_CLAC ++ ASM_PAX_CLOSE_USERLAND + pax_force_retaddr ret .section .fixup,"ax" -@@ -251,6 +226,7 @@ ENTRY(copy_user_generic_string) +@@ -235,6 +168,7 @@ ENDPROC(copy_user_generic_unrolled) + */ + ENTRY(copy_user_generic_string) + CFI_STARTPROC ++ ASM_PAX_OPEN_USERLAND + ASM_STAC + andl %edx,%edx + jz 4f +@@ -251,6 +185,8 @@ ENTRY(copy_user_generic_string) movsb 4: xorl %eax,%eax ASM_CLAC ++ ASM_PAX_CLOSE_USERLAND + pax_force_retaddr ret .section .fixup,"ax" -@@ -286,6 +262,7 @@ ENTRY(copy_user_enhanced_fast_string) +@@ -278,6 +214,7 @@ ENDPROC(copy_user_generic_string) + */ + ENTRY(copy_user_enhanced_fast_string) + CFI_STARTPROC ++ ASM_PAX_OPEN_USERLAND + ASM_STAC + andl %edx,%edx + jz 2f +@@ -286,6 +223,8 @@ ENTRY(copy_user_enhanced_fast_string) movsb 2: xorl %eax,%eax ASM_CLAC ++ ASM_PAX_CLOSE_USERLAND + pax_force_retaddr ret .section .fixup,"ax" diff --git a/arch/x86/lib/copy_user_nocache_64.S b/arch/x86/lib/copy_user_nocache_64.S -index 6a4f43c..f08b4a2 100644 +index 6a4f43c..55d26f2 100644 --- a/arch/x86/lib/copy_user_nocache_64.S +++ b/arch/x86/lib/copy_user_nocache_64.S @@ -8,6 +8,7 @@ @@ -25352,7 +27065,7 @@ index 6a4f43c..f08b4a2 100644 .macro ALIGN_DESTINATION #ifdef FIX_ALIGNMENT -@@ -49,6 +51,15 @@ +@@ -49,6 +51,16 @@ */ ENTRY(__copy_user_nocache) CFI_STARTPROC @@ -25365,10 +27078,11 @@ index 6a4f43c..f08b4a2 100644 +1: +#endif + ++ ASM_PAX_OPEN_USERLAND ASM_STAC cmpl $8,%edx jb 20f /* less then 8 bytes, go to byte copy loop */ -@@ -59,19 +70,19 @@ ENTRY(__copy_user_nocache) +@@ -59,19 +71,19 @@ ENTRY(__copy_user_nocache) jz 17f 1: movq (%rsi),%r8 2: movq 1*8(%rsi),%r9 @@ -25392,9 +27106,11 @@ index 6a4f43c..f08b4a2 100644 16: movnti %r11,7*8(%rdi) leaq 64(%rsi),%rsi leaq 64(%rdi),%rdi -@@ -99,6 +110,7 @@ ENTRY(__copy_user_nocache) +@@ -98,7 +110,9 @@ ENTRY(__copy_user_nocache) + jnz 21b 23: xorl %eax,%eax ASM_CLAC ++ ASM_PAX_CLOSE_USERLAND sfence + pax_force_retaddr ret @@ -25421,27 +27137,38 @@ index 2419d5f..953ee51 100644 CFI_RESTORE_STATE diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c -index 25b7ae8..169fafc 100644 +index 25b7ae8..c40113e 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c -@@ -52,7 +52,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, +@@ -52,8 +52,12 @@ csum_partial_copy_from_user(const void __user *src, void *dst, len -= 2; } } - isum = csum_partial_copy_generic((__force const void *)src, ++ pax_open_userland(); ++ stac(); + isum = csum_partial_copy_generic((const void __force_kernel *)____m(src), dst, len, isum, errp, NULL); ++ clac(); ++ pax_close_userland(); if (unlikely(*errp)) goto out_err; -@@ -105,7 +105,7 @@ csum_partial_copy_to_user(const void *src, void __user *dst, + +@@ -105,8 +109,13 @@ csum_partial_copy_to_user(const void *src, void __user *dst, } *errp = 0; - return csum_partial_copy_generic(src, (void __force *)dst, -+ return csum_partial_copy_generic(src, (void __force_kernel *)____m(dst), ++ pax_open_userland(); ++ stac(); ++ isum = csum_partial_copy_generic(src, (void __force_kernel *)____m(dst), len, isum, NULL, errp); ++ clac(); ++ pax_close_userland(); ++ return isum; } EXPORT_SYMBOL(csum_partial_copy_to_user); + diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index a451235..1daa956 100644 --- a/arch/x86/lib/getuser.S @@ -25646,9 +27373,18 @@ index 05a95e7..326f2fa 100644 CFI_ENDPROC ENDPROC(__iowrite32_copy) diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S -index 56313a3..aa84a79 100644 +index 56313a3..9b59269 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S +@@ -24,7 +24,7 @@ + * This gets patched over the unrolled variant (below) via the + * alternative instructions framework: + */ +- .section .altinstr_replacement, "ax", @progbits ++ .section .altinstr_replacement, "a", @progbits + .Lmemcpy_c: + movq %rdi, %rax + movq %rdx, %rcx @@ -33,6 +33,7 @@ rep movsq movl %edx, %ecx @@ -25657,7 +27393,13 @@ index 56313a3..aa84a79 100644 ret .Lmemcpy_e: .previous -@@ -49,6 +50,7 @@ +@@ -44,11 +45,12 @@ + * This gets patched over the unrolled variant (below) via the + * alternative instructions framework: + */ +- .section .altinstr_replacement, "ax", @progbits ++ .section .altinstr_replacement, "a", @progbits + .Lmemcpy_c_e: movq %rdi, %rax movq %rdx, %rcx rep movsb @@ -25737,7 +27479,7 @@ index 56313a3..aa84a79 100644 CFI_ENDPROC ENDPROC(memcpy) diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S -index 65268a6..c9518d1 100644 +index 65268a6..5aa7815 100644 --- a/arch/x86/lib/memmove_64.S +++ b/arch/x86/lib/memmove_64.S @@ -61,13 +61,13 @@ ENTRY(memmove) @@ -25852,7 +27594,7 @@ index 65268a6..c9518d1 100644 jmp 13f 12: cmp $1, %rdx -@@ -202,6 +202,7 @@ ENTRY(memmove) +@@ -202,14 +202,16 @@ ENTRY(memmove) movb (%rsi), %r11b movb %r11b, (%rdi) 13: @@ -25860,7 +27602,9 @@ index 65268a6..c9518d1 100644 retq CFI_ENDPROC -@@ -210,6 +211,7 @@ ENTRY(memmove) +- .section .altinstr_replacement,"ax" ++ .section .altinstr_replacement,"a" + .Lmemmove_begin_forward_efs: /* Forward moving data. */ movq %rdx, %rcx rep movsb @@ -25869,9 +27613,18 @@ index 65268a6..c9518d1 100644 .Lmemmove_end_forward_efs: .previous diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S -index 2dcb380..963660a 100644 +index 2dcb380..50a78bc 100644 --- a/arch/x86/lib/memset_64.S +++ b/arch/x86/lib/memset_64.S +@@ -16,7 +16,7 @@ + * + * rax original destination + */ +- .section .altinstr_replacement, "ax", @progbits ++ .section .altinstr_replacement, "a", @progbits + .Lmemset_c: + movq %rdi,%r9 + movq %rdx,%rcx @@ -30,6 +30,7 @@ movl %edx,%ecx rep stosb @@ -25880,7 +27633,15 @@ index 2dcb380..963660a 100644 ret .Lmemset_e: .previous -@@ -52,6 +53,7 @@ +@@ -45,13 +46,14 @@ + * + * rax original destination + */ +- .section .altinstr_replacement, "ax", @progbits ++ .section .altinstr_replacement, "a", @progbits + .Lmemset_c_e: + movq %rdi,%r9 + movb %sil,%al movq %rdx,%rcx rep stosb movq %r9,%rax @@ -27157,10 +28918,18 @@ index 3eb18ac..6890bc3 100644 +EXPORT_SYMBOL(set_fs); +#endif diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c -index 906fea3..5646695 100644 +index 906fea3..0194a18 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c -@@ -39,7 +39,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size) +@@ -18,6 +18,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size) + might_fault(); + /* no memory constraint because it doesn't change any memory gcc knows + about */ ++ pax_open_userland(); + stac(); + asm volatile( + " testq %[size8],%[size8]\n" +@@ -39,9 +40,10 @@ unsigned long __clear_user(void __user *addr, unsigned long size) _ASM_EXTABLE(0b,3b) _ASM_EXTABLE(1b,2b) : [size8] "=&c"(size), [dst] "=&D" (__d0) @@ -27168,8 +28937,11 @@ index 906fea3..5646695 100644 + : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(____m(addr)), [zero] "r" (0UL), [eight] "r" (8UL)); clac(); ++ pax_close_userland(); return size; -@@ -54,12 +54,11 @@ unsigned long clear_user(void __user *to, unsigned long n) + } + EXPORT_SYMBOL(__clear_user); +@@ -54,12 +56,11 @@ unsigned long clear_user(void __user *to, unsigned long n) } EXPORT_SYMBOL(clear_user); @@ -27186,7 +28958,7 @@ index 906fea3..5646695 100644 } EXPORT_SYMBOL(copy_in_user); -@@ -69,7 +68,7 @@ EXPORT_SYMBOL(copy_in_user); +@@ -69,11 +70,13 @@ EXPORT_SYMBOL(copy_in_user); * it is not necessary to optimize tail handling. */ unsigned long @@ -27195,6 +28967,31 @@ index 906fea3..5646695 100644 { char c; unsigned zero_len; + ++ clac(); ++ pax_close_userland(); + for (; len; --len, to++) { + if (__get_user_nocheck(c, from++, sizeof(char))) + break; +@@ -84,6 +87,5 @@ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest) + for (c = 0, zero_len = len; zerorest && zero_len; --zero_len) + if (__put_user_nocheck(c, to++, sizeof(char))) + break; +- clac(); + return len; + } +diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile +index 23d8e5f..9ccc13a 100644 +--- a/arch/x86/mm/Makefile ++++ b/arch/x86/mm/Makefile +@@ -28,3 +28,7 @@ obj-$(CONFIG_ACPI_NUMA) += srat.o + obj-$(CONFIG_NUMA_EMU) += numa_emulation.o + + obj-$(CONFIG_MEMTEST) += memtest.o ++ ++quote:=" ++obj-$(CONFIG_X86_64) += uderef_64.o ++CFLAGS_uderef_64.o := $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 903ec1e..c4166b2 100644 --- a/arch/x86/mm/extable.c @@ -27250,7 +29047,7 @@ index 903ec1e..c4166b2 100644 } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c -index 654be4a..d36985f 100644 +index 654be4a..a4a3da1 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -14,11 +14,18 @@ @@ -27340,7 +29137,7 @@ index 654be4a..d36985f 100644 DEFINE_SPINLOCK(pgd_lock); LIST_HEAD(pgd_list); -@@ -232,10 +273,22 @@ void vmalloc_sync_all(void) +@@ -232,10 +273,27 @@ void vmalloc_sync_all(void) for (address = VMALLOC_START & PMD_MASK; address >= TASK_SIZE && address < FIXADDR_TOP; address += PMD_SIZE) { @@ -27355,15 +29152,20 @@ index 654be4a..d36985f 100644 + +#ifdef CONFIG_PAX_PER_CPU_PGD + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { -+ pgd_t *pgd = get_cpu_pgd(cpu); ++ pgd_t *pgd = get_cpu_pgd(cpu, user); + pmd_t *ret; ++ ++ ret = vmalloc_sync_one(pgd, address); ++ if (!ret) ++ break; ++ pgd = get_cpu_pgd(cpu, kernel); +#else list_for_each_entry(page, &pgd_list, lru) { + pgd_t *pgd; spinlock_t *pgt_lock; pmd_t *ret; -@@ -243,8 +296,14 @@ void vmalloc_sync_all(void) +@@ -243,8 +301,14 @@ void vmalloc_sync_all(void) pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); @@ -27379,34 +29181,47 @@ index 654be4a..d36985f 100644 if (!ret) break; -@@ -278,6 +337,11 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) +@@ -278,6 +342,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) * an interrupt in the middle of a task switch.. */ pgd_paddr = read_cr3(); + +#ifdef CONFIG_PAX_PER_CPU_PGD -+ BUG_ON(__pa(get_cpu_pgd(smp_processor_id())) != (pgd_paddr & PHYSICAL_PAGE_MASK)); ++ BUG_ON(__pa(get_cpu_pgd(smp_processor_id(), kernel)) != (pgd_paddr & __PHYSICAL_MASK)); ++ vmalloc_sync_one(__va(pgd_paddr + PAGE_SIZE), address); +#endif + pmd_k = vmalloc_sync_one(__va(pgd_paddr), address); if (!pmd_k) return -1; -@@ -373,7 +437,14 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) +@@ -373,11 +443,25 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) * happen within a race in page table update. In the later * case just flush: */ +- pgd = pgd_offset(current->active_mm, address); + + pgd_ref = pgd_offset_k(address); + if (pgd_none(*pgd_ref)) + return -1; + +#ifdef CONFIG_PAX_PER_CPU_PGD -+ BUG_ON(__pa(get_cpu_pgd(smp_processor_id())) != (read_cr3() & PHYSICAL_PAGE_MASK)); -+ pgd = pgd_offset_cpu(smp_processor_id(), address); ++ BUG_ON(__pa(get_cpu_pgd(smp_processor_id(), kernel)) != (read_cr3() & __PHYSICAL_MASK)); ++ pgd = pgd_offset_cpu(smp_processor_id(), user, address); ++ if (pgd_none(*pgd)) { ++ set_pgd(pgd, *pgd_ref); ++ arch_flush_lazy_mmu_mode(); ++ } else { ++ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); ++ } ++ pgd = pgd_offset_cpu(smp_processor_id(), kernel, address); +#else - pgd = pgd_offset(current->active_mm, address); ++ pgd = pgd_offset(current->active_mm, address); +#endif + - pgd_ref = pgd_offset_k(address); - if (pgd_none(*pgd_ref)) - return -1; -@@ -543,7 +614,7 @@ static int is_errata93(struct pt_regs *regs, unsigned long address) + if (pgd_none(*pgd)) { + set_pgd(pgd, *pgd_ref); + arch_flush_lazy_mmu_mode(); +@@ -543,7 +627,7 @@ static int is_errata93(struct pt_regs *regs, unsigned long address) static int is_errata100(struct pt_regs *regs, unsigned long address) { #ifdef CONFIG_X86_64 @@ -27415,7 +29230,7 @@ index 654be4a..d36985f 100644 return 1; #endif return 0; -@@ -570,7 +641,7 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address) +@@ -570,7 +654,7 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address) } static const char nx_warning[] = KERN_CRIT @@ -27424,7 +29239,7 @@ index 654be4a..d36985f 100644 static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, -@@ -579,15 +650,27 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, +@@ -579,15 +663,27 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, if (!oops_may_print()) return; @@ -27454,7 +29269,7 @@ index 654be4a..d36985f 100644 printk(KERN_ALERT "BUG: unable to handle kernel "); if (address < PAGE_SIZE) printk(KERN_CONT "NULL pointer dereference"); -@@ -750,6 +833,22 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, +@@ -750,6 +846,22 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, return; } #endif @@ -27477,7 +29292,7 @@ index 654be4a..d36985f 100644 /* Kernel addresses are always protection faults: */ if (address >= TASK_SIZE) error_code |= PF_PROT; -@@ -835,7 +934,7 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, +@@ -835,7 +947,7 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { printk(KERN_ERR "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", @@ -27486,7 +29301,7 @@ index 654be4a..d36985f 100644 code = BUS_MCEERR_AR; } #endif -@@ -898,6 +997,99 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte) +@@ -898,6 +1010,99 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte) return 1; } @@ -27586,7 +29401,7 @@ index 654be4a..d36985f 100644 /* * Handle a spurious fault caused by a stale TLB entry. * -@@ -964,6 +1156,9 @@ int show_unhandled_signals = 1; +@@ -964,6 +1169,9 @@ int show_unhandled_signals = 1; static inline int access_error(unsigned long error_code, struct vm_area_struct *vma) { @@ -27596,7 +29411,7 @@ index 654be4a..d36985f 100644 if (error_code & PF_WRITE) { /* write, present and write, not present: */ if (unlikely(!(vma->vm_flags & VM_WRITE))) -@@ -992,7 +1187,7 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) +@@ -992,7 +1200,7 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) if (error_code & PF_USER) return false; @@ -27605,7 +29420,7 @@ index 654be4a..d36985f 100644 return false; return true; -@@ -1008,18 +1203,33 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) +@@ -1008,18 +1216,33 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) { struct vm_area_struct *vma; struct task_struct *tsk; @@ -27644,7 +29459,7 @@ index 654be4a..d36985f 100644 /* * Detect and handle instructions that would cause a page fault for -@@ -1080,7 +1290,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) +@@ -1080,7 +1303,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) * User-mode registers count as a user access even for any * potential system fault or CPU buglet: */ @@ -27653,7 +29468,7 @@ index 654be4a..d36985f 100644 local_irq_enable(); error_code |= PF_USER; } else { -@@ -1142,6 +1352,11 @@ retry: +@@ -1142,6 +1365,11 @@ retry: might_sleep(); } @@ -27665,7 +29480,7 @@ index 654be4a..d36985f 100644 vma = find_vma(mm, address); if (unlikely(!vma)) { bad_area(regs, error_code, address); -@@ -1153,18 +1368,24 @@ retry: +@@ -1153,18 +1381,24 @@ retry: bad_area(regs, error_code, address); return; } @@ -27701,7 +29516,7 @@ index 654be4a..d36985f 100644 if (unlikely(expand_stack(vma, address))) { bad_area(regs, error_code, address); return; -@@ -1230,3 +1451,292 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) +@@ -1230,3 +1464,292 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) __do_page_fault(regs, error_code); exception_exit(prev_state); } @@ -28132,7 +29947,7 @@ index ae1aa71..d9bea75 100644 #endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c -index 1f34e92..d252637 100644 +index 1f34e92..c97b98f 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -4,6 +4,7 @@ @@ -28152,15 +29967,18 @@ index 1f34e92..d252637 100644 #include "mm_internal.h" -@@ -465,7 +468,15 @@ void __init init_mem_mapping(void) +@@ -465,7 +468,18 @@ void __init init_mem_mapping(void) early_ioremap_page_table_range_init(); #endif +#ifdef CONFIG_PAX_PER_CPU_PGD -+ clone_pgd_range(get_cpu_pgd(0) + KERNEL_PGD_BOUNDARY, ++ clone_pgd_range(get_cpu_pgd(0, kernel) + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); -+ load_cr3(get_cpu_pgd(0)); ++ clone_pgd_range(get_cpu_pgd(0, user) + KERNEL_PGD_BOUNDARY, ++ swapper_pg_dir + KERNEL_PGD_BOUNDARY, ++ KERNEL_PGD_PTRS); ++ load_cr3(get_cpu_pgd(0, kernel)); +#else load_cr3(swapper_pg_dir); +#endif @@ -28168,7 +29986,7 @@ index 1f34e92..d252637 100644 __flush_tlb_all(); early_memtest(0, max_pfn_mapped << PAGE_SHIFT); -@@ -481,10 +492,40 @@ void __init init_mem_mapping(void) +@@ -481,10 +495,40 @@ void __init init_mem_mapping(void) * Access has to be given to non-kernel-ram areas as well, these contain the PCI * mmio resources as well as potential bios/acpi data regions. */ @@ -28210,7 +30028,7 @@ index 1f34e92..d252637 100644 if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) return 0; if (!page_is_ram(pagenr)) -@@ -538,8 +579,117 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) +@@ -538,8 +582,117 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) #endif } @@ -28591,7 +30409,7 @@ index 3ac7e31..89611b7 100644 printk(KERN_INFO "Write protecting the kernel text: %luk\n", size >> 10); diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c -index bb00c46..f31d2f0 100644 +index bb00c46..bf91a67 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -151,7 +151,7 @@ early_param("gbpages", parse_direct_gbpages_on); @@ -28603,7 +30421,7 @@ index bb00c46..f31d2f0 100644 EXPORT_SYMBOL_GPL(__supported_pte_mask); int force_personality32; -@@ -184,12 +184,22 @@ void sync_global_pgds(unsigned long start, unsigned long end) +@@ -184,12 +184,29 @@ void sync_global_pgds(unsigned long start, unsigned long end) for (address = start; address <= end; address += PGDIR_SIZE) { const pgd_t *pgd_ref = pgd_offset_k(address); @@ -28621,12 +30439,19 @@ index bb00c46..f31d2f0 100644 + +#ifdef CONFIG_PAX_PER_CPU_PGD + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { -+ pgd_t *pgd = pgd_offset_cpu(cpu, address); ++ pgd_t *pgd = pgd_offset_cpu(cpu, user, address); ++ ++ if (pgd_none(*pgd)) ++ set_pgd(pgd, *pgd_ref); ++ else ++ BUG_ON(pgd_page_vaddr(*pgd) ++ != pgd_page_vaddr(*pgd_ref)); ++ pgd = pgd_offset_cpu(cpu, kernel, address); +#else list_for_each_entry(page, &pgd_list, lru) { pgd_t *pgd; spinlock_t *pgt_lock; -@@ -198,6 +208,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) +@@ -198,6 +215,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); @@ -28634,7 +30459,7 @@ index bb00c46..f31d2f0 100644 if (pgd_none(*pgd)) set_pgd(pgd, *pgd_ref); -@@ -205,7 +216,10 @@ void sync_global_pgds(unsigned long start, unsigned long end) +@@ -205,7 +223,10 @@ void sync_global_pgds(unsigned long start, unsigned long end) BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); @@ -28645,7 +30470,7 @@ index bb00c46..f31d2f0 100644 } spin_unlock(&pgd_lock); } -@@ -238,7 +252,7 @@ static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) +@@ -238,7 +259,7 @@ static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) { if (pgd_none(*pgd)) { pud_t *pud = (pud_t *)spp_getpage(); @@ -28654,7 +30479,7 @@ index bb00c46..f31d2f0 100644 if (pud != pud_offset(pgd, 0)) printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n", pud, pud_offset(pgd, 0)); -@@ -250,7 +264,7 @@ static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) +@@ -250,7 +271,7 @@ static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) { if (pud_none(*pud)) { pmd_t *pmd = (pmd_t *) spp_getpage(); @@ -28663,7 +30488,7 @@ index bb00c46..f31d2f0 100644 if (pmd != pmd_offset(pud, 0)) printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud, 0)); -@@ -279,7 +293,9 @@ void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) +@@ -279,7 +300,9 @@ void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) pmd = fill_pmd(pud, vaddr); pte = fill_pte(pmd, vaddr); @@ -28673,7 +30498,7 @@ index bb00c46..f31d2f0 100644 /* * It's enough to flush this one mapping. -@@ -338,14 +354,12 @@ static void __init __init_extra_mapping(unsigned long phys, unsigned long size, +@@ -338,14 +361,12 @@ static void __init __init_extra_mapping(unsigned long phys, unsigned long size, pgd = pgd_offset_k((unsigned long)__va(phys)); if (pgd_none(*pgd)) { pud = (pud_t *) spp_getpage(); @@ -28690,7 +30515,7 @@ index bb00c46..f31d2f0 100644 } pmd = pmd_offset(pud, phys); BUG_ON(!pmd_none(*pmd)); -@@ -586,7 +600,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, +@@ -586,7 +607,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, prot); spin_lock(&init_mm.page_table_lock); @@ -28699,7 +30524,7 @@ index bb00c46..f31d2f0 100644 spin_unlock(&init_mm.page_table_lock); } __flush_tlb_all(); -@@ -627,7 +641,7 @@ kernel_physical_mapping_init(unsigned long start, +@@ -627,7 +648,7 @@ kernel_physical_mapping_init(unsigned long start, page_size_mask); spin_lock(&init_mm.page_table_lock); @@ -28708,7 +30533,7 @@ index bb00c46..f31d2f0 100644 spin_unlock(&init_mm.page_table_lock); pgd_changed = true; } -@@ -1221,8 +1235,8 @@ int kern_addr_valid(unsigned long addr) +@@ -1221,8 +1242,8 @@ int kern_addr_valid(unsigned long addr) static struct vm_area_struct gate_vma = { .vm_start = VSYSCALL_START, .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE), @@ -28719,7 +30544,7 @@ index bb00c46..f31d2f0 100644 }; struct vm_area_struct *get_gate_vma(struct mm_struct *mm) -@@ -1256,7 +1270,7 @@ int in_gate_area_no_mm(unsigned long addr) +@@ -1256,7 +1277,7 @@ int in_gate_area_no_mm(unsigned long addr) const char *arch_vma_name(struct vm_area_struct *vma) { @@ -28982,7 +30807,7 @@ index d0b1773..4c3327c 100644 struct split_state { diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c -index bb32480..aef8278 100644 +index bb32480..75f2f5e 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -261,7 +261,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, @@ -29047,7 +30872,7 @@ index bb32480..aef8278 100644 +#ifdef CONFIG_PAX_PER_CPU_PGD + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { -+ pgd_t *pgd = get_cpu_pgd(cpu); ++ pgd_t *pgd = get_cpu_pgd(cpu, kernel); +#else list_for_each_entry(page, &pgd_list, lru) { - pgd_t *pgd; @@ -29183,10 +31008,10 @@ index 9f0614d..92ae64a 100644 p += get_opcode(p, &opcode); for (i = 0; i < ARRAY_SIZE(imm_wop); i++) diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c -index 17fda6a..489c74a 100644 +index 17fda6a..f7d54a0 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c -@@ -91,10 +91,64 @@ static inline void pgd_list_del(pgd_t *pgd) +@@ -91,10 +91,67 @@ static inline void pgd_list_del(pgd_t *pgd) list_del(&page->lru); } @@ -29199,6 +31024,9 @@ index 17fda6a..489c74a 100644 +{ + unsigned int count = USER_PGD_PTRS; ++ if (!pax_user_shadow_base) ++ return; ++ + while (count--) + *dst++ = __pgd((pgd_val(*src++) | (_PAGE_NX & __supported_pte_mask)) & ~_PAGE_USER); +} @@ -29253,7 +31081,7 @@ index 17fda6a..489c74a 100644 static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm) { BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm)); -@@ -135,6 +189,7 @@ static void pgd_dtor(pgd_t *pgd) +@@ -135,6 +192,7 @@ static void pgd_dtor(pgd_t *pgd) pgd_list_del(pgd); spin_unlock(&pgd_lock); } @@ -29261,7 +31089,7 @@ index 17fda6a..489c74a 100644 /* * List of all pgd's needed for non-PAE so it can invalidate entries -@@ -147,7 +202,7 @@ static void pgd_dtor(pgd_t *pgd) +@@ -147,7 +205,7 @@ static void pgd_dtor(pgd_t *pgd) * -- nyc */ @@ -29270,7 +31098,7 @@ index 17fda6a..489c74a 100644 /* * In PAE mode, we need to do a cr3 reload (=tlb flush) when * updating the top-level pagetable entries to guarantee the -@@ -159,7 +214,7 @@ static void pgd_dtor(pgd_t *pgd) +@@ -159,7 +217,7 @@ static void pgd_dtor(pgd_t *pgd) * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate * and initialize the kernel pmds here. */ @@ -29279,7 +31107,7 @@ index 17fda6a..489c74a 100644 void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) { -@@ -177,36 +232,38 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) +@@ -177,36 +235,38 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) */ flush_tlb_mm(mm); } @@ -29329,7 +31157,7 @@ index 17fda6a..489c74a 100644 return -ENOMEM; } -@@ -219,51 +276,55 @@ static int preallocate_pmds(pmd_t *pmds[]) +@@ -219,51 +279,55 @@ static int preallocate_pmds(pmd_t *pmds[]) * preallocate which never got a corresponding vma will need to be * freed manually. */ @@ -29402,7 +31230,7 @@ index 17fda6a..489c74a 100644 pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); -@@ -272,11 +333,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm) +@@ -272,11 +336,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm) mm->pgd = pgd; @@ -29416,7 +31244,7 @@ index 17fda6a..489c74a 100644 /* * Make sure that pre-populating the pmds is atomic with -@@ -286,14 +347,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm) +@@ -286,14 +350,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm) spin_lock(&pgd_lock); pgd_ctor(mm, pgd); @@ -29434,7 +31262,7 @@ index 17fda6a..489c74a 100644 out_free_pgd: free_page((unsigned long)pgd); out: -@@ -302,7 +363,7 @@ out: +@@ -302,7 +366,7 @@ out: void pgd_free(struct mm_struct *mm, pgd_t *pgd) { @@ -29532,6 +31360,49 @@ index 282375f..e03a98f 100644 } } EXPORT_SYMBOL_GPL(leave_mm); +diff --git a/arch/x86/mm/uderef_64.c b/arch/x86/mm/uderef_64.c +new file mode 100644 +index 0000000..dace51c +--- /dev/null ++++ b/arch/x86/mm/uderef_64.c +@@ -0,0 +1,37 @@ ++#include <linux/mm.h> ++#include <asm/pgtable.h> ++#include <asm/uaccess.h> ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++/* PaX: due to the special call convention these functions must ++ * - remain leaf functions under all configurations, ++ * - never be called directly, only dereferenced from the wrappers. ++ */ ++void __pax_open_userland(void) ++{ ++ unsigned int cpu; ++ ++ if (unlikely(!segment_eq(get_fs(), USER_DS))) ++ return; ++ ++ cpu = raw_get_cpu(); ++ BUG_ON((read_cr3() & ~PAGE_MASK) != PCID_KERNEL); ++ write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER | PCID_NOFLUSH); ++ raw_put_cpu_no_resched(); ++} ++EXPORT_SYMBOL(__pax_open_userland); ++ ++void __pax_close_userland(void) ++{ ++ unsigned int cpu; ++ ++ if (unlikely(!segment_eq(get_fs(), USER_DS))) ++ return; ++ ++ cpu = raw_get_cpu(); ++ BUG_ON((read_cr3() & ~PAGE_MASK) != PCID_USER); ++ write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); ++ raw_put_cpu_no_resched(); ++} ++EXPORT_SYMBOL(__pax_close_userland); ++#endif diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S index 877b9a1..a8ecf42 100644 --- a/arch/x86/net/bpf_jit.S @@ -30444,7 +32315,7 @@ index c77b24a..c979855 100644 } EXPORT_SYMBOL(pcibios_set_irq_routing); diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c -index 40e4469..0592924 100644 +index 40e4469..d915bf9 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -44,11 +44,22 @@ void efi_call_phys_prelog(void) @@ -30487,7 +32358,7 @@ index 40e4469..0592924 100644 load_gdt(&gdt_descr); +#ifdef CONFIG_PAX_PER_CPU_PGD -+ load_cr3(get_cpu_pgd(smp_processor_id())); ++ load_cr3(get_cpu_pgd(smp_processor_id(), kernel)); +#else load_cr3(swapper_pg_dir); +#endif @@ -30496,7 +32367,7 @@ index 40e4469..0592924 100644 local_irq_restore(efi_rt_eflags); diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c -index 39a0e7f1..ecc2f1e 100644 +index 39a0e7f1..872396e 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -76,6 +76,11 @@ void __init efi_call_phys_prelog(void) @@ -30517,7 +32388,7 @@ index 39a0e7f1..ecc2f1e 100644 kfree(save_pgd); + +#ifdef CONFIG_PAX_PER_CPU_PGD -+ load_cr3(get_cpu_pgd(smp_processor_id())); ++ load_cr3(get_cpu_pgd(smp_processor_id(), kernel)); +#endif + __flush_tlb_all(); @@ -30884,10 +32755,18 @@ index c1b2791..f9e31c7 100644 END(trampoline_header) diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S -index bb360dc..3e5945f 100644 +index bb360dc..d0fd8f8 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S -@@ -107,7 +107,7 @@ ENTRY(startup_32) +@@ -94,6 +94,7 @@ ENTRY(startup_32) + movl %edx, %gs + + movl pa_tr_cr4, %eax ++ andl $~X86_CR4_PCIDE, %eax + movl %eax, %cr4 # Enable PAE mode + + # Setup trampoline 4 level pagetables +@@ -107,7 +108,7 @@ ENTRY(startup_32) wrmsr # Enable paging and in turn activate Long Mode @@ -34436,10 +36315,10 @@ index 84ddc55..1d32f1e 100644 return 0; } diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c -index 1b456fe..2510242 100644 +index fc45567..fa2a590 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c -@@ -679,7 +679,7 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, +@@ -682,7 +682,7 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, if (to_user) { ssize_t ret; @@ -34448,7 +36327,7 @@ index 1b456fe..2510242 100644 if (ret) return -EFAULT; } else { -@@ -778,7 +778,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, +@@ -785,7 +785,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, if (!port_has_data(port) && !port->host_connected) return 0; @@ -34508,6 +36387,19 @@ index a2b2541..bc1e7ff 100644 .notifier_call = arch_timer_cpu_notify, }; +diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c +index 350f493..489479e 100644 +--- a/drivers/clocksource/bcm_kona_timer.c ++++ b/drivers/clocksource/bcm_kona_timer.c +@@ -199,7 +199,7 @@ static struct irqaction kona_timer_irq = { + .handler = kona_timer_interrupt, + }; + +-static void __init kona_timer_init(void) ++static void __init kona_timer_init(struct device_node *np) + { + kona_timers_init(); + kona_timer_clockevents_init(); diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index ade7513..069445f 100644 --- a/drivers/clocksource/metag_generic.c @@ -34574,10 +36466,10 @@ index edc089e..bc7c0bc 100644 pr_debug("CPU%u - ACPI performance management activated.\n", cpu); for (i = 0; i < perf->state_count; i++) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index 178fe7a..5ee8501 100644 +index 6485547..477033e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c -@@ -1853,7 +1853,7 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, +@@ -1854,7 +1854,7 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } @@ -34586,7 +36478,7 @@ index 178fe7a..5ee8501 100644 .notifier_call = cpufreq_cpu_callback, }; -@@ -1885,8 +1885,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) +@@ -1886,8 +1886,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) pr_debug("trying to register driver %s\n", driver_data->name); @@ -34601,7 +36493,7 @@ index 178fe7a..5ee8501 100644 write_lock_irqsave(&cpufreq_driver_lock, flags); if (cpufreq_driver) { diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c -index 5af40ad..ddf907b 100644 +index a86ff72..aad2b03 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -235,7 +235,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, @@ -34632,7 +36524,7 @@ index 5af40ad..ddf907b 100644 cpufreq_unregister_notifier(cs_ops->notifier_block, CPUFREQ_TRANSITION_NOTIFIER); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h -index e16a961..0e68927 100644 +index 0d9e6be..461fd3b 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -204,7 +204,7 @@ struct common_dbs_data { @@ -34645,7 +36537,7 @@ index e16a961..0e68927 100644 /* Governer Per policy data */ diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c -index 93eb5cb..f8ab572 100644 +index c087347..dad6268 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -615,14 +615,18 @@ void od_register_powersave_bias_handler(unsigned int (*f) @@ -35634,7 +37526,7 @@ index e913d32..4d9b351 100644 if (IS_GEN6(dev) || IS_GEN7(dev)) { seq_printf(m, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c -index f968590..19115e35 100644 +index 17d9b0b..860e6d9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1259,7 +1259,7 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) @@ -35823,10 +37715,10 @@ index e5e32869..1678f36 100644 iir = I915_READ(IIR); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index e1f4e6e..c94a4b3 100644 +index eea5982..eeef407 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c -@@ -8933,13 +8933,13 @@ struct intel_quirk { +@@ -8935,13 +8935,13 @@ struct intel_quirk { int subsystem_vendor; int subsystem_device; void (*hook)(struct drm_device *dev); @@ -35842,7 +37734,7 @@ index e1f4e6e..c94a4b3 100644 static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) { -@@ -8947,18 +8947,20 @@ static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) +@@ -8949,18 +8949,20 @@ static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) return 1; } @@ -40059,6 +41951,19 @@ index f975696..4597e21 100644 #ifdef CONFIG_NET_POLL_CONTROLLER /* +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c +index 25723d8..925ab8e 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb.c +@@ -649,7 +649,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) + if ((mc->ptr + rec_len) > mc->end) + goto decode_failed; + +- memcpy(cf->data, mc->ptr, rec_len); ++ memcpy(cf->data, mc->ptr, cf->can_dlc); + mc->ptr += rec_len; + } + diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index e1d2643..7f4133b 100644 --- a/drivers/net/ethernet/8390/ax88796.c @@ -40377,6 +42282,18 @@ index d3f8797..82a03d3 100644 vlan_req = (struct qlcnic_vlan_req *)&req->words[1]; vlan_req->vlan_id = cpu_to_le16(vlan_id); +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 887aebe..9095ff9 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -524,6 +524,7 @@ rx_status_loop: + PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&cp->pdev->dev, new_mapping)) { + dev->stats.rx_dropped++; ++ kfree_skb(new_skb); + goto rx_next; + } + diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 393f961..d343034 100644 --- a/drivers/net/ethernet/realtek/r8169.c @@ -40594,10 +42511,32 @@ index b305105..8ead6df 100644 }; diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index 2491eb2..694b2ec 100644 +index 2491eb2..1a453eb 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c -@@ -1869,7 +1869,7 @@ unlock: +@@ -1076,8 +1076,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + u32 rxhash; + + if (!(tun->flags & TUN_NO_PI)) { +- if ((len -= sizeof(pi)) > total_len) ++ if (len < sizeof(pi)) + return -EINVAL; ++ len -= sizeof(pi); + + if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) + return -EFAULT; +@@ -1085,8 +1086,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + } + + if (tun->flags & TUN_VNET_HDR) { +- if ((len -= tun->vnet_hdr_sz) > total_len) ++ if (len < tun->vnet_hdr_sz) + return -EINVAL; ++ len -= tun->vnet_hdr_sz; + + if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) + return -EFAULT; +@@ -1869,7 +1871,7 @@ unlock: } static long __tun_chr_ioctl(struct file *file, unsigned int cmd, @@ -40606,7 +42545,7 @@ index 2491eb2..694b2ec 100644 { struct tun_file *tfile = file->private_data; struct tun_struct *tun; -@@ -1881,6 +1881,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, +@@ -1881,6 +1883,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, int vnet_hdr_sz; int ret; @@ -41203,7 +43142,7 @@ index 7510723..5ba37f5 100644 static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c -index 2c12311..7b77f24 100644 +index d955741..8730748 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -252,9 +252,9 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, @@ -42925,7 +44864,7 @@ index 4d231c1..2892c37 100644 ddb_entry->default_relogin_timeout = (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ? diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c -index 3b1ea34..1583a72 100644 +index eaa808e..95f8841 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -661,7 +661,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) @@ -50073,10 +52012,10 @@ index 3752b9f..8db5569 100644 atomic_set(&midCount, 0); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h -index 4f07f6f..55de8ce 100644 +index ea3a0b3..0194e39 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h -@@ -751,35 +751,35 @@ struct cifs_tcon { +@@ -752,35 +752,35 @@ struct cifs_tcon { __u16 Flags; /* optional support bits */ enum statusEnum tidStatus; #ifdef CONFIG_CIFS_STATS @@ -50136,7 +52075,7 @@ index 4f07f6f..55de8ce 100644 } smb2_stats; #endif /* CONFIG_CIFS_SMB2 */ } stats; -@@ -1080,7 +1080,7 @@ convert_delimiter(char *path, char delim) +@@ -1081,7 +1081,7 @@ convert_delimiter(char *path, char delim) } #ifdef CONFIG_CIFS_STATS @@ -50145,7 +52084,7 @@ index 4f07f6f..55de8ce 100644 static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon, unsigned int bytes) -@@ -1445,8 +1445,8 @@ GLOBAL_EXTERN atomic_t tconInfoReconnectCount; +@@ -1446,8 +1446,8 @@ GLOBAL_EXTERN atomic_t tconInfoReconnectCount; /* Various Debug counters */ GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ #ifdef CONFIG_CIFS_STATS2 @@ -50833,7 +52772,7 @@ index f09b908..04b9690 100644 dcache_init(); inode_init(); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c -index 4888cb3..e0f7cf8 100644 +index c7c83ff..bda9461 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -415,7 +415,11 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); @@ -50884,7 +52823,7 @@ index e4141f2..d8263e8 100644 i += packet_length_size; if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size)) diff --git a/fs/exec.c b/fs/exec.c -index ffd7a81..d95acf6 100644 +index ffd7a81..3c84660 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -55,8 +55,20 @@ @@ -51091,6 +53030,24 @@ index ffd7a81..d95acf6 100644 /* * cover the whole range: [new_start, old_end) */ +@@ -607,7 +653,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) + return -ENOMEM; + + lru_add_drain(); +- tlb_gather_mmu(&tlb, mm, 0); ++ tlb_gather_mmu(&tlb, mm, old_start, old_end); + if (new_end > old_start) { + /* + * when the old and new regions overlap clear from new_end. +@@ -624,7 +670,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) + free_pgd_range(&tlb, old_start, old_end, new_end, + vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); + } +- tlb_finish_mmu(&tlb, new_end, old_end); ++ tlb_finish_mmu(&tlb, old_start, old_end); + + /* + * Shrink the vma to just the new range. Always succeeds. @@ -672,10 +718,6 @@ int setup_arg_pages(struct linux_binprm *bprm, stack_top = arch_align_stack(stack_top); stack_top = PAGE_ALIGN(stack_top); @@ -51366,7 +53323,7 @@ index ffd7a81..d95acf6 100644 out: if (bprm->mm) { acct_arg_size(bprm, 0); -@@ -1701,3 +1875,285 @@ asmlinkage long compat_sys_execve(const char __user * filename, +@@ -1701,3 +1875,287 @@ asmlinkage long compat_sys_execve(const char __user * filename, return error; } #endif @@ -51475,7 +53432,7 @@ index ffd7a81..d95acf6 100644 + offset = vma_fault->vm_pgoff << PAGE_SHIFT; + if (vma_fault->vm_file) + path_fault = pax_get_path(&vma_fault->vm_file->f_path, buffer_fault, PAGE_SIZE); -+ else if (pc >= mm->start_brk && pc < mm->brk) ++ else if ((unsigned long)pc >= mm->start_brk && (unsigned long)pc < mm->brk) + path_fault = "<heap>"; + else if (vma_fault->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) + path_fault = "<stack>"; @@ -51513,7 +53470,9 @@ index ffd7a81..d95acf6 100644 + printk(KERN_ERR "PAX: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n", current->comm, task_pid_nr(current), + from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid())); + print_symbol(KERN_ERR "PAX: refcount overflow occured at: %s\n", instruction_pointer(regs)); ++ preempt_disable(); + show_regs(regs); ++ preempt_enable(); + force_sig_info(SIGKILL, SEND_SIG_FORCED, current); +} +#endif @@ -51905,7 +53864,7 @@ index 49d3c01..9579efd 100644 else if (input->reserved_blocks > input->blocks_count / 5) ext4_warning(sb, "Reserved blocks too high (%u)", diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 6681c03..d88cd33 100644 +index 3f7c39e..227f24f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1236,7 +1236,7 @@ static ext4_fsblk_t get_sb_block(void **data) @@ -53671,7 +55630,7 @@ index 916da8c..1588998 100644 next->d_inode->i_ino, dt_type(next->d_inode)) < 0) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c -index 9760ecb..9b838ef 100644 +index acd3947..1f896e2 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -36,11 +36,11 @@ static const struct rpc_call_ops nlmclnt_cancel_ops; @@ -54659,18 +56618,10 @@ index e7bc1d7..06bd4bb 100644 } diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c -index 6c80083..a1e6299 100644 +index 77cc85d..a1e6299 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c -@@ -122,6 +122,7 @@ static int fill_event_metadata(struct fsnotify_group *group, - metadata->event_len = FAN_EVENT_METADATA_LEN; - metadata->metadata_len = FAN_EVENT_METADATA_LEN; - metadata->vers = FANOTIFY_METADATA_VERSION; -+ metadata->reserved = 0; - metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS; - metadata->pid = pid_vnr(event->tgid); - if (unlikely(event->mask & FAN_Q_OVERFLOW)) -@@ -252,8 +253,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, +@@ -253,8 +253,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, fd = fanotify_event_metadata.fd; ret = -EFAULT; @@ -54729,6 +56680,50 @@ index c5670b8..01a3656 100644 -const struct inode_operations ntfs_empty_inode_ops = {}; +const struct inode_operations ntfs_empty_inode_ops __read_only; +diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c +index 20dfec7..e238cb7 100644 +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -1756,7 +1756,7 @@ try_again: + goto out; + } else if (ret == 1) { + clusters_need = wc->w_clen; +- ret = ocfs2_refcount_cow(inode, filp, di_bh, ++ ret = ocfs2_refcount_cow(inode, di_bh, + wc->w_cpos, wc->w_clen, UINT_MAX); + if (ret) { + mlog_errno(ret); +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index ff54014..ff125fd 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -370,7 +370,7 @@ static int ocfs2_cow_file_pos(struct inode *inode, + if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) + goto out; + +- return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1); ++ return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1); + + out: + return status; +@@ -899,7 +899,7 @@ static int ocfs2_zero_extend_get_range(struct inode *inode, + zero_clusters = last_cpos - zero_cpos; + + if (needs_cow) { +- rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos, ++ rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, + zero_clusters, UINT_MAX); + if (rc) { + mlog_errno(rc); +@@ -2078,7 +2078,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode, + + *meta_level = 1; + +- ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX); ++ ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX); + if (ret) + mlog_errno(ret); + out: diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index aebeacd..0dcdd26 100644 --- a/fs/ocfs2/localalloc.c @@ -54742,6 +56737,19 @@ index aebeacd..0dcdd26 100644 bail: if (handle) +diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c +index f1fc172..452068b 100644 +--- a/fs/ocfs2/move_extents.c ++++ b/fs/ocfs2/move_extents.c +@@ -69,7 +69,7 @@ static int __ocfs2_move_extent(handle_t *handle, + u64 ino = ocfs2_metadata_cache_owner(context->et.et_ci); + u64 old_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cpos); + +- ret = ocfs2_duplicate_clusters_by_page(handle, context->file, cpos, ++ ret = ocfs2_duplicate_clusters_by_page(handle, inode, cpos, + p_cpos, new_p_cpos, len); + if (ret) { + mlog_errno(ret); diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index d355e6e..578d905 100644 --- a/fs/ocfs2/ocfs2.h @@ -54763,6 +56771,188 @@ index d355e6e..578d905 100644 }; enum ocfs2_local_alloc_state +diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c +index 998b17e..aefe414 100644 +--- a/fs/ocfs2/refcounttree.c ++++ b/fs/ocfs2/refcounttree.c +@@ -49,7 +49,6 @@ + + struct ocfs2_cow_context { + struct inode *inode; +- struct file *file; + u32 cow_start; + u32 cow_len; + struct ocfs2_extent_tree data_et; +@@ -66,7 +65,7 @@ struct ocfs2_cow_context { + u32 *num_clusters, + unsigned int *extent_flags); + int (*cow_duplicate_clusters)(handle_t *handle, +- struct file *file, ++ struct inode *inode, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len); + }; +@@ -2922,14 +2921,12 @@ static int ocfs2_clear_cow_buffer(handle_t *handle, struct buffer_head *bh) + } + + int ocfs2_duplicate_clusters_by_page(handle_t *handle, +- struct file *file, ++ struct inode *inode, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len) + { + int ret = 0, partial; +- struct inode *inode = file_inode(file); +- struct ocfs2_caching_info *ci = INODE_CACHE(inode); +- struct super_block *sb = ocfs2_metadata_cache_get_super(ci); ++ struct super_block *sb = inode->i_sb; + u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); + struct page *page; + pgoff_t page_index; +@@ -2973,13 +2970,6 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, + if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) + BUG_ON(PageDirty(page)); + +- if (PageReadahead(page)) { +- page_cache_async_readahead(mapping, +- &file->f_ra, file, +- page, page_index, +- readahead_pages); +- } +- + if (!PageUptodate(page)) { + ret = block_read_full_page(page, ocfs2_get_block); + if (ret) { +@@ -2999,7 +2989,8 @@ int ocfs2_duplicate_clusters_by_page(handle_t *handle, + } + } + +- ocfs2_map_and_dirty_page(inode, handle, from, to, ++ ocfs2_map_and_dirty_page(inode, ++ handle, from, to, + page, 0, &new_block); + mark_page_accessed(page); + unlock: +@@ -3015,12 +3006,11 @@ unlock: + } + + int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, +- struct file *file, ++ struct inode *inode, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len) + { + int ret = 0; +- struct inode *inode = file_inode(file); + struct super_block *sb = inode->i_sb; + struct ocfs2_caching_info *ci = INODE_CACHE(inode); + int i, blocks = ocfs2_clusters_to_blocks(sb, new_len); +@@ -3145,7 +3135,7 @@ static int ocfs2_replace_clusters(handle_t *handle, + + /*If the old clusters is unwritten, no need to duplicate. */ + if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { +- ret = context->cow_duplicate_clusters(handle, context->file, ++ ret = context->cow_duplicate_clusters(handle, context->inode, + cpos, old, new, len); + if (ret) { + mlog_errno(ret); +@@ -3423,35 +3413,12 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context) + return ret; + } + +-static void ocfs2_readahead_for_cow(struct inode *inode, +- struct file *file, +- u32 start, u32 len) +-{ +- struct address_space *mapping; +- pgoff_t index; +- unsigned long num_pages; +- int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits; +- +- if (!file) +- return; +- +- mapping = file->f_mapping; +- num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT; +- if (!num_pages) +- num_pages = 1; +- +- index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT; +- page_cache_sync_readahead(mapping, &file->f_ra, file, +- index, num_pages); +-} +- + /* + * Starting at cpos, try to CoW write_len clusters. Don't CoW + * past max_cpos. This will stop when it runs into a hole or an + * unrefcounted extent. + */ + static int ocfs2_refcount_cow_hunk(struct inode *inode, +- struct file *file, + struct buffer_head *di_bh, + u32 cpos, u32 write_len, u32 max_cpos) + { +@@ -3480,8 +3447,6 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, + + BUG_ON(cow_len == 0); + +- ocfs2_readahead_for_cow(inode, file, cow_start, cow_len); +- + context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); + if (!context) { + ret = -ENOMEM; +@@ -3503,7 +3468,6 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, + context->ref_root_bh = ref_root_bh; + context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; + context->get_clusters = ocfs2_di_get_clusters; +- context->file = file; + + ocfs2_init_dinode_extent_tree(&context->data_et, + INODE_CACHE(inode), di_bh); +@@ -3532,7 +3496,6 @@ out: + * clusters between cpos and cpos+write_len are safe to modify. + */ + int ocfs2_refcount_cow(struct inode *inode, +- struct file *file, + struct buffer_head *di_bh, + u32 cpos, u32 write_len, u32 max_cpos) + { +@@ -3552,7 +3515,7 @@ int ocfs2_refcount_cow(struct inode *inode, + num_clusters = write_len; + + if (ext_flags & OCFS2_EXT_REFCOUNTED) { +- ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos, ++ ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos, + num_clusters, max_cpos); + if (ret) { + mlog_errno(ret); +diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h +index 7754608..6422bbcdb 100644 +--- a/fs/ocfs2/refcounttree.h ++++ b/fs/ocfs2/refcounttree.h +@@ -53,7 +53,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, + int *credits, + int *ref_blocks); + int ocfs2_refcount_cow(struct inode *inode, +- struct file *filep, struct buffer_head *di_bh, ++ struct buffer_head *di_bh, + u32 cpos, u32 write_len, u32 max_cpos); + + typedef int (ocfs2_post_refcount_func)(struct inode *inode, +@@ -85,11 +85,11 @@ int ocfs2_refcount_cow_xattr(struct inode *inode, + u32 cpos, u32 write_len, + struct ocfs2_post_refcount *post); + int ocfs2_duplicate_clusters_by_page(handle_t *handle, +- struct file *file, ++ struct inode *inode, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len); + int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, +- struct file *file, ++ struct inode *inode, + u32 cpos, u32 old_cluster, + u32 new_cluster, u32 new_len); + int ocfs2_cow_sync_writeback(struct super_block *sb, diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index b7e74b5..19c6536 100644 --- a/fs/ocfs2/suballoc.c @@ -56263,7 +58453,7 @@ index 6b6a993..807cccc 100644 kfree(s); } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 3e636d8..83e3b71 100644 +index 3e636d8..350cc48 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -11,12 +11,19 @@ @@ -56430,6 +58620,34 @@ index 3e636d8..83e3b71 100644 mss.resident >> 10, (unsigned long)(mss.pss >> (10 + PSS_SHIFT)), mss.shared_clean >> 10, +@@ -792,14 +843,14 @@ typedef struct { + } pagemap_entry_t; + + struct pagemapread { +- int pos, len; ++ int pos, len; /* units: PM_ENTRY_BYTES, not bytes */ + pagemap_entry_t *buffer; + }; + + #define PAGEMAP_WALK_SIZE (PMD_SIZE) + #define PAGEMAP_WALK_MASK (PMD_MASK) + +-#define PM_ENTRY_BYTES sizeof(u64) ++#define PM_ENTRY_BYTES sizeof(pagemap_entry_t) + #define PM_STATUS_BITS 3 + #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) + #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) +@@ -1038,8 +1089,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, + if (!count) + goto out_task; + +- pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); +- pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); ++ pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); ++ pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY); + ret = -ENOMEM; + if (!pm.buffer) + goto out_task; @@ -1264,6 +1315,13 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) int n; char buffer[50]; @@ -56686,10 +58904,10 @@ index 2b7882b..1c5ef48 100644 /* balance leaf returns 0 except if combining L R and S into diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c -index 33532f7..4846ade 100644 +index 1d48974..2f8f4e0 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c -@@ -112,7 +112,7 @@ static int show_super(struct seq_file *m, struct super_block *sb) +@@ -114,7 +114,7 @@ static int show_super(struct seq_file *m, void *unused) "SMALL_TAILS " : "NO_TAILS ", replay_only(sb) ? "REPLAY_ONLY " : "", convert_reiserfs(sb) ? "CONV " : "", @@ -68342,6 +70560,36 @@ index a59ff51..2594a70 100644 #endif /* CONFIG_MMU */ #endif /* !__ASSEMBLY__ */ +diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h +index 13821c3..5672d7e 100644 +--- a/include/asm-generic/tlb.h ++++ b/include/asm-generic/tlb.h +@@ -112,7 +112,7 @@ struct mmu_gather { + + #define HAVE_GENERIC_MMU_GATHER + +-void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm); ++void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end); + void tlb_flush_mmu(struct mmu_gather *tlb); + void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, + unsigned long end); +diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h +index c184aa8..d049942 100644 +--- a/include/asm-generic/uaccess.h ++++ b/include/asm-generic/uaccess.h +@@ -343,4 +343,12 @@ clear_user(void __user *to, unsigned long n) + return __clear_user(to, n); + } + ++#ifndef __HAVE_ARCH_PAX_OPEN_USERLAND ++//static inline unsigned long pax_open_userland(void) { return 0; } ++#endif ++ ++#ifndef __HAVE_ARCH_PAX_CLOSE_USERLAND ++//static inline unsigned long pax_close_userland(void) { return 0; } ++#endif ++ + #endif /* __ASM_GENERIC_UACCESS_H */ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index eb58d2d..df131bf 100644 --- a/include/asm-generic/vmlinux.lds.h @@ -68631,7 +70879,7 @@ index 1186098..f87e53d 100644 /** * struct clk_init_data - holds init data that's common to all clocks and is diff --git a/include/linux/compat.h b/include/linux/compat.h -index 7f0c1dd..b5729c6 100644 +index 7f0c1dd..206ac34 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -312,7 +312,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, @@ -68652,6 +70900,14 @@ index 7f0c1dd..b5729c6 100644 asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, size_t); /* +@@ -669,6 +669,7 @@ asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, + + int compat_restore_altstack(const compat_stack_t __user *uss); + int __compat_save_altstack(compat_stack_t __user *, unsigned long); ++void __compat_save_altstack_ex(compat_stack_t __user *, unsigned long); + + asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, + struct compat_timespec __user *interval); diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 842de22..7f3a41f 100644 --- a/include/linux/compiler-gcc4.h @@ -70929,7 +73185,7 @@ index 3e203eb..3fe68d0 100644 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, u32 offset, struct device_node *); diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h -index 6883e19..06992b1 100644 +index 6883e19..e854fcb 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -15,7 +15,8 @@ @@ -70942,12 +73198,13 @@ index 6883e19..06992b1 100644 /* Lookup the address for a symbol. Returns 0 if not found. */ unsigned long kallsyms_lookup_name(const char *name); -@@ -106,6 +107,17 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u +@@ -106,6 +107,21 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u /* Stupid that this does nothing, but I didn't create this mess. */ #define __print_symbol(fmt, addr) #endif /*CONFIG_KALLSYMS*/ -+#else /* when included by kallsyms.c, vsnprintf.c, or ++#else /* when included by kallsyms.c, vsnprintf.c, kprobes.c, or + arch/x86/kernel/dumpstack.c, with HIDESYM enabled */ ++extern unsigned long kallsyms_lookup_name(const char *name); +extern void __print_symbol(const char *fmt, unsigned long address); +extern int sprint_backtrace(char *buffer, unsigned long address); +extern int sprint_symbol(char *buffer, unsigned long address); @@ -70956,6 +73213,9 @@ index 6883e19..06992b1 100644 + unsigned long *symbolsize, + unsigned long *offset, + char **modname, char *namebuf); ++extern int kallsyms_lookup_size_offset(unsigned long addr, ++ unsigned long *symbolsize, ++ unsigned long *offset); +#endif /* This macro allows us to keep printk typechecking */ @@ -71133,7 +73393,7 @@ index b83e565..baa6c1d 100644 * list_move - delete from one list and add as another's head * @list: the entry to move diff --git a/include/linux/math64.h b/include/linux/math64.h -index 2913b86..4209244 100644 +index 2913b86..8dcbb1e 100644 --- a/include/linux/math64.h +++ b/include/linux/math64.h @@ -15,7 +15,7 @@ @@ -71145,6 +73405,15 @@ index 2913b86..4209244 100644 { *remainder = dividend % divisor; return dividend / divisor; +@@ -33,7 +33,7 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) + /** + * div64_u64 - unsigned 64bit divide with 64bit divisor + */ +-static inline u64 div64_u64(u64 dividend, u64 divisor) ++static inline u64 __intentional_overflow(0) div64_u64(u64 dividend, u64 divisor) + { + return dividend / divisor; + } @@ -52,7 +52,7 @@ static inline s64 div64_s64(s64 dividend, s64 divisor) #define div64_ul(x, y) div_u64((x), (y)) @@ -72097,6 +74366,61 @@ index 4ea1d37..80f4b33 100644 /* * The return value from decompress routine is the length of the +diff --git a/include/linux/preempt.h b/include/linux/preempt.h +index f5d4723..a6ea2fa 100644 +--- a/include/linux/preempt.h ++++ b/include/linux/preempt.h +@@ -18,8 +18,13 @@ + # define sub_preempt_count(val) do { preempt_count() -= (val); } while (0) + #endif + ++#define raw_add_preempt_count(val) do { preempt_count() += (val); } while (0) ++#define raw_sub_preempt_count(val) do { preempt_count() -= (val); } while (0) ++ + #define inc_preempt_count() add_preempt_count(1) ++#define raw_inc_preempt_count() raw_add_preempt_count(1) + #define dec_preempt_count() sub_preempt_count(1) ++#define raw_dec_preempt_count() raw_sub_preempt_count(1) + + #define preempt_count() (current_thread_info()->preempt_count) + +@@ -64,6 +69,12 @@ do { \ + barrier(); \ + } while (0) + ++#define raw_preempt_disable() \ ++do { \ ++ raw_inc_preempt_count(); \ ++ barrier(); \ ++} while (0) ++ + #define sched_preempt_enable_no_resched() \ + do { \ + barrier(); \ +@@ -72,6 +83,12 @@ do { \ + + #define preempt_enable_no_resched() sched_preempt_enable_no_resched() + ++#define raw_preempt_enable_no_resched() \ ++do { \ ++ barrier(); \ ++ raw_dec_preempt_count(); \ ++} while (0) ++ + #define preempt_enable() \ + do { \ + preempt_enable_no_resched(); \ +@@ -116,8 +133,10 @@ do { \ + * region. + */ + #define preempt_disable() barrier() ++#define raw_preempt_disable() barrier() + #define sched_preempt_enable_no_resched() barrier() + #define preempt_enable_no_resched() barrier() ++#define raw_preempt_enable_no_resched() barrier() + #define preempt_enable() barrier() + + #define preempt_disable_notrace() barrier() diff --git a/include/linux/printk.h b/include/linux/printk.h index 22c7052..ad3fa0a 100644 --- a/include/linux/printk.h @@ -72629,6 +74953,18 @@ index 429c199..4d42e38 100644 }; /* shm_mode upper byte flags */ +diff --git a/include/linux/signal.h b/include/linux/signal.h +index d897484..323ba98 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -433,6 +433,7 @@ void signals_init(void); + + int restore_altstack(const stack_t __user *); + int __save_altstack(stack_t __user *, unsigned long); ++void __save_altstack_ex(stack_t __user *, unsigned long); + + #ifdef CONFIG_PROC_FS + struct seq_file; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index dec1748..112c1f9 100644 --- a/include/linux/skbuff.h @@ -72953,6 +75289,20 @@ index 027276f..092bfe8 100644 void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); #ifdef CONFIG_TRACING +diff --git a/include/linux/smp.h b/include/linux/smp.h +index c848876..11e8a84 100644 +--- a/include/linux/smp.h ++++ b/include/linux/smp.h +@@ -221,7 +221,9 @@ static inline void kick_all_cpus_sync(void) { } + #endif + + #define get_cpu() ({ preempt_disable(); smp_processor_id(); }) ++#define raw_get_cpu() ({ raw_preempt_disable(); raw_smp_processor_id(); }) + #define put_cpu() preempt_enable() ++#define raw_put_cpu_no_resched() raw_preempt_enable_no_resched() + + /* + * 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 54f91d3..be2c379 100644 --- a/include/linux/sock_diag.h @@ -75126,7 +77476,7 @@ index a67ef9d..2d17ed9 100644 #ifdef CONFIG_BLK_DEV_RAM int fd; diff --git a/init/main.c b/init/main.c -index 9484f4b..4c01430 100644 +index 9484f4b..0eac7c3 100644 --- a/init/main.c +++ b/init/main.c @@ -100,6 +100,8 @@ static inline void mark_rodata_ro(void) { } @@ -75138,7 +77488,7 @@ index 9484f4b..4c01430 100644 /* * Debug helper: via this flag we know that we are in 'early bootup code' * where only the boot processor is running with IRQ disabled. This means -@@ -153,6 +155,64 @@ static int __init set_reset_devices(char *str) +@@ -153,6 +155,74 @@ static int __init set_reset_devices(char *str) __setup("reset_devices", set_reset_devices); @@ -75153,11 +77503,10 @@ index 9484f4b..4c01430 100644 +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) -+unsigned long pax_user_shadow_base __read_only = 1UL << TASK_SIZE_MAX_SHIFT; ++unsigned long pax_user_shadow_base __read_only; +EXPORT_SYMBOL(pax_user_shadow_base); +extern char pax_enter_kernel_user[]; +extern char pax_exit_kernel_user[]; -+extern pgdval_t clone_pgd_mask; +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_PAX_MEMORY_UDEREF) @@ -75182,11 +77531,22 @@ index 9484f4b..4c01430 100644 + memcpy(pax_exit_kernel_user, (unsigned char []){0xc3}, 1); + clone_pgd_mask = ~(pgdval_t)0UL; + pax_user_shadow_base = 0UL; ++ setup_clear_cpu_cap(X86_FEATURE_PCID); +#endif + + return 0; +} +early_param("pax_nouderef", setup_pax_nouderef); ++ ++#ifdef CONFIG_X86_64 ++static int __init setup_pax_weakuderef(char *str) ++{ ++ if (clone_pgd_mask != ~(pgdval_t)0UL) ++ pax_user_shadow_base = 1UL << TASK_SIZE_MAX_SHIFT; ++ return 1; ++} ++__setup("pax_weakuderef", setup_pax_weakuderef); ++#endif +#endif + +#ifdef CONFIG_PAX_SOFTMODE @@ -75203,7 +77563,7 @@ index 9484f4b..4c01430 100644 static const char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; const char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; static const char *panic_later, *panic_param; -@@ -655,8 +715,6 @@ static void __init do_ctors(void) +@@ -655,8 +725,6 @@ static void __init do_ctors(void) bool initcall_debug; core_param(initcall_debug, initcall_debug, bool, 0644); @@ -75212,7 +77572,7 @@ index 9484f4b..4c01430 100644 static int __init_or_module do_one_initcall_debug(initcall_t fn) { ktime_t calltime, delta, rettime; -@@ -679,23 +737,22 @@ int __init_or_module do_one_initcall(initcall_t fn) +@@ -679,23 +747,22 @@ int __init_or_module do_one_initcall(initcall_t fn) { int count = preempt_count(); int ret; @@ -75240,7 +77600,7 @@ index 9484f4b..4c01430 100644 return ret; } -@@ -748,8 +805,14 @@ static void __init do_initcall_level(int level) +@@ -748,8 +815,14 @@ static void __init do_initcall_level(int level) level, level, &repair_env_string); @@ -75256,7 +77616,7 @@ index 9484f4b..4c01430 100644 } static void __init do_initcalls(void) -@@ -783,8 +846,14 @@ static void __init do_pre_smp_initcalls(void) +@@ -783,8 +856,14 @@ static void __init do_pre_smp_initcalls(void) { initcall_t *fn; @@ -75272,7 +77632,7 @@ index 9484f4b..4c01430 100644 } /* -@@ -802,8 +871,8 @@ static int run_init_process(const char *init_filename) +@@ -802,8 +881,8 @@ static int run_init_process(const char *init_filename) { argv_init[0] = init_filename; return do_execve(init_filename, @@ -75283,7 +77643,7 @@ index 9484f4b..4c01430 100644 } static noinline void __init kernel_init_freeable(void); -@@ -880,7 +949,7 @@ static noinline void __init kernel_init_freeable(void) +@@ -880,7 +959,7 @@ static noinline void __init kernel_init_freeable(void) do_basic_setup(); /* Open the /dev/console on the rootfs, this should never fail */ @@ -75292,7 +77652,7 @@ index 9484f4b..4c01430 100644 pr_err("Warning: unable to open an initial console.\n"); (void) sys_dup(0); -@@ -893,11 +962,13 @@ static noinline void __init kernel_init_freeable(void) +@@ -893,11 +972,13 @@ static noinline void __init kernel_init_freeable(void) if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; @@ -75721,10 +78081,10 @@ index f6c2ce5..982c0f9 100644 + return ns_capable_nolog(ns, cap) && kuid_has_mapping(ns, inode->i_uid); +} diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index c6e77ef..af531a0 100644 +index 2e9b387..61817b1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c -@@ -5391,7 +5391,7 @@ static int cgroup_css_links_read(struct cgroup *cont, +@@ -5398,7 +5398,7 @@ static int cgroup_css_links_read(struct cgroup *cont, struct css_set *cg = link->cg; struct task_struct *task; int count = 0; @@ -77144,10 +79504,20 @@ index 8241906..d625f2c 100644 kernel_cap_t new_cap; int err, i; diff --git a/kernel/kprobes.c b/kernel/kprobes.c -index bddf3b2..07b90dd 100644 +index bddf3b2..233bf40 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c -@@ -185,7 +185,7 @@ static kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c) +@@ -31,6 +31,9 @@ + * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi + * <prasanna@in.ibm.com> added function-return probes. + */ ++#ifdef CONFIG_GRKERNSEC_HIDESYM ++#define __INCLUDED_BY_HIDESYM 1 ++#endif + #include <linux/kprobes.h> + #include <linux/hash.h> + #include <linux/init.h> +@@ -185,7 +188,7 @@ static kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c) * kernel image and loaded module images reside. This is required * so x86_64 can correctly handle the %rip-relative fixups. */ @@ -77156,7 +79526,7 @@ index bddf3b2..07b90dd 100644 if (!kip->insns) { kfree(kip); return NULL; -@@ -225,7 +225,7 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) +@@ -225,7 +228,7 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) */ if (!list_is_singular(&kip->list)) { list_del(&kip->list); @@ -77165,7 +79535,7 @@ index bddf3b2..07b90dd 100644 kfree(kip); } return 1; -@@ -2083,7 +2083,7 @@ static int __init init_kprobes(void) +@@ -2083,7 +2086,7 @@ static int __init init_kprobes(void) { int i, err = 0; unsigned long offset = 0, size = 0; @@ -77174,7 +79544,7 @@ index bddf3b2..07b90dd 100644 const char *symbol_name; void *addr; struct kprobe_blackpoint *kb; -@@ -2168,11 +2168,11 @@ static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, +@@ -2168,11 +2171,11 @@ static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, kprobe_type = "k"; if (sym) @@ -77188,7 +79558,7 @@ index bddf3b2..07b90dd 100644 p->addr, kprobe_type, p->addr); if (!pp) -@@ -2209,7 +2209,7 @@ static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v) +@@ -2209,7 +2212,7 @@ static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v) const char *sym = NULL; unsigned int i = *(loff_t *) v; unsigned long offset = 0; @@ -79709,7 +82079,7 @@ index ce39224d..0e09343 100644 #define sched_class_highest (&stop_sched_class) #define for_each_class(class) \ diff --git a/kernel/signal.c b/kernel/signal.c -index 113411b..17190e2 100644 +index 113411b..20d0a99 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -51,12 +51,12 @@ static struct kmem_cache *sigqueue_cachep; @@ -79835,7 +82205,24 @@ index 113411b..17190e2 100644 if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { error = check_kill_permission(sig, info, p); /* -@@ -3240,8 +3271,8 @@ COMPAT_SYSCALL_DEFINE2(sigaltstack, +@@ -3219,6 +3250,16 @@ int __save_altstack(stack_t __user *uss, unsigned long sp) + __put_user(t->sas_ss_size, &uss->ss_size); + } + ++#ifdef CONFIG_X86 ++void __save_altstack_ex(stack_t __user *uss, unsigned long sp) ++{ ++ struct task_struct *t = current; ++ put_user_ex((void __user *)t->sas_ss_sp, &uss->ss_sp); ++ put_user_ex(sas_ss_flags(sp), &uss->ss_flags); ++ put_user_ex(t->sas_ss_size, &uss->ss_size); ++} ++#endif ++ + #ifdef CONFIG_COMPAT + COMPAT_SYSCALL_DEFINE2(sigaltstack, + const compat_stack_t __user *, uss_ptr, +@@ -3240,8 +3281,8 @@ COMPAT_SYSCALL_DEFINE2(sigaltstack, } seg = get_fs(); set_fs(KERNEL_DS); @@ -79846,6 +82233,23 @@ index 113411b..17190e2 100644 compat_user_stack_pointer()); set_fs(seg); if (ret >= 0 && uoss_ptr) { +@@ -3268,6 +3309,16 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp) + __put_user(sas_ss_flags(sp), &uss->ss_flags) | + __put_user(t->sas_ss_size, &uss->ss_size); + } ++ ++#ifdef CONFIG_X86 ++void __compat_save_altstack_ex(compat_stack_t __user *uss, unsigned long sp) ++{ ++ struct task_struct *t = current; ++ put_user_ex(ptr_to_compat((void __user *)t->sas_ss_sp), &uss->ss_sp); ++ put_user_ex(sas_ss_flags(sp), &uss->ss_flags); ++ put_user_ex(t->sas_ss_size, &uss->ss_size); ++} ++#endif + #endif + + #ifdef __ARCH_WANT_SYS_SIGPENDING diff --git a/kernel/smp.c b/kernel/smp.c index 4dba0f7..fe9f773 100644 --- a/kernel/smp.c @@ -80999,10 +83403,10 @@ index e444ff8..438b8f4 100644 *data_page = bpage; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index f7bc3ce..b8ef9b5 100644 +index 06a5bce..53ad6e7 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c -@@ -3303,7 +3303,7 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) +@@ -3347,7 +3347,7 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) return 0; } @@ -81162,10 +83566,10 @@ index b20428c..4845a10 100644 local_irq_save(flags); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c -index d8c30db..f2f6af5 100644 +index 9064b91..1f5d2f8 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c -@@ -79,6 +79,21 @@ int create_user_ns(struct cred *new) +@@ -82,6 +82,21 @@ int create_user_ns(struct cred *new) !kgid_has_mapping(parent_ns, group)) return -EPERM; @@ -81187,30 +83591,7 @@ index d8c30db..f2f6af5 100644 ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL); if (!ns) return -ENOMEM; -@@ -105,6 +120,7 @@ int create_user_ns(struct cred *new) - int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) - { - struct cred *cred; -+ int err; - - if (!(unshare_flags & CLONE_NEWUSER)) - return 0; -@@ -113,8 +129,12 @@ int unshare_userns(unsigned long unshare_flags, struct cred **new_cred) - if (!cred) - return -ENOMEM; - -- *new_cred = cred; -- return create_user_ns(cred); -+ err = create_user_ns(cred); -+ if (err) -+ put_cred(cred); -+ else -+ *new_cred = cred; -+ return err; - } - - void free_user_ns(struct user_namespace *ns) -@@ -853,7 +873,7 @@ static int userns_install(struct nsproxy *nsproxy, void *ns) +@@ -862,7 +877,7 @@ static int userns_install(struct nsproxy *nsproxy, void *ns) if (atomic_read(¤t->mm->mm_users) > 1) return -EINVAL; @@ -81246,10 +83627,10 @@ index 05039e3..17490c7 100644 .thread_should_run = watchdog_should_run, .thread_fn = watchdog, diff --git a/kernel/workqueue.c b/kernel/workqueue.c -index ee8e29a..410568e 100644 +index 6f01921..139869b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c -@@ -4584,7 +4584,7 @@ static void rebind_workers(struct worker_pool *pool) +@@ -4596,7 +4596,7 @@ static void rebind_workers(struct worker_pool *pool) WARN_ON_ONCE(!(worker_flags & WORKER_UNBOUND)); worker_flags |= WORKER_REBOUND; worker_flags &= ~WORKER_UNBOUND; @@ -82024,7 +84405,7 @@ index b32b70c..e512eb0 100644 set_page_address(page, (void *)vaddr); diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 5cf99bf..28634c8 100644 +index 5cf99bf..5c01c2f 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2022,15 +2022,17 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy, @@ -82069,6 +84450,15 @@ index 5cf99bf..28634c8 100644 if (ret) goto out; +@@ -2490,7 +2494,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, + + mm = vma->vm_mm; + +- tlb_gather_mmu(&tlb, mm, 0); ++ tlb_gather_mmu(&tlb, mm, start, end); + __unmap_hugepage_range(&tlb, vma, start, end, ref_page); + tlb_finish_mmu(&tlb, start, end); + } @@ -2545,6 +2549,27 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, return 1; } @@ -82159,7 +84549,7 @@ index 5cf99bf..28634c8 100644 if (!ptep) return VM_FAULT_OOM; diff --git a/mm/internal.h b/mm/internal.h -index 8562de0..7fdfe92 100644 +index 8562de0..92b2073 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -100,6 +100,7 @@ extern pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address); @@ -82170,6 +84560,15 @@ index 8562de0..7fdfe92 100644 extern void prep_compound_page(struct page *page, unsigned long order); #ifdef CONFIG_MEMORY_FAILURE extern bool is_free_buddy_page(struct page *page); +@@ -355,7 +356,7 @@ extern u32 hwpoison_filter_enable; + + extern unsigned long vm_mmap_pgoff(struct file *, unsigned long, + unsigned long, unsigned long, +- unsigned long, unsigned long); ++ unsigned long, unsigned long) __intentional_overflow(-1); + + extern void set_pageblock_order(void); + unsigned long reclaim_clean_pages_from_list(struct zone *zone, diff --git a/mm/kmemleak.c b/mm/kmemleak.c index c8d7f31..2dbeffd 100644 --- a/mm/kmemleak.c @@ -82412,10 +84811,39 @@ index ceb0c7f..b2b8e94 100644 } else { pr_info("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n", diff --git a/mm/memory.c b/mm/memory.c -index 5e50800..c47ba9a 100644 +index 5e50800..7c0340f 100644 --- a/mm/memory.c +++ b/mm/memory.c -@@ -429,6 +429,7 @@ static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud, +@@ -211,14 +211,15 @@ static int tlb_next_batch(struct mmu_gather *tlb) + * tear-down from @mm. The @fullmm argument is used when @mm is without + * users and we're going to destroy the full address space (exit/execve). + */ +-void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm) ++void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) + { + tlb->mm = mm; + +- tlb->fullmm = fullmm; ++ /* Is it from 0 to ~0? */ ++ tlb->fullmm = !(start | (end+1)); + tlb->need_flush_all = 0; +- tlb->start = -1UL; +- tlb->end = 0; ++ tlb->start = start; ++ tlb->end = end; + tlb->need_flush = 0; + tlb->local.next = NULL; + tlb->local.nr = 0; +@@ -258,8 +259,6 @@ void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long e + { + struct mmu_gather_batch *batch, *next; + +- tlb->start = start; +- tlb->end = end; + tlb_flush_mmu(tlb); + + /* keep the page table cache within bounds */ +@@ -429,6 +428,7 @@ static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud, free_pte_range(tlb, pmd, addr); } while (pmd++, addr = next, addr != end); @@ -82423,7 +84851,7 @@ index 5e50800..c47ba9a 100644 start &= PUD_MASK; if (start < floor) return; -@@ -443,6 +444,8 @@ static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud, +@@ -443,6 +443,8 @@ static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud, pmd = pmd_offset(pud, start); pud_clear(pud); pmd_free_tlb(tlb, pmd, start); @@ -82432,7 +84860,7 @@ index 5e50800..c47ba9a 100644 } static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, -@@ -462,6 +465,7 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, +@@ -462,6 +464,7 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, free_pmd_range(tlb, pud, addr, next, floor, ceiling); } while (pud++, addr = next, addr != end); @@ -82440,7 +84868,7 @@ index 5e50800..c47ba9a 100644 start &= PGDIR_MASK; if (start < floor) return; -@@ -476,6 +480,8 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, +@@ -476,6 +479,8 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, pud = pud_offset(pgd, start); pgd_clear(pgd); pud_free_tlb(tlb, pud, start); @@ -82449,7 +84877,65 @@ index 5e50800..c47ba9a 100644 } /* -@@ -1638,12 +1644,6 @@ no_page_table: +@@ -1101,7 +1106,6 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, + spinlock_t *ptl; + pte_t *start_pte; + pte_t *pte; +- unsigned long range_start = addr; + + again: + init_rss_vec(rss); +@@ -1204,17 +1208,25 @@ again: + * and page-free while holding it. + */ + if (force_flush) { ++ unsigned long old_end; ++ + force_flush = 0; + +-#ifdef HAVE_GENERIC_MMU_GATHER +- tlb->start = range_start; ++ /* ++ * Flush the TLB just for the previous segment, ++ * then update the range to be the remaining ++ * TLB range. ++ */ ++ old_end = tlb->end; + tlb->end = addr; +-#endif ++ + tlb_flush_mmu(tlb); +- if (addr != end) { +- range_start = addr; ++ ++ tlb->start = addr; ++ tlb->end = old_end; ++ ++ if (addr != end) + goto again; +- } + } + + return addr; +@@ -1399,7 +1411,7 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end = start + size; + + lru_add_drain(); +- tlb_gather_mmu(&tlb, mm, 0); ++ tlb_gather_mmu(&tlb, mm, start, end); + update_hiwater_rss(mm); + mmu_notifier_invalidate_range_start(mm, start, end); + for ( ; vma && vma->vm_start < end; vma = vma->vm_next) +@@ -1425,7 +1437,7 @@ static void zap_page_range_single(struct vm_area_struct *vma, unsigned long addr + unsigned long end = address + size; + + lru_add_drain(); +- tlb_gather_mmu(&tlb, mm, 0); ++ tlb_gather_mmu(&tlb, mm, address, end); + update_hiwater_rss(mm); + mmu_notifier_invalidate_range_start(mm, address, end); + unmap_single_vma(&tlb, vma, address, end, details); +@@ -1638,12 +1650,6 @@ no_page_table: return page; } @@ -82462,7 +84948,7 @@ index 5e50800..c47ba9a 100644 /** * __get_user_pages() - pin user pages in memory * @tsk: task_struct of target task -@@ -1730,10 +1730,10 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, +@@ -1730,10 +1736,10 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, i = 0; @@ -82475,7 +84961,7 @@ index 5e50800..c47ba9a 100644 if (!vma && in_gate_area(mm, start)) { unsigned long pg = start & PAGE_MASK; pgd_t *pgd; -@@ -1782,7 +1782,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, +@@ -1782,7 +1788,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, goto next_page; } @@ -82484,7 +84970,7 @@ index 5e50800..c47ba9a 100644 (vma->vm_flags & (VM_IO | VM_PFNMAP)) || !(vm_flags & vma->vm_flags)) return i ? : -EFAULT; -@@ -1811,11 +1811,6 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, +@@ -1811,11 +1817,6 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, int ret; unsigned int fault_flags = 0; @@ -82496,7 +84982,7 @@ index 5e50800..c47ba9a 100644 if (foll_flags & FOLL_WRITE) fault_flags |= FAULT_FLAG_WRITE; if (nonblocking) -@@ -1895,7 +1890,7 @@ next_page: +@@ -1895,7 +1896,7 @@ next_page: start += page_increm * PAGE_SIZE; nr_pages -= page_increm; } while (nr_pages && start < vma->vm_end); @@ -82505,7 +84991,7 @@ index 5e50800..c47ba9a 100644 return i; } EXPORT_SYMBOL(__get_user_pages); -@@ -2102,6 +2097,10 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr, +@@ -2102,6 +2103,10 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr, page_add_file_rmap(page); set_pte_at(mm, addr, pte, mk_pte(page, prot)); @@ -82516,7 +85002,7 @@ index 5e50800..c47ba9a 100644 retval = 0; pte_unmap_unlock(pte, ptl); return retval; -@@ -2146,9 +2145,21 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, +@@ -2146,9 +2151,21 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, if (!page_count(page)) return -EINVAL; if (!(vma->vm_flags & VM_MIXEDMAP)) { @@ -82538,7 +85024,7 @@ index 5e50800..c47ba9a 100644 } return insert_page(vma, addr, page, vma->vm_page_prot); } -@@ -2231,6 +2242,7 @@ int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, +@@ -2231,6 +2248,7 @@ int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) { BUG_ON(!(vma->vm_flags & VM_MIXEDMAP)); @@ -82546,7 +85032,7 @@ index 5e50800..c47ba9a 100644 if (addr < vma->vm_start || addr >= vma->vm_end) return -EFAULT; -@@ -2478,7 +2490,9 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud, +@@ -2478,7 +2496,9 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud, BUG_ON(pud_huge(*pud)); @@ -82557,7 +85043,7 @@ index 5e50800..c47ba9a 100644 if (!pmd) return -ENOMEM; do { -@@ -2498,7 +2512,9 @@ static int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd, +@@ -2498,7 +2518,9 @@ static int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd, unsigned long next; int err; @@ -82568,7 +85054,7 @@ index 5e50800..c47ba9a 100644 if (!pud) return -ENOMEM; do { -@@ -2586,6 +2602,186 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo +@@ -2586,6 +2608,186 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo copy_user_highpage(dst, src, va, vma); } @@ -82755,7 +85241,7 @@ index 5e50800..c47ba9a 100644 /* * This routine handles present pages, when users try to write * to a shared page. It is done by copying the page to a new address -@@ -2802,6 +2998,12 @@ gotten: +@@ -2802,6 +3004,12 @@ gotten: */ page_table = pte_offset_map_lock(mm, pmd, address, &ptl); if (likely(pte_same(*page_table, orig_pte))) { @@ -82768,7 +85254,7 @@ index 5e50800..c47ba9a 100644 if (old_page) { if (!PageAnon(old_page)) { dec_mm_counter_fast(mm, MM_FILEPAGES); -@@ -2853,6 +3055,10 @@ gotten: +@@ -2853,6 +3061,10 @@ gotten: page_remove_rmap(old_page); } @@ -82779,7 +85265,7 @@ index 5e50800..c47ba9a 100644 /* Free the old page.. */ new_page = old_page; ret |= VM_FAULT_WRITE; -@@ -3128,6 +3334,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3128,6 +3340,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, swap_free(entry); if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) try_to_free_swap(page); @@ -82791,7 +85277,7 @@ index 5e50800..c47ba9a 100644 unlock_page(page); if (page != swapcache) { /* -@@ -3151,6 +3362,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3151,6 +3368,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, /* No need to invalidate - it was non-present before */ update_mmu_cache(vma, address, page_table); @@ -82803,7 +85289,7 @@ index 5e50800..c47ba9a 100644 unlock: pte_unmap_unlock(page_table, ptl); out: -@@ -3170,40 +3386,6 @@ out_release: +@@ -3170,40 +3392,6 @@ out_release: } /* @@ -82844,7 +85330,7 @@ index 5e50800..c47ba9a 100644 * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurrent faults), and pte mapped but not yet locked. * We return with mmap_sem still held, but pte unmapped and unlocked. -@@ -3212,27 +3394,23 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3212,27 +3400,23 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, pte_t *page_table, pmd_t *pmd, unsigned int flags) { @@ -82877,7 +85363,7 @@ index 5e50800..c47ba9a 100644 if (unlikely(anon_vma_prepare(vma))) goto oom; page = alloc_zeroed_user_highpage_movable(vma, address); -@@ -3256,6 +3434,11 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3256,6 +3440,11 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, if (!pte_none(*page_table)) goto release; @@ -82889,7 +85375,7 @@ index 5e50800..c47ba9a 100644 inc_mm_counter_fast(mm, MM_ANONPAGES); page_add_new_anon_rmap(page, vma, address); setpte: -@@ -3263,6 +3446,12 @@ setpte: +@@ -3263,6 +3452,12 @@ setpte: /* No need to invalidate - it was non-present before */ update_mmu_cache(vma, address, page_table); @@ -82902,7 +85388,7 @@ index 5e50800..c47ba9a 100644 unlock: pte_unmap_unlock(page_table, ptl); return 0; -@@ -3406,6 +3595,12 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3406,6 +3601,12 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, */ /* Only go through if we didn't race with anybody else... */ if (likely(pte_same(*page_table, orig_pte))) { @@ -82915,7 +85401,7 @@ index 5e50800..c47ba9a 100644 flush_icache_page(vma, page); entry = mk_pte(page, vma->vm_page_prot); if (flags & FAULT_FLAG_WRITE) -@@ -3425,6 +3620,14 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3425,6 +3626,14 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, /* no need to invalidate: a not-present page won't be cached */ update_mmu_cache(vma, address, page_table); @@ -82930,7 +85416,7 @@ index 5e50800..c47ba9a 100644 } else { if (cow_page) mem_cgroup_uncharge_page(cow_page); -@@ -3746,6 +3949,12 @@ int handle_pte_fault(struct mm_struct *mm, +@@ -3746,6 +3955,12 @@ int handle_pte_fault(struct mm_struct *mm, if (flags & FAULT_FLAG_WRITE) flush_tlb_fix_spurious_fault(vma, address); } @@ -82943,7 +85429,7 @@ index 5e50800..c47ba9a 100644 unlock: pte_unmap_unlock(pte, ptl); return 0; -@@ -3762,6 +3971,10 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3762,6 +3977,10 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, pmd_t *pmd; pte_t *pte; @@ -82954,7 +85440,7 @@ index 5e50800..c47ba9a 100644 __set_current_state(TASK_RUNNING); count_vm_event(PGFAULT); -@@ -3773,6 +3986,34 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -3773,6 +3992,34 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(is_vm_hugetlb_page(vma))) return hugetlb_fault(mm, vma, address, flags); @@ -82989,7 +85475,7 @@ index 5e50800..c47ba9a 100644 retry: pgd = pgd_offset(mm, address); pud = pud_alloc(mm, pgd, address); -@@ -3871,6 +4112,23 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) +@@ -3871,6 +4118,23 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) spin_unlock(&mm->page_table_lock); return 0; } @@ -83013,7 +85499,7 @@ index 5e50800..c47ba9a 100644 #endif /* __PAGETABLE_PUD_FOLDED */ #ifndef __PAGETABLE_PMD_FOLDED -@@ -3901,6 +4159,30 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) +@@ -3901,6 +4165,30 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) spin_unlock(&mm->page_table_lock); return 0; } @@ -83044,7 +85530,7 @@ index 5e50800..c47ba9a 100644 #endif /* __PAGETABLE_PMD_FOLDED */ #if !defined(__HAVE_ARCH_GATE_AREA) -@@ -3914,7 +4196,7 @@ static int __init gate_vma_init(void) +@@ -3914,7 +4202,7 @@ static int __init gate_vma_init(void) gate_vma.vm_start = FIXADDR_USER_START; gate_vma.vm_end = FIXADDR_USER_END; gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; @@ -83053,7 +85539,7 @@ index 5e50800..c47ba9a 100644 return 0; } -@@ -4048,8 +4330,8 @@ out: +@@ -4048,8 +4336,8 @@ out: return ret; } @@ -83064,7 +85550,7 @@ index 5e50800..c47ba9a 100644 { resource_size_t phys_addr; unsigned long prot = 0; -@@ -4074,8 +4356,8 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, +@@ -4074,8 +4362,8 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, * Access another process' address space as given in mm. If non-NULL, use the * given task for page fault accounting. */ @@ -83075,7 +85561,7 @@ index 5e50800..c47ba9a 100644 { struct vm_area_struct *vma; void *old_buf = buf; -@@ -4083,7 +4365,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, +@@ -4083,7 +4371,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, down_read(&mm->mmap_sem); /* ignore errors, just check how much was successfully transferred */ while (len) { @@ -83084,7 +85570,7 @@ index 5e50800..c47ba9a 100644 void *maddr; struct page *page = NULL; -@@ -4142,8 +4424,8 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, +@@ -4142,8 +4430,8 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, * * The caller must hold a reference on @mm. */ @@ -83095,7 +85581,7 @@ index 5e50800..c47ba9a 100644 { return __access_remote_vm(NULL, mm, addr, buf, len, write); } -@@ -4153,11 +4435,11 @@ int access_remote_vm(struct mm_struct *mm, unsigned long addr, +@@ -4153,11 +4441,11 @@ int access_remote_vm(struct mm_struct *mm, unsigned long addr, * Source/target buffer must be kernel space, * Do not walk the page table directly, use get_user_pages */ @@ -83272,7 +85758,7 @@ index 79b7cf7..9944291 100644 capable(CAP_IPC_LOCK)) ret = do_mlockall(flags); diff --git a/mm/mmap.c b/mm/mmap.c -index 7dbe397..e84c411 100644 +index 7dbe397..bfb7626 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -36,6 +36,7 @@ @@ -84141,6 +86627,15 @@ index 7dbe397..e84c411 100644 if (vma->vm_flags & VM_ACCOUNT) nr_accounted += nrpages; vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); +@@ -2356,7 +2728,7 @@ static void unmap_region(struct mm_struct *mm, + struct mmu_gather tlb; + + lru_add_drain(); +- tlb_gather_mmu(&tlb, mm, 0); ++ tlb_gather_mmu(&tlb, mm, start, end); + update_hiwater_rss(mm); + unmap_vmas(&tlb, vma, start, end); + free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, @@ -2379,6 +2751,16 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, insertion_point = (prev ? &prev->vm_next : &mm->mmap); vma->vm_prev = NULL; @@ -84446,6 +86941,15 @@ index 7dbe397..e84c411 100644 return addr; } +@@ -2735,7 +3232,7 @@ void exit_mmap(struct mm_struct *mm) + + lru_add_drain(); + flush_cache_mm(mm); +- tlb_gather_mmu(&tlb, mm, 1); ++ tlb_gather_mmu(&tlb, mm, 0, -1); + /* update_hiwater_rss(mm) here? but nobody should be looking */ + /* Use -1 here to ensure all VMAs in the mm are unmapped */ + unmap_vmas(&tlb, vma, 0, -1); @@ -2750,6 +3247,7 @@ void exit_mmap(struct mm_struct *mm) while (vma) { if (vma->vm_flags & VM_ACCOUNT) @@ -86930,6 +89434,89 @@ index f680ee1..97e3542 100644 if (batadv_ogm_packet->flags & BATADV_DIRECTLINK) has_directlink_flag = 1; +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index de27b31..7058bfe 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -1522,6 +1522,8 @@ out: + * in these cases, the skb is further handled by this function and + * returns 1, otherwise it returns 0 and the caller shall further + * process the skb. ++ * ++ * This call might reallocate skb data. + */ + int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid) + { +diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c +index f105219..7614af3 100644 +--- a/net/batman-adv/gateway_client.c ++++ b/net/batman-adv/gateway_client.c +@@ -508,6 +508,7 @@ out: + return 0; + } + ++/* this call might reallocate skb data */ + static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len) + { + int ret = false; +@@ -568,6 +569,7 @@ out: + return ret; + } + ++/* this call might reallocate skb data */ + bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) + { + struct ethhdr *ethhdr; +@@ -619,6 +621,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) + + if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) + return false; ++ ++ /* skb->data might have been reallocated by pskb_may_pull() */ ++ ethhdr = (struct ethhdr *)skb->data; ++ if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) ++ ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); ++ + udphdr = (struct udphdr *)(skb->data + *header_len); + *header_len += sizeof(*udphdr); + +@@ -634,12 +642,14 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) + return true; + } + ++/* this call might reallocate skb data */ + bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, +- struct sk_buff *skb, struct ethhdr *ethhdr) ++ struct sk_buff *skb) + { + struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; + struct batadv_orig_node *orig_dst_node = NULL; + struct batadv_gw_node *curr_gw = NULL; ++ struct ethhdr *ethhdr; + bool ret, out_of_range = false; + unsigned int header_len = 0; + uint8_t curr_tq_avg; +@@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, + if (!ret) + goto out; + ++ ethhdr = (struct ethhdr *)skb->data; + orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, + ethhdr->h_dest); + if (!orig_dst_node) +diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h +index 039902d..1037d75 100644 +--- a/net/batman-adv/gateway_client.h ++++ b/net/batman-adv/gateway_client.h +@@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv, + void batadv_gw_node_purge(struct batadv_priv *bat_priv); + int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset); + bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len); +-bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, +- struct sk_buff *skb, struct ethhdr *ethhdr); ++bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb); + + #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 522243a..b48c0ef 100644 --- a/net/batman-adv/hard-interface.c @@ -86953,10 +89540,31 @@ index 522243a..b48c0ef 100644 return hard_iface; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c -index 819dfb0..9a672d1 100644 +index 819dfb0..226bacd 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c -@@ -253,7 +253,7 @@ static int batadv_interface_tx(struct sk_buff *skb, +@@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb, + if (batadv_bla_tx(bat_priv, skb, vid)) + goto dropped; + ++ /* skb->data might have been reallocated by batadv_bla_tx() */ ++ ethhdr = (struct ethhdr *)skb->data; ++ + /* Register the client MAC in the transtable */ + if (!is_multicast_ether_addr(ethhdr->h_source)) + batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); +@@ -220,6 +223,10 @@ static int batadv_interface_tx(struct sk_buff *skb, + default: + break; + } ++ ++ /* reminder: ethhdr might have become unusable from here on ++ * (batadv_gw_is_dhcp_target() might have reallocated skb data) ++ */ + } + + /* ethernet packet should be broadcasted */ +@@ -253,7 +260,7 @@ static int batadv_interface_tx(struct sk_buff *skb, primary_if->net_dev->dev_addr, ETH_ALEN); /* set broadcast sequence number */ @@ -86965,7 +89573,16 @@ index 819dfb0..9a672d1 100644 bcast_packet->seqno = htonl(seqno); batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay); -@@ -472,7 +472,7 @@ static int batadv_softif_init_late(struct net_device *dev) +@@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb, + /* unicast packet */ + } else { + if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) { +- ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr); ++ ret = batadv_gw_out_of_range(bat_priv, skb); + if (ret) + goto dropped; + } +@@ -472,7 +479,7 @@ static int batadv_softif_init_late(struct net_device *dev) atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN); atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); @@ -87006,7 +89623,7 @@ index aba8364..50fcbb8 100644 atomic_t batman_queue_left; char num_ifaces; diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c -index 0bb3b59..ffcbf2f 100644 +index 0bb3b59..0e3052e 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -270,7 +270,7 @@ int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv, @@ -87018,6 +89635,58 @@ index 0bb3b59..ffcbf2f 100644 frag1->seqno = htons(seqno - 1); frag2->seqno = htons(seqno); +@@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size, + * @skb: the skb containing the payload to encapsulate + * @orig_node: the destination node + * +- * Returns false if the payload could not be encapsulated or true otherwise ++ * Returns false if the payload could not be encapsulated or true otherwise. ++ * ++ * This call might reallocate skb data. + */ + static bool batadv_unicast_prepare_skb(struct sk_buff *skb, + struct batadv_orig_node *orig_node) +@@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb, + * @orig_node: the destination node + * @packet_subtype: the batman 4addr packet subtype to use + * +- * Returns false if the payload could not be encapsulated or true otherwise ++ * Returns false if the payload could not be encapsulated or true otherwise. ++ * ++ * This call might reallocate skb data. + */ + bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv, + struct sk_buff *skb, +@@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, + struct batadv_neigh_node *neigh_node; + int data_len = skb->len; + int ret = NET_RX_DROP; +- unsigned int dev_mtu; ++ unsigned int dev_mtu, header_len; + + /* get routing information */ + if (is_multicast_ether_addr(ethhdr->h_dest)) { +@@ -429,10 +433,12 @@ find_router: + switch (packet_type) { + case BATADV_UNICAST: + batadv_unicast_prepare_skb(skb, orig_node); ++ header_len = sizeof(struct batadv_unicast_packet); + break; + case BATADV_UNICAST_4ADDR: + batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node, + packet_subtype); ++ header_len = sizeof(struct batadv_unicast_4addr_packet); + break; + default: + /* this function supports UNICAST and UNICAST_4ADDR only. It +@@ -441,6 +447,7 @@ find_router: + goto out; + } + ++ ethhdr = (struct ethhdr *)(skb->data + header_len); + unicast_packet = (struct batadv_unicast_packet *)skb->data; + + /* inform the destination node that we are still missing a correct route diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ace5e55..a65a1c0 100644 --- a/net/bluetooth/hci_core.c @@ -87739,7 +90408,7 @@ index f9765203..9feaef8 100644 return error; } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c -index a08bd2b..4e8f43c 100644 +index a08bd2b..c59bd7c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -58,7 +58,7 @@ struct rtnl_link { @@ -87777,6 +90446,15 @@ index a08bd2b..4e8f43c 100644 } EXPORT_SYMBOL_GPL(__rtnl_link_unregister); +@@ -2374,7 +2377,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) + struct nlattr *extfilt; + u32 filter_mask = 0; + +- extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct rtgenmsg), ++ extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg), + IFLA_EXT_MASK); + if (extfilt) + filter_mask = nla_get_u32(extfilt); diff --git a/net/core/scm.c b/net/core/scm.c index 03795d0..eaf7368 100644 --- a/net/core/scm.c @@ -88223,9 +90901,18 @@ index dfc39d4..0d4fa52 100644 #endif if (dflt != &ipv4_devconf_dflt) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c -index 4cfe34d..a6ba66e 100644 +index 4cfe34d..d2fac8a 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c +@@ -477,7 +477,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) + } + + return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - +- net_adj) & ~(align - 1)) + (net_adj - 2); ++ net_adj) & ~(align - 1)) + net_adj - 2; + } + + static void esp4_err(struct sk_buff *skb, u32 info) @@ -503,7 +503,7 @@ static void esp4_err(struct sk_buff *skb, u32 info) return; @@ -88276,6 +90963,30 @@ index 8f6cb7a..34507f9 100644 return nh->nh_saddr; } +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 49616fe..6e8a13d 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -71,7 +71,6 @@ + #include <linux/init.h> + #include <linux/list.h> + #include <linux/slab.h> +-#include <linux/prefetch.h> + #include <linux/export.h> + #include <net/net_namespace.h> + #include <net/ip.h> +@@ -1761,10 +1760,8 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) + if (!c) + continue; + +- if (IS_LEAF(c)) { +- prefetch(rcu_dereference_rtnl(p->child[idx])); ++ if (IS_LEAF(c)) + return (struct leaf *) c; +- } + + /* Rescan start scanning in new node */ + p = (struct tnode *) c; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 6acb541..9ea617d 100644 --- a/net/ipv4/inet_connection_sock.c @@ -88385,7 +91096,7 @@ index b66910a..cfe416e 100644 return -ENOMEM; } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c -index 855004f..68e7458 100644 +index 855004f..9644112 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -115,7 +115,7 @@ static bool log_ecn_error = true; @@ -88397,6 +91108,15 @@ index 855004f..68e7458 100644 static int ipgre_tunnel_init(struct net_device *dev); static int ipgre_net_id __read_mostly; +@@ -572,7 +572,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, + if (daddr) + memcpy(&iph->daddr, daddr, 4); + if (iph->daddr) +- return t->hlen; ++ return t->hlen + sizeof(*iph); + + return -(t->hlen + sizeof(*iph)); + } @@ -919,7 +919,7 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, }; @@ -88749,10 +91469,10 @@ index d35bbf0..faa3ab8 100644 sizeof(net->ipv4.dev_addr_genid)); return 0; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c -index fa2f63f..6554815 100644 +index 3f25e75..3ae0f4d 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c -@@ -55,7 +55,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, +@@ -57,7 +57,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, { int ret; int range[2]; @@ -88761,7 +91481,7 @@ index fa2f63f..6554815 100644 .data = &range, .maxlen = sizeof(range), .mode = table->mode, -@@ -108,7 +108,7 @@ static int ipv4_ping_group_range(ctl_table *table, int write, +@@ -110,7 +110,7 @@ static int ipv4_ping_group_range(ctl_table *table, int write, int ret; gid_t urange[2]; kgid_t low, high; @@ -88770,7 +91490,7 @@ index fa2f63f..6554815 100644 .data = &urange, .maxlen = sizeof(urange), .mode = table->mode, -@@ -139,7 +139,7 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, +@@ -141,7 +141,7 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { char val[TCP_CA_NAME_MAX]; @@ -88779,7 +91499,7 @@ index fa2f63f..6554815 100644 .data = val, .maxlen = TCP_CA_NAME_MAX, }; -@@ -158,7 +158,7 @@ static int proc_tcp_available_congestion_control(ctl_table *ctl, +@@ -160,7 +160,7 @@ static int proc_tcp_available_congestion_control(ctl_table *ctl, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -88788,7 +91508,7 @@ index fa2f63f..6554815 100644 int ret; tbl.data = kmalloc(tbl.maxlen, GFP_USER); -@@ -175,7 +175,7 @@ static int proc_allowed_congestion_control(ctl_table *ctl, +@@ -177,7 +177,7 @@ static int proc_allowed_congestion_control(ctl_table *ctl, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -88797,7 +91517,7 @@ index fa2f63f..6554815 100644 int ret; tbl.data = kmalloc(tbl.maxlen, GFP_USER); -@@ -201,15 +201,17 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, +@@ -203,15 +203,17 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, struct mem_cgroup *memcg; #endif @@ -88818,7 +91538,7 @@ index fa2f63f..6554815 100644 } ret = proc_doulongvec_minmax(&tmp, write, buffer, lenp, ppos); -@@ -236,7 +238,7 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, +@@ -238,7 +240,7 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, static int proc_tcp_fastopen_key(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -88827,7 +91547,7 @@ index fa2f63f..6554815 100644 struct tcp_fastopen_context *ctxt; int ret; u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ -@@ -477,7 +479,7 @@ static struct ctl_table ipv4_table[] = { +@@ -481,7 +483,7 @@ static struct ctl_table ipv4_table[] = { }, { .procname = "ip_local_reserved_ports", @@ -88836,7 +91556,7 @@ index fa2f63f..6554815 100644 .maxlen = 65536, .mode = 0644, .proc_handler = proc_do_large_bitmap, -@@ -842,11 +844,10 @@ static struct ctl_table ipv4_net_table[] = { +@@ -846,11 +848,10 @@ static struct ctl_table ipv4_net_table[] = { static __net_init int ipv4_sysctl_init_net(struct net *net) { @@ -88850,7 +91570,7 @@ index fa2f63f..6554815 100644 if (table == NULL) goto err_alloc; -@@ -881,15 +882,17 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) +@@ -885,15 +886,17 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) tcp_init_mem(net); @@ -88871,7 +91591,7 @@ index fa2f63f..6554815 100644 err_alloc: return -ENOMEM; } -@@ -911,16 +914,6 @@ static __net_initdata struct pernet_operations ipv4_sysctl_ops = { +@@ -915,16 +918,6 @@ static __net_initdata struct pernet_operations ipv4_sysctl_ops = { static __init int sysctl_ipv4_init(void) { struct ctl_table_header *hdr; @@ -89269,6 +91989,19 @@ index fb8c94c..fb18024 100644 int ret; /* +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 40ffd72..aeac0dc 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -425,7 +425,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) + net_adj = 0; + + return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - +- net_adj) & ~(align - 1)) + (net_adj - 2); ++ net_adj) & ~(align - 1)) + net_adj - 2; + } + + static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b4ff0a4..db9b764 100644 --- a/net/ipv6/icmp.c @@ -89887,10 +92620,10 @@ index 4fe76ff..426a904 100644 }; diff --git a/net/key/af_key.c b/net/key/af_key.c -index 9da8620..97070ad 100644 +index ab8bd2c..cd2d641 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c -@@ -3047,10 +3047,10 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, const struc +@@ -3048,10 +3048,10 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, const struc static u32 get_acqseq(void) { u32 res; @@ -89904,10 +92637,10 @@ index 9da8620..97070ad 100644 return res; } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index 4fdb306e..920086a 100644 +index ae36f8e..09d42ac 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -804,7 +804,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, +@@ -806,7 +806,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, ret = ieee80211_vif_use_channel(sdata, chandef, IEEE80211_CHANCTX_EXCLUSIVE); } @@ -89916,7 +92649,7 @@ index 4fdb306e..920086a 100644 local->_oper_chandef = *chandef; ieee80211_hw_config(local, 0); } -@@ -2920,7 +2920,7 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, +@@ -2922,7 +2922,7 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, else local->probe_req_reg--; @@ -89925,7 +92658,7 @@ index 4fdb306e..920086a 100644 break; ieee80211_queue_work(&local->hw, &local->reconfig_filter); -@@ -3383,8 +3383,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, +@@ -3385,8 +3385,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, if (chanctx_conf) { *chandef = chanctx_conf->def; ret = 0; @@ -90047,7 +92780,7 @@ index 8a7bfc4..4407cd0 100644 /* * Goal: diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c -index 7fc5d0d..07ea536 100644 +index 3401262..d5cd68d 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -12,7 +12,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) @@ -90068,7 +92801,7 @@ index 7fc5d0d..07ea536 100644 if (local->wowlan) { int err = drv_suspend(local, wowlan); if (err < 0) { -@@ -113,7 +113,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) +@@ -116,7 +116,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) WARN_ON(!list_empty(&local->chanctx_list)); /* stop hardware - this must stop RX */ @@ -90471,6 +93204,49 @@ index a99b6c3..3841268 100644 return -NF_ACCEPT; } +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 4d4d8f1..e0f9a32 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -526,7 +526,7 @@ static bool tcp_in_window(const struct nf_conn *ct, + const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; + __u32 seq, ack, sack, end, win, swin; + s16 receiver_offset; +- bool res; ++ bool res, in_recv_win; + + /* + * Get the required data from the packet. +@@ -649,14 +649,18 @@ static bool tcp_in_window(const struct nf_conn *ct, + receiver->td_end, receiver->td_maxend, receiver->td_maxwin, + receiver->td_scale); + ++ /* Is the ending sequence in the receive window (if available)? */ ++ in_recv_win = !receiver->td_maxwin || ++ after(end, sender->td_end - receiver->td_maxwin - 1); ++ + pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n", + before(seq, sender->td_maxend + 1), +- after(end, sender->td_end - receiver->td_maxwin - 1), ++ (in_recv_win ? 1 : 0), + before(sack, receiver->td_end + 1), + after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)); + + if (before(seq, sender->td_maxend + 1) && +- after(end, sender->td_end - receiver->td_maxwin - 1) && ++ in_recv_win && + before(sack, receiver->td_end + 1) && + after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) { + /* +@@ -725,7 +729,7 @@ static bool tcp_in_window(const struct nf_conn *ct, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, + "nf_ct_tcp: %s ", + before(seq, sender->td_maxend + 1) ? +- after(end, sender->td_end - receiver->td_maxwin - 1) ? ++ in_recv_win ? + before(sack, receiver->td_end + 1) ? + after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG" + : "ACK is under the lower bound (possible overly delayed ACK)" diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index bd700b4..4a3dc61 100644 --- a/net/netfilter/nf_conntrack_standalone.c @@ -90553,7 +93329,7 @@ index f042ae5..30ea486 100644 } EXPORT_SYMBOL(nf_unregister_sockopt); diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c -index 962e979..d4ae2e9 100644 +index 962e979..e46f350 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -82,7 +82,7 @@ static int nfnl_log_net_id __read_mostly; @@ -90565,7 +93341,27 @@ index 962e979..d4ae2e9 100644 }; static struct nfnl_log_net *nfnl_log_pernet(struct net *net) -@@ -559,7 +559,7 @@ __build_packet_message(struct nfnl_log_net *log, +@@ -419,6 +419,7 @@ __build_packet_message(struct nfnl_log_net *log, + nfmsg->version = NFNETLINK_V0; + nfmsg->res_id = htons(inst->group_num); + ++ memset(&pmsg, 0, sizeof(pmsg)); + pmsg.hw_protocol = skb->protocol; + pmsg.hook = hooknum; + +@@ -498,7 +499,10 @@ __build_packet_message(struct nfnl_log_net *log, + if (indev && skb->dev && + skb->mac_header != skb->network_header) { + struct nfulnl_msg_packet_hw phw; +- int len = dev_parse_header(skb, phw.hw_addr); ++ int len; ++ ++ memset(&phw, 0, sizeof(phw)); ++ len = dev_parse_header(skb, phw.hw_addr); + if (len > 0) { + phw.hw_addrlen = htons(len); + if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) +@@ -559,7 +563,7 @@ __build_packet_message(struct nfnl_log_net *log, /* global sequence number */ if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) && nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL, @@ -90574,6 +93370,130 @@ index 962e979..d4ae2e9 100644 goto nla_put_failure; if (data_len) { +diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c +index 5352b2d..e0083ce 100644 +--- a/net/netfilter/nfnetlink_queue_core.c ++++ b/net/netfilter/nfnetlink_queue_core.c +@@ -444,7 +444,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, + if (indev && entskb->dev && + entskb->mac_header != entskb->network_header) { + struct nfqnl_msg_packet_hw phw; +- int len = dev_parse_header(entskb, phw.hw_addr); ++ int len; ++ ++ memset(&phw, 0, sizeof(phw)); ++ len = dev_parse_header(entskb, phw.hw_addr); + if (len) { + phw.hw_addrlen = htons(len); + if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw)) +diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c +index 7011c71..6113cc7 100644 +--- a/net/netfilter/xt_TCPMSS.c ++++ b/net/netfilter/xt_TCPMSS.c +@@ -52,7 +52,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, + { + const struct xt_tcpmss_info *info = par->targinfo; + struct tcphdr *tcph; +- unsigned int tcplen, i; ++ int len, tcp_hdrlen; ++ unsigned int i; + __be16 oldval; + u16 newmss; + u8 *opt; +@@ -64,11 +65,14 @@ tcpmss_mangle_packet(struct sk_buff *skb, + if (!skb_make_writable(skb, skb->len)) + return -1; + +- tcplen = skb->len - tcphoff; ++ len = skb->len - tcphoff; ++ if (len < (int)sizeof(struct tcphdr)) ++ return -1; ++ + tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); ++ tcp_hdrlen = tcph->doff * 4; + +- /* Header cannot be larger than the packet */ +- if (tcplen < tcph->doff*4) ++ if (len < tcp_hdrlen) + return -1; + + if (info->mss == XT_TCPMSS_CLAMP_PMTU) { +@@ -87,9 +91,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, + newmss = info->mss; + + opt = (u_int8_t *)tcph; +- for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) { +- if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS && +- opt[i+1] == TCPOLEN_MSS) { ++ for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) { ++ if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { + u_int16_t oldmss; + + oldmss = (opt[i+2] << 8) | opt[i+3]; +@@ -112,9 +115,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, + } + + /* There is data after the header so the option can't be added +- without moving it, and doing so may make the SYN packet +- itself too large. Accept the packet unmodified instead. */ +- if (tcplen > tcph->doff*4) ++ * without moving it, and doing so may make the SYN packet ++ * itself too large. Accept the packet unmodified instead. ++ */ ++ if (len > tcp_hdrlen) + return 0; + + /* +@@ -143,10 +147,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, + newmss = min(newmss, (u16)1220); + + opt = (u_int8_t *)tcph + sizeof(struct tcphdr); +- memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); ++ memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr)); + + inet_proto_csum_replace2(&tcph->check, skb, +- htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); ++ htons(len), htons(len + TCPOLEN_MSS), 1); + opt[0] = TCPOPT_MSS; + opt[1] = TCPOLEN_MSS; + opt[2] = (newmss & 0xff00) >> 8; +diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c +index b68fa19..625fa1d 100644 +--- a/net/netfilter/xt_TCPOPTSTRIP.c ++++ b/net/netfilter/xt_TCPOPTSTRIP.c +@@ -38,7 +38,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, + struct tcphdr *tcph; + u_int16_t n, o; + u_int8_t *opt; +- int len; ++ int len, tcp_hdrlen; + + /* This is a fragment, no TCP header is available */ + if (par->fragoff != 0) +@@ -52,7 +52,9 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, + return NF_DROP; + + tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); +- if (tcph->doff * 4 > len) ++ tcp_hdrlen = tcph->doff * 4; ++ ++ if (len < tcp_hdrlen) + return NF_DROP; + + opt = (u_int8_t *)tcph; +@@ -61,10 +63,10 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, + * Walk through all TCP options - if we find some option to remove, + * set all octets to %TCPOPT_NOP and adjust checksum. + */ +- for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) { ++ for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) { + optl = optlen(opt, i); + +- if (i + optl > tcp_hdrlen(skb)) ++ if (i + optl > tcp_hdrlen) + break; + + if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i])) diff --git a/net/netfilter/xt_gradm.c b/net/netfilter/xt_gradm.c new file mode 100644 index 0000000..c566332 @@ -90688,7 +93608,7 @@ index 57ee84d..8b99cf5 100644 ); diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c -index 2fd6dbe..1032269 100644 +index 1076fe1..8285fd7 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -310,18 +310,20 @@ int genl_register_ops(struct genl_family *family, struct genl_ops *ops) @@ -90729,6 +93649,27 @@ index 2fd6dbe..1032269 100644 return 0; } } +@@ -789,6 +791,10 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) + struct net *net = sock_net(skb->sk); + int chains_to_skip = cb->args[0]; + int fams_to_skip = cb->args[1]; ++ bool need_locking = chains_to_skip || fams_to_skip; ++ ++ if (need_locking) ++ genl_lock(); + + for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { + n = 0; +@@ -810,6 +816,9 @@ errout: + cb->args[0] = i; + cb->args[1] = n; + ++ if (need_locking) ++ genl_unlock(); ++ + return skb->len; + } + diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index ec0c80f..41e1830 100644 --- a/net/netrom/af_netrom.c @@ -91296,18 +94237,6 @@ index f226709..0e735a8 100644 _proto("Tx RESPONSE %%%u", ntohl(hdr->serial)); ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 3, len); -diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c -index ca8e0a5..1f9c314 100644 ---- a/net/sched/sch_atm.c -+++ b/net/sched/sch_atm.c -@@ -605,6 +605,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, - struct sockaddr_atmpvc pvc; - int state; - -+ memset(&pvc, 0, sizeof(pvc)); - pvc.sap_family = AF_ATMPVC; - pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; - pvc.sap_addr.vpi = flow->vcc->vpi; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 391a245..296b3d7 100644 --- a/net/sctp/ipv6.c @@ -91513,6 +94442,25 @@ index bf3c6e8..376d8d0 100644 int i; table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 098f1d5f..60da2f7 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -178,12 +178,12 @@ static void sctp_transport_destroy(struct sctp_transport *transport) + { + SCTP_ASSERT(transport->dead, "Transport is not dead", return); + +- call_rcu(&transport->rcu, sctp_transport_destroy_rcu); +- + sctp_packet_free(&transport->packet); + + if (transport->asoc) + sctp_association_put(transport->asoc); ++ ++ call_rcu(&transport->rcu, sctp_transport_destroy_rcu); + } + + /* Start T3_rtx timer if it is not already running and update the heartbeat diff --git a/net/socket.c b/net/socket.c index 4ca1526..df83e47 100644 --- a/net/socket.c @@ -91760,7 +94708,7 @@ index 4ca1526..df83e47 100644 set_fs(KERNEL_DS); if (level == SOL_SOCKET) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c -index 5a750b9..ca5d7af 100644 +index 426f8fc..1ef9c32 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1288,7 +1288,9 @@ call_start(struct rpc_task *task) @@ -92179,6 +95127,19 @@ index 8800604..0526440 100644 table = kmemdup(unix_table, sizeof(unix_table), GFP_KERNEL); if (table == NULL) +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 3f77f42..662d89b 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -335,7 +335,7 @@ void vsock_for_each_connected_socket(void (*fn)(struct sock *sk)) + for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) { + struct vsock_sock *vsk; + list_for_each_entry(vsk, &vsock_connected_table[i], +- connected_table); ++ connected_table) + fn(sk_vsock(vsk)); + } + diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index c8717c1..08539f5 100644 --- a/net/wireless/wext-core.c @@ -92861,10 +95822,10 @@ index f5eb43d..1814de8 100644 shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); shstrtab_sec = shdr + r2(&ehdr->e_shstrndx); diff --git a/security/Kconfig b/security/Kconfig -index e9c6ac7..a4d558d 100644 +index e9c6ac7..3e3f362 100644 --- a/security/Kconfig +++ b/security/Kconfig -@@ -4,6 +4,956 @@ +@@ -4,6 +4,959 @@ menu "Security options" @@ -93232,7 +96193,7 @@ index e9c6ac7..a4d558d 100644 +config PAX_NOEXEC + bool "Enforce non-executable pages" + default y if GRKERNSEC_CONFIG_AUTO -+ depends on ALPHA || (ARM && (CPU_V6 || CPU_V7)) || IA64 || MIPS || PARISC || PPC || S390 || SPARC || X86 ++ depends on ALPHA || (ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || IA64 || MIPS || PARISC || PPC || S390 || SPARC || X86 + help + By design some architectures do not allow for protecting memory + pages against execution or even if they do, Linux does not make @@ -93262,8 +96223,6 @@ index e9c6ac7..a4d558d 100644 + bool "Paging based non-executable pages" + default y if GRKERNSEC_CONFIG_AUTO + depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MATOM || MPENTIUM4 || MPSC || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2 || MVIAC7) -+ select S390_SWITCH_AMODE if S390 -+ select S390_EXEC_PROTECT if S390 + select ARCH_TRACK_EXEC_LIMIT if X86_32 + help + This implementation is based on the paging feature of the CPU. @@ -93445,7 +96404,7 @@ index e9c6ac7..a4d558d 100644 +config PAX_KERNEXEC + bool "Enforce non-executable kernel pages" + default y if GRKERNSEC_CONFIG_AUTO && (GRKERNSEC_CONFIG_VIRT_NONE || (GRKERNSEC_CONFIG_VIRT_EPT && GRKERNSEC_CONFIG_VIRT_GUEST) || (GRKERNSEC_CONFIG_VIRT_EPT && GRKERNSEC_CONFIG_VIRT_KVM)) -+ depends on (X86 || (ARM && (CPU_V6 || CPU_V7) && !(ARM_LPAE && MODULES))) && !XEN ++ depends on (X86 || (ARM && (CPU_V6 || CPU_V6K || CPU_V7) && !(ARM_LPAE && MODULES))) && !XEN + select PAX_PER_CPU_PGD if X86_64 || (X86_32 && X86_PAE) + select PAX_KERNEXEC_PLUGIN if X86_64 + help @@ -93677,7 +96636,7 @@ index e9c6ac7..a4d558d 100644 +config PAX_MEMORY_UDEREF + bool "Prevent invalid userland pointer dereference" + default y if GRKERNSEC_CONFIG_AUTO && !(X86_64 && GRKERNSEC_CONFIG_PRIORITY_PERF) && (GRKERNSEC_CONFIG_VIRT_NONE || GRKERNSEC_CONFIG_VIRT_EPT) -+ depends on (X86 || (ARM && (CPU_V6 || CPU_V7) && !ARM_LPAE)) && !UML_X86 && !XEN ++ depends on (X86 || (ARM && (CPU_V6 || CPU_V6K || CPU_V7) && !ARM_LPAE)) && !UML_X86 && !XEN + select PAX_PER_CPU_PGD if X86_64 + help + By saying Y here the kernel will be prevented from dereferencing @@ -93694,10 +96653,15 @@ index e9c6ac7..a4d558d 100644 + VMs running on CPUs without hardware virtualization support (i.e., + the majority of IA-32 CPUs) will likely experience the slowdown. + ++ On X86_64 the kernel will make use of PCID support when available ++ (Intel's Westmere, Sandy Bridge, etc) for better security (default) ++ or performance impact. Pass pax_weakuderef on the kernel command ++ line to choose the latter. ++ +config PAX_REFCOUNT + bool "Prevent various kernel object reference counter overflows" + default y if GRKERNSEC_CONFIG_AUTO -+ depends on GRKERNSEC && ((ARM && (CPU_32v6 || CPU_32v6K || CPU_32v7)) || SPARC64 || X86) ++ depends on GRKERNSEC && ((ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || SPARC64 || X86) + help + By saying Y here the kernel will detect and prevent overflowing + various (but not all) kinds of object reference counters. Such @@ -93821,7 +96785,7 @@ index e9c6ac7..a4d558d 100644 source security/keys/Kconfig config SECURITY_DMESG_RESTRICT -@@ -103,7 +1053,7 @@ config INTEL_TXT +@@ -103,7 +1056,7 @@ config INTEL_TXT config LSM_MMAP_MIN_ADDR int "Low address space for LSM to protect from user allocation" depends on SECURITY && SECURITY_SELINUX @@ -106228,6 +109192,32 @@ index 0000000..4fae911 + + return 0; +} +diff --git a/tools/lib/lk/Makefile b/tools/lib/lk/Makefile +index 926cbf3..b8403e0 100644 +--- a/tools/lib/lk/Makefile ++++ b/tools/lib/lk/Makefile +@@ -10,7 +10,7 @@ LIB_OBJS += $(OUTPUT)debugfs.o + + LIBFILE = liblk.a + +-CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC ++CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC + EXTLIBS = -lpthread -lrt -lelf -lm + ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + ALL_LDFLAGS = $(LDFLAGS) +diff --git a/tools/perf/Makefile b/tools/perf/Makefile +index b0f164b..63c9f7d 100644 +--- a/tools/perf/Makefile ++++ b/tools/perf/Makefile +@@ -188,7 +188,7 @@ endif + + ifndef PERF_DEBUG + ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y) +- CFLAGS := $(CFLAGS) -D_FORTIFY_SOURCE=2 ++ CFLAGS := $(CFLAGS) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 + endif + endif + diff --git a/tools/perf/util/include/asm/alternative-asm.h b/tools/perf/util/include/asm/alternative-asm.h index 6789d78..4afd019e 100644 --- a/tools/perf/util/include/asm/alternative-asm.h diff --git a/main/linux-grsec/net-ip_gre-fix-ipgre_header-to-return-correct-offset.patch b/main/linux-grsec/net-ip_gre-fix-ipgre_header-to-return-correct-offset.patch deleted file mode 100644 index aeaeb33d7a..0000000000 --- a/main/linux-grsec/net-ip_gre-fix-ipgre_header-to-return-correct-offset.patch +++ /dev/null @@ -1,45 +0,0 @@ -From patchwork Tue Aug 6 10:45:43 2013 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -Subject: [net] ip_gre: fix ipgre_header to return correct offset -From: =?utf-8?q?Timo_Ter=C3=A4s?= <timo.teras@iki.fi> -X-Patchwork-Id: 264994 -Message-Id: <1375785943-23908-1-git-send-email-timo.teras@iki.fi> -To: netdev@vger.kernel.org -Cc: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>, - Pravin B Shelar <pshelar@nicira.com> -Date: Tue, 6 Aug 2013 13:45:43 +0300 - -Fix ipgre_header() (header_ops->create) to return the correct -amount of bytes pushed. Most callers of dev_hard_header() seem -to care only if it was success, but af_packet.c uses it as -offset to the skb to copy from userspace only once. In practice -this fixes packet socket sendto()/sendmsg() to gre tunnels. - -Regression introduced in c54419321455631079c7d6e60bc732dd0c5914c5 -("GRE: Refactor GRE tunneling code.") - -Cc: Pravin B Shelar <pshelar@nicira.com> -Signed-off-by: Timo Teräs <timo.teras@iki.fi> - ---- -Should go to 3.10-stable too. Without this dmvpn setup does not work -at all, as opennhrp uses packet sockets to send the nhrp packets. - - net/ipv4/ip_gre.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c -index 855004f..c52fee0 100644 ---- a/net/ipv4/ip_gre.c -+++ b/net/ipv4/ip_gre.c -@@ -572,7 +572,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, - if (daddr) - memcpy(&iph->daddr, daddr, 4); - if (iph->daddr) -- return t->hlen; -+ return t->hlen + sizeof(*iph); - - return -(t->hlen + sizeof(*iph)); - } |