From 572b430895e61e9500891fe2ef851ede8e61508e Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 1 Aug 2012 14:42:28 +0200 Subject: [PATCH] kernel: Update to 3.4.6. RC_MAP has been disabled because of compiler errors on armv5tel. On armv5tel, there is also setting KALLSYMS_EXTRA_PASS=1 required in order to build the kernel. --- kernel/config-generic | 2 +- kernel/kernel.nm | 13 +- ...grsecurity-2.9.1-3.4.6-201207281946.patch} | 3040 ++++++++++++----- 3 files changed, 2242 insertions(+), 813 deletions(-) rename kernel/patches/{grsecurity-2.9.1-3.4.4-201206251759.patch => grsecurity-2.9.1-3.4.6-201207281946.patch} (97%) diff --git a/kernel/config-generic b/kernel/config-generic index 044a46c5c..202a0a19b 100644 --- a/kernel/config-generic +++ b/kernel/config-generic @@ -2306,7 +2306,7 @@ CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m CONFIG_RC_CORE=m CONFIG_LIRC=m -CONFIG_RC_MAP=m +# CONFIG_RC_MAP is not set CONFIG_IR_NEC_DECODER=m CONFIG_IR_RC5_DECODER=m CONFIG_IR_RC6_DECODER=m diff --git a/kernel/kernel.nm b/kernel/kernel.nm index c2e98d598..c5afa3c69 100644 --- a/kernel/kernel.nm +++ b/kernel/kernel.nm @@ -4,8 +4,8 @@ ############################################################################### name = kernel -version = 3.4.4 -release = 3 +version = 3.4.6 +release = 1 thisapp = linux-%{version} maintainer = Michael Tremer @@ -64,6 +64,9 @@ build # Should we build cpupower? build_cpupower = 1 + # Arguments that are passed to the kernel build command. + kernel_build_flags = + kernel_target = bzImage if "%{DISTRO_ARCH}" == "i686" # Build a default and legacy kernel for the @@ -98,6 +101,9 @@ build # ARM does not support cpupower. build_cpupower = 0 + + # http://lists.infradead.org/pipermail/linux-arm-kernel/2012-March/091404.html + kernel_build_flags = KALLSYMS_EXTRA_PASS=1 end if "%{DISTRO_ARCH}" == "armv7hl" @@ -213,7 +219,8 @@ build # Run the build. make ARCH=%{kernel_arch} oldnoconfig >/dev/null - make ARCH=%{kernel_arch} CC="gcc -fno-PIE" %{kernel_target} modules %{PARALLELISMFLAGS} + make ARCH=%{kernel_arch} CC="gcc -fno-PIE" %{kernel_target} modules \ + %{kernel_build_flags} %{PARALLELISMFLAGS} # Install the results. mkdir -pv %{BUILDROOT}/boot %{BUILDROOT}/lib/modules/${fullversion} diff --git a/kernel/patches/grsecurity-2.9.1-3.4.4-201206251759.patch b/kernel/patches/grsecurity-2.9.1-3.4.6-201207281946.patch similarity index 97% rename from kernel/patches/grsecurity-2.9.1-3.4.4-201206251759.patch rename to kernel/patches/grsecurity-2.9.1-3.4.6-201207281946.patch index 083b3e128..357f472e5 100644 --- a/kernel/patches/grsecurity-2.9.1-3.4.4-201206251759.patch +++ b/kernel/patches/grsecurity-2.9.1-3.4.6-201207281946.patch @@ -1,5 +1,5 @@ diff --git a/Documentation/dontdiff b/Documentation/dontdiff -index b4a898f..a0e01d0 100644 +index b4a898f..781c7ad 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -2,9 +2,11 @@ @@ -22,7 +22,7 @@ index b4a898f..a0e01d0 100644 *.grep *.grp *.gz -@@ -48,9 +51,11 @@ +@@ -48,14 +51,17 @@ *.tab.h *.tex *.ver @@ -34,7 +34,14 @@ index b4a898f..a0e01d0 100644 *_vga16.c *~ \#*# -@@ -69,6 +74,7 @@ Image + *.9 +-.* ++.[^g]* ++.gen* + .*.d + .mm + 53c700_d.h +@@ -69,6 +75,7 @@ Image Module.markers Module.symvers PENDING @@ -42,7 +49,7 @@ index b4a898f..a0e01d0 100644 SCCS System.map* TAGS -@@ -80,6 +86,7 @@ aic7*seq.h* +@@ -80,6 +87,7 @@ aic7*seq.h* aicasm aicdb.h* altivec*.c @@ -50,7 +57,7 @@ index b4a898f..a0e01d0 100644 asm-offsets.h asm_offsets.h autoconf.h* -@@ -92,19 +99,24 @@ bounds.h +@@ -92,19 +100,24 @@ bounds.h bsetup btfixupprep build @@ -75,7 +82,7 @@ index b4a898f..a0e01d0 100644 conmakehash consolemap_deftbl.c* cpustr.h -@@ -115,9 +127,11 @@ devlist.h* +@@ -115,9 +128,11 @@ devlist.h* dnotify_test docproc dslm @@ -87,7 +94,7 @@ index b4a898f..a0e01d0 100644 fixdep flask.h fore200e_mkfirm -@@ -125,12 +139,15 @@ fore200e_pca_fw.c* +@@ -125,12 +140,15 @@ fore200e_pca_fw.c* gconf gconf.glade.h gen-devlist @@ -103,7 +110,7 @@ index b4a898f..a0e01d0 100644 hpet_example hugepage-mmap hugepage-shm -@@ -145,7 +162,7 @@ int32.c +@@ -145,7 +163,7 @@ int32.c int4.c int8.c kallsyms @@ -112,7 +119,7 @@ index b4a898f..a0e01d0 100644 keywords.c ksym.c* ksym.h* -@@ -153,7 +170,7 @@ kxgettext +@@ -153,7 +171,7 @@ kxgettext lkc_defs.h lex.c lex.*.c @@ -121,7 +128,7 @@ index b4a898f..a0e01d0 100644 logo_*.c logo_*_clut224.c logo_*_mono.c -@@ -164,14 +181,15 @@ machtypes.h +@@ -164,14 +182,15 @@ machtypes.h map map_hugetlb maui_boot.h @@ -138,7 +145,7 @@ index b4a898f..a0e01d0 100644 mkprep mkregtable mktables -@@ -188,6 +206,7 @@ oui.c* +@@ -188,6 +207,7 @@ oui.c* page-types parse.c parse.h @@ -146,7 +153,7 @@ index b4a898f..a0e01d0 100644 patches* pca200e.bin pca200e_ecd.bin2 -@@ -197,6 +216,7 @@ perf-archive +@@ -197,6 +217,7 @@ perf-archive piggyback piggy.gzip piggy.S @@ -154,7 +161,7 @@ index b4a898f..a0e01d0 100644 pnmtologo ppc_defs.h* pss_boot.h -@@ -207,6 +227,7 @@ r300_reg_safe.h +@@ -207,6 +228,7 @@ r300_reg_safe.h r420_reg_safe.h r600_reg_safe.h recordmcount @@ -162,7 +169,7 @@ index b4a898f..a0e01d0 100644 relocs rlim_names.h rn50_reg_safe.h -@@ -216,7 +237,9 @@ series +@@ -216,7 +238,9 @@ series setup setup.bin setup.elf @@ -172,7 +179,7 @@ index b4a898f..a0e01d0 100644 sm_tbl* split-include syscalltab.h -@@ -227,6 +250,7 @@ tftpboot.img +@@ -227,6 +251,7 @@ tftpboot.img timeconst.h times.h* trix_boot.h @@ -180,7 +187,7 @@ index b4a898f..a0e01d0 100644 utsrelease.h* vdso-syms.lds vdso.lds -@@ -238,13 +262,17 @@ vdso32.lds +@@ -238,13 +263,17 @@ vdso32.lds vdso32.so.dbg vdso64.lds vdso64.so.dbg @@ -198,7 +205,7 @@ index b4a898f..a0e01d0 100644 vmlinuz voffset.h vsyscall.lds -@@ -252,9 +280,11 @@ vsyscall_32.lds +@@ -252,9 +281,11 @@ vsyscall_32.lds wanxlfw.inc uImage unifdef @@ -229,7 +236,7 @@ index c1601e5..08557ce 100644 pcd. [PARIDE] diff --git a/Makefile b/Makefile -index 058320d..817f7ad 100644 +index 5d0edcb..f69ee4c 100644 --- a/Makefile +++ b/Makefile @@ -245,8 +245,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -255,7 +262,7 @@ index 058320d..817f7ad 100644 $(Q)$(MAKE) $(build)=scripts/basic $(Q)rm -f .tmp_quiet_recordmcount -@@ -564,6 +565,56 @@ else +@@ -564,6 +565,60 @@ else KBUILD_CFLAGS += -O2 endif @@ -286,12 +293,16 @@ index 058320d..817f7ad 100644 +endif +COLORIZE_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/colorize_plugin.so +ifdef CONFIG_PAX_SIZE_OVERFLOW -+SIZE_OVERFLOW_PLUGIN := -fplugin=$(objtree)/tools/gcc/size_overflow_plugin.so -DSIZE_OVERFLOW_PLUGIN ++SIZE_OVERFLOW_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/size_overflow_plugin.so -DSIZE_OVERFLOW_PLUGIN ++endif ++ifdef CONFIG_PAX_LATENT_ENTROPY ++LATENT_ENTROPY_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/latent_entropy_plugin.so -DLATENT_ENTROPY_PLUGIN +endif +GCC_PLUGINS_CFLAGS := $(CONSTIFY_PLUGIN_CFLAGS) $(STACKLEAK_PLUGIN_CFLAGS) $(KALLOCSTAT_PLUGIN_CFLAGS) -+GCC_PLUGINS_CFLAGS += $(KERNEXEC_PLUGIN_CFLAGS) $(CHECKER_PLUGIN_CFLAGS) $(COLORIZE_PLUGIN_CFLAGS) $(SIZE_OVERFLOW_PLUGIN) ++GCC_PLUGINS_CFLAGS += $(KERNEXEC_PLUGIN_CFLAGS) $(CHECKER_PLUGIN_CFLAGS) $(COLORIZE_PLUGIN_CFLAGS) ++GCC_PLUGINS_CFLAGS += $(SIZE_OVERFLOW_PLUGIN_CFLAGS) $(LATENT_ENTROPY_PLUGIN_CFLAGS) +GCC_PLUGINS_AFLAGS := $(KERNEXEC_PLUGIN_AFLAGS) -+export PLUGINCC CONSTIFY_PLUGIN STACKLEAK_PLUGIN KERNEXEC_PLUGIN CHECKER_PLUGIN SIZE_OVERFLOW_PLUGIN ++export PLUGINCC CONSTIFY_PLUGIN +ifeq ($(KBUILD_EXTMOD),) +gcc-plugins: + $(Q)$(MAKE) $(build)=tools/gcc @@ -312,7 +323,7 @@ index 058320d..817f7ad 100644 include $(srctree)/arch/$(SRCARCH)/Makefile ifneq ($(CONFIG_FRAME_WARN),0) -@@ -708,7 +759,7 @@ export mod_strip_cmd +@@ -708,7 +763,7 @@ export mod_strip_cmd ifeq ($(KBUILD_EXTMOD),) @@ -321,7 +332,7 @@ index 058320d..817f7ad 100644 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ -@@ -932,6 +983,8 @@ vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE +@@ -932,6 +987,8 @@ vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE # The actual objects are generated when descending, # make sure no implicit rule kicks in @@ -330,7 +341,7 @@ index 058320d..817f7ad 100644 $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ; # Handle descending into subdirectories listed in $(vmlinux-dirs) -@@ -941,7 +994,7 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ; +@@ -941,7 +998,7 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ; # Error messages still appears in the original language PHONY += $(vmlinux-dirs) @@ -339,7 +350,7 @@ index 058320d..817f7ad 100644 $(Q)$(MAKE) $(build)=$@ # Store (new) KERNELRELASE string in include/config/kernel.release -@@ -985,6 +1038,7 @@ prepare0: archprepare FORCE +@@ -985,6 +1042,7 @@ prepare0: archprepare FORCE $(Q)$(MAKE) $(build)=. # All the preparing.. @@ -347,7 +358,7 @@ index 058320d..817f7ad 100644 prepare: prepare0 # Generate some files -@@ -1092,6 +1146,8 @@ all: modules +@@ -1092,6 +1150,8 @@ all: modules # using awk while concatenating to the final file. PHONY += modules @@ -356,7 +367,7 @@ index 058320d..817f7ad 100644 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order @$(kecho) ' Building modules, stage 2.'; -@@ -1107,7 +1163,7 @@ modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) +@@ -1107,7 +1167,7 @@ modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) # Target to prepare building external modules PHONY += modules_prepare @@ -365,7 +376,7 @@ index 058320d..817f7ad 100644 # Target to install modules PHONY += modules_install -@@ -1166,7 +1222,7 @@ CLEAN_FILES += vmlinux System.map \ +@@ -1166,7 +1226,7 @@ CLEAN_FILES += vmlinux System.map \ MRPROPER_DIRS += include/config usr/include include/generated \ arch/*/include/generated MRPROPER_FILES += .config .config.old .version .old_version \ @@ -374,7 +385,7 @@ index 058320d..817f7ad 100644 Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS # clean - Delete most, but leave enough to build external modules -@@ -1204,6 +1260,7 @@ distclean: mrproper +@@ -1204,6 +1264,7 @@ distclean: mrproper \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' \ @@ -382,7 +393,7 @@ index 058320d..817f7ad 100644 -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ -type f -print | xargs rm -f -@@ -1364,6 +1421,8 @@ PHONY += $(module-dirs) modules +@@ -1364,6 +1425,8 @@ PHONY += $(module-dirs) modules $(module-dirs): crmodverdir $(objtree)/Module.symvers $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) @@ -391,7 +402,7 @@ index 058320d..817f7ad 100644 modules: $(module-dirs) @$(kecho) ' Building modules, stage 2.'; $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost -@@ -1490,17 +1549,21 @@ else +@@ -1490,17 +1553,21 @@ else target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@)) endif @@ -417,7 +428,7 @@ index 058320d..817f7ad 100644 $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) %.symtypes: %.c prepare scripts FORCE $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) -@@ -1510,11 +1573,15 @@ endif +@@ -1510,11 +1577,15 @@ endif $(cmd_crmodverdir) $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ $(build)=$(build-dir) @@ -6516,7 +6527,7 @@ index 301421c..e2535d1 100644 obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o obj-y += fault_$(BITS).o diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c -index df3155a..eb708b8 100644 +index df3155a..b6e32fa 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -21,6 +21,9 @@ @@ -6529,7 +6540,7 @@ index df3155a..eb708b8 100644 #include #include -@@ -207,6 +210,268 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) +@@ -207,6 +210,277 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) return safe_compute_effective_address(regs, insn); } @@ -6620,40 +6631,49 @@ index df3155a..eb708b8 100644 + } + } while (0); + -+ { /* PaX: patched PLT emulation #2 */ ++ do { /* PaX: patched PLT emulation #2 */ + unsigned int ba; + + err = get_user(ba, (unsigned int *)regs->pc); + -+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) { ++ if (err) ++ break; ++ ++ if ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30480000U) { + unsigned int addr; + -+ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); ++ if ((ba & 0xFFC00000U) == 0x30800000U) ++ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); ++ else ++ addr = regs->pc + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); + regs->pc = addr; + regs->npc = addr+4; + return 2; + } -+ } ++ } while (0); + + do { /* PaX: patched PLT emulation #3 */ -+ unsigned int sethi, jmpl, nop; ++ unsigned int sethi, bajmpl, nop; + + err = get_user(sethi, (unsigned int *)regs->pc); -+ err |= get_user(jmpl, (unsigned int *)(regs->pc+4)); ++ err |= get_user(bajmpl, (unsigned int *)(regs->pc+4)); + err |= get_user(nop, (unsigned int *)(regs->pc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && -+ (jmpl & 0xFFFFE000U) == 0x81C06000U && ++ ((bajmpl & 0xFFFFE000U) == 0x81C06000U || (bajmpl & 0xFFF80000U) == 0x30480000U) && + nop == 0x01000000U) + { + unsigned int addr; + + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; -+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); ++ if ((bajmpl & 0xFFFFE000U) == 0x81C06000U) ++ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); ++ else ++ addr = regs->pc + ((((bajmpl | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); + regs->pc = addr; + regs->npc = addr+4; + return 2; @@ -6798,7 +6818,7 @@ index df3155a..eb708b8 100644 static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs, int text_fault) { -@@ -282,6 +547,24 @@ good_area: +@@ -282,6 +556,24 @@ good_area: if(!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { @@ -6824,7 +6844,7 @@ index df3155a..eb708b8 100644 if(!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c -index 1fe0429..aee2e87 100644 +index 1fe0429..8dd5dd5 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -21,6 +21,9 @@ @@ -6846,7 +6866,7 @@ index 1fe0429..aee2e87 100644 printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr); dump_stack(); unhandled_fault(regs->tpc, current, regs); -@@ -272,6 +275,457 @@ static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, +@@ -272,6 +275,466 @@ static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, show_regs(regs); } @@ -6941,15 +6961,21 @@ index 1fe0429..aee2e87 100644 + } + } while (0); + -+ { /* PaX: patched PLT emulation #2 */ ++ do { /* PaX: patched PLT emulation #2 */ + unsigned int ba; + + err = get_user(ba, (unsigned int *)regs->tpc); + -+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) { ++ if (err) ++ break; ++ ++ if ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30480000U) { + unsigned long addr; + -+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); ++ if ((ba & 0xFFC00000U) == 0x30800000U) ++ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); ++ else ++ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; @@ -6958,27 +6984,30 @@ index 1fe0429..aee2e87 100644 + regs->tnpc = addr+4; + return 2; + } -+ } ++ } while (0); + + do { /* PaX: patched PLT emulation #3 */ -+ unsigned int sethi, jmpl, nop; ++ unsigned int sethi, bajmpl, nop; + + err = get_user(sethi, (unsigned int *)regs->tpc); -+ err |= get_user(jmpl, (unsigned int *)(regs->tpc+4)); ++ err |= get_user(bajmpl, (unsigned int *)(regs->tpc+4)); + err |= get_user(nop, (unsigned int *)(regs->tpc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && -+ (jmpl & 0xFFFFE000U) == 0x81C06000U && ++ ((bajmpl & 0xFFFFE000U) == 0x81C06000U || (bajmpl & 0xFFF80000U) == 0x30480000U) && + nop == 0x01000000U) + { + unsigned long addr; + + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; -+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); ++ if ((bajmpl & 0xFFFFE000U) == 0x81C06000U) ++ addr += (((bajmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); ++ else ++ addr = regs->tpc + ((((bajmpl | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; @@ -7304,7 +7333,7 @@ index 1fe0429..aee2e87 100644 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; -@@ -343,6 +797,29 @@ retry: +@@ -343,6 +806,29 @@ retry: if (!vma) goto bad_area; @@ -8595,7 +8624,7 @@ index 07b3a68..bd2a388 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 a69245b..6d145f4 100644 +index 4f5bfac..e1ef0d3 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -168,7 +168,7 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, @@ -9130,7 +9159,7 @@ index 20370c6..a2eb9b0 100644 "popl %%ebp\n\t" "popl %%edi\n\t" diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h -index 58cb6d4..ca9010d 100644 +index 58cb6d4..a4b806c 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -22,7 +22,18 @@ @@ -9538,6 +9567,51 @@ index 58cb6d4..ca9010d 100644 /* * atomic_dec_if_positive - decrement by 1 if old value positive +@@ -293,14 +552,37 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2) + #endif + + /* These are x86-specific, used by some header files */ +-#define atomic_clear_mask(mask, addr) \ +- asm volatile(LOCK_PREFIX "andl %0,%1" \ +- : : "r" (~(mask)), "m" (*(addr)) : "memory") ++static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) ++{ ++ asm volatile(LOCK_PREFIX "andl %1,%0" ++ : "+m" (v->counter) ++ : "r" (~(mask)) ++ : "memory"); ++} + +-#define atomic_set_mask(mask, addr) \ +- asm volatile(LOCK_PREFIX "orl %0,%1" \ +- : : "r" ((unsigned)(mask)), "m" (*(addr)) \ +- : "memory") ++static inline void atomic_clear_mask_unchecked(unsigned int mask, atomic_unchecked_t *v) ++{ ++ asm volatile(LOCK_PREFIX "andl %1,%0" ++ : "+m" (v->counter) ++ : "r" (~(mask)) ++ : "memory"); ++} ++ ++static inline void atomic_set_mask(unsigned int mask, atomic_t *v) ++{ ++ asm volatile(LOCK_PREFIX "orl %1,%0" ++ : "+m" (v->counter) ++ : "r" (mask) ++ : "memory"); ++} ++ ++static inline void atomic_set_mask_unchecked(unsigned int mask, atomic_unchecked_t *v) ++{ ++ asm volatile(LOCK_PREFIX "orl %1,%0" ++ : "+m" (v->counter) ++ : "r" (mask) ++ : "memory"); ++} + + /* Atomic operations are already serializing on x86 */ + #define smp_mb__before_atomic_dec() barrier() diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index 1981199..36b9dfb 100644 --- a/arch/x86/include/asm/atomic64_32.h @@ -10191,7 +10265,7 @@ index 99480e5..d81165b 100644 ({ \ __typeof__ (*(ptr)) __ret = (inc); \ diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h -index 340ee49..4238ced 100644 +index f91e80f..7f9bd27 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -371,7 +371,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) @@ -11294,67 +11368,10 @@ index 98391db..8f6984e 100644 static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h -index effff47..bbb8295 100644 +index cb00ccc..17e9054 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h -@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) - ptep->pte_low = pte.pte_low; - } - -+#define __HAVE_ARCH_READ_PMD_ATOMIC -+/* -+ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with -+ * a "*pmdp" dereference done by gcc. Problem is, in certain places -+ * where pte_offset_map_lock is called, concurrent page faults are -+ * allowed, if the mmap_sem is hold for reading. An example is mincore -+ * vs page faults vs MADV_DONTNEED. On the page fault side -+ * pmd_populate rightfully does a set_64bit, but if we're reading the -+ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen -+ * because gcc will not read the 64bit of the pmd atomically. To fix -+ * this all places running pmd_offset_map_lock() while holding the -+ * mmap_sem in read mode, shall read the pmdp pointer using this -+ * function to know if the pmd is null nor not, and in turn to know if -+ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd -+ * operations. -+ * -+ * Without THP if the mmap_sem is hold for reading, the -+ * pmd can only transition from null to not null while read_pmd_atomic runs. -+ * So there's no need of literally reading it atomically. -+ * -+ * With THP if the mmap_sem is hold for reading, the pmd can become -+ * THP or null or point to a pte (and in turn become "stable") at any -+ * time under read_pmd_atomic, so it's mandatory to read it atomically -+ * with cmpxchg8b. -+ */ -+#ifndef CONFIG_TRANSPARENT_HUGEPAGE -+static inline pmd_t read_pmd_atomic(pmd_t *pmdp) -+{ -+ pmdval_t ret; -+ u32 *tmp = (u32 *)pmdp; -+ -+ ret = (pmdval_t) (*tmp); -+ if (ret) { -+ /* -+ * If the low part is null, we must not read the high part -+ * or we can end up with a partial pmd. -+ */ -+ smp_rmb(); -+ ret |= ((pmdval_t)*(tmp + 1)) << 32; -+ } -+ -+ return __pmd(ret); -+} -+#else /* CONFIG_TRANSPARENT_HUGEPAGE */ -+static inline pmd_t read_pmd_atomic(pmd_t *pmdp) -+{ -+ return __pmd(atomic64_read((atomic64_t *)pmdp)); -+} -+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ -+ - static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) - { - set_64bit((unsigned long long *)(ptep), native_pte_val(pte)); -@@ -38,12 +88,16 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) +@@ -92,12 +92,16 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) { @@ -18885,7 +18902,7 @@ index 42eb330..139955c 100644 return ret; diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c -index d840e69..98e9581 100644 +index 3034ee5..7cfbfa6 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -35,7 +35,7 @@ void (*pm_power_off)(void); @@ -18968,7 +18985,7 @@ index d840e69..98e9581 100644 } #ifdef CONFIG_APM_MODULE EXPORT_SYMBOL(machine_real_restart); -@@ -556,7 +586,7 @@ void __attribute__((weak)) mach_reboot_fixups(void) +@@ -564,7 +594,7 @@ void __attribute__((weak)) mach_reboot_fixups(void) * try to force a triple fault and then cycle between hitting the keyboard * controller and doing that */ @@ -18977,7 +18994,7 @@ index d840e69..98e9581 100644 { int i; int attempt = 0; -@@ -680,13 +710,13 @@ void native_machine_shutdown(void) +@@ -688,13 +718,13 @@ void native_machine_shutdown(void) #endif } @@ -18993,7 +19010,7 @@ index d840e69..98e9581 100644 { printk("machine restart\n"); -@@ -695,7 +725,7 @@ static void native_machine_restart(char *__unused) +@@ -703,7 +733,7 @@ static void native_machine_restart(char *__unused) __machine_emergency_restart(0); } @@ -19002,7 +19019,7 @@ index d840e69..98e9581 100644 { /* stop other cpus and apics */ machine_shutdown(); -@@ -706,7 +736,7 @@ static void native_machine_halt(void) +@@ -714,7 +744,7 @@ static void native_machine_halt(void) stop_this_cpu(NULL); } @@ -19011,7 +19028,7 @@ index d840e69..98e9581 100644 { if (pm_power_off) { if (!reboot_force) -@@ -715,6 +745,7 @@ static void native_machine_power_off(void) +@@ -723,6 +753,7 @@ static void native_machine_power_off(void) } /* a fallback in case there is no PM info available */ tboot_shutdown(TB_SHUTDOWN_HALT); @@ -29525,7 +29542,7 @@ index 47ff7e4..0c7d340 100644 .part_num = MBCS_PART_NUM, .mfg_num = MBCS_MFG_NUM, diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index d6e9d08..4493e89 100644 +index d6e9d08..0c314bf 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -18,6 +18,7 @@ @@ -29587,7 +29604,7 @@ index d6e9d08..4493e89 100644 - remaining = copy_to_user(buf, ptr, sz); +#ifdef CONFIG_PAX_USERCOPY -+ temp = kmalloc(sz, GFP_KERNEL); ++ temp = kmalloc(sz, GFP_KERNEL|GFP_USERCOPY); + if (!temp) { + unxlate_dev_mem_ptr(p, ptr); + return -ENOMEM; @@ -29632,7 +29649,7 @@ index d6e9d08..4493e89 100644 - if (copy_to_user(buf, kbuf, sz)) +#ifdef CONFIG_PAX_USERCOPY -+ temp = kmalloc(sz, GFP_KERNEL); ++ temp = kmalloc(sz, GFP_KERNEL|GFP_USERCOPY); + if (!temp) + return -ENOMEM; + memcpy(temp, kbuf, sz); @@ -29674,7 +29691,7 @@ index 9df78e2..01ba9ae 100644 *ppos = i; diff --git a/drivers/char/random.c b/drivers/char/random.c -index 4ec04a7..4a092ed 100644 +index 4ec04a7..9918387 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -261,8 +261,13 @@ @@ -29709,7 +29726,25 @@ index 4ec04a7..4a092ed 100644 #if 0 /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */ { 2048, 1638, 1231, 819, 411, 1 }, -@@ -913,7 +925,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, +@@ -726,6 +738,17 @@ void add_disk_randomness(struct gendisk *disk) + } + #endif + ++#ifdef CONFIG_PAX_LATENT_ENTROPY ++u64 latent_entropy; ++ ++__init void transfer_latent_entropy(void) ++{ ++ mix_pool_bytes(&input_pool, &latent_entropy, sizeof(latent_entropy)); ++ mix_pool_bytes(&nonblocking_pool, &latent_entropy, sizeof(latent_entropy)); ++// printk(KERN_INFO "PAX: transferring latent entropy: %16llx\n", latent_entropy); ++} ++#endif ++ + /********************************************************************* + * + * Entropy extraction routines +@@ -913,7 +936,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, extract_buf(r, tmp); i = min_t(int, nbytes, EXTRACT_SIZE); @@ -29718,7 +29753,7 @@ index 4ec04a7..4a092ed 100644 ret = -EFAULT; break; } -@@ -1238,7 +1250,7 @@ EXPORT_SYMBOL(generate_random_uuid); +@@ -1238,7 +1261,7 @@ EXPORT_SYMBOL(generate_random_uuid); #include static int min_read_thresh = 8, min_write_thresh; @@ -30449,10 +30484,10 @@ index de43194..a14c4cc 100644 for (i = 0; i < count; i++) { char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index f57e5cf..c82f79d 100644 +index 26c67a7..8d4cbcb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -472,7 +472,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) +@@ -496,7 +496,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; struct drm_i915_master_private *master_priv; @@ -30461,7 +30496,7 @@ index f57e5cf..c82f79d 100644 /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); -@@ -563,7 +563,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) +@@ -579,7 +579,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) struct drm_i915_master_private *master_priv; u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; @@ -30470,7 +30505,7 @@ index f57e5cf..c82f79d 100644 if (IS_GEN6(dev)) bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; -@@ -1292,7 +1292,7 @@ static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) +@@ -1291,7 +1291,7 @@ static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) int ret = IRQ_NONE, pipe; bool blc_event = false; @@ -30479,7 +30514,7 @@ index f57e5cf..c82f79d 100644 iir = I915_READ(IIR); -@@ -1803,7 +1803,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) +@@ -1802,7 +1802,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -30488,7 +30523,7 @@ index f57e5cf..c82f79d 100644 INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func); -@@ -1980,7 +1980,7 @@ static void i915_driver_irq_preinstall(struct drm_device * dev) +@@ -1979,7 +1979,7 @@ static void i915_driver_irq_preinstall(struct drm_device * dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -30498,7 +30533,7 @@ index f57e5cf..c82f79d 100644 INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index d4d162f..e80037c 100644 +index d4d162f..b49a04e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2254,7 +2254,7 @@ intel_finish_fb(struct drm_framebuffer *old_fb) @@ -30519,16 +30554,19 @@ index d4d162f..e80037c 100644 } static bool intel_crtc_driving_pch(struct drm_crtc *crtc) -@@ -7286,7 +7286,7 @@ static void do_intel_finish_page_flip(struct drm_device *dev, +@@ -7284,9 +7284,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev, + + obj = work->old_fb_obj; - atomic_clear_mask(1 << intel_crtc->plane, - &obj->pending_flip.counter); +- atomic_clear_mask(1 << intel_crtc->plane, +- &obj->pending_flip.counter); - if (atomic_read(&obj->pending_flip) == 0) ++ atomic_clear_mask_unchecked(1 << intel_crtc->plane, &obj->pending_flip); + if (atomic_read_unchecked(&obj->pending_flip) == 0) wake_up(&dev_priv->pending_flip_queue); schedule_work(&work->work); -@@ -7582,7 +7582,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, +@@ -7582,7 +7581,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, /* Block clients from rendering to the new back buffer until * the flip occurs and the object is no longer visible. */ @@ -30537,7 +30575,7 @@ index d4d162f..e80037c 100644 ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); if (ret) -@@ -7596,7 +7596,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, +@@ -7596,7 +7595,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, return 0; cleanup_pending: @@ -31234,10 +31272,10 @@ index 8a8725c..afed796 100644 marker = list_first_entry(&queue->head, struct vmw_marker, head); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 4da66b4..e948655 100644 +index 054677b..741672a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c -@@ -2063,7 +2063,7 @@ static bool hid_ignore(struct hid_device *hdev) +@@ -2070,7 +2070,7 @@ static bool hid_ignore(struct hid_device *hdev) int hid_add_device(struct hid_device *hdev) { @@ -31246,7 +31284,7 @@ index 4da66b4..e948655 100644 int ret; if (WARN_ON(hdev->status & HID_STAT_ADDED)) -@@ -2078,7 +2078,7 @@ int hid_add_device(struct hid_device *hdev) +@@ -2085,7 +2085,7 @@ int hid_add_device(struct hid_device *hdev) /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, @@ -32755,10 +32793,10 @@ index b8d8611..7a4a04b 100644 #include #include diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c -index fd7a0d5..a4af10c 100644 +index 42f7b25..09fcf46 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c -@@ -710,7 +710,7 @@ static void xpad_led_set(struct led_classdev *led_cdev, +@@ -714,7 +714,7 @@ static void xpad_led_set(struct led_classdev *led_cdev, static int xpad_led_probe(struct usb_xpad *xpad) { @@ -32767,7 +32805,7 @@ index fd7a0d5..a4af10c 100644 long led_no; struct xpad_led *led; struct led_classdev *led_cdev; -@@ -723,7 +723,7 @@ static int xpad_led_probe(struct usb_xpad *xpad) +@@ -727,7 +727,7 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (!led) return -ENOMEM; @@ -32958,7 +32996,7 @@ index b5fdcb7..5b6c59f 100644 printk(KERN_INFO "lguest: mapped switcher at %p\n", diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c -index 3980903..ce25c5e 100644 +index 39809035..ce25c5e 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -59,7 +59,7 @@ static struct { @@ -33315,7 +33353,7 @@ index e24143c..ce2f21a1 100644 void dm_uevent_add(struct mapped_device *md, struct list_head *elist) diff --git a/drivers/md/md.c b/drivers/md/md.c -index 2b30ffd..bf789ce 100644 +index 2b30ffd..362b519 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -277,10 +277,10 @@ EXPORT_SYMBOL_GPL(md_trim_bio); @@ -33387,7 +33425,125 @@ index 2b30ffd..bf789ce 100644 INIT_LIST_HEAD(&rdev->same_set); init_waitqueue_head(&rdev->blocked_wait); -@@ -6738,7 +6738,7 @@ static int md_seq_show(struct seq_file *seq, void *v) +@@ -3744,8 +3744,8 @@ array_state_show(struct mddev *mddev, char *page) + return sprintf(page, "%s\n", array_states[st]); + } + +-static int do_md_stop(struct mddev * mddev, int ro, int is_open); +-static int md_set_readonly(struct mddev * mddev, int is_open); ++static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev); ++static int md_set_readonly(struct mddev * mddev, struct block_device *bdev); + static int do_md_run(struct mddev * mddev); + static int restart_array(struct mddev *mddev); + +@@ -3761,14 +3761,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) + /* stopping an active array */ + if (atomic_read(&mddev->openers) > 0) + return -EBUSY; +- err = do_md_stop(mddev, 0, 0); ++ err = do_md_stop(mddev, 0, NULL); + break; + case inactive: + /* stopping an active array */ + if (mddev->pers) { + if (atomic_read(&mddev->openers) > 0) + return -EBUSY; +- err = do_md_stop(mddev, 2, 0); ++ err = do_md_stop(mddev, 2, NULL); + } else + err = 0; /* already inactive */ + break; +@@ -3776,7 +3776,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) + break; /* not supported yet */ + case readonly: + if (mddev->pers) +- err = md_set_readonly(mddev, 0); ++ err = md_set_readonly(mddev, NULL); + else { + mddev->ro = 1; + set_disk_ro(mddev->gendisk, 1); +@@ -3786,7 +3786,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) + case read_auto: + if (mddev->pers) { + if (mddev->ro == 0) +- err = md_set_readonly(mddev, 0); ++ err = md_set_readonly(mddev, NULL); + else if (mddev->ro == 1) + err = restart_array(mddev); + if (err == 0) { +@@ -5124,15 +5124,17 @@ void md_stop(struct mddev *mddev) + } + EXPORT_SYMBOL_GPL(md_stop); + +-static int md_set_readonly(struct mddev *mddev, int is_open) ++static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) + { + int err = 0; + mutex_lock(&mddev->open_mutex); +- if (atomic_read(&mddev->openers) > is_open) { ++ if (atomic_read(&mddev->openers) > !!bdev) { + printk("md: %s still in use.\n",mdname(mddev)); + err = -EBUSY; + goto out; + } ++ if (bdev) ++ sync_blockdev(bdev); + if (mddev->pers) { + __md_stop_writes(mddev); + +@@ -5154,18 +5156,26 @@ out: + * 0 - completely stop and dis-assemble array + * 2 - stop but do not disassemble array + */ +-static int do_md_stop(struct mddev * mddev, int mode, int is_open) ++static int do_md_stop(struct mddev * mddev, int mode, ++ struct block_device *bdev) + { + struct gendisk *disk = mddev->gendisk; + struct md_rdev *rdev; + + mutex_lock(&mddev->open_mutex); +- if (atomic_read(&mddev->openers) > is_open || ++ if (atomic_read(&mddev->openers) > !!bdev || + mddev->sysfs_active) { + printk("md: %s still in use.\n",mdname(mddev)); + mutex_unlock(&mddev->open_mutex); + return -EBUSY; + } ++ if (bdev) ++ /* It is possible IO was issued on some other ++ * open file which was closed before we took ->open_mutex. ++ * As that was not the last close __blkdev_put will not ++ * have called sync_blockdev, so we must. ++ */ ++ sync_blockdev(bdev); + + if (mddev->pers) { + if (mddev->ro) +@@ -5239,7 +5249,7 @@ static void autorun_array(struct mddev *mddev) + err = do_md_run(mddev); + if (err) { + printk(KERN_WARNING "md: do_md_run() returned %d\n", err); +- do_md_stop(mddev, 0, 0); ++ do_md_stop(mddev, 0, NULL); + } + } + +@@ -6237,11 +6247,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, + goto done_unlock; + + case STOP_ARRAY: +- err = do_md_stop(mddev, 0, 1); ++ err = do_md_stop(mddev, 0, bdev); + goto done_unlock; + + case STOP_ARRAY_RO: +- err = md_set_readonly(mddev, 1); ++ err = md_set_readonly(mddev, bdev); + goto done_unlock; + + case BLKROSET: +@@ -6738,7 +6748,7 @@ static int md_seq_show(struct seq_file *seq, void *v) spin_unlock(&pers_lock); seq_printf(seq, "\n"); @@ -33396,7 +33552,7 @@ index 2b30ffd..bf789ce 100644 return 0; } if (v == (void*)2) { -@@ -6841,7 +6841,7 @@ static int md_seq_open(struct inode *inode, struct file *file) +@@ -6841,7 +6851,7 @@ static int md_seq_open(struct inode *inode, struct file *file) return error; seq = file->private_data; @@ -33405,7 +33561,7 @@ index 2b30ffd..bf789ce 100644 return error; } -@@ -6855,7 +6855,7 @@ static unsigned int mdstat_poll(struct file *filp, poll_table *wait) +@@ -6855,7 +6865,7 @@ static unsigned int mdstat_poll(struct file *filp, poll_table *wait) /* always allow read */ mask = POLLIN | POLLRDNORM; @@ -33414,7 +33570,7 @@ index 2b30ffd..bf789ce 100644 mask |= POLLERR | POLLPRI; return mask; } -@@ -6899,7 +6899,7 @@ static int is_mddev_idle(struct mddev *mddev, int init) +@@ -6899,7 +6909,7 @@ static int is_mddev_idle(struct mddev *mddev, int init) struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; curr_events = (int)part_stat_read(&disk->part0, sectors[0]) + (int)part_stat_read(&disk->part0, sectors[1]) - @@ -33453,10 +33609,10 @@ index 1c2063c..9639970 100644 struct md_personality diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c -index 50ed53b..4f29d7d 100644 +index fc90c11..c8cd9a9 100644 --- a/drivers/md/persistent-data/dm-space-map-checker.c +++ b/drivers/md/persistent-data/dm-space-map-checker.c -@@ -159,7 +159,7 @@ static void ca_destroy(struct count_array *ca) +@@ -167,7 +167,7 @@ static int ca_commit(struct count_array *old, struct count_array *new) /*----------------------------------------------------------------*/ struct sm_checker { @@ -33466,7 +33622,7 @@ index 50ed53b..4f29d7d 100644 struct count_array old_counts; struct count_array counts; diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c -index fc469ba..2d91555 100644 +index 3d0ed53..35dc592 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -23,7 +23,7 @@ @@ -33504,7 +33660,7 @@ index 1cbfc6b..56e1dbb 100644 /*----------------------------------------------------------------*/ diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c -index d7e9577..faa512f2 100644 +index d1f74ab..d1b24fd 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1688,7 +1688,7 @@ static int fix_sync_read_error(struct r1bio *r1_bio) @@ -33526,7 +33682,7 @@ index d7e9577..faa512f2 100644 "md/raid1:%s: read error corrected " "(%d sectors at %llu on %s)\n", diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c -index d037adb..ed17dc9 100644 +index a954c95..6e7a21c 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1684,7 +1684,7 @@ static void end_sync_read(struct bio *bio, int error) @@ -33589,10 +33745,10 @@ index d037adb..ed17dc9 100644 rdev_dec_pending(rdev, mddev); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index f351422..85c01bb 100644 +index 73a5800..2b0e3b1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c -@@ -1686,18 +1686,18 @@ static void raid5_end_read_request(struct bio * bi, int error) +@@ -1694,18 +1694,18 @@ static void raid5_end_read_request(struct bio * bi, int error) (unsigned long long)(sh->sector + rdev->data_offset), bdevname(rdev->bdev, b)); @@ -33615,7 +33771,7 @@ index f351422..85c01bb 100644 if (test_bit(R5_ReadRepl, &sh->dev[i].flags)) printk_ratelimited( KERN_WARNING -@@ -1726,7 +1726,7 @@ static void raid5_end_read_request(struct bio * bi, int error) +@@ -1734,7 +1734,7 @@ static void raid5_end_read_request(struct bio * bi, int error) (unsigned long long)(sh->sector + rdev->data_offset), bdn); @@ -33651,7 +33807,7 @@ index a7d876f..8c21b61 100644 struct dvb_demux *demux; void *priv; diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c -index 00a6732..70a682e 100644 +index 39eab73..60033e7 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -192,7 +192,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, @@ -33750,6 +33906,33 @@ index 9cde353..8c6a1c3 100644 struct i2c_client i2c_client; u32 i2c_rc; +diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c +index 7930ca5..235bf7d 100644 +--- a/drivers/media/video/cx25821/cx25821-core.c ++++ b/drivers/media/video/cx25821/cx25821-core.c +@@ -912,9 +912,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) + list_add_tail(&dev->devlist, &cx25821_devlist); + mutex_unlock(&cx25821_devlist_mutex); + +- strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); +- strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); +- + if (dev->pci->device != 0x8210) { + pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); +diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h +index b9aa801..029f293 100644 +--- a/drivers/media/video/cx25821/cx25821.h ++++ b/drivers/media/video/cx25821/cx25821.h +@@ -187,7 +187,7 @@ enum port { + }; + + struct cx25821_board { +- char *name; ++ const char *name; + enum port porta; + enum port portb; + enum port portc; diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 04bf662..e0ac026 100644 --- a/drivers/media/video/cx88/cx88-alsa.c @@ -34561,7 +34744,7 @@ index d783f4f..97fa1b0 100644 {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, {"D-Link DFE-580TX 4 port Server Adapter"}, diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c -index 528a886..e6a98a3 100644 +index 1bbf6b3..430dcd0 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -403,7 +403,7 @@ static void accumulate_16bit_val(u32 *acc, u16 val) @@ -34847,6 +35030,36 @@ index 8636e83..ab9bbc3 100644 struct ixgbe_mbx_stats stats; u32 timeout; u32 usec_delay; +diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +index 307611a..d8e4562 100644 +--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c ++++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +@@ -969,8 +969,6 @@ static irqreturn_t ixgbevf_msix_clean_tx(int irq, void *data) + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + tx_ring = &(adapter->tx_ring[r_idx]); +- tx_ring->total_bytes = 0; +- tx_ring->total_packets = 0; + ixgbevf_clean_tx_irq(adapter, tx_ring); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); +@@ -994,16 +992,6 @@ static irqreturn_t ixgbevf_msix_clean_rx(int irq, void *data) + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbevf_ring *rx_ring; + int r_idx; +- int i; +- +- r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); +- for (i = 0; i < q_vector->rxr_count; i++) { +- rx_ring = &(adapter->rx_ring[r_idx]); +- rx_ring->total_bytes = 0; +- rx_ring->total_packets = 0; +- r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, +- r_idx + 1); +- } + + if (!q_vector->rxr_count) + return IRQ_HANDLED; diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h index 25c951d..cc7cf33 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.h @@ -34924,7 +35137,7 @@ index 4a518a3..936b334 100644 #define VXGE_HW_VIRTUAL_PATH_HANDLE(vpath) \ ((struct __vxge_hw_vpath_handle *)(vpath)->vpath_handles.next) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c -index ce6b44d..74f10c2 100644 +index 161e045..0bb5b86 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -708,17 +708,17 @@ struct rtl8169_private { @@ -34977,10 +35190,10 @@ index c07cfe9..81cbf7e 100644 /* To mask all all interrupts.*/ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -index 48d56da..a27e46c 100644 +index 9bdfaba..3d8f8d4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -1584,7 +1584,7 @@ static const struct file_operations stmmac_rings_status_fops = { +@@ -1587,7 +1587,7 @@ static const struct file_operations stmmac_rings_status_fops = { .open = stmmac_sysfs_ring_open, .read = seq_read, .llseek = seq_lseek, @@ -34989,7 +35202,7 @@ index 48d56da..a27e46c 100644 }; static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) -@@ -1656,7 +1656,7 @@ static const struct file_operations stmmac_dma_cap_fops = { +@@ -1659,7 +1659,7 @@ static const struct file_operations stmmac_dma_cap_fops = { .open = stmmac_sysfs_dma_cap_open, .read = seq_read, .llseek = seq_lseek, @@ -35033,19 +35246,6 @@ index d6be64b..5d97e3b 100644 /* Ignore return since this msg is optional. */ rndis_filter_send_request(dev, request); -diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c -index cb8fd50..003ec38 100644 ---- a/drivers/net/macvtap.c -+++ b/drivers/net/macvtap.c -@@ -528,6 +528,8 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, - } - base = (unsigned long)from->iov_base + offset1; - size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; -+ if (i + size >= MAX_SKB_FRAGS) -+ return -EFAULT; - num_pages = get_user_pages_fast(base, size, 0, &page[i]); - if ((num_pages != size) || - (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 21d7151..8034208 100644 --- a/drivers/net/ppp/ppp_generic.c @@ -35246,7 +35446,7 @@ index 2d2a688..35f2372 100644 hso_start_serial_device(serial_table[i], GFP_NOIO); hso_kick_transmit(dev2ser(serial_table[i])); diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h -index c54b7d37..af1f359 100644 +index 420d69b..74f90a2 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -119,6 +119,7 @@ struct ath_ops { @@ -36534,7 +36734,7 @@ index aceffad..c35c08d 100644 fc_frame_free(fp); } diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c -index 441d88a..689ad71 100644 +index d109cc3..09f4e7d 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -529,7 +529,7 @@ static struct ata_port_operations sas_sata_ops = { @@ -37385,6 +37585,51 @@ index 0d4aa82..f7832d4 100644 extern void tmem_register_hostops(struct tmem_hostops *m); /* core tmem accessor functions */ +diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c +index 30a6770..fa323f8 100644 +--- a/drivers/target/target_core_cdb.c ++++ b/drivers/target/target_core_cdb.c +@@ -1107,7 +1107,7 @@ int target_emulate_write_same(struct se_task *task) + if (num_blocks != 0) + range = num_blocks; + else +- range = (dev->transport->get_blocks(dev) - lba); ++ range = (dev->transport->get_blocks(dev) - lba) + 1; + + pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n", + (unsigned long long)lba, (unsigned long long)range); +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index c3148b1..89d10e6 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -2038,7 +2038,7 @@ static int __core_scsi3_write_aptpl_to_file( + if (IS_ERR(file) || !file || !file->f_dentry) { + pr_err("filp_open(%s) for APTPL metadata" + " failed\n", path); +- return (PTR_ERR(file) < 0 ? PTR_ERR(file) : -ENOENT); ++ return IS_ERR(file) ? PTR_ERR(file) : -ENOENT; + } + + iov[0].iov_base = &buf[0]; +@@ -3826,7 +3826,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) + " SPC-2 reservation is held, returning" + " RESERVATION_CONFLICT\n"); + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; +- ret = EINVAL; ++ ret = -EINVAL; + goto out; + } + +@@ -3836,7 +3836,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) + */ + if (!cmd->se_sess) { + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; +- return -EINVAL; ++ ret = -EINVAL; ++ goto out; + } + + if (cmd->data_length < 24) { diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index f015839..b15dfc4 100644 --- a/drivers/target/target_core_tmr.c @@ -37441,6 +37686,19 @@ index 443704f..92d3517 100644 cmd->t_task_list_num) cmd->transport_state |= CMD_T_SENT; +diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c +index a375f25..da90f64 100644 +--- a/drivers/target/tcm_fc/tfc_cmd.c ++++ b/drivers/target/tcm_fc/tfc_cmd.c +@@ -240,6 +240,8 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd) + { + struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); + ++ if (cmd->aborted) ++ return ~0; + return fc_seq_exch(cmd->seq)->rxid; + } + diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 3436436..772237b 100644 --- a/drivers/tty/hvc/hvcs.c @@ -41631,7 +41889,7 @@ index d146e18..12d1bd1 100644 fd_offset + ex.a_text); if (error != N_DATADDR(ex)) { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index 16f7354..185d8dc 100644 +index 16f7354..7cc1e24 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -32,6 +32,7 @@ @@ -41762,17 +42020,16 @@ index 16f7354..185d8dc 100644 error = -ENOMEM; goto out_close; } -@@ -525,6 +549,351 @@ out: +@@ -525,6 +549,311 @@ out: return error; } -+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) || defined(CONFIG_PAX_XATTR_PAX_FLAGS) ++#ifdef CONFIG_PAX_PT_PAX_FLAGS ++#ifdef CONFIG_PAX_SOFTMODE +static unsigned long pax_parse_pt_pax_softmode(const struct elf_phdr * const elf_phdata) +{ + unsigned long pax_flags = 0UL; + -+#ifdef CONFIG_PAX_PT_PAX_FLAGS -+ +#ifdef CONFIG_PAX_PAGEEXEC + if (elf_phdata->p_flags & PF_PAGEEXEC) + pax_flags |= MF_PAX_PAGEEXEC; @@ -41783,15 +42040,6 @@ index 16f7354..185d8dc 100644 + pax_flags |= MF_PAX_SEGMEXEC; +#endif + -+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) -+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { -+ if ((__supported_pte_mask & _PAGE_NX)) -+ pax_flags &= ~MF_PAX_SEGMEXEC; -+ else -+ pax_flags &= ~MF_PAX_PAGEEXEC; -+ } -+#endif -+ +#ifdef CONFIG_PAX_EMUTRAMP + if (elf_phdata->p_flags & PF_EMUTRAMP) + pax_flags |= MF_PAX_EMUTRAMP; @@ -41807,17 +42055,14 @@ index 16f7354..185d8dc 100644 + pax_flags |= MF_PAX_RANDMMAP; +#endif + -+#endif -+ + return pax_flags; +} ++#endif + +static unsigned long pax_parse_pt_pax_hardmode(const struct elf_phdr * const elf_phdata) +{ + unsigned long pax_flags = 0UL; + -+#ifdef CONFIG_PAX_PT_PAX_FLAGS -+ +#ifdef CONFIG_PAX_PAGEEXEC + if (!(elf_phdata->p_flags & PF_NOPAGEEXEC)) + pax_flags |= MF_PAX_PAGEEXEC; @@ -41828,15 +42073,6 @@ index 16f7354..185d8dc 100644 + pax_flags |= MF_PAX_SEGMEXEC; +#endif + -+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) -+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { -+ if ((__supported_pte_mask & _PAGE_NX)) -+ pax_flags &= ~MF_PAX_SEGMEXEC; -+ else -+ pax_flags &= ~MF_PAX_PAGEEXEC; -+ } -+#endif -+ +#ifdef CONFIG_PAX_EMUTRAMP + if (!(elf_phdata->p_flags & PF_NOEMUTRAMP)) + pax_flags |= MF_PAX_EMUTRAMP; @@ -41852,11 +42088,79 @@ index 16f7354..185d8dc 100644 + pax_flags |= MF_PAX_RANDMMAP; +#endif + ++ return pax_flags; ++} ++#endif ++ ++#ifdef CONFIG_PAX_XATTR_PAX_FLAGS ++#ifdef CONFIG_PAX_SOFTMODE ++static unsigned long pax_parse_xattr_pax_softmode(unsigned long pax_flags_softmode) ++{ ++ unsigned long pax_flags = 0UL; ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (pax_flags_softmode & MF_PAX_PAGEEXEC) ++ pax_flags |= MF_PAX_PAGEEXEC; ++#endif ++ ++#ifdef CONFIG_PAX_SEGMEXEC ++ if (pax_flags_softmode & MF_PAX_SEGMEXEC) ++ pax_flags |= MF_PAX_SEGMEXEC; ++#endif ++ ++#ifdef CONFIG_PAX_EMUTRAMP ++ if (pax_flags_softmode & MF_PAX_EMUTRAMP) ++ pax_flags |= MF_PAX_EMUTRAMP; ++#endif ++ ++#ifdef CONFIG_PAX_MPROTECT ++ if (pax_flags_softmode & MF_PAX_MPROTECT) ++ pax_flags |= MF_PAX_MPROTECT; ++#endif ++ ++#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) ++ if (randomize_va_space && (pax_flags_softmode & MF_PAX_RANDMMAP)) ++ pax_flags |= MF_PAX_RANDMMAP; ++#endif ++ ++ return pax_flags; ++} ++#endif ++ ++static unsigned long pax_parse_xattr_pax_hardmode(unsigned long pax_flags_hardmode) ++{ ++ unsigned long pax_flags = 0UL; ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (!(pax_flags_hardmode & MF_PAX_PAGEEXEC)) ++ pax_flags |= MF_PAX_PAGEEXEC; ++#endif ++ ++#ifdef CONFIG_PAX_SEGMEXEC ++ if (!(pax_flags_hardmode & MF_PAX_SEGMEXEC)) ++ pax_flags |= MF_PAX_SEGMEXEC; ++#endif ++ ++#ifdef CONFIG_PAX_EMUTRAMP ++ if (!(pax_flags_hardmode & MF_PAX_EMUTRAMP)) ++ pax_flags |= MF_PAX_EMUTRAMP; ++#endif ++ ++#ifdef CONFIG_PAX_MPROTECT ++ if (!(pax_flags_hardmode & MF_PAX_MPROTECT)) ++ pax_flags |= MF_PAX_MPROTECT; ++#endif ++ ++#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) ++ if (randomize_va_space && !(pax_flags_hardmode & MF_PAX_RANDMMAP)) ++ pax_flags |= MF_PAX_RANDMMAP; +#endif + + return pax_flags; +} ++#endif + ++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) +static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex) +{ + unsigned long pax_flags = 0UL; @@ -41873,15 +42177,6 @@ index 16f7354..185d8dc 100644 + pax_flags |= MF_PAX_SEGMEXEC; +#endif + -+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) -+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { -+ if ((__supported_pte_mask & _PAGE_NX)) -+ pax_flags &= ~MF_PAX_SEGMEXEC; -+ else -+ pax_flags &= ~MF_PAX_PAGEEXEC; -+ } -+#endif -+ +#ifdef CONFIG_PAX_EMUTRAMP + if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP)) + pax_flags |= MF_PAX_EMUTRAMP; @@ -41903,19 +42198,17 @@ index 16f7354..185d8dc 100644 + pax_flags |= MF_PAX_PAGEEXEC; +#endif + ++#ifdef CONFIG_PAX_SEGMEXEC ++ pax_flags |= MF_PAX_SEGMEXEC; ++#endif ++ +#ifdef CONFIG_PAX_MPROTECT + pax_flags |= MF_PAX_MPROTECT; +#endif + +#ifdef CONFIG_PAX_RANDMMAP -+ pax_flags |= MF_PAX_RANDMMAP; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (!(pax_flags & MF_PAX_PAGEEXEC) || !(__supported_pte_mask & _PAGE_NX)) { -+ pax_flags &= ~MF_PAX_PAGEEXEC; -+ pax_flags |= MF_PAX_SEGMEXEC; -+ } ++ if (randomize_va_space) ++ pax_flags |= MF_PAX_RANDMMAP; +#endif + +#endif @@ -41952,90 +42245,6 @@ index 16f7354..185d8dc 100644 + return ~0UL; +} + -+#ifdef CONFIG_PAX_XATTR_PAX_FLAGS -+static unsigned long pax_parse_xattr_pax_softmode(unsigned long pax_flags_softmode) -+{ -+ unsigned long pax_flags = 0UL; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (pax_flags_softmode & MF_PAX_PAGEEXEC) -+ pax_flags |= MF_PAX_PAGEEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (pax_flags_softmode & MF_PAX_SEGMEXEC) -+ pax_flags |= MF_PAX_SEGMEXEC; -+#endif -+ -+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) -+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { -+ if ((__supported_pte_mask & _PAGE_NX)) -+ pax_flags &= ~MF_PAX_SEGMEXEC; -+ else -+ pax_flags &= ~MF_PAX_PAGEEXEC; -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ if (pax_flags_softmode & MF_PAX_EMUTRAMP) -+ pax_flags |= MF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (pax_flags_softmode & MF_PAX_MPROTECT) -+ pax_flags |= MF_PAX_MPROTECT; -+#endif -+ -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) -+ if (randomize_va_space && (pax_flags_softmode & MF_PAX_RANDMMAP)) -+ pax_flags |= MF_PAX_RANDMMAP; -+#endif -+ -+ return pax_flags; -+} -+ -+static unsigned long pax_parse_xattr_pax_hardmode(unsigned long pax_flags_hardmode) -+{ -+ unsigned long pax_flags = 0UL; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(pax_flags_hardmode & MF_PAX_PAGEEXEC)) -+ pax_flags |= MF_PAX_PAGEEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (!(pax_flags_hardmode & MF_PAX_SEGMEXEC)) -+ pax_flags |= MF_PAX_SEGMEXEC; -+#endif -+ -+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) -+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { -+ if ((__supported_pte_mask & _PAGE_NX)) -+ pax_flags &= ~MF_PAX_SEGMEXEC; -+ else -+ pax_flags &= ~MF_PAX_PAGEEXEC; -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ if (!(pax_flags_hardmode & MF_PAX_EMUTRAMP)) -+ pax_flags |= MF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (!(pax_flags_hardmode & MF_PAX_MPROTECT)) -+ pax_flags |= MF_PAX_MPROTECT; -+#endif -+ -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) -+ if (randomize_va_space && !(pax_flags_hardmode & MF_PAX_RANDMMAP)) -+ pax_flags |= MF_PAX_RANDMMAP; -+#endif -+ -+ return pax_flags; -+} -+#endif -+ +static unsigned long pax_parse_xattr_pax(struct file * const file) +{ + @@ -42103,6 +42312,15 @@ index 16f7354..185d8dc 100644 + if (pt_pax_flags != ~0UL) + pax_flags = pt_pax_flags; + ++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) ++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { ++ if ((__supported_pte_mask & _PAGE_NX)) ++ pax_flags &= ~MF_PAX_SEGMEXEC; ++ else ++ pax_flags &= ~MF_PAX_PAGEEXEC; ++ } ++#endif ++ + if (0 > pax_check_flags(&pax_flags)) + return -EINVAL; + @@ -42114,7 +42332,7 @@ index 16f7354..185d8dc 100644 /* * These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. -@@ -541,6 +910,11 @@ static unsigned long randomize_stack_top(unsigned long stack_top) +@@ -541,6 +870,11 @@ static unsigned long randomize_stack_top(unsigned long stack_top) { unsigned int random_variable = 0; @@ -42126,7 +42344,7 @@ index 16f7354..185d8dc 100644 if ((current->flags & PF_RANDOMIZE) && !(current->personality & ADDR_NO_RANDOMIZE)) { random_variable = get_random_int() & STACK_RND_MASK; -@@ -559,7 +933,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -559,7 +893,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; char * elf_interpreter = NULL; @@ -42135,7 +42353,7 @@ index 16f7354..185d8dc 100644 struct elf_phdr *elf_ppnt, *elf_phdata; unsigned long elf_bss, elf_brk; int retval, i; -@@ -569,11 +943,11 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -569,11 +903,11 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long start_code, end_code, start_data, end_data; unsigned long reloc_func_desc __maybe_unused = 0; int executable_stack = EXSTACK_DEFAULT; @@ -42148,7 +42366,7 @@ index 16f7354..185d8dc 100644 loc = kmalloc(sizeof(*loc), GFP_KERNEL); if (!loc) { -@@ -709,11 +1083,81 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -709,11 +1043,81 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto out_free_dentry; /* OK, This is the point of no return */ @@ -42173,7 +42391,7 @@ index 16f7354..185d8dc 100644 + + current->mm->def_flags = 0; + -+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) || defined(CONFIG_PAX_XATTR_PAX_FLAGS) ++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) + if (0 > pax_parse_pax_flags(&loc->elf_ex, elf_phdata, bprm->file)) { + send_sig(SIGKILL, current, 0); + goto out_free_dentry; @@ -42231,7 +42449,7 @@ index 16f7354..185d8dc 100644 if (elf_read_implies_exec(loc->elf_ex, executable_stack)) current->personality |= READ_IMPLIES_EXEC; -@@ -804,6 +1248,20 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -804,6 +1208,20 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) #else load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); #endif @@ -42252,7 +42470,7 @@ index 16f7354..185d8dc 100644 } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, -@@ -836,9 +1294,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -836,9 +1254,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) * allowed task size. Note that p_filesz must always be * <= p_memsz so it is only necessary to check p_memsz. */ @@ -42265,7 +42483,7 @@ index 16f7354..185d8dc 100644 /* set_brk can never work. Avoid overflows. */ send_sig(SIGKILL, current, 0); retval = -EINVAL; -@@ -877,11 +1335,40 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) +@@ -877,11 +1295,40 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto out_free_dentry; } if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { @@ -42309,7 +42527,7 @@ index 16f7354..185d8dc 100644 if (elf_interpreter) { unsigned long uninitialized_var(interp_map_addr); -@@ -1109,7 +1596,7 @@ static bool always_dump_vma(struct vm_area_struct *vma) +@@ -1109,7 +1556,7 @@ static bool always_dump_vma(struct vm_area_struct *vma) * Decide what to dump of a segment, part, all or none. */ static unsigned long vma_dump_size(struct vm_area_struct *vma, @@ -42318,7 +42536,7 @@ index 16f7354..185d8dc 100644 { #define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type)) -@@ -1146,7 +1633,7 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, +@@ -1146,7 +1593,7 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, if (vma->vm_file == NULL) return 0; @@ -42327,7 +42545,7 @@ index 16f7354..185d8dc 100644 goto whole; /* -@@ -1368,9 +1855,9 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm) +@@ -1368,9 +1815,9 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm) { elf_addr_t *auxv = (elf_addr_t *) mm->saved_auxv; int i = 0; @@ -42339,7 +42557,7 @@ index 16f7354..185d8dc 100644 fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); } -@@ -1892,14 +2379,14 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, +@@ -1892,14 +2339,14 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, } static size_t elf_core_vma_data_size(struct vm_area_struct *gate_vma, @@ -42356,7 +42574,7 @@ index 16f7354..185d8dc 100644 return size; } -@@ -1993,7 +2480,7 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -1993,7 +2440,7 @@ static int elf_core_dump(struct coredump_params *cprm) dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); @@ -42365,7 +42583,7 @@ index 16f7354..185d8dc 100644 offset += elf_core_extra_data_size(); e_shoff = offset; -@@ -2007,10 +2494,12 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -2007,10 +2454,12 @@ static int elf_core_dump(struct coredump_params *cprm) offset = dataoff; size += sizeof(*elf); @@ -42378,7 +42596,7 @@ index 16f7354..185d8dc 100644 if (size > cprm->limit || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note))) goto end_coredump; -@@ -2024,7 +2513,7 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -2024,7 +2473,7 @@ static int elf_core_dump(struct coredump_params *cprm) phdr.p_offset = offset; phdr.p_vaddr = vma->vm_start; phdr.p_paddr = 0; @@ -42387,7 +42605,7 @@ index 16f7354..185d8dc 100644 phdr.p_memsz = vma->vm_end - vma->vm_start; offset += phdr.p_filesz; phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; -@@ -2035,6 +2524,7 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -2035,6 +2484,7 @@ static int elf_core_dump(struct coredump_params *cprm) phdr.p_align = ELF_EXEC_PAGESIZE; size += sizeof(phdr); @@ -42395,7 +42613,7 @@ index 16f7354..185d8dc 100644 if (size > cprm->limit || !dump_write(cprm->file, &phdr, sizeof(phdr))) goto end_coredump; -@@ -2059,7 +2549,7 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -2059,7 +2509,7 @@ static int elf_core_dump(struct coredump_params *cprm) unsigned long addr; unsigned long end; @@ -42404,7 +42622,7 @@ index 16f7354..185d8dc 100644 for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { struct page *page; -@@ -2068,6 +2558,7 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -2068,6 +2518,7 @@ static int elf_core_dump(struct coredump_params *cprm) page = get_dump_page(addr); if (page) { void *kaddr = kmap(page); @@ -42412,7 +42630,7 @@ index 16f7354..185d8dc 100644 stop = ((size += PAGE_SIZE) > cprm->limit) || !dump_write(cprm->file, kaddr, PAGE_SIZE); -@@ -2085,6 +2576,7 @@ static int elf_core_dump(struct coredump_params *cprm) +@@ -2085,6 +2536,7 @@ static int elf_core_dump(struct coredump_params *cprm) if (e_phnum == PN_XNUM) { size += sizeof(*shdr4extnum); @@ -42420,7 +42638,7 @@ index 16f7354..185d8dc 100644 if (size > cprm->limit || !dump_write(cprm->file, shdr4extnum, sizeof(*shdr4extnum))) -@@ -2105,6 +2597,97 @@ out: +@@ -2105,6 +2557,97 @@ out: #endif /* CONFIG_ELF_CORE */ @@ -42555,7 +42773,7 @@ index 6b2daf9..a70dccb 100644 goto err; } diff --git a/fs/bio.c b/fs/bio.c -index 84da885..2149cd9 100644 +index 84da885..bac1d48 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -838,7 +838,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, @@ -42563,6 +42781,15 @@ index 84da885..2149cd9 100644 * Overflow, abort */ - if (end < start) ++ if (end < start || end - start > INT_MAX - nr_pages) + return ERR_PTR(-EINVAL); + + nr_pages += end - start; +@@ -972,7 +972,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, + /* + * Overflow, abort + */ +- if (end < start) + if (end < start || end - start > INT_MAX - nr_pages) return ERR_PTR(-EINVAL); @@ -43457,10 +43684,10 @@ index ab35b11..b30af66 100644 /* Free the char* */ kfree(buf); diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c -index 3a06f40..f7af544 100644 +index c0038f6..47ab347 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c -@@ -345,7 +345,7 @@ check_list: +@@ -355,7 +355,7 @@ check_list: goto out_unlock_msg_ctx; i = PKT_TYPE_SIZE + PKT_CTR_SIZE; if (msg_ctx->msg) { @@ -43492,7 +43719,7 @@ index b2a34a1..162fa69 100644 return rc; } diff --git a/fs/exec.c b/fs/exec.c -index b1fd202..582240d 100644 +index 29e5f84..8bfc7cb 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -55,6 +55,15 @@ @@ -43952,7 +44179,7 @@ index b1fd202..582240d 100644 cn->corename = kmalloc(cn->size, GFP_KERNEL); cn->used = 0; -@@ -1821,6 +1953,228 @@ out: +@@ -1821,6 +1953,250 @@ out: return ispipe; } @@ -44097,7 +44324,7 @@ index b1fd202..582240d 100644 + +#ifdef CONFIG_PAX_USERCOPY +/* 0: not at all, 1: fully, 2: fully inside frame, -1: partially (implies an error) */ -+int object_is_on_stack(const void *obj, unsigned long len) ++static noinline int check_stack_object(const void *obj, unsigned long len) +{ + const void * const stack = task_stack_page(current); + const void * const stackend = stack + THREAD_SIZE; @@ -44143,7 +44370,7 @@ index b1fd202..582240d 100644 +#endif +} + -+__noreturn void pax_report_usercopy(const void *ptr, unsigned long len, bool to, const char *type) ++static __noreturn void pax_report_usercopy(const void *ptr, unsigned long len, bool to, const char *type) +{ + if (current->signal->curr_ip) + printk(KERN_ERR "PAX: From %pI4: kernel memory %s attempt detected %s %p (%s) (%lu bytes)\n", @@ -44157,6 +44384,28 @@ index b1fd202..582240d 100644 +} +#endif + ++void check_object_size(const void *ptr, unsigned long n, bool to) ++{ ++ ++#ifdef CONFIG_PAX_USERCOPY ++ const char *type; ++ ++ if (!n) ++ return; ++ ++ type = check_heap_object(ptr, n, to); ++ if (!type) { ++ if (check_stack_object(ptr, n) != -1) ++ return; ++ type = ""; ++ } ++ ++ pax_report_usercopy(ptr, n, to, type); ++#endif ++ ++} ++EXPORT_SYMBOL(check_object_size); ++ +#ifdef CONFIG_PAX_MEMORY_STACKLEAK +void pax_track_stack(void) +{ @@ -44181,7 +44430,7 @@ index b1fd202..582240d 100644 static int zap_process(struct task_struct *start, int exit_code) { struct task_struct *t; -@@ -2018,17 +2372,17 @@ static void wait_for_dump_helpers(struct file *file) +@@ -2018,17 +2394,17 @@ static void wait_for_dump_helpers(struct file *file) pipe = file->f_path.dentry->d_inode->i_pipe; pipe_lock(pipe); @@ -44204,7 +44453,7 @@ index b1fd202..582240d 100644 pipe_unlock(pipe); } -@@ -2089,7 +2443,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2089,7 +2465,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) int retval = 0; int flag = 0; int ispipe; @@ -44213,7 +44462,7 @@ index b1fd202..582240d 100644 struct coredump_params cprm = { .signr = signr, .regs = regs, -@@ -2104,6 +2458,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2104,6 +2480,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) audit_core_dumps(signr); @@ -44223,7 +44472,7 @@ index b1fd202..582240d 100644 binfmt = mm->binfmt; if (!binfmt || !binfmt->core_dump) goto fail; -@@ -2171,7 +2528,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2171,7 +2550,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) } cprm.limit = RLIM_INFINITY; @@ -44232,7 +44481,7 @@ index b1fd202..582240d 100644 if (core_pipe_limit && (core_pipe_limit < dump_count)) { printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", task_tgid_vnr(current), current->comm); -@@ -2198,6 +2555,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2198,6 +2577,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) } else { struct inode *inode; @@ -44241,7 +44490,7 @@ index b1fd202..582240d 100644 if (cprm.limit < binfmt->min_coredump) goto fail_unlock; -@@ -2241,7 +2600,7 @@ close_fail: +@@ -2241,7 +2622,7 @@ close_fail: filp_close(cprm.file, NULL); fail_dropcount: if (ispipe) @@ -44250,7 +44499,7 @@ index b1fd202..582240d 100644 fail_unlock: kfree(cn.corename); fail_corename: -@@ -2260,7 +2619,7 @@ fail: +@@ -2260,7 +2641,7 @@ fail: */ int dump_write(struct file *file, const void *addr, int nr) { @@ -44338,6 +44587,18 @@ index 0e01e90..ae2bd5e 100644 atomic_t s_lock_busy; /* locality groups */ +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index 1365903..9727522 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -261,7 +261,6 @@ group_extend_out: + err = ext4_move_extents(filp, donor_filp, me.orig_start, + me.donor_start, me.len, &me.moved_len); + mnt_drop_write_file(filp); +- mnt_drop_write(filp->f_path.mnt); + + if (copy_to_user((struct move_extent __user *)arg, + &me, sizeof(me))) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6b0a57e..1955a44 100644 --- a/fs/ext4/mballoc.c @@ -44498,10 +44759,10 @@ index 75e7c1f..1eb3e4d 100644 break; err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0); diff --git a/fs/fifo.c b/fs/fifo.c -index b1a524d..4ee270e 100644 +index cf6f434..3d7942c 100644 --- a/fs/fifo.c +++ b/fs/fifo.c -@@ -58,10 +58,10 @@ static int fifo_open(struct inode *inode, struct file *filp) +@@ -59,10 +59,10 @@ static int fifo_open(struct inode *inode, struct file *filp) */ filp->f_op = &read_pipefifo_fops; pipe->r_counter++; @@ -44530,10 +44791,10 @@ index b1a524d..4ee270e 100644 - if (!pipe->readers) { + if (!atomic_read(&pipe->readers)) { - wait_for_partner(inode, &pipe->r_counter); - if (signal_pending(current)) + if (wait_for_partner(inode, &pipe->r_counter)) goto err_wr; -@@ -105,11 +105,11 @@ static int fifo_open(struct inode *inode, struct file *filp) + } +@@ -104,11 +104,11 @@ static int fifo_open(struct inode *inode, struct file *filp) */ filp->f_op = &rdwr_pipefifo_fops; @@ -44548,7 +44809,7 @@ index b1a524d..4ee270e 100644 wake_up_partner(inode); break; -@@ -123,19 +123,19 @@ static int fifo_open(struct inode *inode, struct file *filp) +@@ -122,19 +122,19 @@ static int fifo_open(struct inode *inode, struct file *filp) return 0; err_rd: @@ -46208,9 +46469,36 @@ index 8392cb8..80d6193 100644 memcpy(c->data, &cookie, 4); c->len=4; diff --git a/fs/locks.c b/fs/locks.c -index 0d68f1f..f216b79 100644 +index 6a64f15..c3dacf2 100644 --- a/fs/locks.c +++ b/fs/locks.c +@@ -308,7 +308,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock, + return 0; + } + +-static int assign_type(struct file_lock *fl, int type) ++static int assign_type(struct file_lock *fl, long type) + { + switch (type) { + case F_RDLCK: +@@ -445,7 +445,7 @@ static const struct lock_manager_operations lease_manager_ops = { + /* + * Initialize a lease, use the default lock manager operations + */ +-static int lease_init(struct file *filp, int type, struct file_lock *fl) ++static int lease_init(struct file *filp, long type, struct file_lock *fl) + { + if (assign_type(fl, type) != 0) + return -EINVAL; +@@ -463,7 +463,7 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl) + } + + /* Allocate a file_lock initialised to this type of lease */ +-static struct file_lock *lease_alloc(struct file *filp, int type) ++static struct file_lock *lease_alloc(struct file *filp, long type) + { + struct file_lock *fl = locks_alloc_lock(); + int error = -ENOMEM; @@ -2075,16 +2075,16 @@ void locks_remove_flock(struct file *filp) return; @@ -46233,7 +46521,7 @@ index 0d68f1f..f216b79 100644 lock_flocks(); diff --git a/fs/namei.c b/fs/namei.c -index c427919..e37fd3f 100644 +index c427919..232326c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -278,16 +278,32 @@ int generic_permission(struct inode *inode, int mask) @@ -46308,7 +46596,27 @@ index c427919..e37fd3f 100644 error = 0; if (s) error = __vfs_follow_link(nd, s); -@@ -1753,6 +1769,21 @@ static int path_lookupat(int dfd, const char *name, +@@ -1355,6 +1371,9 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) + if (!res) + res = walk_component(nd, path, &nd->last, + nd->last_type, LOOKUP_FOLLOW); ++ if (res >= 0 && gr_handle_symlink_owner(&link, nd->inode)) { ++ res = -EACCES; ++ } + put_link(nd, &link, cookie); + } while (res > 0); + +@@ -1746,6 +1765,9 @@ static int path_lookupat(int dfd, const char *name, + err = follow_link(&link, nd, &cookie); + if (!err) + err = lookup_last(nd, &path); ++ if (!err && gr_handle_symlink_owner(&link, nd->inode)) { ++ err = -EACCES; ++ } + put_link(nd, &link, cookie); + } + } +@@ -1753,6 +1775,21 @@ static int path_lookupat(int dfd, const char *name, if (!err) err = complete_walk(nd); @@ -46330,7 +46638,7 @@ index c427919..e37fd3f 100644 if (!err && nd->flags & LOOKUP_DIRECTORY) { if (!nd->inode->i_op->lookup) { path_put(&nd->path); -@@ -1780,6 +1811,15 @@ static int do_path_lookup(int dfd, const char *name, +@@ -1780,6 +1817,15 @@ static int do_path_lookup(int dfd, const char *name, retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd); if (likely(!retval)) { @@ -46346,7 +46654,7 @@ index c427919..e37fd3f 100644 if (unlikely(!audit_dummy_context())) { if (nd->path.dentry && nd->inode) audit_inode(name, nd->path.dentry); -@@ -2126,6 +2166,13 @@ static int may_open(struct path *path, int acc_mode, int flag) +@@ -2126,6 +2172,13 @@ static int may_open(struct path *path, int acc_mode, int flag) if (flag & O_NOATIME && !inode_owner_or_capable(inode)) return -EPERM; @@ -46360,7 +46668,7 @@ index c427919..e37fd3f 100644 return 0; } -@@ -2187,6 +2234,16 @@ static struct file *do_last(struct nameidata *nd, struct path *path, +@@ -2187,6 +2240,16 @@ static struct file *do_last(struct nameidata *nd, struct path *path, error = complete_walk(nd); if (error) return ERR_PTR(error); @@ -46377,7 +46685,7 @@ index c427919..e37fd3f 100644 audit_inode(pathname, nd->path.dentry); if (open_flag & O_CREAT) { error = -EISDIR; -@@ -2197,6 +2254,16 @@ static struct file *do_last(struct nameidata *nd, struct path *path, +@@ -2197,6 +2260,16 @@ static struct file *do_last(struct nameidata *nd, struct path *path, error = complete_walk(nd); if (error) return ERR_PTR(error); @@ -46394,7 +46702,7 @@ index c427919..e37fd3f 100644 audit_inode(pathname, dir); goto ok; } -@@ -2218,6 +2285,16 @@ static struct file *do_last(struct nameidata *nd, struct path *path, +@@ -2218,6 +2291,16 @@ static struct file *do_last(struct nameidata *nd, struct path *path, error = complete_walk(nd); if (error) return ERR_PTR(error); @@ -46411,7 +46719,7 @@ index c427919..e37fd3f 100644 error = -ENOTDIR; if (nd->flags & LOOKUP_DIRECTORY) { -@@ -2258,6 +2335,12 @@ static struct file *do_last(struct nameidata *nd, struct path *path, +@@ -2258,6 +2341,12 @@ static struct file *do_last(struct nameidata *nd, struct path *path, /* Negative dentry, just create the file */ if (!dentry->d_inode) { umode_t mode = op->mode; @@ -46424,7 +46732,7 @@ index c427919..e37fd3f 100644 if (!IS_POSIXACL(dir->d_inode)) mode &= ~current_umask(); /* -@@ -2281,6 +2364,8 @@ static struct file *do_last(struct nameidata *nd, struct path *path, +@@ -2281,6 +2370,8 @@ static struct file *do_last(struct nameidata *nd, struct path *path, error = vfs_create(dir->d_inode, dentry, mode, nd); if (error) goto exit_mutex_unlock; @@ -46433,7 +46741,7 @@ index c427919..e37fd3f 100644 mutex_unlock(&dir->d_inode->i_mutex); dput(nd->path.dentry); nd->path.dentry = dentry; -@@ -2290,6 +2375,19 @@ static struct file *do_last(struct nameidata *nd, struct path *path, +@@ -2290,6 +2381,19 @@ static struct file *do_last(struct nameidata *nd, struct path *path, /* * It already exists. */ @@ -46453,7 +46761,23 @@ index c427919..e37fd3f 100644 mutex_unlock(&dir->d_inode->i_mutex); audit_inode(pathname, path->dentry); -@@ -2502,6 +2600,11 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path +@@ -2407,8 +2511,14 @@ static struct file *path_openat(int dfd, const char *pathname, + error = follow_link(&link, nd, &cookie); + if (unlikely(error)) + filp = ERR_PTR(error); +- else ++ else { + filp = do_last(nd, &path, op, pathname); ++ if (!IS_ERR(filp) && gr_handle_symlink_owner(&link, nd->inode)) { ++ if (filp) ++ fput(filp); ++ filp = ERR_PTR(-EACCES); ++ } ++ } + put_link(nd, &link, cookie); + } + out: +@@ -2502,6 +2612,11 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path *path = nd.path; return dentry; eexist: @@ -46465,7 +46789,7 @@ index c427919..e37fd3f 100644 dput(dentry); dentry = ERR_PTR(-EEXIST); fail: -@@ -2524,6 +2627,20 @@ struct dentry *user_path_create(int dfd, const char __user *pathname, struct pat +@@ -2524,6 +2639,20 @@ struct dentry *user_path_create(int dfd, const char __user *pathname, struct pat } EXPORT_SYMBOL(user_path_create); @@ -46486,7 +46810,7 @@ index c427919..e37fd3f 100644 int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { int error = may_create(dir, dentry); -@@ -2591,6 +2708,17 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, +@@ -2591,6 +2720,17 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, error = mnt_want_write(path.mnt); if (error) goto out_dput; @@ -46504,7 +46828,7 @@ index c427919..e37fd3f 100644 error = security_path_mknod(&path, dentry, mode, dev); if (error) goto out_drop_write; -@@ -2608,6 +2736,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, +@@ -2608,6 +2748,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, } out_drop_write: mnt_drop_write(path.mnt); @@ -46514,7 +46838,7 @@ index c427919..e37fd3f 100644 out_dput: dput(dentry); mutex_unlock(&path.dentry->d_inode->i_mutex); -@@ -2661,12 +2792,21 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode) +@@ -2661,12 +2804,21 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode) error = mnt_want_write(path.mnt); if (error) goto out_dput; @@ -46536,7 +46860,7 @@ index c427919..e37fd3f 100644 out_dput: dput(dentry); mutex_unlock(&path.dentry->d_inode->i_mutex); -@@ -2746,6 +2886,8 @@ static long do_rmdir(int dfd, const char __user *pathname) +@@ -2746,6 +2898,8 @@ static long do_rmdir(int dfd, const char __user *pathname) char * name; struct dentry *dentry; struct nameidata nd; @@ -46545,7 +46869,7 @@ index c427919..e37fd3f 100644 error = user_path_parent(dfd, pathname, &nd, &name); if (error) -@@ -2774,6 +2916,15 @@ static long do_rmdir(int dfd, const char __user *pathname) +@@ -2774,6 +2928,15 @@ static long do_rmdir(int dfd, const char __user *pathname) error = -ENOENT; goto exit3; } @@ -46561,7 +46885,7 @@ index c427919..e37fd3f 100644 error = mnt_want_write(nd.path.mnt); if (error) goto exit3; -@@ -2781,6 +2932,8 @@ static long do_rmdir(int dfd, const char __user *pathname) +@@ -2781,6 +2944,8 @@ static long do_rmdir(int dfd, const char __user *pathname) if (error) goto exit4; error = vfs_rmdir(nd.path.dentry->d_inode, dentry); @@ -46570,7 +46894,7 @@ index c427919..e37fd3f 100644 exit4: mnt_drop_write(nd.path.mnt); exit3: -@@ -2843,6 +2996,8 @@ static long do_unlinkat(int dfd, const char __user *pathname) +@@ -2843,6 +3008,8 @@ static long do_unlinkat(int dfd, const char __user *pathname) struct dentry *dentry; struct nameidata nd; struct inode *inode = NULL; @@ -46579,7 +46903,7 @@ index c427919..e37fd3f 100644 error = user_path_parent(dfd, pathname, &nd, &name); if (error) -@@ -2865,6 +3020,16 @@ static long do_unlinkat(int dfd, const char __user *pathname) +@@ -2865,6 +3032,16 @@ static long do_unlinkat(int dfd, const char __user *pathname) if (!inode) goto slashes; ihold(inode); @@ -46596,7 +46920,7 @@ index c427919..e37fd3f 100644 error = mnt_want_write(nd.path.mnt); if (error) goto exit2; -@@ -2872,6 +3037,8 @@ static long do_unlinkat(int dfd, const char __user *pathname) +@@ -2872,6 +3049,8 @@ static long do_unlinkat(int dfd, const char __user *pathname) if (error) goto exit3; error = vfs_unlink(nd.path.dentry->d_inode, dentry); @@ -46605,7 +46929,7 @@ index c427919..e37fd3f 100644 exit3: mnt_drop_write(nd.path.mnt); exit2: -@@ -2947,10 +3114,18 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, +@@ -2947,10 +3126,18 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, error = mnt_want_write(path.mnt); if (error) goto out_dput; @@ -46624,7 +46948,7 @@ index c427919..e37fd3f 100644 out_drop_write: mnt_drop_write(path.mnt); out_dput: -@@ -3025,6 +3200,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, +@@ -3025,6 +3212,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, { struct dentry *new_dentry; struct path old_path, new_path; @@ -46632,7 +46956,7 @@ index c427919..e37fd3f 100644 int how = 0; int error; -@@ -3048,7 +3224,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, +@@ -3048,7 +3236,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, if (error) return error; @@ -46641,7 +46965,7 @@ index c427919..e37fd3f 100644 error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto out; -@@ -3059,13 +3235,30 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, +@@ -3059,13 +3247,30 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, error = mnt_want_write(new_path.mnt); if (error) goto out_dput; @@ -46672,7 +46996,7 @@ index c427919..e37fd3f 100644 dput(new_dentry); mutex_unlock(&new_path.dentry->d_inode->i_mutex); path_put(&new_path); -@@ -3299,6 +3492,12 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, +@@ -3299,6 +3504,12 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, if (new_dentry == trap) goto exit5; @@ -46685,7 +47009,7 @@ index c427919..e37fd3f 100644 error = mnt_want_write(oldnd.path.mnt); if (error) goto exit5; -@@ -3308,6 +3507,9 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, +@@ -3308,6 +3519,9 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, goto exit6; error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); @@ -46695,7 +47019,7 @@ index c427919..e37fd3f 100644 exit6: mnt_drop_write(oldnd.path.mnt); exit5: -@@ -3333,6 +3535,8 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna +@@ -3333,6 +3547,8 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) { @@ -46704,7 +47028,7 @@ index c427919..e37fd3f 100644 int len; len = PTR_ERR(link); -@@ -3342,7 +3546,14 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const c +@@ -3342,7 +3558,14 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const c len = strlen(link); if (len > (unsigned) buflen) len = buflen; @@ -47053,7 +47377,7 @@ index 5d22872..523db20 100644 kfree(link); } diff --git a/fs/open.c b/fs/open.c -index 5720854..ccfe124 100644 +index 3f1108b..822d7f7 100644 --- a/fs/open.c +++ b/fs/open.c @@ -31,6 +31,8 @@ @@ -47478,7 +47802,7 @@ index f9bd395..acb7847 100644 +} +#endif diff --git a/fs/proc/base.c b/fs/proc/base.c -index 9fc77b4..04761b8 100644 +index 9fc77b4..4877d08 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -109,6 +109,14 @@ struct pid_entry { @@ -47496,7 +47820,19 @@ index 9fc77b4..04761b8 100644 #define NOD(NAME, MODE, IOP, FOP, OP) { \ .name = (NAME), \ .len = sizeof(NAME) - 1, \ -@@ -213,6 +221,9 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer) +@@ -198,11 +206,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path) + return result; + } + +-struct mm_struct *mm_for_maps(struct task_struct *task) +-{ +- return mm_access(task, PTRACE_MODE_READ); +-} +- + static int proc_pid_cmdline(struct task_struct *task, char * buffer) + { + int res = 0; +@@ -213,6 +216,9 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer) if (!mm->arg_end) goto out_mm; /* Shh! No looking before we're done */ @@ -47506,7 +47842,7 @@ index 9fc77b4..04761b8 100644 len = mm->arg_end - mm->arg_start; if (len > PAGE_SIZE) -@@ -240,12 +251,28 @@ out: +@@ -240,12 +246,28 @@ out: return res; } @@ -47518,7 +47854,8 @@ index 9fc77b4..04761b8 100644 + static int proc_pid_auxv(struct task_struct *task, char *buffer) { - struct mm_struct *mm = mm_for_maps(task); +- struct mm_struct *mm = mm_for_maps(task); ++ struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ); int res = PTR_ERR(mm); if (mm && !IS_ERR(mm)) { unsigned int nwords = 0; @@ -47535,7 +47872,7 @@ index 9fc77b4..04761b8 100644 do { nwords += 2; } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ -@@ -259,7 +286,7 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer) +@@ -259,7 +281,7 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer) } @@ -47544,7 +47881,7 @@ index 9fc77b4..04761b8 100644 /* * Provides a wchan file via kallsyms in a proper one-value-per-file format. * Returns the resolved symbol. If that fails, simply return the address. -@@ -298,7 +325,7 @@ static void unlock_trace(struct task_struct *task) +@@ -298,7 +320,7 @@ static void unlock_trace(struct task_struct *task) mutex_unlock(&task->signal->cred_guard_mutex); } @@ -47553,7 +47890,7 @@ index 9fc77b4..04761b8 100644 #define MAX_STACK_TRACE_DEPTH 64 -@@ -489,7 +516,7 @@ static int proc_pid_limits(struct task_struct *task, char *buffer) +@@ -489,7 +511,7 @@ static int proc_pid_limits(struct task_struct *task, char *buffer) return count; } @@ -47562,7 +47899,7 @@ index 9fc77b4..04761b8 100644 static int proc_pid_syscall(struct task_struct *task, char *buffer) { long nr; -@@ -518,7 +545,7 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer) +@@ -518,7 +540,7 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer) /************************************************************************/ /* permission checks */ @@ -47571,7 +47908,7 @@ index 9fc77b4..04761b8 100644 { struct task_struct *task; int allowed = 0; -@@ -528,7 +555,10 @@ static int proc_fd_access_allowed(struct inode *inode) +@@ -528,7 +550,10 @@ static int proc_fd_access_allowed(struct inode *inode) */ task = get_proc_task(inode); if (task) { @@ -47583,7 +47920,7 @@ index 9fc77b4..04761b8 100644 put_task_struct(task); } return allowed; -@@ -566,10 +596,35 @@ static bool has_pid_permissions(struct pid_namespace *pid, +@@ -566,10 +591,35 @@ static bool has_pid_permissions(struct pid_namespace *pid, struct task_struct *task, int hide_pid_min) { @@ -47619,7 +47956,7 @@ index 9fc77b4..04761b8 100644 return ptrace_may_access(task, PTRACE_MODE_READ); } -@@ -587,7 +642,11 @@ static int proc_pid_permission(struct inode *inode, int mask) +@@ -587,7 +637,11 @@ static int proc_pid_permission(struct inode *inode, int mask) put_task_struct(task); if (!has_perms) { @@ -47631,18 +47968,57 @@ index 9fc77b4..04761b8 100644 /* * Let's make getdents(), stat(), and open() * consistent with each other. If a process -@@ -702,6 +761,10 @@ static int mem_open(struct inode* inode, struct file* file) - file->f_mode |= FMODE_UNSIGNED_OFFSET; - file->private_data = mm; +@@ -677,7 +731,7 @@ static const struct file_operations proc_single_file_operations = { + .release = single_release, + }; + +-static int mem_open(struct inode* inode, struct file* file) ++static int __mem_open(struct inode *inode, struct file *file, unsigned int mode) + { + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); + struct mm_struct *mm; +@@ -685,7 +739,12 @@ static int mem_open(struct inode* inode, struct file* file) + if (!task) + return -ESRCH; + +- mm = mm_access(task, PTRACE_MODE_ATTACH); ++ if (gr_acl_handle_procpidmem(task)) { ++ put_task_struct(task); ++ return -EPERM; ++ } ++ ++ mm = mm_access(task, mode); + put_task_struct(task); + + if (IS_ERR(mm)) +@@ -698,11 +757,24 @@ static int mem_open(struct inode* inode, struct file* file) + mmput(mm); + } ++ file->private_data = mm; ++ +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP + file->f_version = current->exec_id; +#endif + - return 0; ++ return 0; ++} ++ ++static int mem_open(struct inode *inode, struct file *file) ++{ ++ int ret; ++ ret = __mem_open(inode, file, PTRACE_MODE_ATTACH); ++ + /* OK to pass negative loff_t, we can catch out-of-range */ + file->f_mode |= FMODE_UNSIGNED_OFFSET; +- file->private_data = mm; + +- return 0; ++ return ret; } -@@ -713,6 +776,17 @@ static ssize_t mem_rw(struct file *file, char __user *buf, + static ssize_t mem_rw(struct file *file, char __user *buf, +@@ -713,6 +785,17 @@ static ssize_t mem_rw(struct file *file, char __user *buf, ssize_t copied; char *page; @@ -47660,17 +48036,101 @@ index 9fc77b4..04761b8 100644 if (!mm) return 0; -@@ -813,6 +887,9 @@ static ssize_t environ_read(struct file *file, char __user *buf, - if (!task) - goto out_no_task; +@@ -801,42 +884,49 @@ static const struct file_operations proc_mem_operations = { + .release = mem_release, + }; -+ if (gr_acl_handle_procpidmem(task)) -+ goto out; ++static int environ_open(struct inode *inode, struct file *file) ++{ ++ return __mem_open(inode, file, PTRACE_MODE_READ); ++} + - ret = -ENOMEM; + static ssize_t environ_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) + { +- struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + char *page; + unsigned long src = *ppos; +- int ret = -ESRCH; +- struct mm_struct *mm; ++ int ret = 0; ++ struct mm_struct *mm = file->private_data; + +- if (!task) +- goto out_no_task; ++ if (!mm) ++ return 0; ++ ++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP ++ if (file->f_version != current->exec_id) { ++ gr_log_badprocpid("environ"); ++ return 0; ++ } ++#endif + +- ret = -ENOMEM; page = (char *)__get_free_page(GFP_TEMPORARY); if (!page) -@@ -1433,7 +1510,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) +- goto out; +- +- +- mm = mm_for_maps(task); +- ret = PTR_ERR(mm); +- if (!mm || IS_ERR(mm)) +- goto out_free; ++ return -ENOMEM; + + ret = 0; ++ if (!atomic_inc_not_zero(&mm->mm_users)) ++ goto free; + while (count > 0) { +- int this_len, retval, max_len; ++ size_t this_len, max_len; ++ int retval; ++ ++ if (src >= (mm->env_end - mm->env_start)) ++ break; + + this_len = mm->env_end - (mm->env_start + src); + +- if (this_len <= 0) +- break; ++ max_len = min_t(size_t, PAGE_SIZE, count); ++ this_len = min(max_len, this_len); + +- max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; +- this_len = (this_len > max_len) ? max_len : this_len; +- +- retval = access_process_vm(task, (mm->env_start + src), ++ retval = access_remote_vm(mm, (mm->env_start + src), + page, this_len, 0); + + if (retval <= 0) { +@@ -855,19 +945,18 @@ static ssize_t environ_read(struct file *file, char __user *buf, + count -= retval; + } + *ppos = src; +- + mmput(mm); +-out_free: ++ ++free: + free_page((unsigned long) page); +-out: +- put_task_struct(task); +-out_no_task: + return ret; + } + + static const struct file_operations proc_environ_operations = { ++ .open = environ_open, + .read = environ_read, + .llseek = generic_file_llseek, ++ .release = mem_release, + }; + + static ssize_t oom_adjust_read(struct file *file, char __user *buf, +@@ -1433,7 +1522,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) path_put(&nd->path); /* Are we allowed to snoop on the tasks file descriptors? */ @@ -47679,7 +48139,7 @@ index 9fc77b4..04761b8 100644 goto out; error = PROC_I(inode)->op.proc_get_link(dentry, &nd->path); -@@ -1472,8 +1549,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b +@@ -1472,8 +1561,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b struct path path; /* Are we allowed to snoop on the tasks file descriptors? */ @@ -47700,7 +48160,7 @@ index 9fc77b4..04761b8 100644 error = PROC_I(inode)->op.proc_get_link(dentry, &path); if (error) -@@ -1538,7 +1625,11 @@ struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *t +@@ -1538,7 +1637,11 @@ struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *t rcu_read_lock(); cred = __task_cred(task); inode->i_uid = cred->euid; @@ -47712,7 +48172,7 @@ index 9fc77b4..04761b8 100644 rcu_read_unlock(); } security_task_to_inode(task, inode); -@@ -1574,10 +1665,19 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +@@ -1574,10 +1677,19 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) return -ENOENT; } if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || @@ -47732,7 +48192,7 @@ index 9fc77b4..04761b8 100644 } } rcu_read_unlock(); -@@ -1615,11 +1715,20 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd) +@@ -1615,11 +1727,20 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd) if (task) { if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || @@ -47753,7 +48213,7 @@ index 9fc77b4..04761b8 100644 rcu_read_unlock(); } else { inode->i_uid = 0; -@@ -1737,7 +1846,8 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info) +@@ -1737,7 +1858,8 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info) int fd = proc_fd(inode); if (task) { @@ -47763,7 +48223,21 @@ index 9fc77b4..04761b8 100644 put_task_struct(task); } if (files) { -@@ -2338,11 +2448,21 @@ static const struct file_operations proc_map_files_operations = { +@@ -2025,11 +2147,8 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd) + if (!task) + goto out_notask; + +- if (!ptrace_may_access(task, PTRACE_MODE_READ)) +- goto out; +- +- mm = get_task_mm(task); +- if (!mm) ++ mm = mm_access(task, PTRACE_MODE_READ); ++ if (IS_ERR_OR_NULL(mm)) + goto out; + + if (!dname_to_vma_addr(dentry, &vm_start, &vm_end)) { +@@ -2338,11 +2457,21 @@ static const struct file_operations proc_map_files_operations = { */ static int proc_fd_permission(struct inode *inode, int mask) { @@ -47787,7 +48261,7 @@ index 9fc77b4..04761b8 100644 return rv; } -@@ -2452,6 +2572,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir, +@@ -2452,6 +2581,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir, if (!task) goto out_no_task; @@ -47797,7 +48271,7 @@ index 9fc77b4..04761b8 100644 /* * Yes, it does not scale. And it should not. Don't add * new entries into /proc// without very good reasons. -@@ -2496,6 +2619,9 @@ static int proc_pident_readdir(struct file *filp, +@@ -2496,6 +2628,9 @@ static int proc_pident_readdir(struct file *filp, if (!task) goto out_no_task; @@ -47807,7 +48281,7 @@ index 9fc77b4..04761b8 100644 ret = 0; i = filp->f_pos; switch (i) { -@@ -2766,7 +2892,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) +@@ -2766,7 +2901,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) { @@ -47816,7 +48290,7 @@ index 9fc77b4..04761b8 100644 if (!IS_ERR(s)) __putname(s); } -@@ -2967,7 +3093,7 @@ static const struct pid_entry tgid_base_stuff[] = { +@@ -2967,7 +3102,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations), #endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), @@ -47825,7 +48299,7 @@ index 9fc77b4..04761b8 100644 INF("syscall", S_IRUGO, proc_pid_syscall), #endif INF("cmdline", S_IRUGO, proc_pid_cmdline), -@@ -2992,10 +3118,10 @@ static const struct pid_entry tgid_base_stuff[] = { +@@ -2992,10 +3127,10 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_SECURITY DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), #endif @@ -47838,7 +48312,7 @@ index 9fc77b4..04761b8 100644 ONE("stack", S_IRUGO, proc_pid_stack), #endif #ifdef CONFIG_SCHEDSTATS -@@ -3029,6 +3155,9 @@ static const struct pid_entry tgid_base_stuff[] = { +@@ -3029,6 +3164,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_HARDWALL INF("hardwall", S_IRUGO, proc_pid_hardwall), #endif @@ -47848,7 +48322,7 @@ index 9fc77b4..04761b8 100644 }; static int proc_tgid_base_readdir(struct file * filp, -@@ -3155,7 +3284,14 @@ static struct dentry *proc_pid_instantiate(struct inode *dir, +@@ -3155,7 +3293,14 @@ static struct dentry *proc_pid_instantiate(struct inode *dir, if (!inode) goto out; @@ -47863,7 +48337,7 @@ index 9fc77b4..04761b8 100644 inode->i_op = &proc_tgid_base_inode_operations; inode->i_fop = &proc_tgid_base_operations; inode->i_flags|=S_IMMUTABLE; -@@ -3197,7 +3333,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct +@@ -3197,7 +3342,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct if (!task) goto out; @@ -47875,7 +48349,7 @@ index 9fc77b4..04761b8 100644 put_task_struct(task); out: return result; -@@ -3260,6 +3400,8 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi +@@ -3260,6 +3409,8 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi static int fake_filldir(void *buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type) { @@ -47884,7 +48358,7 @@ index 9fc77b4..04761b8 100644 return 0; } -@@ -3326,7 +3468,7 @@ static const struct pid_entry tid_base_stuff[] = { +@@ -3326,7 +3477,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), @@ -47893,7 +48367,7 @@ index 9fc77b4..04761b8 100644 INF("syscall", S_IRUGO, proc_pid_syscall), #endif INF("cmdline", S_IRUGO, proc_pid_cmdline), -@@ -3350,10 +3492,10 @@ static const struct pid_entry tid_base_stuff[] = { +@@ -3350,10 +3501,10 @@ static const struct pid_entry tid_base_stuff[] = { #ifdef CONFIG_SECURITY DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), #endif @@ -47987,10 +48461,19 @@ index 205c922..2ee4c57 100644 if (de->size) inode->i_size = de->size; diff --git a/fs/proc/internal.h b/fs/proc/internal.h -index 5f79bb8..eeccee4 100644 +index 5f79bb8..e9ab85d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h -@@ -54,6 +54,9 @@ extern int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, +@@ -31,8 +31,6 @@ struct vmalloc_info { + unsigned long largest_chunk; + }; + +-extern struct mm_struct *mm_for_maps(struct task_struct *); +- + #ifdef CONFIG_MMU + #define VMALLOC_TOTAL (VMALLOC_END - VMALLOC_START) + extern void get_vmalloc_info(struct vmalloc_info *vmi); +@@ -54,6 +52,9 @@ extern int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task); extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task); @@ -48259,7 +48742,7 @@ index eed44bf..abeb499 100644 } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 7faaf2a..096c28b 100644 +index 7faaf2a..7793015 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -11,12 +11,19 @@ @@ -48319,6 +48802,15 @@ index 7faaf2a..096c28b 100644 } unsigned long task_vsize(struct mm_struct *mm) +@@ -125,7 +149,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) + if (!priv->task) + return ERR_PTR(-ESRCH); + +- mm = mm_for_maps(priv->task); ++ mm = mm_access(priv->task, PTRACE_MODE_READ); + if (!mm || IS_ERR(mm)) + return mm; + down_read(&mm->mmap_sem); @@ -231,13 +255,13 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; } @@ -48426,6 +48918,15 @@ index 7faaf2a..096c28b 100644 mss.resident >> 10, (unsigned long)(mss.pss >> (10 + PSS_SHIFT)), mss.shared_clean >> 10, +@@ -919,7 +970,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, + if (!pm.buffer) + goto out_task; + +- mm = mm_for_maps(task); ++ mm = mm_access(task, PTRACE_MODE_READ); + ret = PTR_ERR(mm); + if (!mm || IS_ERR(mm)) + goto out_free; @@ -1138,6 +1189,13 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) int n; char buffer[50]; @@ -48458,7 +48959,7 @@ index 7faaf2a..096c28b 100644 seq_printf(m, " heap"); } else { diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index 74fe164..899e77b 100644 +index 74fe164..0848f95 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -51,7 +51,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm) @@ -48479,6 +48980,15 @@ index 74fe164..899e77b 100644 } else if (mm) { pid_t tid = vm_is_stack(priv->task, vma, is_pid); +@@ -223,7 +223,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) + if (!priv->task) + return ERR_PTR(-ESRCH); + +- mm = mm_for_maps(priv->task); ++ mm = mm_access(priv->task, PTRACE_MODE_READ); + if (!mm || IS_ERR(mm)) { + put_task_struct(priv->task); + priv->task = NULL; diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c index d67908b..d13f6a6 100644 --- a/fs/quota/netlink.c @@ -48672,7 +49182,7 @@ index 17d33d0..da0bf5c 100644 return -EINVAL; diff --git a/fs/seq_file.c b/fs/seq_file.c -index 0cbd049..cab1127 100644 +index 0cbd049..64e705c 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -9,6 +9,7 @@ @@ -48693,6 +49203,42 @@ index 0cbd049..cab1127 100644 /* * Wrappers around seq_open(e.g. swaps_open) need to be +@@ -92,7 +96,7 @@ static int traverse(struct seq_file *m, loff_t offset) + return 0; + } + if (!m->buf) { +- m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); ++ m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL | GFP_USERCOPY); + if (!m->buf) + return -ENOMEM; + } +@@ -132,7 +136,7 @@ static int traverse(struct seq_file *m, loff_t offset) + Eoverflow: + m->op->stop(m, p); + kfree(m->buf); +- m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); ++ m->buf = kmalloc(m->size <<= 1, GFP_KERNEL | GFP_USERCOPY); + return !m->buf ? -ENOMEM : -EAGAIN; + } + +@@ -187,7 +191,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) + + /* grab buffer if we didn't have one */ + if (!m->buf) { +- m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); ++ m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL | GFP_USERCOPY); + if (!m->buf) + goto Enomem; + } +@@ -228,7 +232,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) + goto Fill; + m->op->stop(m, p); + kfree(m->buf); +- m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); ++ m->buf = kmalloc(m->size <<= 1, GFP_KERNEL | GFP_USERCOPY); + if (!m->buf) + goto Enomem; + m->count = 0; @@ -567,7 +571,7 @@ static void single_stop(struct seq_file *p, void *v) int single_open(struct file *file, int (*show)(struct seq_file *, void *), void *data) @@ -48703,7 +49249,7 @@ index 0cbd049..cab1127 100644 if (op) { diff --git a/fs/splice.c b/fs/splice.c -index f847684..156619e 100644 +index 5cac690..f833a99 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -194,7 +194,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, @@ -48727,7 +49273,7 @@ index f847684..156619e 100644 } pipe_unlock(pipe); -@@ -560,7 +560,7 @@ static ssize_t kernel_readv(struct file *file, const struct iovec *vec, +@@ -563,7 +563,7 @@ static ssize_t kernel_readv(struct file *file, const struct iovec *vec, old_fs = get_fs(); set_fs(get_ds()); /* The cast to a user pointer is valid due to the set_fs() */ @@ -48736,7 +49282,7 @@ index f847684..156619e 100644 set_fs(old_fs); return res; -@@ -575,7 +575,7 @@ static ssize_t kernel_write(struct file *file, const char *buf, size_t count, +@@ -578,7 +578,7 @@ static ssize_t kernel_write(struct file *file, const char *buf, size_t count, old_fs = get_fs(); set_fs(get_ds()); /* The cast to a user pointer is valid due to the set_fs() */ @@ -48745,7 +49291,7 @@ index f847684..156619e 100644 set_fs(old_fs); return res; -@@ -626,7 +626,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, +@@ -630,7 +630,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, goto err; this_len = min_t(size_t, len, PAGE_CACHE_SIZE - offset); @@ -48754,7 +49300,7 @@ index f847684..156619e 100644 vec[i].iov_len = this_len; spd.pages[i] = page; spd.nr_pages++; -@@ -845,10 +845,10 @@ EXPORT_SYMBOL(splice_from_pipe_feed); +@@ -849,10 +849,10 @@ EXPORT_SYMBOL(splice_from_pipe_feed); int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd) { while (!pipe->nrbufs) { @@ -48767,7 +49313,7 @@ index f847684..156619e 100644 return 0; if (sd->flags & SPLICE_F_NONBLOCK) -@@ -1181,7 +1181,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, +@@ -1185,7 +1185,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, * out of the pipe right after the splice_to_pipe(). So set * PIPE_READERS appropriately. */ @@ -48776,7 +49322,7 @@ index f847684..156619e 100644 current->splice_pipe = pipe; } -@@ -1733,9 +1733,9 @@ static int ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags) +@@ -1738,9 +1738,9 @@ static int ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags) ret = -ERESTARTSYS; break; } @@ -48788,7 +49334,7 @@ index f847684..156619e 100644 if (flags & SPLICE_F_NONBLOCK) { ret = -EAGAIN; break; -@@ -1767,7 +1767,7 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) +@@ -1772,7 +1772,7 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) pipe_lock(pipe); while (pipe->nrbufs >= pipe->buffers) { @@ -48797,7 +49343,7 @@ index f847684..156619e 100644 send_sig(SIGPIPE, current, 0); ret = -EPIPE; break; -@@ -1780,9 +1780,9 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) +@@ -1785,9 +1785,9 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) ret = -ERESTARTSYS; break; } @@ -48809,7 +49355,7 @@ index f847684..156619e 100644 } pipe_unlock(pipe); -@@ -1818,14 +1818,14 @@ retry: +@@ -1823,14 +1823,14 @@ retry: pipe_double_lock(ipipe, opipe); do { @@ -48826,7 +49372,7 @@ index f847684..156619e 100644 break; /* -@@ -1922,7 +1922,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, +@@ -1927,7 +1927,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, pipe_double_lock(ipipe, opipe); do { @@ -48835,7 +49381,7 @@ index f847684..156619e 100644 send_sig(SIGPIPE, current, 0); if (!ret) ret = -EPIPE; -@@ -1967,7 +1967,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, +@@ -1972,7 +1972,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, * return EAGAIN if we have the potential of some data in the * future, otherwise just return 0 */ @@ -49109,10 +49655,10 @@ index 3011b87..1ab03e9 100644 kfree(s); diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig new file mode 100644 -index 0000000..2d6e3a8 +index 0000000..4d533f1 --- /dev/null +++ b/grsecurity/Kconfig -@@ -0,0 +1,915 @@ +@@ -0,0 +1,941 @@ +# +# grecurity configuration +# @@ -49241,6 +49787,7 @@ index 0000000..2d6e3a8 +config GRKERNSEC_HIDESYM + bool "Hide kernel symbols" + default y if GRKERNSEC_CONFIG_AUTO ++ select PAX_USERCOPY_SLABS + help + If you say Y here, getting information on loaded modules, and + displaying all kernel symbols through a syscall will be restricted @@ -49386,6 +49933,31 @@ index 0000000..2d6e3a8 + able to hardlink to files they do not own. If the sysctl option is + enabled, a sysctl option with name "linking_restrictions" is created. + ++config GRKERNSEC_SYMLINKOWN ++ bool "Kernel-enforced SymlinksIfOwnerMatch" ++ default y if GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_SERVER ++ help ++ Apache's SymlinksIfOwnerMatch option has an inherent race condition ++ that prevents it from being used as a security feature. As Apache ++ verifies the symlink by performing a stat() against the target of ++ the symlink before it is followed, an attacker can setup a symlink ++ to point to a same-owned file, then replace the symlink with one ++ that targets another user's file just after Apache "validates" the ++ symlink -- a classic TOCTOU race. If you say Y here, a complete, ++ race-free replacement for Apache's "SymlinksIfOwnerMatch" option ++ will be in place for the group you specify. If the sysctl option ++ is enabled, a sysctl option with name "enforce_symlinksifowner" is ++ created. ++ ++config GRKERNSEC_SYMLINKOWN_GID ++ int "GID for users with kernel-enforced SymlinksIfOwnerMatch" ++ depends on GRKERNSEC_SYMLINKOWN ++ default 1006 ++ help ++ Setting this GID determines what group kernel-enforced ++ SymlinksIfOwnerMatch will be enabled for. If the sysctl option ++ is enabled, a sysctl option with name "symlinkown_gid" is created. ++ +config GRKERNSEC_FIFO + bool "FIFO restrictions" + default y if GRKERNSEC_CONFIG_AUTO @@ -49789,7 +50361,7 @@ index 0000000..2d6e3a8 + +config GRKERNSEC_TPE + bool "Trusted Path Execution (TPE)" -+ default y if GRKERNSEC_CONFIG_AUTO ++ default y if GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_SERVER + help + If you say Y here, you will be able to choose a gid to add to the + supplementary groups of users you want to mark as "untrusted." @@ -50074,10 +50646,10 @@ index 0000000..1b9afa9 +endif diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c new file mode 100644 -index 0000000..00b6c54 +index 0000000..7a5922f --- /dev/null +++ b/grsecurity/gracl.c -@@ -0,0 +1,4012 @@ +@@ -0,0 +1,4016 @@ +#include +#include +#include @@ -50100,6 +50672,7 @@ index 0000000..00b6c54 +#include +#include +#include ++#include +#include +#include +#include "../fs/mount.h" @@ -52350,18 +52923,17 @@ index 0000000..00b6c54 +void +gr_copy_label(struct task_struct *tsk) +{ -+ /* plain copying of fields is already done by dup_task_struct */ + tsk->signal->used_accept = 0; + tsk->acl_sp_role = 0; -+ //tsk->acl_role_id = current->acl_role_id; -+ //tsk->acl = current->acl; -+ //tsk->role = current->role; ++ tsk->acl_role_id = current->acl_role_id; ++ tsk->acl = current->acl; ++ tsk->role = current->role; + tsk->signal->curr_ip = current->signal->curr_ip; + tsk->signal->saved_ip = current->signal->saved_ip; + if (current->exec_file) + get_file(current->exec_file); -+ //tsk->exec_file = current->exec_file; -+ //tsk->is_writable = current->is_writable; ++ tsk->exec_file = current->exec_file; ++ tsk->is_writable = current->is_writable; + if (unlikely(current->signal->used_accept)) { + current->signal->curr_ip = 0; + current->signal->saved_ip = 0; @@ -53170,6 +53742,15 @@ index 0000000..00b6c54 + return 1; +} + ++static int gr_rbac_disable(void *unused) ++{ ++ pax_open_kernel(); ++ gr_status &= ~GR_READY; ++ pax_close_kernel(); ++ ++ return 0; ++} ++ +ssize_t +write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos) +{ @@ -53254,15 +53835,12 @@ index 0000000..00b6c54 + case GR_SHUTDOWN: + if ((gr_status & GR_READY) + && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { -+ pax_open_kernel(); -+ gr_status &= ~GR_READY; -+ pax_close_kernel(); -+ -+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG); ++ stop_machine(gr_rbac_disable, NULL, NULL); + free_variables(); + memset(gr_usermode, 0, sizeof (struct gr_arg)); + memset(gr_system_salt, 0, GR_SALT_LEN); + memset(gr_system_sum, 0, GR_SHA_LEN); ++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG); + } else if (gr_status & GR_READY) { + gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG); + error = -EPERM; @@ -53287,20 +53865,14 @@ index 0000000..00b6c54 + gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION); + error = -EAGAIN; + } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { -+ preempt_disable(); -+ -+ pax_open_kernel(); -+ gr_status &= ~GR_READY; -+ pax_close_kernel(); -+ ++ stop_machine(gr_rbac_disable, NULL, NULL); + free_variables(); -+ if (!(error2 = gracl_init(gr_usermode))) { -+ preempt_enable(); ++ error2 = gracl_init(gr_usermode); ++ if (!error2) + gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION); -+ } else { -+ preempt_enable(); -+ error = error2; ++ else { + gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION); ++ error = error2; + } + } else { + gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION); @@ -54032,11 +54604,15 @@ index 0000000..00b6c54 + return 1; + + subj = task->acl; ++ read_lock(&gr_inode_lock); + do { + obj = lookup_acl_obj_label(ino, dev, subj); -+ if (obj != NULL) ++ if (obj != NULL) { ++ read_unlock(&gr_inode_lock); + return (obj->mode & GR_FIND) ? 1 : 0; ++ } + } while ((subj = subj->parent_subject)); ++ read_unlock(&gr_inode_lock); + + /* this is purely an optimization since we're looking for an object + for the directory we're doing a readdir on @@ -56869,10 +57445,10 @@ index 0000000..8ca18bf +} diff --git a/grsecurity/grsec_init.c b/grsecurity/grsec_init.c new file mode 100644 -index 0000000..01ddde4 +index 0000000..05a6015 --- /dev/null +++ b/grsecurity/grsec_init.c -@@ -0,0 +1,277 @@ +@@ -0,0 +1,283 @@ +#include +#include +#include @@ -56884,6 +57460,8 @@ index 0000000..01ddde4 + +int grsec_enable_ptrace_readexec; +int grsec_enable_setxid; ++int grsec_enable_symlinkown; ++int grsec_symlinkown_gid; +int grsec_enable_brute; +int grsec_enable_link; +int grsec_enable_dmesg; @@ -57127,6 +57705,10 @@ index 0000000..01ddde4 +#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL + grsec_enable_chroot_sysctl = 1; +#endif ++#ifdef CONFIG_GRKERNSEC_SYMLINKOWN ++ grsec_enable_symlinkown = 1; ++ grsec_symlinkown_gid = CONFIG_GRKERNSEC_SYMLINKOWN_GID; ++#endif +#ifdef CONFIG_GRKERNSEC_TPE + grsec_enable_tpe = 1; + grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID; @@ -57152,16 +57734,32 @@ index 0000000..01ddde4 +} diff --git a/grsecurity/grsec_link.c b/grsecurity/grsec_link.c new file mode 100644 -index 0000000..3efe141 +index 0000000..35a96d1 --- /dev/null +++ b/grsecurity/grsec_link.c -@@ -0,0 +1,43 @@ +@@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + ++int gr_handle_symlink_owner(const struct path *link, const struct inode *target) ++{ ++#ifdef CONFIG_GRKERNSEC_SYMLINKOWN ++ const struct inode *link_inode = link->dentry->d_inode; ++ ++ if (grsec_enable_symlinkown && in_group_p(grsec_symlinkown_gid) && ++ /* ignore root-owned links, e.g. /proc/self */ ++ link_inode->i_uid && ++ link_inode->i_uid != target->i_uid) { ++ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINKOWNER_MSG, link->dentry, link->mnt, link_inode->i_uid, target->i_uid); ++ return 1; ++ } ++#endif ++ return 0; ++} ++ +int +gr_handle_follow_link(const struct inode *parent, + const struct inode *inode, @@ -58184,10 +58782,10 @@ index 0000000..4030d57 +} diff --git a/grsecurity/grsec_sysctl.c b/grsecurity/grsec_sysctl.c new file mode 100644 -index 0000000..8316f6f +index 0000000..f55ef0f --- /dev/null +++ b/grsecurity/grsec_sysctl.c -@@ -0,0 +1,453 @@ +@@ -0,0 +1,469 @@ +#include +#include +#include @@ -58235,6 +58833,22 @@ index 0000000..8316f6f + .proc_handler = &proc_dointvec, + }, +#endif ++#ifdef CONFIG_GRKERNSEC_SYMLINKOWN ++ { ++ .procname = "enforce_symlinksifowner", ++ .data = &grsec_enable_symlinkown, ++ .maxlen = sizeof(int), ++ .mode = 0600, ++ .proc_handler = &proc_dointvec, ++ }, ++ { ++ .procname = "symlinkown_gid", ++ .data = &grsec_symlinkown_gid, ++ .maxlen = sizeof(int), ++ .mode = 0600, ++ .proc_handler = &proc_dointvec, ++ }, ++#endif +#ifdef CONFIG_GRKERNSEC_BRUTE + { + .procname = "deter_bruteforce", @@ -58823,7 +59437,7 @@ index f1c8ca6..b5c1cc7 100644 #define ACPI_DRIVER_ALL_NOTIFY_EVENTS 0x1 /* system AND device events */ diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h -index b7babf0..71e4e74 100644 +index b7babf0..3ba8aee 100644 --- a/include/asm-generic/atomic-long.h +++ b/include/asm-generic/atomic-long.h @@ -22,6 +22,12 @@ @@ -59076,7 +59690,7 @@ index b7babf0..71e4e74 100644 static inline long atomic_long_dec_return(atomic_long_t *l) { atomic_t *v = (atomic_t *)l; -@@ -255,4 +393,49 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u) +@@ -255,4 +393,55 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u) #endif /* BITS_PER_LONG == 64 */ @@ -59094,6 +59708,10 @@ index b7babf0..71e4e74 100644 + atomic_dec_unchecked((atomic_unchecked_t *)NULL); + atomic_cmpxchg_unchecked((atomic_unchecked_t *)NULL, 0, 0); + (void)atomic_xchg_unchecked((atomic_unchecked_t *)NULL, 0); ++#ifdef CONFIG_X86 ++ atomic_clear_mask_unchecked(0, NULL); ++ atomic_set_mask_unchecked(0, NULL); ++#endif + + atomic_long_read_unchecked((atomic_long_unchecked_t *)NULL); + atomic_long_set_unchecked((atomic_long_unchecked_t *)NULL, 0); @@ -59115,6 +59733,8 @@ index b7babf0..71e4e74 100644 +#define atomic_dec_unchecked(v) atomic_dec(v) +#define atomic_cmpxchg_unchecked(v, o, n) atomic_cmpxchg((v), (o), (n)) +#define atomic_xchg_unchecked(v, i) atomic_xchg((v), (i)) ++#define atomic_clear_mask_unchecked(mask, v) atomic_clear_mask((mask), (v)) ++#define atomic_set_mask_unchecked(mask, v) atomic_set_mask((mask), (v)) + +#define atomic_long_read_unchecked(v) atomic_long_read(v) +#define atomic_long_set_unchecked(v, i) atomic_long_set((v), (i)) @@ -59126,6 +59746,19 @@ index b7babf0..71e4e74 100644 +#endif + #endif /* _ASM_GENERIC_ATOMIC_LONG_H */ +diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h +index 1ced641..c896ee8 100644 +--- a/include/asm-generic/atomic.h ++++ b/include/asm-generic/atomic.h +@@ -159,7 +159,7 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) + * Atomically clears the bits set in @mask from @v + */ + #ifndef atomic_clear_mask +-static inline void atomic_clear_mask(unsigned long mask, atomic_t *v) ++static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) + { + unsigned long flags; + diff --git a/include/asm-generic/atomic64.h b/include/asm-generic/atomic64.h index b18ce4f..2ee2843 100644 --- a/include/asm-generic/atomic64.h @@ -59293,49 +59926,10 @@ index 810431d..0ec4804f 100644 * (puds are folded into pgds so this doesn't get actually called, * but the define is needed for a generic inline function.) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 125c54e..e95c18e 100644 +index c7ec2cd..909d125 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h -@@ -446,6 +446,18 @@ static inline int pmd_write(pmd_t pmd) - #endif /* __HAVE_ARCH_PMD_WRITE */ - #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ - -+#ifndef __HAVE_ARCH_READ_PMD_ATOMIC -+static inline pmd_t read_pmd_atomic(pmd_t *pmdp) -+{ -+ /* -+ * Depend on compiler for an atomic pmd read. NOTE: this is -+ * only going to work, if the pmdval_t isn't larger than -+ * an unsigned long. -+ */ -+ return *pmdp; -+} -+#endif /* __HAVE_ARCH_READ_PMD_ATOMIC */ -+ - /* - * This function is meant to be used by sites walking pagetables with - * the mmap_sem hold in read mode to protect against MADV_DONTNEED and -@@ -459,11 +471,17 @@ static inline int pmd_write(pmd_t pmd) - * undefined so behaving like if the pmd was none is safe (because it - * can return none anyway). The compiler level barrier() is critically - * important to compute the two checks atomically on the same pmdval. -+ * -+ * For 32bit kernels with a 64bit large pmd_t this automatically takes -+ * care of reading the pmd atomically to avoid SMP race conditions -+ * against pmd_populate() when the mmap_sem is hold for reading by the -+ * caller (a special atomic read not done by "gcc" as in the generic -+ * version above, is also needed when THP is disabled because the page -+ * fault can populate the pmd from under us). - */ - static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) - { -- /* depend on compiler for an atomic pmd read */ -- pmd_t pmdval = *pmd; -+ pmd_t pmdval = read_pmd_atomic(pmd); - /* - * The barrier will stabilize the pmdval in a register or on - * the stack so that it will stop changing under the code. -@@ -503,6 +521,14 @@ static inline int pmd_trans_unstable(pmd_t *pmd) +@@ -531,6 +531,14 @@ static inline int pmd_trans_unstable(pmd_t *pmd) #endif } @@ -59630,10 +60224,10 @@ index 42e55de..1cd0e66 100644 extern struct cleancache_ops cleancache_register_ops(struct cleancache_ops *ops); diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h -index 2f40791..a62d196 100644 +index 2f40791..9c9e13c 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h -@@ -32,6 +32,16 @@ +@@ -32,6 +32,20 @@ #define __linktime_error(message) __attribute__((__error__(message))) #if __GNUC_MINOR__ >= 5 @@ -59646,11 +60240,15 @@ index 2f40791..a62d196 100644 +#ifdef SIZE_OVERFLOW_PLUGIN +#define __size_overflow(...) __attribute__((size_overflow(__VA_ARGS__))) +#endif ++ ++#ifdef LATENT_ENTROPY_PLUGIN ++#define __latent_entropy __attribute__((latent_entropy)) ++#endif + /* * Mark a position in code as unreachable. This can be used to * suppress control flow warnings after asm blocks that transfer -@@ -47,6 +57,11 @@ +@@ -47,6 +61,11 @@ #define __noclone __attribute__((__noclone__)) #endif @@ -59663,7 +60261,7 @@ index 2f40791..a62d196 100644 #if __GNUC_MINOR__ > 0 diff --git a/include/linux/compiler.h b/include/linux/compiler.h -index 923d093..726c17f 100644 +index 923d093..1fef491 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -5,31 +5,62 @@ @@ -59739,7 +60337,7 @@ index 923d093..726c17f 100644 #endif #ifdef __KERNEL__ -@@ -264,6 +297,18 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); +@@ -264,6 +297,22 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); # define __attribute_const__ /* unimplemented */ #endif @@ -59754,11 +60352,15 @@ index 923d093..726c17f 100644 +#ifndef __size_overflow +# define __size_overflow(...) +#endif ++ ++#ifndef __latent_entropy ++# define __latent_entropy ++#endif + /* * Tell gcc if a function is cold. The compiler will assume any path * directly leading to the call is unlikely. -@@ -273,6 +318,22 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); +@@ -273,6 +322,22 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #define __cold #endif @@ -59781,7 +60383,7 @@ index 923d093..726c17f 100644 /* Simple shorthand for a section definition */ #ifndef __section # define __section(S) __attribute__ ((__section__(#S))) -@@ -308,6 +369,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); +@@ -308,6 +373,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); * use is to mediate communication between process-level code and irq/NMI * handlers, all running on the same CPU. */ @@ -60092,6 +60694,49 @@ index 017a7fb..33a8507 100644 struct disk_events *ev; #ifdef CONFIG_BLK_DEV_INTEGRITY struct blk_integrity *integrity; +diff --git a/include/linux/gfp.h b/include/linux/gfp.h +index 581e74b..8c34a24 100644 +--- a/include/linux/gfp.h ++++ b/include/linux/gfp.h +@@ -38,6 +38,12 @@ struct vm_area_struct; + #define ___GFP_OTHER_NODE 0x800000u + #define ___GFP_WRITE 0x1000000u + ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++#define ___GFP_USERCOPY 0x2000000u ++#else ++#define ___GFP_USERCOPY 0 ++#endif ++ + /* + * GFP bitmasks.. + * +@@ -87,6 +93,7 @@ struct vm_area_struct; + #define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD) + #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */ + #define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) /* Allocator intends to dirty page */ ++#define __GFP_USERCOPY ((__force gfp_t)___GFP_USERCOPY)/* Allocator intends to copy page to/from userland */ + + /* + * This may seem redundant, but it's a way of annotating false positives vs. +@@ -94,7 +101,7 @@ struct vm_area_struct; + */ + #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK) + +-#define __GFP_BITS_SHIFT 25 /* Room for N __GFP_FOO bits */ ++#define __GFP_BITS_SHIFT 26 /* Room for N __GFP_FOO bits */ + #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) + + /* This equals 0, but use constants in case they ever change */ +@@ -148,6 +155,8 @@ struct vm_area_struct; + /* 4GB DMA on some platforms */ + #define GFP_DMA32 __GFP_DMA32 + ++#define GFP_USERCOPY __GFP_USERCOPY ++ + /* Convert GFP flags to their corresponding migrate type */ + static inline int allocflags_to_migratetype(gfp_t gfp_flags) + { diff --git a/include/linux/gracl.h b/include/linux/gracl.h new file mode 100644 index 0000000..c938b1f @@ -60580,10 +61225,10 @@ index 0000000..b30e9bc +#endif diff --git a/include/linux/grinternal.h b/include/linux/grinternal.h new file mode 100644 -index 0000000..da390f1 +index 0000000..c9292f7 --- /dev/null +++ b/include/linux/grinternal.h -@@ -0,0 +1,221 @@ +@@ -0,0 +1,223 @@ +#ifndef __GRINTERNAL_H +#define __GRINTERNAL_H + @@ -60645,6 +61290,8 @@ index 0000000..da390f1 +extern int grsec_enable_chroot_caps; +extern int grsec_enable_chroot_sysctl; +extern int grsec_enable_chroot_unix; ++extern int grsec_enable_symlinkown; ++extern int grsec_symlinkown_gid; +extern int grsec_enable_tpe; +extern int grsec_tpe_gid; +extern int grsec_enable_tpe_all; @@ -60807,10 +61454,10 @@ index 0000000..da390f1 +#endif diff --git a/include/linux/grmsg.h b/include/linux/grmsg.h new file mode 100644 -index 0000000..ae576a1 +index 0000000..54f4e85 --- /dev/null +++ b/include/linux/grmsg.h -@@ -0,0 +1,109 @@ +@@ -0,0 +1,110 @@ +#define DEFAULTSECMSG "%.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u, parent %.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u" +#define GR_ACL_PROCACCT_MSG "%.256s[%.16s:%d] IP:%pI4 TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u run time:[%ud %uh %um %us] cpu time:[%ud %uh %um %us] %s with exit code %ld, parent %.256s[%.16s:%d] IP:%pI4 TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u" +#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by " @@ -60920,12 +61567,13 @@ index 0000000..ae576a1 +#define GR_PTRACE_READEXEC_MSG "denied ptrace of unreadable binary %.950s by " +#define GR_INIT_TRANSFER_MSG "persistent special role transferred privilege to init by " +#define GR_BADPROCPID_MSG "denied read of sensitive /proc/pid/%s entry via fd passed across exec by " ++#define GR_SYMLINKOWNER_MSG "denied following symlink %.950s since symlink owner %u does not match target owner %u, by " diff --git a/include/linux/grsecurity.h b/include/linux/grsecurity.h new file mode 100644 -index 0000000..acd05db +index 0000000..38bfb04 --- /dev/null +++ b/include/linux/grsecurity.h -@@ -0,0 +1,232 @@ +@@ -0,0 +1,233 @@ +#ifndef GR_SECURITY_H +#define GR_SECURITY_H +#include @@ -61110,6 +61758,7 @@ index 0000000..acd05db + const struct vfsmount *parent_mnt, + const struct dentry *old_dentry, + const struct vfsmount *old_mnt, const char *to); ++int gr_handle_symlink_owner(const struct path *link, const struct inode *target); +int gr_acl_handle_rename(struct dentry *new_dentry, + struct dentry *parent_dentry, + const struct vfsmount *parent_mnt, @@ -61266,10 +61915,54 @@ index 58404b0..439ed95 100644 }; diff --git a/include/linux/init.h b/include/linux/init.h -index 6b95109..4aca62c 100644 +index 6b95109..bcbdd68 100644 --- a/include/linux/init.h +++ b/include/linux/init.h -@@ -294,13 +294,13 @@ void __init parse_early_options(char *cmdline); +@@ -39,9 +39,15 @@ + * Also note, that this data cannot be "const". + */ + ++#ifdef MODULE ++#define add_latent_entropy ++#else ++#define add_latent_entropy __latent_entropy ++#endif ++ + /* These are for everybody (although not all archs will actually + discard it in modules) */ +-#define __init __section(.init.text) __cold notrace ++#define __init __section(.init.text) __cold notrace add_latent_entropy + #define __initdata __section(.init.data) + #define __initconst __section(.init.rodata) + #define __exitdata __section(.exit.data) +@@ -83,7 +89,7 @@ + #define __exit __section(.exit.text) __exitused __cold notrace + + /* Used for HOTPLUG */ +-#define __devinit __section(.devinit.text) __cold notrace ++#define __devinit __section(.devinit.text) __cold notrace add_latent_entropy + #define __devinitdata __section(.devinit.data) + #define __devinitconst __section(.devinit.rodata) + #define __devexit __section(.devexit.text) __exitused __cold notrace +@@ -91,7 +97,7 @@ + #define __devexitconst __section(.devexit.rodata) + + /* Used for HOTPLUG_CPU */ +-#define __cpuinit __section(.cpuinit.text) __cold notrace ++#define __cpuinit __section(.cpuinit.text) __cold notrace add_latent_entropy + #define __cpuinitdata __section(.cpuinit.data) + #define __cpuinitconst __section(.cpuinit.rodata) + #define __cpuexit __section(.cpuexit.text) __exitused __cold notrace +@@ -99,7 +105,7 @@ + #define __cpuexitconst __section(.cpuexit.rodata) + + /* Used for MEMORY_HOTPLUG */ +-#define __meminit __section(.meminit.text) __cold notrace ++#define __meminit __section(.meminit.text) __cold notrace add_latent_entropy + #define __meminitdata __section(.meminit.data) + #define __meminitconst __section(.meminit.rodata) + #define __memexit __section(.memexit.text) __exitused __cold notrace +@@ -294,13 +300,13 @@ void __init parse_early_options(char *cmdline); /* Each module must use one module_init(). */ #define module_init(initfn) \ @@ -61708,10 +62401,10 @@ index 74aa71b..4ae97ba 100644 #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index 3cc3062..efeaeb7 100644 +index b35752f..41075a0 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h -@@ -252,6 +252,8 @@ struct vm_area_struct { +@@ -262,6 +262,8 @@ struct vm_area_struct { #ifdef CONFIG_NUMA struct mempolicy *vm_policy; /* NUMA policy for the VMA */ #endif @@ -61720,7 +62413,7 @@ index 3cc3062..efeaeb7 100644 }; struct core_thread { -@@ -326,7 +328,7 @@ struct mm_struct { +@@ -336,7 +338,7 @@ struct mm_struct { unsigned long def_flags; unsigned long nr_ptes; /* Page table pages */ unsigned long start_code, end_code, start_data, end_data; @@ -61729,7 +62422,7 @@ index 3cc3062..efeaeb7 100644 unsigned long arg_start, arg_end, env_start, env_end; unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */ -@@ -388,6 +390,24 @@ struct mm_struct { +@@ -398,6 +400,24 @@ struct mm_struct { #ifdef CONFIG_CPUMASK_OFFSTACK struct cpumask cpumask_allocation; #endif @@ -61775,7 +62468,7 @@ index 1d1b1e1..2a13c78 100644 #define pmdp_clear_flush_notify(__vma, __address, __pmdp) \ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h -index dff7115..0e001c8 100644 +index 5f6806b..49db2b2 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -380,7 +380,7 @@ struct zone { @@ -62201,10 +62894,21 @@ index 85c5073..51fac8b 100644 struct ctl_table_header; struct ctl_table; diff --git a/include/linux/random.h b/include/linux/random.h -index 8f74538..02a1012 100644 +index 8f74538..de61694 100644 --- a/include/linux/random.h +++ b/include/linux/random.h -@@ -69,12 +69,17 @@ void srandom32(u32 seed); +@@ -54,6 +54,10 @@ extern void add_input_randomness(unsigned int type, unsigned int code, + unsigned int value); + extern void add_interrupt_randomness(int irq); + ++#ifdef CONFIG_PAX_LATENT_ENTROPY ++extern void transfer_latent_entropy(void); ++#endif ++ + extern void get_random_bytes(void *buf, int nbytes); + void generate_random_uuid(unsigned char uuid_out[16]); + +@@ -69,12 +73,17 @@ void srandom32(u32 seed); u32 prandom32(struct rnd_state *); @@ -62317,7 +63021,7 @@ index fd07c45..4676b8e 100644 static inline void anon_vma_merge(struct vm_area_struct *vma, struct vm_area_struct *next) diff --git a/include/linux/sched.h b/include/linux/sched.h -index 81a173c..85ccd8f 100644 +index 7b06169..c92adbe 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -100,6 +100,7 @@ struct bio_list; @@ -62501,12 +63205,12 @@ index 81a173c..85ccd8f 100644 +extern void pax_report_fault(struct pt_regs *regs, void *pc, void *sp); +extern void pax_report_insns(struct pt_regs *regs, void *pc, void *sp); +extern void pax_report_refcount_overflow(struct pt_regs *regs); -+extern __noreturn void pax_report_usercopy(const void *ptr, unsigned long len, bool to, const char *type); ++extern void check_object_size(const void *ptr, unsigned long n, bool to); + /* Future-safe accessor for struct task_struct's cpus_allowed. */ #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) -@@ -2138,7 +2230,9 @@ void yield(void); +@@ -2146,7 +2238,9 @@ void yield(void); extern struct exec_domain default_exec_domain; union thread_union { @@ -62516,7 +63220,7 @@ index 81a173c..85ccd8f 100644 unsigned long stack[THREAD_SIZE/sizeof(long)]; }; -@@ -2171,6 +2265,7 @@ extern struct pid_namespace init_pid_ns; +@@ -2179,6 +2273,7 @@ extern struct pid_namespace init_pid_ns; */ extern struct task_struct *find_task_by_vpid(pid_t nr); @@ -62524,7 +63228,7 @@ index 81a173c..85ccd8f 100644 extern struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns); -@@ -2314,7 +2409,7 @@ extern void __cleanup_sighand(struct sighand_struct *); +@@ -2322,7 +2417,7 @@ extern void __cleanup_sighand(struct sighand_struct *); extern void exit_itimers(struct signal_struct *); extern void flush_itimer_signals(void); @@ -62533,7 +63237,7 @@ index 81a173c..85ccd8f 100644 extern void daemonize(const char *, ...); extern int allow_signal(int); -@@ -2515,13 +2610,17 @@ static inline unsigned long *end_of_stack(struct task_struct *p) +@@ -2523,9 +2618,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) #endif @@ -62545,14 +63249,6 @@ index 81a173c..85ccd8f 100644 return (obj >= stack) && (obj < (stack + THREAD_SIZE)); } - -+#ifdef CONFIG_PAX_USERCOPY -+extern int object_is_on_stack(const void *obj, unsigned long len); -+#endif -+ - extern void thread_info_cache_init(void); - - #ifdef CONFIG_DEBUG_STACK_USAGE diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h index 899fbb4..1cb4138 100644 --- a/include/linux/screen_info.h @@ -62617,10 +63313,10 @@ index 92808b8..c28cac4 100644 /* shm_mode upper byte flags */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index c168907..c7756db 100644 +index c1bae8d..2dbcd31 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -666,7 +666,7 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) +@@ -663,7 +663,7 @@ static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) */ static inline int skb_queue_empty(const struct sk_buff_head *list) { @@ -62629,7 +63325,7 @@ index c168907..c7756db 100644 } /** -@@ -679,7 +679,7 @@ static inline int skb_queue_empty(const struct sk_buff_head *list) +@@ -676,7 +676,7 @@ static inline int skb_queue_empty(const struct sk_buff_head *list) static inline bool skb_queue_is_last(const struct sk_buff_head *list, const struct sk_buff *skb) { @@ -62638,7 +63334,7 @@ index c168907..c7756db 100644 } /** -@@ -692,7 +692,7 @@ static inline bool skb_queue_is_last(const struct sk_buff_head *list, +@@ -689,7 +689,7 @@ static inline bool skb_queue_is_last(const struct sk_buff_head *list, static inline bool skb_queue_is_first(const struct sk_buff_head *list, const struct sk_buff *skb) { @@ -62647,7 +63343,7 @@ index c168907..c7756db 100644 } /** -@@ -1587,7 +1587,7 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len) +@@ -1584,7 +1584,7 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len) * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) */ #ifndef NET_SKB_PAD @@ -62657,7 +63353,7 @@ index c168907..c7756db 100644 extern int ___pskb_trim(struct sk_buff *skb, unsigned int len); diff --git a/include/linux/slab.h b/include/linux/slab.h -index a595dce..c403597 100644 +index a595dce..dfab0d2 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -11,12 +11,20 @@ @@ -62672,7 +63368,7 @@ index a595dce..c403597 100644 */ #define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */ + -+#ifdef CONFIG_PAX_USERCOPY ++#ifdef CONFIG_PAX_USERCOPY_SLABS +#define SLAB_USERCOPY 0x00000200UL /* PaX: Allow copying objs to/from userland */ +#else +#define SLAB_USERCOPY 0x00000000UL @@ -62698,15 +63394,16 @@ index a595dce..c403597 100644 /* * struct kmem_cache related prototypes -@@ -161,6 +172,7 @@ void * __must_check krealloc(const void *, size_t, gfp_t); +@@ -161,6 +172,8 @@ void * __must_check krealloc(const void *, size_t, gfp_t); void kfree(const void *); void kzfree(const void *); size_t ksize(const void *); -+void check_object_size(const void *ptr, unsigned long n, bool to); ++const char *check_heap_object(const void *ptr, unsigned long n, bool to); ++bool is_usercopy_object(const void *ptr); /* * Allocator specific definitions. These are mainly used to establish optimized -@@ -240,6 +252,7 @@ size_t ksize(const void *); +@@ -240,6 +253,7 @@ size_t ksize(const void *); * for general use, and so are not documented here. For a full list of * potential flags, always refer to linux/gfp.h. */ @@ -62714,7 +63411,7 @@ index a595dce..c403597 100644 static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) { if (size != 0 && n > ULONG_MAX / size) -@@ -298,7 +311,7 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, +@@ -298,7 +312,7 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) @@ -62723,7 +63420,7 @@ index a595dce..c403597 100644 #define kmalloc_track_caller(size, flags) \ __kmalloc_track_caller(size, flags, _RET_IP_) #else -@@ -317,7 +330,7 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); +@@ -317,7 +331,7 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) @@ -62733,7 +63430,7 @@ index a595dce..c403597 100644 __kmalloc_node_track_caller(size, flags, node, \ _RET_IP_) diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h -index fbd1117..d4d8ef8 100644 +index fbd1117..0a3d314 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -66,10 +66,10 @@ struct kmem_cache { @@ -62751,7 +63448,16 @@ index fbd1117..d4d8ef8 100644 /* * If debugging is enabled, then the allocator can add additional -@@ -107,7 +107,7 @@ struct cache_sizes { +@@ -103,11 +103,16 @@ struct cache_sizes { + #ifdef CONFIG_ZONE_DMA + struct kmem_cache *cs_dmacachep; + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ struct kmem_cache *cs_usercopycachep; ++#endif ++ + }; extern struct cache_sizes malloc_sizes[]; void *kmem_cache_alloc(struct kmem_cache *, gfp_t); @@ -62760,7 +63466,21 @@ index fbd1117..d4d8ef8 100644 #ifdef CONFIG_TRACING extern void *kmem_cache_alloc_trace(size_t size, -@@ -160,7 +160,7 @@ found: +@@ -150,6 +155,13 @@ found: + cachep = malloc_sizes[i].cs_dmacachep; + else + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ if (flags & GFP_USERCOPY) ++ cachep = malloc_sizes[i].cs_usercopycachep; ++ else ++#endif ++ + cachep = malloc_sizes[i].cs_cachep; + + ret = kmem_cache_alloc_trace(size, cachep, flags); +@@ -160,7 +172,7 @@ found: } #ifdef CONFIG_NUMA @@ -62769,6 +63489,20 @@ index fbd1117..d4d8ef8 100644 extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); #ifdef CONFIG_TRACING +@@ -203,6 +215,13 @@ found: + cachep = malloc_sizes[i].cs_dmacachep; + else + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ if (flags & GFP_USERCOPY) ++ cachep = malloc_sizes[i].cs_usercopycachep; ++ else ++#endif ++ + cachep = malloc_sizes[i].cs_cachep; + + return kmem_cache_alloc_node_trace(size, cachep, flags, node); diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h index 0ec00b3..39cb7fc 100644 --- a/include/linux/slob_def.h @@ -63336,10 +64070,10 @@ index 6c469db..7743b8e 100644 #endif diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h -index b94765e..053f68b 100644 +index 2040bff..f4c0733 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h -@@ -48,8 +48,8 @@ struct inet_peer { +@@ -51,8 +51,8 @@ struct inet_peer { */ union { struct { @@ -63350,7 +64084,7 @@ index b94765e..053f68b 100644 __u32 tcp_ts; __u32 tcp_ts_stamp; }; -@@ -115,11 +115,11 @@ static inline int inet_getid(struct inet_peer *p, int more) +@@ -118,11 +118,11 @@ static inline int inet_getid(struct inet_peer *p, int more) more++; inet_peer_refcheck(p); do { @@ -63378,7 +64112,7 @@ index 10422ef..662570f 100644 fib_info_update_nh_saddr((net), &FIB_RES_NH(res))) #define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h -index 72522f0..6f03a2b 100644 +index 72522f0..2965e05 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -510,7 +510,7 @@ struct ip_vs_conn { @@ -63399,6 +64133,15 @@ index 72522f0..6f03a2b 100644 atomic_t weight; /* server weight */ atomic_t refcnt; /* reference counter */ +@@ -1356,7 +1356,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb) + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + + if (!ct || !nf_ct_is_untracked(ct)) { +- nf_reset(skb); ++ nf_conntrack_put(skb->nfct); + skb->nfct = &nf_ct_untracked_get()->ct_general; + skb->nfctinfo = IP_CT_NEW; + nf_conntrack_get(skb->nfct); diff --git a/include/net/irda/ircomm_core.h b/include/net/irda/ircomm_core.h index 69b610a..fe3962c 100644 --- a/include/net/irda/ircomm_core.h @@ -63602,10 +64345,10 @@ index 8f9dfba..610ab6c 100644 u8 qfull; enum fc_lport_state state; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h -index 6efb2e1..cdad57f 100644 +index ba96988..ecf2eb9 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h -@@ -162,9 +162,9 @@ struct scsi_device { +@@ -163,9 +163,9 @@ struct scsi_device { unsigned int max_device_blocked; /* what device_blocked counts down from */ #define SCSI_DEFAULT_DEVICE_BLOCKED 3 @@ -63874,7 +64617,7 @@ index 0993a22..32ba2fe 100644 void *pmi_pal; u8 *vbe_state_orig; /* diff --git a/init/Kconfig b/init/Kconfig -index 6cfd71d..73cb68d 100644 +index 6cfd71d..16006e6 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -790,6 +790,7 @@ endif # CGROUPS @@ -63894,6 +64637,15 @@ index 6cfd71d..73cb68d 100644 help Randomizing heap placement makes heap exploits harder, but it also breaks ancient binaries (including anything libc5 based). +@@ -1423,7 +1424,7 @@ config INIT_ALL_POSSIBLE + config STOP_MACHINE + bool + default y +- depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU ++ depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU || GRKERNSEC + help + Need stop_machine() primitive. + diff --git a/init/do_mounts.c b/init/do_mounts.c index 42b0707..c06eef4 100644 --- a/init/do_mounts.c @@ -64197,7 +64949,7 @@ index 8216c30..25e8e32 100644 next_state = Reset; return 0; diff --git a/init/main.c b/init/main.c -index b08c5f7..09f865e 100644 +index b08c5f7..bf65a52 100644 --- a/init/main.c +++ b/init/main.c @@ -95,6 +95,8 @@ static inline void mark_rodata_ro(void) { } @@ -64287,7 +65039,39 @@ index b08c5f7..09f865e 100644 } return ret; -@@ -865,7 +911,7 @@ static int __init kernel_init(void * unused) +@@ -747,8 +793,14 @@ static void __init do_initcall_level(int level) + level, level, + repair_env_string); + +- for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) ++ for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) { + do_one_initcall(*fn); ++ ++#ifdef CONFIG_PAX_LATENT_ENTROPY ++ transfer_latent_entropy(); ++#endif ++ ++ } + } + + static void __init do_initcalls(void) +@@ -782,8 +834,14 @@ static void __init do_pre_smp_initcalls(void) + { + initcall_t *fn; + +- for (fn = __initcall_start; fn < __initcall0_start; fn++) ++ for (fn = __initcall_start; fn < __initcall0_start; fn++) { + do_one_initcall(*fn); ++ ++#ifdef CONFIG_PAX_LATENT_ENTROPY ++ transfer_latent_entropy(); ++#endif ++ ++ } + } + + static void run_init_process(const char *init_filename) +@@ -865,7 +923,7 @@ static int __init kernel_init(void * unused) do_basic_setup(); /* Open the /dev/console on the rootfs, this should never fail */ @@ -64296,7 +65080,7 @@ index b08c5f7..09f865e 100644 printk(KERN_WARNING "Warning: unable to open an initial console.\n"); (void) sys_dup(0); -@@ -878,11 +924,13 @@ static int __init kernel_init(void * unused) +@@ -878,11 +936,13 @@ static int __init kernel_init(void * unused) if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; @@ -65146,7 +65930,7 @@ index fd126f8..70b755b 100644 /* diff --git a/kernel/exit.c b/kernel/exit.c -index d8bd3b42..26bd8dc 100644 +index 9d81012..d7911f1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -59,6 +59,10 @@ @@ -65198,7 +65982,7 @@ index d8bd3b42..26bd8dc 100644 /* * If we were started as result of loading a module, close all of the * user space pages. We don't need them, and if we didn't close them -@@ -900,6 +919,8 @@ void do_exit(long code) +@@ -901,6 +920,8 @@ void do_exit(long code) struct task_struct *tsk = current; int group_dead; @@ -65207,7 +65991,7 @@ index d8bd3b42..26bd8dc 100644 profile_task_exit(tsk); WARN_ON(blk_needs_flush_plug(tsk)); -@@ -916,7 +937,6 @@ void do_exit(long code) +@@ -917,7 +938,6 @@ void do_exit(long code) * mm_release()->clear_child_tid() from writing to a user-controlled * kernel address. */ @@ -65215,7 +65999,7 @@ index d8bd3b42..26bd8dc 100644 ptrace_event(PTRACE_EVENT_EXIT, code); -@@ -977,6 +997,9 @@ void do_exit(long code) +@@ -978,6 +998,9 @@ void do_exit(long code) tsk->exit_code = code; taskstats_exit(tsk, group_dead); @@ -65225,7 +66009,7 @@ index d8bd3b42..26bd8dc 100644 exit_mm(tsk); if (group_dead) -@@ -1093,7 +1116,7 @@ SYSCALL_DEFINE1(exit, int, error_code) +@@ -1094,7 +1117,7 @@ SYSCALL_DEFINE1(exit, int, error_code) * Take down every thread in the group. This is called by fatal signals * as well as by sys_exit_group (below). */ @@ -65235,10 +66019,30 @@ index d8bd3b42..26bd8dc 100644 { struct signal_struct *sig = current->signal; diff --git a/kernel/fork.c b/kernel/fork.c -index 8163333..efb4692 100644 +index 8163333..aee97f3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -286,7 +286,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) +@@ -274,19 +274,24 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) + } + + err = arch_dup_task_struct(tsk, orig); +- if (err) +- goto out; + ++ /* ++ * We defer looking at err, because we will need this setup ++ * for the clean up path to work correctly. ++ */ + tsk->stack = ti; +- + setup_thread_stack(tsk, orig); ++ ++ if (err) ++ goto out; ++ + clear_user_return_notifier(tsk); + clear_tsk_need_resched(tsk); + stackend = end_of_stack(tsk); *stackend = STACK_END_MAGIC; /* for overflow detection */ #ifdef CONFIG_CC_STACKPROTECTOR @@ -65247,7 +66051,7 @@ index 8163333..efb4692 100644 #endif /* -@@ -310,13 +310,78 @@ out: +@@ -310,13 +315,78 @@ out: } #ifdef CONFIG_MMU @@ -65328,7 +66132,7 @@ index 8163333..efb4692 100644 down_write(&oldmm->mmap_sem); flush_cache_dup_mm(oldmm); -@@ -328,8 +393,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -328,8 +398,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) mm->locked_vm = 0; mm->mmap = NULL; mm->mmap_cache = NULL; @@ -65339,7 +66143,7 @@ index 8163333..efb4692 100644 mm->map_count = 0; cpumask_clear(mm_cpumask(mm)); mm->mm_rb = RB_ROOT; -@@ -345,8 +410,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -345,8 +415,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) prev = NULL; for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { @@ -65348,7 +66152,7 @@ index 8163333..efb4692 100644 if (mpnt->vm_flags & VM_DONTCOPY) { long pages = vma_pages(mpnt); mm->total_vm -= pages; -@@ -354,54 +417,11 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -354,54 +422,11 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) -pages); continue; } @@ -65407,7 +66211,7 @@ index 8163333..efb4692 100644 /* * Link in the new vma and copy the page table entries. -@@ -424,6 +444,31 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -424,6 +449,31 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (retval) goto out; } @@ -65439,7 +66243,7 @@ index 8163333..efb4692 100644 /* a new mm has just been created */ arch_dup_mmap(oldmm, mm); retval = 0; -@@ -432,14 +477,6 @@ out: +@@ -432,14 +482,6 @@ out: flush_tlb_mm(oldmm); up_write(&oldmm->mmap_sem); return retval; @@ -65454,7 +66258,7 @@ index 8163333..efb4692 100644 } static inline int mm_alloc_pgd(struct mm_struct *mm) -@@ -676,8 +713,8 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) +@@ -676,8 +718,8 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) return ERR_PTR(err); mm = get_task_mm(task); @@ -65465,7 +66269,7 @@ index 8163333..efb4692 100644 mmput(mm); mm = ERR_PTR(-EACCES); } -@@ -899,13 +936,14 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) +@@ -899,13 +941,14 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) spin_unlock(&fs->lock); return -EAGAIN; } @@ -65481,7 +66285,7 @@ index 8163333..efb4692 100644 return 0; } -@@ -1172,6 +1210,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1172,6 +1215,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); #endif retval = -EAGAIN; @@ -65491,16 +66295,17 @@ index 8163333..efb4692 100644 if (atomic_read(&p->real_cred->user->processes) >= task_rlimit(p, RLIMIT_NPROC)) { if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && -@@ -1328,6 +1369,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - if (clone_flags & CLONE_THREAD) - p->tgid = current->tgid; +@@ -1392,6 +1438,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, + /* Need tasklist lock for parent etc handling! */ + write_lock_irq(&tasklist_lock); ++ /* synchronizes with gr_set_acls() */ + gr_copy_label(p); + - p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; - /* - * Clear TID on mm_release()? -@@ -1502,6 +1545,8 @@ bad_fork_cleanup_count: + /* CLONE_PARENT re-uses the old parent */ + if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { + p->real_parent = current->real_parent; +@@ -1502,6 +1551,8 @@ bad_fork_cleanup_count: bad_fork_free: free_task(p); fork_out: @@ -65509,7 +66314,7 @@ index 8163333..efb4692 100644 return ERR_PTR(retval); } -@@ -1602,6 +1647,8 @@ long do_fork(unsigned long clone_flags, +@@ -1602,6 +1653,8 @@ long do_fork(unsigned long clone_flags, if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); @@ -65518,7 +66323,7 @@ index 8163333..efb4692 100644 if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); -@@ -1700,7 +1747,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) +@@ -1700,7 +1753,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) return 0; /* don't need lock here; in the worst case we'll do useless copy */ @@ -65527,7 +66332,7 @@ index 8163333..efb4692 100644 return 0; *new_fsp = copy_fs_struct(fs); -@@ -1789,7 +1836,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) +@@ -1789,7 +1842,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) fs = current->fs; spin_lock(&fs->lock); current->fs = new_fs; @@ -65607,18 +66412,18 @@ index 9b22d03..6295b62 100644 prev->next = info->next; else diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c -index ae34bf5..4e2f3d0 100644 +index 6db7a5e..25b6648 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c -@@ -1393,7 +1393,7 @@ void hrtimer_peek_ahead_timers(void) +@@ -1407,7 +1407,7 @@ void hrtimer_peek_ahead_timers(void) local_irq_restore(flags); } -static void run_hrtimer_softirq(struct softirq_action *h) +static void run_hrtimer_softirq(void) { - hrtimer_peek_ahead_timers(); - } + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 4304919..408c4c0 100644 --- a/kernel/jump_label.c @@ -65655,7 +66460,7 @@ index 4304919..408c4c0 100644 static int diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c -index 079f1d3..a407562 100644 +index 079f1d3..4e80e69 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -11,6 +11,9 @@ @@ -65751,7 +66556,30 @@ index 079f1d3..a407562 100644 /* Some debugging symbols have no name. Ignore them. */ if (!iter->name[0]) return 0; -@@ -540,7 +583,7 @@ static int kallsyms_open(struct inode *inode, struct file *file) +@@ -515,11 +558,22 @@ static int s_show(struct seq_file *m, void *p) + */ + type = iter->exported ? toupper(iter->type) : + tolower(iter->type); ++ ++#ifdef CONFIG_GRKERNSEC_HIDESYM ++ seq_printf(m, "%pP %c %s\t[%s]\n", (void *)iter->value, ++ type, iter->name, iter->module_name); ++#else + seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value, + type, iter->name, iter->module_name); ++#endif + } else ++#ifdef CONFIG_GRKERNSEC_HIDESYM ++ seq_printf(m, "%pP %c %s\n", (void *)iter->value, ++ iter->type, iter->name); ++#else + seq_printf(m, "%pK %c %s\n", (void *)iter->value, + iter->type, iter->name); ++#endif + return 0; + } + +@@ -540,7 +594,7 @@ static int kallsyms_open(struct inode *inode, struct file *file) struct kallsym_iter *iter; int ret; @@ -67852,10 +68680,10 @@ index 0984a21..939f183 100644 #ifdef CONFIG_RT_GROUP_SCHED /* diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index 2000e06..79cf3d8 100644 +index 817bf70..9099fb4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c -@@ -3907,6 +3907,8 @@ int can_nice(const struct task_struct *p, const int nice) +@@ -4038,6 +4038,8 @@ int can_nice(const struct task_struct *p, const int nice) /* convert nice value [19,-20] to rlimit style value [1,40] */ int nice_rlim = 20 - nice; @@ -67864,7 +68692,7 @@ index 2000e06..79cf3d8 100644 return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) || capable(CAP_SYS_NICE)); } -@@ -3940,7 +3942,8 @@ SYSCALL_DEFINE1(nice, int, increment) +@@ -4071,7 +4073,8 @@ SYSCALL_DEFINE1(nice, int, increment) if (nice > 19) nice = 19; @@ -67874,7 +68702,7 @@ index 2000e06..79cf3d8 100644 return -EPERM; retval = security_task_setnice(current, nice); -@@ -4097,6 +4100,7 @@ recheck: +@@ -4228,6 +4231,7 @@ recheck: unsigned long rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO); @@ -68611,7 +69439,7 @@ index f113755..ec24223 100644 cpumask_clear_cpu(cpu, tick_get_broadcast_mask()); tick_broadcast_clear_oneshot(cpu); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c -index d42574df..247414c 100644 +index 7c50de8..e29a94d 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -14,6 +14,7 @@ @@ -68622,7 +69450,7 @@ index d42574df..247414c 100644 #include #include #include -@@ -373,6 +374,8 @@ int do_settimeofday(const struct timespec *tv) +@@ -388,6 +389,8 @@ int do_settimeofday(const struct timespec *tv) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; @@ -68826,10 +69654,10 @@ index 0fa92f6..89950b2 100644 struct ftrace_func_probe *entry; struct ftrace_page *pg; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index 464a96f..bc0bd88 100644 +index 55e4d4c..8c915ec 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c -@@ -4312,10 +4312,9 @@ static const struct file_operations tracing_dyn_info_fops = { +@@ -4316,10 +4316,9 @@ static const struct file_operations tracing_dyn_info_fops = { }; #endif @@ -68841,7 +69669,7 @@ index 464a96f..bc0bd88 100644 static int once; if (d_tracer) -@@ -4335,10 +4334,9 @@ struct dentry *tracing_init_dentry(void) +@@ -4339,10 +4338,9 @@ struct dentry *tracing_init_dentry(void) return d_tracer; } @@ -69239,7 +70067,7 @@ index 3ac50dc..240bb7e 100644 static inline void *ptr_to_indirect(void *ptr) { diff --git a/lib/vsprintf.c b/lib/vsprintf.c -index abbabec..362988d 100644 +index abbabec..d5eba6c 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -16,6 +16,9 @@ @@ -69282,8 +70110,21 @@ index abbabec..362988d 100644 * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] * - 'M' For a 6-byte MAC address, it prints the address in the -@@ -868,12 +877,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, +@@ -866,14 +875,25 @@ static noinline_for_stack + char *pointer(const char *fmt, char *buf, char *end, void *ptr, + struct printf_spec spec) { ++#ifdef CONFIG_GRKERNSEC_HIDESYM ++ /* 'P' = approved pointers to copy to userland, ++ as in the /proc/kallsyms case, as we make it display nothing ++ for non-root users, and the real contents for root users ++ */ ++ if (ptr > TASK_SIZE && *fmt != 'P' && is_usercopy_object(buf)) { ++ ptr = NULL; ++ goto simple; ++ } ++#endif ++ if (!ptr && *fmt != 'K') { /* - * Print (null) with the same width as a pointer so it makes @@ -69297,7 +70138,7 @@ index abbabec..362988d 100644 } switch (*fmt) { -@@ -883,6 +892,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, +@@ -883,6 +903,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, /* Fallthrough */ case 'S': case 's': @@ -69311,7 +70152,26 @@ index abbabec..362988d 100644 case 'B': return symbol_string(buf, end, ptr, spec, *fmt); case 'R': -@@ -1653,11 +1669,11 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) +@@ -920,6 +947,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, + va_end(va); + return buf; + } ++ case 'P': ++ break; + case 'K': + /* + * %pK cannot be used in IRQ context because its test +@@ -942,6 +971,9 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, + } + break; + } ++#ifdef CONFIG_GRKERNSEC_HIDESYM ++simple: ++#endif + spec.flags |= SMALL; + if (spec.field_width == -1) { + spec.field_width = 2 * sizeof(void *); +@@ -1653,11 +1685,11 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) typeof(type) value; \ if (sizeof(type) == 8) { \ args = PTR_ALIGN(args, sizeof(u32)); \ @@ -69326,7 +70186,7 @@ index abbabec..362988d 100644 } \ args += sizeof(type); \ value; \ -@@ -1720,7 +1736,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) +@@ -1720,7 +1752,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) case FORMAT_TYPE_STR: { const char *str_arg = args; args += strlen(str_arg) + 1; @@ -69589,10 +70449,10 @@ index d53adf9..03a24bf 100644 set_fs(old_fs); diff --git a/mm/madvise.c b/mm/madvise.c -index 1ccbba5..79e16f9 100644 +index 55f645c..cde5320 100644 --- a/mm/madvise.c +++ b/mm/madvise.c -@@ -45,6 +45,10 @@ static long madvise_behavior(struct vm_area_struct * vma, +@@ -46,6 +46,10 @@ static long madvise_behavior(struct vm_area_struct * vma, pgoff_t pgoff; unsigned long new_flags = vma->vm_flags; @@ -69603,7 +70463,7 @@ index 1ccbba5..79e16f9 100644 switch (behavior) { case MADV_NORMAL: new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ; -@@ -116,6 +120,13 @@ success: +@@ -117,6 +121,13 @@ success: /* * vm_flags is protected by the mmap_sem held in write mode. */ @@ -69617,7 +70477,7 @@ index 1ccbba5..79e16f9 100644 vma->vm_flags = new_flags; out: -@@ -174,6 +185,11 @@ static long madvise_dontneed(struct vm_area_struct * vma, +@@ -175,6 +186,11 @@ static long madvise_dontneed(struct vm_area_struct * vma, struct vm_area_struct ** prev, unsigned long start, unsigned long end) { @@ -69629,7 +70489,7 @@ index 1ccbba5..79e16f9 100644 *prev = vma; if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP)) return -EINVAL; -@@ -186,6 +202,21 @@ static long madvise_dontneed(struct vm_area_struct * vma, +@@ -187,6 +203,21 @@ static long madvise_dontneed(struct vm_area_struct * vma, zap_page_range(vma, start, end - start, &details); } else zap_page_range(vma, start, end - start, NULL); @@ -69651,7 +70511,7 @@ index 1ccbba5..79e16f9 100644 return 0; } -@@ -384,6 +415,16 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) +@@ -394,6 +425,16 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior) if (end < start) goto out; @@ -70474,7 +71334,7 @@ index bf5b485..e44c2cb 100644 capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE); diff --git a/mm/mlock.c b/mm/mlock.c -index ef726e8..13e0901 100644 +index ef726e8..cd7f1ec 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -13,6 +13,7 @@ @@ -70485,6 +71345,15 @@ index ef726e8..13e0901 100644 #include #include #include +@@ -376,7 +377,7 @@ static int do_mlock(unsigned long start, size_t len, int on) + { + unsigned long nstart, end, tmp; + struct vm_area_struct * vma, * prev; +- int error; ++ int error = 0; + + VM_BUG_ON(start & ~PAGE_MASK); + VM_BUG_ON(len != PAGE_ALIGN(len)); @@ -385,6 +386,9 @@ static int do_mlock(unsigned long start, size_t len, int on) return -EINVAL; if (end == start) @@ -72402,7 +73271,7 @@ index 5b5ad58..0f77903 100644 struct anon_vma_chain *avc; struct anon_vma *anon_vma; diff --git a/mm/shmem.c b/mm/shmem.c -index f99ff3e..faea8b6 100644 +index 9d65a02..7c877e7 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -31,7 +31,7 @@ @@ -72423,7 +73292,7 @@ index f99ff3e..faea8b6 100644 struct shmem_xattr { struct list_head list; /* anchored by shmem_inode_info->xattr_list */ -@@ -2235,8 +2235,7 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent) +@@ -2236,8 +2236,7 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent) int err = -ENOMEM; /* Round up to L1_CACHE_BYTES to resist false sharing */ @@ -72434,7 +73303,7 @@ index f99ff3e..faea8b6 100644 return -ENOMEM; diff --git a/mm/slab.c b/mm/slab.c -index e901a36..ee8fe97 100644 +index e901a36..ca479fc 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -153,7 +153,7 @@ @@ -72488,16 +73357,36 @@ index e901a36..ee8fe97 100644 { u32 offset = (obj - slab->s_mem); return reciprocal_divide(offset, cache->reciprocal_buffer_size); -@@ -568,7 +568,7 @@ struct cache_names { +@@ -563,12 +563,13 @@ EXPORT_SYMBOL(malloc_sizes); + struct cache_names { + char *name; + char *name_dma; ++ char *name_usercopy; + }; + static struct cache_names __initdata cache_names[] = { - #define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" }, +-#define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" }, ++#define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)", .name_usercopy = "size-" #x "(USERCOPY)" }, #include - {NULL,} + {NULL} #undef CACHE }; -@@ -1588,7 +1588,7 @@ void __init kmem_cache_init(void) +@@ -756,6 +757,12 @@ static inline struct kmem_cache *__find_general_cachep(size_t size, + if (unlikely(gfpflags & GFP_DMA)) + return csizep->cs_dmacachep; + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ if (unlikely(gfpflags & GFP_USERCOPY)) ++ return csizep->cs_usercopycachep; ++#endif ++ + return csizep->cs_cachep; + } + +@@ -1588,7 +1595,7 @@ void __init kmem_cache_init(void) sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name, sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN, @@ -72506,7 +73395,7 @@ index e901a36..ee8fe97 100644 NULL); if (INDEX_AC != INDEX_L3) { -@@ -1596,7 +1596,7 @@ void __init kmem_cache_init(void) +@@ -1596,7 +1603,7 @@ void __init kmem_cache_init(void) kmem_cache_create(names[INDEX_L3].name, sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN, @@ -72515,7 +73404,7 @@ index e901a36..ee8fe97 100644 NULL); } -@@ -1614,7 +1614,7 @@ void __init kmem_cache_init(void) +@@ -1614,7 +1621,7 @@ void __init kmem_cache_init(void) sizes->cs_cachep = kmem_cache_create(names->name, sizes->cs_size, ARCH_KMALLOC_MINALIGN, @@ -72524,7 +73413,24 @@ index e901a36..ee8fe97 100644 NULL); } #ifdef CONFIG_ZONE_DMA -@@ -4390,10 +4390,10 @@ static int s_show(struct seq_file *m, void *p) +@@ -1626,6 +1633,16 @@ void __init kmem_cache_init(void) + SLAB_PANIC, + NULL); + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ sizes->cs_usercopycachep = kmem_cache_create( ++ names->name_usercopy, ++ sizes->cs_size, ++ ARCH_KMALLOC_MINALIGN, ++ ARCH_KMALLOC_FLAGS|SLAB_PANIC|SLAB_USERCOPY, ++ NULL); ++#endif ++ + sizes++; + names++; + } +@@ -4390,10 +4407,10 @@ static int s_show(struct seq_file *m, void *p) } /* cpu stats */ { @@ -72539,7 +73445,7 @@ index e901a36..ee8fe97 100644 seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu", allochit, allocmiss, freehit, freemiss); -@@ -4652,13 +4652,62 @@ static int __init slab_proc_init(void) +@@ -4652,13 +4669,68 @@ static int __init slab_proc_init(void) { proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations); #ifdef CONFIG_DEBUG_SLAB_LEAK @@ -72551,60 +73457,66 @@ index e901a36..ee8fe97 100644 module_init(slab_proc_init); #endif -+void check_object_size(const void *ptr, unsigned long n, bool to) ++bool is_usercopy_object(const void *ptr) +{ ++ struct page *page; ++ struct kmem_cache *cachep; ++ ++ if (ZERO_OR_NULL_PTR(ptr)) ++ return false; ++ ++ if (!virt_addr_valid(ptr)) ++ return false; ++ ++ page = virt_to_head_page(ptr); ++ ++ if (!PageSlab(page)) ++ return false; ++ ++ cachep = page_get_cache(page); ++ return cachep->flags & SLAB_USERCOPY; ++} + +#ifdef CONFIG_PAX_USERCOPY ++const char *check_heap_object(const void *ptr, unsigned long n, bool to) ++{ + struct page *page; -+ struct kmem_cache *cachep = NULL; ++ struct kmem_cache *cachep; + struct slab *slabp; + unsigned int objnr; + unsigned long offset; -+ const char *type; -+ -+ if (!n) -+ return; + -+ type = ""; + if (ZERO_OR_NULL_PTR(ptr)) -+ goto report; ++ return ""; + + if (!virt_addr_valid(ptr)) -+ return; ++ return NULL; + + page = virt_to_head_page(ptr); + -+ type = ""; -+ if (!PageSlab(page)) { -+ if (object_is_on_stack(ptr, n) == -1) -+ goto report; -+ return; -+ } ++ if (!PageSlab(page)) ++ return NULL; + + cachep = page_get_cache(page); -+ type = cachep->name; + if (!(cachep->flags & SLAB_USERCOPY)) -+ goto report; ++ return cachep->name; + + slabp = page_get_slab(page); + objnr = obj_to_index(cachep, slabp, ptr); + BUG_ON(objnr >= cachep->num); + offset = ptr - index_to_obj(cachep, slabp, objnr) - obj_offset(cachep); + if (offset <= obj_size(cachep) && n <= obj_size(cachep) - offset) -+ return; -+ -+report: -+ pax_report_usercopy(ptr, n, to, type); -+#endif ++ return NULL; + ++ return cachep->name; +} -+EXPORT_SYMBOL(check_object_size); ++#endif + /** * ksize - get the actual amount of memory allocated for a given object * @objp: Pointer to the object diff --git a/mm/slob.c b/mm/slob.c -index 8105be4..e045f96 100644 +index 8105be4..3c15e57 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -29,7 +29,7 @@ @@ -72755,7 +73667,7 @@ index 8105be4..e045f96 100644 return ret; } EXPORT_SYMBOL(__kmalloc_node); -@@ -533,13 +547,92 @@ void kfree(const void *block) +@@ -533,13 +547,83 @@ void kfree(const void *block) sp = slob_page(block); if (is_slob_page(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); @@ -72773,40 +73685,34 @@ index 8105be4..e045f96 100644 } EXPORT_SYMBOL(kfree); -+void check_object_size(const void *ptr, unsigned long n, bool to) ++bool is_usercopy_object(const void *ptr) +{ ++ return false; ++} + +#ifdef CONFIG_PAX_USERCOPY ++const char *check_heap_object(const void *ptr, unsigned long n, bool to) ++{ + struct slob_page *sp; + const slob_t *free; + const void *base; + unsigned long flags; -+ const char *type; -+ -+ if (!n) -+ return; + -+ type = ""; + if (ZERO_OR_NULL_PTR(ptr)) -+ goto report; ++ return ""; + + if (!virt_addr_valid(ptr)) -+ return; ++ return NULL; + -+ type = ""; + sp = slob_page(ptr); -+ if (!PageSlab((struct page *)sp)) { -+ if (object_is_on_stack(ptr, n) == -1) -+ goto report; -+ return; -+ } ++ if (!PageSlab((struct page *)sp)) ++ return NULL; + -+ type = ""; + if (sp->size) { + base = page_address(&sp->page); + if (base <= ptr && n <= sp->size - (ptr - base)) -+ return; -+ goto report; ++ return NULL; ++ return ""; + } + + /* some tricky double walking to find the chunk */ @@ -72837,21 +73743,18 @@ index 8105be4..e045f96 100644 + break; + + spin_unlock_irqrestore(&slob_lock, flags); -+ return; ++ return NULL; + } + + spin_unlock_irqrestore(&slob_lock, flags); -+report: -+ pax_report_usercopy(ptr, n, to, type); -+#endif -+ ++ return ""; +} -+EXPORT_SYMBOL(check_object_size); ++#endif + /* can't use ksize for kmem_cache_alloc memory, only kmalloc */ size_t ksize(const void *block) { -@@ -552,10 +645,10 @@ size_t ksize(const void *block) +@@ -552,10 +636,10 @@ size_t ksize(const void *block) sp = slob_page(block); if (is_slob_page(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); @@ -72865,11 +73768,11 @@ index 8105be4..e045f96 100644 } EXPORT_SYMBOL(ksize); -@@ -571,8 +664,13 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, +@@ -571,8 +655,13 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, { struct kmem_cache *c; -+#ifdef CONFIG_PAX_USERCOPY ++#ifdef CONFIG_PAX_USERCOPY_SLABS + c = __kmalloc_node_align(sizeof(struct kmem_cache), + GFP_KERNEL, -1, ARCH_KMALLOC_MINALIGN); +#else @@ -72879,11 +73782,11 @@ index 8105be4..e045f96 100644 if (c) { c->name = name; -@@ -614,17 +712,25 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) +@@ -614,17 +703,25 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) lockdep_trace_alloc(flags); -+#ifdef CONFIG_PAX_USERCOPY ++#ifdef CONFIG_PAX_USERCOPY_SLABS + b = __kmalloc_node_align(c->size, flags, node, c->align); +#else if (c->size < PAGE_SIZE) { @@ -72905,7 +73808,7 @@ index 8105be4..e045f96 100644 if (c->ctor) c->ctor(b); -@@ -636,10 +742,16 @@ EXPORT_SYMBOL(kmem_cache_alloc_node); +@@ -636,10 +733,16 @@ EXPORT_SYMBOL(kmem_cache_alloc_node); static void __kmem_cache_free(void *b, int size) { @@ -72924,13 +73827,13 @@ index 8105be4..e045f96 100644 } static void kmem_rcu_free(struct rcu_head *head) -@@ -652,17 +764,31 @@ static void kmem_rcu_free(struct rcu_head *head) +@@ -652,17 +755,31 @@ static void kmem_rcu_free(struct rcu_head *head) void kmem_cache_free(struct kmem_cache *c, void *b) { + int size = c->size; + -+#ifdef CONFIG_PAX_USERCOPY ++#ifdef CONFIG_PAX_USERCOPY_SLABS + if (size + c->align < PAGE_SIZE) { + size += c->align; + b -= c->align; @@ -72950,7 +73853,7 @@ index 8105be4..e045f96 100644 + __kmem_cache_free(b, size); } -+#ifdef CONFIG_PAX_USERCOPY ++#ifdef CONFIG_PAX_USERCOPY_SLABS + trace_kfree(_RET_IP_, b); +#else trace_kmem_cache_free(_RET_IP_, b); @@ -72960,7 +73863,7 @@ index 8105be4..e045f96 100644 EXPORT_SYMBOL(kmem_cache_free); diff --git a/mm/slub.c b/mm/slub.c -index 71de9b5..dd263c5 100644 +index 71de9b5..a93d4a4 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -209,7 +209,7 @@ struct track { @@ -73018,58 +73921,89 @@ index 71de9b5..dd263c5 100644 list_del(&s->list); up_write(&slub_lock); if (kmem_cache_close(s)) { -@@ -3405,6 +3406,50 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) +@@ -3223,6 +3224,10 @@ static struct kmem_cache *kmem_cache; + static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT]; + #endif + ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++static struct kmem_cache *kmalloc_usercopy_caches[SLUB_PAGE_SHIFT]; ++#endif ++ + static int __init setup_slub_min_order(char *str) + { + get_option(&str, &slub_min_order); +@@ -3337,6 +3342,13 @@ static struct kmem_cache *get_slab(size_t size, gfp_t flags) + return kmalloc_dma_caches[index]; + + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ if (flags & SLAB_USERCOPY) ++ return kmalloc_usercopy_caches[index]; ++ ++#endif ++ + return kmalloc_caches[index]; + } + +@@ -3405,6 +3417,56 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) EXPORT_SYMBOL(__kmalloc_node); #endif -+void check_object_size(const void *ptr, unsigned long n, bool to) ++bool is_usercopy_object(const void *ptr) +{ ++ struct page *page; ++ struct kmem_cache *s; ++ ++ if (ZERO_OR_NULL_PTR(ptr)) ++ return false; ++ ++ if (!virt_addr_valid(ptr)) ++ return false; ++ ++ page = virt_to_head_page(ptr); ++ ++ if (!PageSlab(page)) ++ return false; ++ ++ s = page->slab; ++ return s->flags & SLAB_USERCOPY; ++} + +#ifdef CONFIG_PAX_USERCOPY ++const char *check_heap_object(const void *ptr, unsigned long n, bool to) ++{ + struct page *page; -+ struct kmem_cache *s = NULL; ++ struct kmem_cache *s; + unsigned long offset; -+ const char *type; + -+ if (!n) -+ return; -+ -+ type = ""; + if (ZERO_OR_NULL_PTR(ptr)) -+ goto report; ++ return ""; + + if (!virt_addr_valid(ptr)) -+ return; ++ return NULL; + + page = virt_to_head_page(ptr); + -+ type = ""; -+ if (!PageSlab(page)) { -+ if (object_is_on_stack(ptr, n) == -1) -+ goto report; -+ return; -+ } ++ if (!PageSlab(page)) ++ return NULL; + + s = page->slab; -+ type = s->name; + if (!(s->flags & SLAB_USERCOPY)) -+ goto report; ++ return s->name; + + offset = (ptr - page_address(page)) % s->size; + if (offset <= s->objsize && n <= s->objsize - offset) -+ return; -+ -+report: -+ pax_report_usercopy(ptr, n, to, type); -+#endif ++ return NULL; + ++ return s->name; +} -+EXPORT_SYMBOL(check_object_size); ++#endif + size_t ksize(const void *object) { struct page *page; -@@ -3679,7 +3724,7 @@ static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s) +@@ -3679,7 +3741,7 @@ static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s) int node; list_add(&s->list, &slab_caches); @@ -73078,7 +74012,7 @@ index 71de9b5..dd263c5 100644 for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); -@@ -3799,17 +3844,17 @@ void __init kmem_cache_init(void) +@@ -3799,17 +3861,17 @@ void __init kmem_cache_init(void) /* Caches that are not of the two-to-the-power-of size */ if (KMALLOC_MIN_SIZE <= 32) { @@ -73099,7 +74033,30 @@ index 71de9b5..dd263c5 100644 caches++; } -@@ -3877,7 +3922,7 @@ static int slab_unmergeable(struct kmem_cache *s) +@@ -3851,6 +3913,22 @@ void __init kmem_cache_init(void) + } + } + #endif ++ ++#ifdef CONFIG_PAX_USERCOPY_SLABS ++ for (i = 0; i < SLUB_PAGE_SHIFT; i++) { ++ struct kmem_cache *s = kmalloc_caches[i]; ++ ++ if (s && s->size) { ++ char *name = kasprintf(GFP_NOWAIT, ++ "usercopy-kmalloc-%d", s->objsize); ++ ++ BUG_ON(!name); ++ kmalloc_usercopy_caches[i] = create_kmalloc_cache(name, ++ s->objsize, SLAB_USERCOPY); ++ } ++ } ++#endif ++ + printk(KERN_INFO + "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d," + " CPUs=%d, Nodes=%d\n", +@@ -3877,7 +3955,7 @@ static int slab_unmergeable(struct kmem_cache *s) /* * We may have set a slab to be unmergeable during bootstrap. */ @@ -73108,7 +74065,7 @@ index 71de9b5..dd263c5 100644 return 1; return 0; -@@ -3936,7 +3981,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, +@@ -3936,7 +4014,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, down_write(&slub_lock); s = find_mergeable(size, align, flags, name, ctor); if (s) { @@ -73117,7 +74074,7 @@ index 71de9b5..dd263c5 100644 /* * Adjust the object sizes so that we clear * the complete object on kzalloc. -@@ -3945,7 +3990,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, +@@ -3945,7 +4023,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); if (sysfs_slab_alias(s, name)) { @@ -73126,7 +74083,7 @@ index 71de9b5..dd263c5 100644 goto err; } up_write(&slub_lock); -@@ -4074,7 +4119,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, +@@ -4074,7 +4152,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, } #endif @@ -73135,7 +74092,7 @@ index 71de9b5..dd263c5 100644 static int count_inuse(struct page *page) { return page->inuse; -@@ -4461,12 +4506,12 @@ static void resiliency_test(void) +@@ -4461,12 +4539,12 @@ static void resiliency_test(void) validate_slab_cache(kmalloc_caches[9]); } #else @@ -73150,7 +74107,7 @@ index 71de9b5..dd263c5 100644 enum slab_stat_type { SL_ALL, /* All slabs */ SL_PARTIAL, /* Only partially allocated slabs */ -@@ -4709,7 +4754,7 @@ SLAB_ATTR_RO(ctor); +@@ -4709,7 +4787,7 @@ SLAB_ATTR_RO(ctor); static ssize_t aliases_show(struct kmem_cache *s, char *buf) { @@ -73159,7 +74116,7 @@ index 71de9b5..dd263c5 100644 } SLAB_ATTR_RO(aliases); -@@ -5280,6 +5325,7 @@ static char *create_unique_id(struct kmem_cache *s) +@@ -5280,6 +5358,7 @@ static char *create_unique_id(struct kmem_cache *s) return name; } @@ -73167,7 +74124,7 @@ index 71de9b5..dd263c5 100644 static int sysfs_slab_add(struct kmem_cache *s) { int err; -@@ -5342,6 +5388,7 @@ static void sysfs_slab_remove(struct kmem_cache *s) +@@ -5342,6 +5421,7 @@ static void sysfs_slab_remove(struct kmem_cache *s) kobject_del(&s->kobj); kobject_put(&s->kobj); } @@ -73175,7 +74132,7 @@ index 71de9b5..dd263c5 100644 /* * Need to buffer aliases during bootup until sysfs becomes -@@ -5355,6 +5402,7 @@ struct saved_alias { +@@ -5355,6 +5435,7 @@ struct saved_alias { static struct saved_alias *alias_list; @@ -73183,7 +74140,7 @@ index 71de9b5..dd263c5 100644 static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; -@@ -5377,6 +5425,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name) +@@ -5377,6 +5458,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name) alias_list = al; return 0; } @@ -73513,6 +74470,22 @@ index 1196c77..2e608e8 100644 if (!vas || !vms) goto err_free2; +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 4607cc6..be5bc0a 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3013,7 +3013,10 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx) + * them before going back to sleep. + */ + set_pgdat_percpu_threshold(pgdat, calculate_normal_threshold); +- schedule(); ++ ++ if (!kthread_should_stop()) ++ schedule(); ++ + set_pgdat_percpu_threshold(pgdat, calculate_pressure_threshold); + } else { + if (remaining) diff --git a/mm/vmstat.c b/mm/vmstat.c index 7db1b9b..e9f6b07 100644 --- a/mm/vmstat.c @@ -73862,6 +74835,21 @@ index 5fe2ff3..10968b5 100644 BUGPRINT("c2u Didn't work\n"); ret = -EFAULT; break; +diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c +index aa6f716..7bf4c21 100644 +--- a/net/caif/caif_dev.c ++++ b/net/caif/caif_dev.c +@@ -562,9 +562,9 @@ static int __init caif_device_init(void) + + static void __exit caif_device_exit(void) + { +- unregister_pernet_subsys(&caif_net_ops); + unregister_netdevice_notifier(&caif_device_notifier); + dev_remove_pack(&caif_packet_type); ++ unregister_pernet_subsys(&caif_net_ops); + } + + module_init(caif_device_init); diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 5cf5222..6f704ad 100644 --- a/net/caif/cfctrl.c @@ -74063,7 +75051,7 @@ index e4fbfd6..6a6ac94 100644 return err; diff --git a/net/core/dev.c b/net/core/dev.c -index 99e1d75..adf968a 100644 +index 533c586..f78a55f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1136,9 +1136,13 @@ void dev_load(struct net *net, const char *name) @@ -74107,7 +75095,7 @@ index 99e1d75..adf968a 100644 #define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb) -@@ -2898,7 +2902,7 @@ enqueue: +@@ -2877,7 +2881,7 @@ enqueue: local_irq_restore(flags); @@ -74116,7 +75104,7 @@ index 99e1d75..adf968a 100644 kfree_skb(skb); return NET_RX_DROP; } -@@ -2970,7 +2974,7 @@ int netif_rx_ni(struct sk_buff *skb) +@@ -2949,7 +2953,7 @@ int netif_rx_ni(struct sk_buff *skb) } EXPORT_SYMBOL(netif_rx_ni); @@ -74125,7 +75113,7 @@ index 99e1d75..adf968a 100644 { struct softnet_data *sd = &__get_cpu_var(softnet_data); -@@ -3258,7 +3262,7 @@ ncls: +@@ -3237,7 +3241,7 @@ ncls: if (pt_prev) { ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } else { @@ -74134,7 +75122,7 @@ index 99e1d75..adf968a 100644 kfree_skb(skb); /* Jamal, now you will not able to escape explaining * me how you were going to use this. :-) -@@ -3818,7 +3822,7 @@ void netif_napi_del(struct napi_struct *napi) +@@ -3797,7 +3801,7 @@ void netif_napi_del(struct napi_struct *napi) } EXPORT_SYMBOL(netif_napi_del); @@ -74143,7 +75131,7 @@ index 99e1d75..adf968a 100644 { struct softnet_data *sd = &__get_cpu_var(softnet_data); unsigned long time_limit = jiffies + 2; -@@ -4288,8 +4292,13 @@ static int ptype_seq_show(struct seq_file *seq, void *v) +@@ -4267,8 +4271,13 @@ static int ptype_seq_show(struct seq_file *seq, void *v) else seq_printf(seq, "%04x", ntohs(pt->type)); @@ -74157,7 +75145,7 @@ index 99e1d75..adf968a 100644 } return 0; -@@ -5839,7 +5848,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, +@@ -5818,7 +5827,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, } else { netdev_stats_to_stats64(storage, &dev->stats); } @@ -74282,7 +75270,7 @@ index 611c5ef..88f6d6d 100644 { int new_fd; diff --git a/net/core/sock.c b/net/core/sock.c -index b2e14c0..6651b32 100644 +index 0f8402e..f0b6338 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -340,7 +340,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) @@ -74357,7 +75345,7 @@ index b2e14c0..6651b32 100644 return -EFAULT; lenout: if (put_user(len, optlen)) -@@ -2128,7 +2128,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) +@@ -2131,7 +2131,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) */ smp_wmb(); atomic_set(&sk->sk_refcnt, 1); @@ -74433,6 +75421,23 @@ index 39a2d29..f39c0fe 100644 ---help--- Econet is a fairly old and slow networking protocol mainly used by Acorn computers to access file and print servers. It uses native +diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c +index c48adc5..667c1d4 100644 +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) + case CIPSO_V4_TAG_LOCAL: + /* This is a non-standard tag that we only allow for + * local connections, so if the incoming interface is +- * not the loopback device drop the packet. */ +- if (!(skb->dev->flags & IFF_LOOPBACK)) { ++ * not the loopback device drop the packet. Further, ++ * there is no legitimate reason for setting this from ++ * userspace so reject it if skb is NULL. */ ++ if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) { + err_offset = opt_iter; + goto validate_return_locked; + } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index cbe3a68..a879b75 100644 --- a/net/ipv4/fib_frontend.c @@ -74504,7 +75509,7 @@ index 984ec65..97ac518 100644 inet_twsk_deschedule(tw, death_row); while (twrefcnt) { diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c -index d4d61b6..b81aec8 100644 +index dfba343..c827d50 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -487,8 +487,8 @@ relookup: @@ -75410,10 +76415,10 @@ index 6b9d5a0..4dffaf1 100644 seq_printf(m, "Max header size: %d\n", self->max_header_size); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c -index 07d7d55..541de95 100644 +index cd6f7a9..e63fe89 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c -@@ -783,10 +783,10 @@ static int iucv_sock_autobind(struct sock *sk) +@@ -782,10 +782,10 @@ static int iucv_sock_autobind(struct sock *sk) write_lock_bh(&iucv_sk_list.lock); @@ -75692,7 +76697,7 @@ index 00bdb1d..6725a48 100644 if ((ipvs->sync_state & IP_VS_STATE_MASTER) && cp->protocol == IPPROTO_SCTP) { diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c -index f558998..9cdff60 100644 +index f558998..7dfb054 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -788,7 +788,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, @@ -75704,7 +76709,30 @@ index f558998..9cdff60 100644 /* bind the service */ if (!dest->svc) { -@@ -2028,7 +2028,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) +@@ -1521,11 +1521,12 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, + { + struct net_device *dev = ptr; + struct net *net = dev_net(dev); ++ struct netns_ipvs *ipvs = net_ipvs(net); + struct ip_vs_service *svc; + struct ip_vs_dest *dest; + unsigned int idx; + +- if (event != NETDEV_UNREGISTER) ++ if (event != NETDEV_UNREGISTER || !ipvs) + return NOTIFY_DONE; + IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); + EnterFunction(2); +@@ -1551,7 +1552,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, + } + } + +- list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { ++ list_for_each_entry(dest, &ipvs->dest_trash, n_list) { + __ip_vs_dev_reset(dest, dev); + } + mutex_unlock(&__ip_vs_mutex); +@@ -2028,7 +2029,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) " %-7s %-6d %-10d %-10d\n", &dest->addr.in6, ntohs(dest->port), @@ -75713,7 +76741,7 @@ index f558998..9cdff60 100644 atomic_read(&dest->weight), atomic_read(&dest->activeconns), atomic_read(&dest->inactconns)); -@@ -2039,7 +2039,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) +@@ -2039,7 +2040,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v) "%-7s %-6d %-10d %-10d\n", ntohl(dest->addr.ip), ntohs(dest->port), @@ -75722,7 +76750,7 @@ index f558998..9cdff60 100644 atomic_read(&dest->weight), atomic_read(&dest->activeconns), atomic_read(&dest->inactconns)); -@@ -2509,7 +2509,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, +@@ -2509,7 +2510,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, entry.addr = dest->addr.ip; entry.port = dest->port; @@ -75731,7 +76759,7 @@ index f558998..9cdff60 100644 entry.weight = atomic_read(&dest->weight); entry.u_threshold = dest->u_threshold; entry.l_threshold = dest->l_threshold; -@@ -3042,7 +3042,7 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) +@@ -3042,7 +3043,7 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) NLA_PUT_U16(skb, IPVS_DEST_ATTR_PORT, dest->port); NLA_PUT_U32(skb, IPVS_DEST_ATTR_FWD_METHOD, @@ -76465,6 +77493,36 @@ index 7635107..4670276 100644 _proto("Tx RESPONSE %%%u", ntohl(hdr->serial)); ret = kernel_sendmsg(conn->trans->local->socket, &msg, iov, 3, len); +diff --git a/net/sctp/input.c b/net/sctp/input.c +index 80f71af..be772c0 100644 +--- a/net/sctp/input.c ++++ b/net/sctp/input.c +@@ -736,15 +736,12 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) + + epb = &ep->base; + +- if (hlist_unhashed(&epb->node)) +- return; +- + epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); + + head = &sctp_ep_hashtable[epb->hashent]; + + sctp_write_lock(&head->lock); +- __hlist_del(&epb->node); ++ hlist_del_init(&epb->node); + sctp_write_unlock(&head->lock); + } + +@@ -825,7 +822,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) + head = &sctp_assoc_hashtable[epb->hashent]; + + sctp_write_lock(&head->lock); +- __hlist_del(&epb->node); ++ hlist_del_init(&epb->node); + sctp_write_unlock(&head->lock); + } + diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 1e2eee8..ce3967e 100644 --- a/net/sctp/proc.c @@ -76480,10 +77538,38 @@ index 1e2eee8..ce3967e 100644 assoc->assoc_id, assoc->sndbuf_used, diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 92ba71d..9a97902 100644 +index 92ba71d..9352c05 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c -@@ -4569,7 +4569,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, +@@ -1231,8 +1231,14 @@ out_free: + SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" + " kaddrs: %p err: %d\n", + asoc, kaddrs, err); +- if (asoc) ++ if (asoc) { ++ /* sctp_primitive_ASSOCIATE may have added this association ++ * To the hash table, try to unhash it, just in case, its a noop ++ * if it wasn't hashed so we're safe ++ */ ++ sctp_unhash_established(asoc); + sctp_association_free(asoc); ++ } + return err; + } + +@@ -1942,8 +1948,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, + goto out_unlock; + + out_free: +- if (new_asoc) ++ if (new_asoc) { ++ sctp_unhash_established(asoc); + sctp_association_free(asoc); ++ } + out_unlock: + sctp_release_sock(sk); + +@@ -4569,7 +4577,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; if (space_left < addrlen) return -ENOMEM; @@ -77456,7 +78542,7 @@ index 44ddaa5..a3119bd 100644 sprintf(alias, "dmi*"); diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c -index c4e7d15..4241aef 100644 +index c4e7d15..dad16c1 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -922,6 +922,7 @@ enum mismatch { @@ -77498,12 +78584,12 @@ index c4e7d15..4241aef 100644 free(prl_to); break; + case DATA_TO_TEXT: -+/* ++#if 0 + fprintf(stderr, -+ "The variable %s references\n" -+ "the %s %s%s%s\n", -+ fromsym, to, sec2annotation(tosec), tosym, to_p); -+*/ ++ "The %s %s:%s references\n" ++ "the %s %s:%s%s\n", ++ from, fromsec, fromsym, to, tosec, tosym, to_p); ++#endif + break; } fprintf(stderr, "\n"); @@ -77602,19 +78688,42 @@ index 5c11312..72742b5 100644 write_hex_cnt = 0; for (i = 0; i < logo_clutsize; i++) { diff --git a/security/Kconfig b/security/Kconfig -index ccc61f8..3334dd6 100644 +index ccc61f8..5e68d73 100644 --- a/security/Kconfig +++ b/security/Kconfig -@@ -4,6 +4,849 @@ +@@ -4,6 +4,875 @@ menu "Security options" +menu "Grsecurity" + ++ config ARCH_TRACK_EXEC_LIMIT ++ bool ++ ++ config PAX_KERNEXEC_PLUGIN ++ bool ++ ++ config PAX_PER_CPU_PGD ++ bool ++ ++ config TASK_SIZE_MAX_SHIFT ++ int ++ depends on X86_64 ++ default 47 if !PAX_PER_CPU_PGD ++ default 42 if PAX_PER_CPU_PGD ++ ++ config PAX_ENABLE_PAE ++ bool ++ default y if (X86_32 && (MPENTIUM4 || MK8 || MPSC || MCORE2 || MATOM)) ++ ++ config PAX_USERCOPY_SLABS ++ bool ++ +config GRKERNSEC + bool "Grsecurity" + select CRYPTO + select CRYPTO_SHA256 ++ select STOP_MACHINE + help + If you say Y here, you will be able to configure many features + that will enhance the security of your system. It is highly @@ -77781,6 +78890,7 @@ index ccc61f8..3334dd6 100644 + +config GRKERNSEC_TPE_GID + int "GID for untrusted users" ++ depends on GRKERNSEC_CONFIG_SERVER + default 1005 + help + Setting this GID determines which group untrusted users should @@ -77789,6 +78899,16 @@ index ccc61f8..3334dd6 100644 + The users will only be able to execute binaries in directories owned and + writable only by the root user. + ++config GRKERNSEC_SYMLINKOWN_GID ++ int "GID for users with kernel-enforced SymlinksIfOwnerMatch" ++ depends on GRKERNSEC_CONFIG_SERVER ++ default 1006 ++ help ++ Setting this GID determines what group kernel-enforced ++ SymlinksIfOwnerMatch will be enabled for. If the sysctl option ++ is enabled, a sysctl option with name "symlinkown_gid" is created. ++ ++ +endmenu + +menu "Customize Configuration" @@ -77796,25 +78916,6 @@ index ccc61f8..3334dd6 100644 + +menu "PaX" + -+ config ARCH_TRACK_EXEC_LIMIT -+ bool -+ -+ config PAX_KERNEXEC_PLUGIN -+ bool -+ -+ config PAX_PER_CPU_PGD -+ bool -+ -+ config TASK_SIZE_MAX_SHIFT -+ int -+ depends on X86_64 -+ default 47 if !PAX_PER_CPU_PGD -+ default 42 if PAX_PER_CPU_PGD -+ -+ config PAX_ENABLE_PAE -+ bool -+ default y if (X86_32 && (MPENTIUM4 || MK8 || MPSC || MCORE2 || MATOM)) -+ +config PAX + bool "Enable various PaX features" + default y if GRKERNSEC_CONFIG_AUTO @@ -77852,13 +78953,12 @@ index ccc61f8..3334dd6 100644 + has been deprecated in favour of PT_PAX_FLAGS and XATTR_PAX_FLAGS + support. + -+ If you have applications not marked by the PT_PAX_FLAGS ELF program -+ header and you cannot use XATTR_PAX_FLAGS then you MUST enable this -+ option otherwise they will not get any protection. -+ + Note that if you enable PT_PAX_FLAGS or XATTR_PAX_FLAGS marking + support as well, they will override the legacy EI_PAX marks. + ++ If you enable none of the marking options then all applications ++ will run with PaX enabled on them by default. ++ +config PAX_PT_PAX_FLAGS + bool 'Use ELF program header marking' + default y if GRKERNSEC_CONFIG_AUTO @@ -77871,15 +78971,14 @@ index ccc61f8..3334dd6 100644 + integrated into the toolchain (the binutils patch is available + from http://pax.grsecurity.net). + -+ If you have applications not marked by the PT_PAX_FLAGS ELF program -+ header then you MUST enable either XATTR_PAX_FLAGS or EI_PAX marking -+ support otherwise they will not get any protection. ++ Note that if you enable the legacy EI_PAX marking support as well, ++ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks. + + If you enable both PT_PAX_FLAGS and XATTR_PAX_FLAGS support then you + must make sure that the marks are the same if a binary has both marks. + -+ Note that if you enable the legacy EI_PAX marking support as well, -+ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks. ++ If you enable none of the marking options then all applications ++ will run with PaX enabled on them by default. + +config PAX_XATTR_PAX_FLAGS + bool 'Use filesystem extended attributes marking' @@ -77904,15 +79003,14 @@ index ccc61f8..3334dd6 100644 + isofs, udf, vfat) so copying files through such filesystems will + lose the extended attributes and these PaX markings. + -+ If you have applications not marked by the PT_PAX_FLAGS ELF program -+ header then you MUST enable either XATTR_PAX_FLAGS or EI_PAX marking -+ support otherwise they will not get any protection. ++ Note that if you enable the legacy EI_PAX marking support as well, ++ the EI_PAX marks will be overridden by the XATTR_PAX_FLAGS marks. + + If you enable both PT_PAX_FLAGS and XATTR_PAX_FLAGS support then you + must make sure that the marks are the same if a binary has both marks. + -+ Note that if you enable the legacy EI_PAX marking support as well, -+ the EI_PAX marks will be overridden by the XATTR_PAX_FLAGS marks. ++ If you enable none of the marking options then all applications ++ will run with PaX enabled on them by default. + +choice + prompt 'MAC system integration' @@ -78402,6 +79500,7 @@ index ccc61f8..3334dd6 100644 + default y if GRKERNSEC_CONFIG_AUTO + depends on X86 || PPC || SPARC || ARM + depends on GRKERNSEC && (SLAB || SLUB || SLOB) ++ select PAX_USERCOPY_SLABS + help + By saying Y here the kernel will enforce the size of heap objects + when they are copied in either direction between the kernel and @@ -78442,6 +79541,19 @@ index ccc61f8..3334dd6 100644 + Homepage: + http://www.grsecurity.net/~ephox/overflow_plugin/ + ++config PAX_LATENT_ENTROPY ++ bool "Generate some entropy during boot" ++ default y if GRKERNSEC_CONFIG_AUTO ++ help ++ By saying Y here the kernel will instrument early boot code to ++ extract some entropy from both original and artificially created ++ program state. This will help especially embedded systems where ++ there is little 'natural' source of entropy normally. The cost ++ is some slowdown of the boot process. ++ ++ Note that entropy extracted this way is not cryptographically ++ secure! ++ +endmenu + +endmenu @@ -78455,7 +79567,7 @@ index ccc61f8..3334dd6 100644 config KEYS bool "Enable access key retention support" help -@@ -169,7 +1012,7 @@ config INTEL_TXT +@@ -169,7 +1038,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 @@ -79319,12 +80431,19 @@ index da5fa1a..113cd02 100644 int last_frame_number; /* stored frame number */ int last_delay; /* stored delay */ }; +diff --git a/tools/gcc/.gitignore b/tools/gcc/.gitignore +new file mode 100644 +index 0000000..50f2f2f +--- /dev/null ++++ b/tools/gcc/.gitignore +@@ -0,0 +1 @@ ++size_overflow_hash.h diff --git a/tools/gcc/Makefile b/tools/gcc/Makefile new file mode 100644 -index 0000000..f4f9986 +index 0000000..1d09b7e --- /dev/null +++ b/tools/gcc/Makefile -@@ -0,0 +1,41 @@ +@@ -0,0 +1,43 @@ +#CC := gcc +#PLUGIN_SOURCE_FILES := pax_plugin.c +#PLUGIN_OBJECT_FILES := $(patsubst %.c,%.o,$(PLUGIN_SOURCE_FILES)) @@ -79346,6 +80465,7 @@ index 0000000..f4f9986 +$(HOSTLIBS)-$(CONFIG_CHECKER_PLUGIN) += checker_plugin.so +$(HOSTLIBS)-y += colorize_plugin.so +$(HOSTLIBS)-$(CONFIG_PAX_SIZE_OVERFLOW) += size_overflow_plugin.so ++$(HOSTLIBS)-$(CONFIG_PAX_LATENT_ENTROPY) += latent_entropy_plugin.so + +always := $($(HOSTLIBS)-y) + @@ -79356,6 +80476,7 @@ index 0000000..f4f9986 +checker_plugin-objs := checker_plugin.o +colorize_plugin-objs := colorize_plugin.o +size_overflow_plugin-objs := size_overflow_plugin.o ++latent_entropy_plugin-objs := latent_entropy_plugin.o + +$(obj)/size_overflow_plugin.o: $(objtree)/$(obj)/size_overflow_hash.h + @@ -79545,7 +80666,7 @@ index 0000000..d41b5af +} diff --git a/tools/gcc/colorize_plugin.c b/tools/gcc/colorize_plugin.c new file mode 100644 -index 0000000..7a5e311 +index 0000000..846aeb0 --- /dev/null +++ b/tools/gcc/colorize_plugin.c @@ -0,0 +1,148 @@ @@ -79683,7 +80804,7 @@ index 0000000..7a5e311 + struct register_pass_info colorize_rearm_pass_info = { + .pass = &pass_ipa_colorize_rearm.pass, + .reference_pass_name = "*free_lang_data", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER + }; + @@ -79699,7 +80820,7 @@ index 0000000..7a5e311 +} diff --git a/tools/gcc/constify_plugin.c b/tools/gcc/constify_plugin.c new file mode 100644 -index 0000000..89b7f56 +index 0000000..048d4ff --- /dev/null +++ b/tools/gcc/constify_plugin.c @@ -0,0 +1,328 @@ @@ -80005,7 +81126,7 @@ index 0000000..89b7f56 + struct register_pass_info local_variable_pass_info = { + .pass = &pass_local_variable.pass, + .reference_pass_name = "*referenced_vars", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER + }; + @@ -80133,7 +81254,7 @@ index 0000000..a0fe8b2 +exit 0 diff --git a/tools/gcc/kallocstat_plugin.c b/tools/gcc/kallocstat_plugin.c new file mode 100644 -index 0000000..a5eabce +index 0000000..a86e422 --- /dev/null +++ b/tools/gcc/kallocstat_plugin.c @@ -0,0 +1,167 @@ @@ -80290,7 +81411,7 @@ index 0000000..a5eabce + struct register_pass_info kallocstat_pass_info = { + .pass = &kallocstat_pass.pass, + .reference_pass_name = "ssa", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER + }; + @@ -80306,7 +81427,7 @@ index 0000000..a5eabce +} diff --git a/tools/gcc/kernexec_plugin.c b/tools/gcc/kernexec_plugin.c new file mode 100644 -index 0000000..d8a8da2 +index 0000000..98011fa --- /dev/null +++ b/tools/gcc/kernexec_plugin.c @@ -0,0 +1,427 @@ @@ -80682,19 +81803,19 @@ index 0000000..d8a8da2 + struct register_pass_info kernexec_reload_pass_info = { + .pass = &kernexec_reload_pass.pass, + .reference_pass_name = "ssa", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER + }; + struct register_pass_info kernexec_fptr_pass_info = { + .pass = &kernexec_fptr_pass.pass, + .reference_pass_name = "ssa", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER + }; + struct register_pass_info kernexec_retaddr_pass_info = { + .pass = &kernexec_retaddr_pass.pass, + .reference_pass_name = "pro_and_epilogue", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER + }; + @@ -80737,6 +81858,307 @@ index 0000000..d8a8da2 + + return 0; +} +diff --git a/tools/gcc/latent_entropy_plugin.c b/tools/gcc/latent_entropy_plugin.c +new file mode 100644 +index 0000000..b8008f7 +--- /dev/null ++++ b/tools/gcc/latent_entropy_plugin.c +@@ -0,0 +1,295 @@ ++/* ++ * Copyright 2012 by the PaX Team ++ * Licensed under the GPL v2 ++ * ++ * Note: the choice of the license means that the compilation process is ++ * NOT 'eligible' as defined by gcc's library exception to the GPL v3, ++ * but for the kernel it doesn't matter since it doesn't link against ++ * any of the gcc libraries ++ * ++ * gcc plugin to help generate a little bit of entropy from program state, ++ * used during boot in the kernel ++ * ++ * TODO: ++ * - add ipa pass to identify not explicitly marked candidate functions ++ * - mix in more program state (function arguments/return values, loop variables, etc) ++ * - more instrumentation control via attribute parameters ++ * ++ * BUGS: ++ * - LTO needs -flto-partition=none for now ++ */ ++#include "gcc-plugin.h" ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tree.h" ++#include "tree-pass.h" ++#include "flags.h" ++#include "intl.h" ++#include "toplev.h" ++#include "plugin.h" ++//#include "expr.h" where are you... ++#include "diagnostic.h" ++#include "plugin-version.h" ++#include "tm.h" ++#include "function.h" ++#include "basic-block.h" ++#include "gimple.h" ++#include "rtl.h" ++#include "emit-rtl.h" ++#include "tree-flow.h" ++ ++int plugin_is_GPL_compatible; ++ ++static tree latent_entropy_decl; ++ ++static struct plugin_info latent_entropy_plugin_info = { ++ .version = "201207271820", ++ .help = NULL ++}; ++ ++static unsigned int execute_latent_entropy(void); ++static bool gate_latent_entropy(void); ++ ++static struct gimple_opt_pass latent_entropy_pass = { ++ .pass = { ++ .type = GIMPLE_PASS, ++ .name = "latent_entropy", ++ .gate = gate_latent_entropy, ++ .execute = execute_latent_entropy, ++ .sub = NULL, ++ .next = NULL, ++ .static_pass_number = 0, ++ .tv_id = TV_NONE, ++ .properties_required = PROP_gimple_leh | PROP_cfg, ++ .properties_provided = 0, ++ .properties_destroyed = 0, ++ .todo_flags_start = 0, //TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts, ++ .todo_flags_finish = TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_update_ssa ++ } ++}; ++ ++static tree handle_latent_entropy_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs) ++{ ++ if (TREE_CODE(*node) != FUNCTION_DECL) { ++ *no_add_attrs = true; ++ error("%qE attribute only applies to functions", name); ++ } ++ return NULL_TREE; ++} ++ ++static struct attribute_spec latent_entropy_attr = { ++ .name = "latent_entropy", ++ .min_length = 0, ++ .max_length = 0, ++ .decl_required = true, ++ .type_required = false, ++ .function_type_required = false, ++ .handler = handle_latent_entropy_attribute, ++#if BUILDING_GCC_VERSION >= 4007 ++ .affects_type_identity = false ++#endif ++}; ++ ++static void register_attributes(void *event_data, void *data) ++{ ++ register_attribute(&latent_entropy_attr); ++} ++ ++static bool gate_latent_entropy(void) ++{ ++ tree latent_entropy_attr; ++ ++ latent_entropy_attr = lookup_attribute("latent_entropy", DECL_ATTRIBUTES(current_function_decl)); ++ return latent_entropy_attr != NULL_TREE; ++} ++ ++static unsigned HOST_WIDE_INT seed; ++static unsigned HOST_WIDE_INT get_random_const(void) ++{ ++ seed = (seed >> 1U) ^ (-(seed & 1ULL) & 0xD800000000000000ULL); ++ return seed; ++} ++ ++static enum tree_code get_op(tree *rhs) ++{ ++ static enum tree_code op; ++ unsigned HOST_WIDE_INT random_const; ++ ++ random_const = get_random_const(); ++ ++ switch (op) { ++ case BIT_XOR_EXPR: ++ op = PLUS_EXPR; ++ break; ++ ++ case PLUS_EXPR: ++ if (rhs) { ++ op = LROTATE_EXPR; ++ random_const &= HOST_BITS_PER_WIDE_INT - 1; ++ break; ++ } ++ ++ case LROTATE_EXPR: ++ default: ++ op = BIT_XOR_EXPR; ++ break; ++ } ++ if (rhs) ++ *rhs = build_int_cstu(unsigned_intDI_type_node, random_const); ++ return op; ++} ++ ++static void perturb_local_entropy(basic_block bb, tree local_entropy) ++{ ++ gimple_stmt_iterator gsi; ++ gimple assign; ++ tree addxorrol, rhs; ++ enum tree_code op; ++ ++ op = get_op(&rhs); ++ addxorrol = fold_build2_loc(UNKNOWN_LOCATION, op, unsigned_intDI_type_node, local_entropy, rhs); ++ assign = gimple_build_assign(local_entropy, addxorrol); ++ find_referenced_vars_in(assign); ++//debug_bb(bb); ++ gsi = gsi_after_labels(bb); ++ gsi_insert_before(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++} ++ ++static void perturb_latent_entropy(basic_block bb, tree rhs) ++{ ++ gimple_stmt_iterator gsi; ++ gimple assign; ++ tree addxorrol, temp; ++ ++ // 1. create temporary copy of latent_entropy ++ temp = create_tmp_var(unsigned_intDI_type_node, "temp_latent_entropy"); ++ add_referenced_var(temp); ++ mark_sym_for_renaming(temp); ++ ++ // 2. read... ++ assign = gimple_build_assign(temp, latent_entropy_decl); ++ find_referenced_vars_in(assign); ++ gsi = gsi_after_labels(bb); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++ ++ // 3. ...modify... ++ addxorrol = fold_build2_loc(UNKNOWN_LOCATION, get_op(NULL), unsigned_intDI_type_node, temp, rhs); ++ assign = gimple_build_assign(temp, addxorrol); ++ find_referenced_vars_in(assign); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++ ++ // 4. ...write latent_entropy ++ assign = gimple_build_assign(latent_entropy_decl, temp); ++ find_referenced_vars_in(assign); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++} ++ ++static unsigned int execute_latent_entropy(void) ++{ ++ basic_block bb; ++ gimple assign; ++ gimple_stmt_iterator gsi; ++ tree local_entropy; ++ ++ if (!latent_entropy_decl) { ++ struct varpool_node *node; ++ ++ for (node = varpool_nodes; node; node = node->next) { ++ tree var = node->decl; ++ if (strcmp(IDENTIFIER_POINTER(DECL_NAME(var)), "latent_entropy")) ++ continue; ++ latent_entropy_decl = var; ++// debug_tree(var); ++ break; ++ } ++ if (!latent_entropy_decl) { ++// debug_tree(current_function_decl); ++ return 0; ++ } ++ } ++ ++//fprintf(stderr, "latent_entropy: %s\n", IDENTIFIER_POINTER(DECL_NAME(current_function_decl))); ++ ++ // 1. create local entropy variable ++ local_entropy = create_tmp_var(unsigned_intDI_type_node, "local_entropy"); ++ add_referenced_var(local_entropy); ++ mark_sym_for_renaming(local_entropy); ++ ++ // 2. initialize local entropy variable ++ bb = split_block_after_labels(ENTRY_BLOCK_PTR)->dest; ++ if (dom_info_available_p(CDI_DOMINATORS)) ++ set_immediate_dominator(CDI_DOMINATORS, bb, ENTRY_BLOCK_PTR); ++ gsi = gsi_start_bb(bb); ++ ++ assign = gimple_build_assign(local_entropy, build_int_cstu(unsigned_intDI_type_node, get_random_const())); ++// gimple_set_location(assign, loc); ++ find_referenced_vars_in(assign); ++ gsi_insert_after(&gsi, assign, GSI_NEW_STMT); ++ update_stmt(assign); ++ bb = bb->next_bb; ++ ++ // 3. instrument each BB with an operation on the local entropy variable ++ while (bb != EXIT_BLOCK_PTR) { ++ perturb_local_entropy(bb, local_entropy); ++ bb = bb->next_bb; ++ }; ++ ++ // 4. mix local entropy into the global entropy variable ++ perturb_latent_entropy(EXIT_BLOCK_PTR->prev_bb, local_entropy); ++ return 0; ++} ++ ++static void start_unit_callback(void *gcc_data, void *user_data) ++{ ++#if BUILDING_GCC_VERSION >= 4007 ++ seed = get_random_seed(false); ++#else ++ sscanf(get_random_seed(false), "%" HOST_WIDE_INT_PRINT "x", &seed); ++ seed *= seed; ++#endif ++ ++ if (in_lto_p) ++ return; ++ ++ // extern u64 latent_entropy ++ latent_entropy_decl = build_decl(UNKNOWN_LOCATION, VAR_DECL, get_identifier("latent_entropy"), unsigned_intDI_type_node); ++ ++ TREE_STATIC(latent_entropy_decl) = 1; ++ TREE_PUBLIC(latent_entropy_decl) = 1; ++ TREE_USED(latent_entropy_decl) = 1; ++ TREE_THIS_VOLATILE(latent_entropy_decl) = 1; ++ DECL_EXTERNAL(latent_entropy_decl) = 1; ++ DECL_ARTIFICIAL(latent_entropy_decl) = 0; ++ DECL_INITIAL(latent_entropy_decl) = NULL; ++// DECL_ASSEMBLER_NAME(latent_entropy_decl); ++// varpool_finalize_decl(latent_entropy_decl); ++// varpool_mark_needed_node(latent_entropy_decl); ++} ++ ++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) ++{ ++ const char * const plugin_name = plugin_info->base_name; ++ struct register_pass_info latent_entropy_pass_info = { ++ .pass = &latent_entropy_pass.pass, ++ .reference_pass_name = "optimized", ++ .ref_pass_instance_number = 1, ++ .pos_op = PASS_POS_INSERT_BEFORE ++ }; ++ ++ if (!plugin_default_version_check(version, &gcc_version)) { ++ error(G_("incompatible gcc/plugin versions")); ++ return 1; ++ } ++ ++ register_callback(plugin_name, PLUGIN_INFO, NULL, &latent_entropy_plugin_info); ++ register_callback ("start_unit", PLUGIN_START_UNIT, &start_unit_callback, NULL); ++ register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &latent_entropy_pass_info); ++ register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL); ++ ++ return 0; ++} diff --git a/tools/gcc/size_overflow_hash.data b/tools/gcc/size_overflow_hash.data new file mode 100644 index 0000000..daaa86c @@ -84441,7 +85863,7 @@ index 0000000..cc96254 +} diff --git a/tools/gcc/stackleak_plugin.c b/tools/gcc/stackleak_plugin.c new file mode 100644 -index 0000000..b87ec9d +index 0000000..38d2014 --- /dev/null +++ b/tools/gcc/stackleak_plugin.c @@ -0,0 +1,313 @@ @@ -84714,13 +86136,13 @@ index 0000000..b87ec9d + .pass = &stackleak_tree_instrument_pass.pass, +// .reference_pass_name = "tree_profile", + .reference_pass_name = "optimized", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_BEFORE + }; + struct register_pass_info stackleak_final_pass_info = { + .pass = &stackleak_final_rtl_opt_pass.pass, + .reference_pass_name = "final", -+ .ref_pass_instance_number = 0, ++ .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_BEFORE + }; + -- 2.39.5