From: Piotr Karbowski Date: Tue, 10 Nov 2015 03:08:04 +0000 (+0100) Subject: Auto commit, 1 new patch{es}. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2d1b3edcce4a84ad10e3853f20a14ace80e16f74;p=thirdparty%2Fgrsecurity-scrape.git Auto commit, 1 new patch{es}. --- diff --git a/test/changelog-test.txt b/test/changelog-test.txt index 3cf16c6..134248e 100644 --- a/test/changelog-test.txt +++ b/test/changelog-test.txt @@ -1,3 +1,51 @@ +commit 9c49029fe4cb9a52cb174aebfd5946a9d26b9956 +Merge: 5482e7e 7033393 +Author: Brad Spengler +Date: Mon Nov 9 19:51:58 2015 -0500 + + Merge branch 'pax-test' into grsec-test + +commit 70333935932c9f3eb333a354dd760b4233efcc37 +Author: Brad Spengler +Date: Mon Nov 9 19:51:19 2015 -0500 + + Update to pax-linux-4.2.6-test18.patch: + - cleaned up the last of the FPU changes, by spender + - fixed a few KERNEXEC regressions (backported from 4.3) + - Emese fixed a few size overflow false positives in kvm, reported by Christian Roessner (https://bugs.gentoo.org/show_bug.cgi?id=558138#c23) + - David Sterba fixed a few integer overflows in btrfs caught by the size overflow plugin (https://patchwork.kernel.org/patch/7585611/ and https://patchwork.kernel.org/patch/7582351/), reported by Victor, Stebalien and alan.d (https://forums.grsecurity.net/viewtopic.php?f=1&t=4284) + + arch/x86/include/asm/fpu/internal.h | 2 +- + arch/x86/include/asm/fpu/types.h | 1 - + arch/x86/kernel/apic/apic.c | 4 ++- + arch/x86/kernel/fpu/init.c | 36 -------------------- + arch/x86/kernel/process_64.c | 6 +-- + arch/x86/kernel/vsmp_64.c | 13 +++++-- + drivers/acpi/video_detect.c | 2 +- + drivers/lguest/core.c | 2 +- + fs/btrfs/file.c | 10 ++++-- + fs/btrfs/inode.c | 12 ++++++ + .../disable_size_overflow_hash.data | 5 ++- + .../size_overflow_plugin/size_overflow_hash.data | 7 +--- + 12 files changed, 42 insertions(+), 58 deletions(-) + +commit 5482e7eb4ba3c5cc90472ccdb1bfe2cec64413e2 +Merge: 81e2642 682ba19 +Author: Brad Spengler +Date: Mon Nov 9 18:19:48 2015 -0500 + + Merge branch 'pax-test' into grsec-test + + Conflicts: + drivers/pci/pci-sysfs.c + +commit 682ba19ce305f501c9bc5c42a76f2c7442aa22fc +Merge: 7755256 1c02865 +Author: Brad Spengler +Date: Mon Nov 9 18:18:24 2015 -0500 + + Merge branch 'linux-4.2.y' into pax-test + commit 81e26429b7a36f0c75de3ab42754256720c0a159 Author: Brad Spengler Date: Mon Nov 9 07:37:30 2015 -0500 diff --git a/test/grsecurity-3.1-4.2.6-201511092040.patch b/test/grsecurity-3.1-4.2.6-201511092040.patch new file mode 100644 index 0000000..49aefe7 --- /dev/null +++ b/test/grsecurity-3.1-4.2.6-201511092040.patch @@ -0,0 +1,7213 @@ +diff --git a/Documentation/dontdiff b/Documentation/dontdiff +index 9de9813..1462492 100644 +--- a/Documentation/dontdiff ++++ b/Documentation/dontdiff +@@ -3,9 +3,11 @@ + *.bc + *.bin + *.bz2 ++*.c.[012]*.* + *.cis + *.cpio + *.csp ++*.dbg + *.dsp + *.dvi + *.elf +@@ -15,6 +17,7 @@ + *.gcov + *.gen.S + *.gif ++*.gmo + *.grep + *.grp + *.gz +@@ -51,14 +54,17 @@ + *.tab.h + *.tex + *.ver ++*.vim + *.xml + *.xz + *_MODULES ++*_reg_safe.h + *_vga16.c + *~ + \#*# + *.9 +-.* ++.[^g]* ++.gen* + .*.d + .mm + 53c700_d.h +@@ -72,9 +78,11 @@ Image + Module.markers + Module.symvers + PENDING ++PERF* + SCCS + System.map* + TAGS ++TRACEEVENT-CFLAGS + aconf + af_names.h + aic7*reg.h* +@@ -83,6 +91,7 @@ aic7*seq.h* + aicasm + aicdb.h* + altivec*.c ++ashldi3.S + asm-offsets.h + asm_offsets.h + autoconf.h* +@@ -95,32 +104,40 @@ bounds.h + bsetup + btfixupprep + build ++builtin-policy.h + bvmlinux + bzImage* + capability_names.h + capflags.c + classlist.h* ++clut_vga16.c ++common-cmds.h + comp*.log + compile.h* + conf + config + config-* + config_data.h* ++config.c + config.mak + config.mak.autogen ++config.tmp + conmakehash + consolemap_deftbl.c* + cpustr.h + crc32table.h* + cscope.* + defkeymap.c ++devicetable-offsets.h + devlist.h* + dnotify_test + docproc + dslm ++dtc-lexer.lex.c + elf2ecoff + elfconfig.h* + evergreen_reg_safe.h ++exception_policy.conf + fixdep + flask.h + fore200e_mkfirm +@@ -128,12 +145,15 @@ fore200e_pca_fw.c* + gconf + gconf.glade.h + gen-devlist ++gen-kdb_cmds.c + gen_crc32table + gen_init_cpio + generated + genheaders + genksyms + *_gray256.c ++hash ++hid-example + hpet_example + hugepage-mmap + hugepage-shm +@@ -148,14 +168,14 @@ int32.c + int4.c + int8.c + kallsyms +-kconfig ++kern_constants.h + keywords.c + ksym.c* + ksym.h* + kxgettext + lex.c + lex.*.c +-linux ++lib1funcs.S + logo_*.c + logo_*_clut224.c + logo_*_mono.c +@@ -165,14 +185,15 @@ mach-types.h + machtypes.h + map + map_hugetlb +-media + mconf ++mdp + miboot* + mk_elfconfig + mkboot + mkbugboot + mkcpustr + mkdep ++mkpiggy + mkprep + mkregtable + mktables +@@ -188,6 +209,8 @@ oui.c* + page-types + parse.c + parse.h ++parse-events* ++pasyms.h + patches* + pca200e.bin + pca200e_ecd.bin2 +@@ -197,6 +220,7 @@ perf-archive + piggyback + piggy.gzip + piggy.S ++pmu-* + pnmtologo + ppc_defs.h* + pss_boot.h +@@ -206,7 +230,12 @@ r200_reg_safe.h + r300_reg_safe.h + r420_reg_safe.h + r600_reg_safe.h ++randomize_layout_hash.h ++randomize_layout_seed.h ++realmode.lds ++realmode.relocs + recordmcount ++regdb.c + relocs + rlim_names.h + rn50_reg_safe.h +@@ -216,8 +245,12 @@ series + setup + setup.bin + setup.elf ++signing_key* ++size_overflow_hash.h + sImage ++slabinfo + sm_tbl* ++sortextable + split-include + syscalltab.h + tables.c +@@ -227,6 +260,7 @@ tftpboot.img + timeconst.h + times.h* + trix_boot.h ++user_constants.h + utsrelease.h* + vdso-syms.lds + vdso.lds +@@ -238,13 +272,17 @@ vdso32.lds + vdso32.so.dbg + vdso64.lds + vdso64.so.dbg ++vdsox32.lds ++vdsox32-syms.lds + version.h* + vmImage + vmlinux + vmlinux-* + vmlinux.aout + vmlinux.bin.all ++vmlinux.bin.bz2 + vmlinux.lds ++vmlinux.relocs + vmlinuz + voffset.h + vsyscall.lds +@@ -252,9 +290,12 @@ vsyscall_32.lds + wanxlfw.inc + uImage + unifdef ++utsrelease.h + wakeup.bin + wakeup.elf + wakeup.lds ++x509* + zImage* + zconf.hash.c ++zconf.lex.c + zoffset.h +diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt +index 13f888a..250729b 100644 +--- a/Documentation/kbuild/makefiles.txt ++++ b/Documentation/kbuild/makefiles.txt +@@ -23,10 +23,11 @@ This document describes the Linux kernel Makefiles. + === 4 Host Program support + --- 4.1 Simple Host Program + --- 4.2 Composite Host Programs +- --- 4.3 Using C++ for host programs +- --- 4.4 Controlling compiler options for host programs +- --- 4.5 When host programs are actually built +- --- 4.6 Using hostprogs-$(CONFIG_FOO) ++ --- 4.3 Defining shared libraries ++ --- 4.4 Using C++ for host programs ++ --- 4.5 Controlling compiler options for host programs ++ --- 4.6 When host programs are actually built ++ --- 4.7 Using hostprogs-$(CONFIG_FOO) + + === 5 Kbuild clean infrastructure + +@@ -643,7 +644,29 @@ Both possibilities are described in the following. + Finally, the two .o files are linked to the executable, lxdialog. + Note: The syntax -y is not permitted for host-programs. + +---- 4.3 Using C++ for host programs ++--- 4.3 Defining shared libraries ++ ++ Objects with extension .so are considered shared libraries, and ++ will be compiled as position independent objects. ++ Kbuild provides support for shared libraries, but the usage ++ shall be restricted. ++ In the following example the libkconfig.so shared library is used ++ to link the executable conf. ++ ++ Example: ++ #scripts/kconfig/Makefile ++ hostprogs-y := conf ++ conf-objs := conf.o libkconfig.so ++ libkconfig-objs := expr.o type.o ++ ++ Shared libraries always require a corresponding -objs line, and ++ in the example above the shared library libkconfig is composed by ++ the two objects expr.o and type.o. ++ expr.o and type.o will be built as position independent code and ++ linked as a shared library libkconfig.so. C++ is not supported for ++ shared libraries. ++ ++--- 4.4 Using C++ for host programs + + kbuild offers support for host programs written in C++. This was + introduced solely to support kconfig, and is not recommended +@@ -666,7 +689,7 @@ Both possibilities are described in the following. + qconf-cxxobjs := qconf.o + qconf-objs := check.o + +---- 4.4 Controlling compiler options for host programs ++--- 4.5 Controlling compiler options for host programs + + When compiling host programs, it is possible to set specific flags. + The programs will always be compiled utilising $(HOSTCC) passed +@@ -694,7 +717,7 @@ Both possibilities are described in the following. + When linking qconf, it will be passed the extra option + "-L$(QTDIR)/lib". + +---- 4.5 When host programs are actually built ++--- 4.6 When host programs are actually built + + Kbuild will only build host-programs when they are referenced + as a prerequisite. +@@ -725,7 +748,7 @@ Both possibilities are described in the following. + This will tell kbuild to build lxdialog even if not referenced in + any rule. + +---- 4.6 Using hostprogs-$(CONFIG_FOO) ++--- 4.7 Using hostprogs-$(CONFIG_FOO) + + A typical pattern in a Kbuild file looks like this: + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 1d6f045..2714987 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1244,6 +1244,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + Format: such that (rxsize & ~0x1fffc0) == 0. + Default: 1024 + ++ grsec_proc_gid= [GRKERNSEC_PROC_USERGROUP] Chooses GID to ++ ignore grsecurity's /proc restrictions ++ ++ grsec_sysfs_restrict= Format: 0 | 1 ++ Default: 1 ++ Disables GRKERNSEC_SYSFS_RESTRICT if enabled in config ++ + hashdist= [KNL,NUMA] Large hashes allocated during boot + are distributed across NUMA nodes. Defaults on + for 64-bit NUMA, off otherwise. +@@ -2364,6 +2371,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + noexec=on: enable non-executable mappings (default) + noexec=off: disable non-executable mappings + ++ nopcid [X86-64] ++ Disable PCID (Process-Context IDentifier) even if it ++ is supported by the processor. ++ + nosmap [X86] + Disable SMAP (Supervisor Mode Access Prevention) + even if it is supported by processor. +@@ -2662,6 +2673,30 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + the specified number of seconds. This is to be used if + your oopses keep scrolling off the screen. + ++ pax_nouderef [X86] disables UDEREF. Most likely needed under certain ++ virtualization environments that don't cope well with the ++ expand down segment used by UDEREF on X86-32 or the frequent ++ page table updates on X86-64. ++ ++ pax_sanitize_slab= ++ Format: { 0 | 1 | off | fast | full } ++ Options '0' and '1' are only provided for backward ++ compatibility, 'off' or 'fast' should be used instead. ++ 0|off : disable slab object sanitization ++ 1|fast: enable slab object sanitization excluding ++ whitelisted slabs (default) ++ full : sanitize all slabs, even the whitelisted ones ++ ++ pax_softmode= 0/1 to disable/enable PaX softmode on boot already. ++ ++ pax_extra_latent_entropy ++ Enable a very simple form of latent entropy extraction ++ from the first 4GB of memory as the bootmem allocator ++ passes the memory pages to the buddy allocator. ++ ++ pax_weakuderef [X86-64] enables the weaker but faster form of UDEREF ++ when the processor supports PCID. ++ + pcbit= [HW,ISDN] + + pcd. [PARIDE] +diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt +index 6fccb69..60c7c7a 100644 +--- a/Documentation/sysctl/kernel.txt ++++ b/Documentation/sysctl/kernel.txt +@@ -41,6 +41,7 @@ show up in /proc/sys/kernel: + - kptr_restrict + - kstack_depth_to_print [ X86 only ] + - l2cr [ PPC only ] ++- modify_ldt [ X86 only ] + - modprobe ==> Documentation/debugging-modules.txt + - modules_disabled + - msg_next_id [ sysv ipc ] +@@ -391,6 +392,20 @@ This flag controls the L2 cache of G3 processor boards. If + + ============================================================== + ++modify_ldt: (X86 only) ++ ++Enables (1) or disables (0) the modify_ldt syscall. Modifying the LDT ++(Local Descriptor Table) may be needed to run a 16-bit or segmented code ++such as Dosemu or Wine. This is done via a system call which is not needed ++to run portable applications, and which can sometimes be abused to exploit ++some weaknesses of the architecture, opening new vulnerabilities. ++ ++This sysctl allows one to increase the system's security by disabling the ++system call, or to restore compatibility with specific applications when it ++was already disabled. ++ ++============================================================== ++ + modules_disabled: + + A toggle value indicating if modules are allowed to be loaded +diff --git a/Makefile b/Makefile +index 9ef3739..20b7716 100644 +--- a/Makefile ++++ b/Makefile +@@ -298,7 +298,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + HOSTCC = gcc + HOSTCXX = g++ + HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 +-HOSTCXXFLAGS = -O2 ++HOSTCFLAGS = -W -Wno-unused-parameter -Wno-missing-field-initializers -fno-delete-null-pointer-checks ++HOSTCFLAGS += $(call cc-option, -Wno-empty-body) ++HOSTCXXFLAGS = -O2 -Wall -W -Wno-array-bounds + + ifeq ($(shell $(HOSTCC) -v 2>&1 | grep -c "clang version"), 1) + HOSTCFLAGS += -Wno-unused-value -Wno-unused-parameter \ +@@ -434,8 +436,8 @@ export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \ + # Rules shared between *config targets and build targets + + # Basic helpers built in scripts/ +-PHONY += scripts_basic +-scripts_basic: ++PHONY += scripts_basic gcc-plugins ++scripts_basic: gcc-plugins + $(Q)$(MAKE) $(build)=scripts/basic + $(Q)rm -f .tmp_quiet_recordmcount + +@@ -615,6 +617,74 @@ endif + # Tell gcc to never replace conditional load with a non-conditional one + KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0) + ++ifndef DISABLE_PAX_PLUGINS ++ifeq ($(call cc-ifversion, -ge, 0408, y), y) ++PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(HOSTCXX)" "$(HOSTCXX)" "$(CC)") ++else ++PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(HOSTCC)" "$(HOSTCXX)" "$(CC)") ++endif ++ifneq ($(PLUGINCC),) ++ifdef CONFIG_PAX_CONSTIFY_PLUGIN ++CONSTIFY_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/constify_plugin.so -DCONSTIFY_PLUGIN ++endif ++ifdef CONFIG_PAX_MEMORY_STACKLEAK ++STACKLEAK_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/stackleak_plugin.so -DSTACKLEAK_PLUGIN ++STACKLEAK_PLUGIN_CFLAGS += -fplugin-arg-stackleak_plugin-track-lowest-sp=100 ++endif ++ifdef CONFIG_KALLOCSTAT_PLUGIN ++KALLOCSTAT_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/kallocstat_plugin.so ++endif ++ifdef CONFIG_PAX_KERNEXEC_PLUGIN ++KERNEXEC_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/kernexec_plugin.so ++KERNEXEC_PLUGIN_CFLAGS += -fplugin-arg-kernexec_plugin-method=$(CONFIG_PAX_KERNEXEC_PLUGIN_METHOD) -DKERNEXEC_PLUGIN ++KERNEXEC_PLUGIN_AFLAGS := -DKERNEXEC_PLUGIN ++endif ++ifdef CONFIG_GRKERNSEC_RANDSTRUCT ++RANDSTRUCT_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/randomize_layout_plugin.so -DRANDSTRUCT_PLUGIN ++ifdef CONFIG_GRKERNSEC_RANDSTRUCT_PERFORMANCE ++RANDSTRUCT_PLUGIN_CFLAGS += -fplugin-arg-randomize_layout_plugin-performance-mode ++endif ++endif ++ifdef CONFIG_CHECKER_PLUGIN ++ifeq ($(call cc-ifversion, -ge, 0406, y), y) ++CHECKER_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/checker_plugin.so -DCHECKER_PLUGIN ++endif ++endif ++COLORIZE_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/colorize_plugin.so ++ifdef CONFIG_PAX_SIZE_OVERFLOW ++SIZE_OVERFLOW_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/size_overflow_plugin/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 ++ifdef CONFIG_PAX_MEMORY_STRUCTLEAK ++STRUCTLEAK_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/structleak_plugin.so -DSTRUCTLEAK_PLUGIN ++endif ++INITIFY_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/initify_plugin.so -DINITIFY_PLUGIN ++GCC_PLUGINS_CFLAGS := $(CONSTIFY_PLUGIN_CFLAGS) $(STACKLEAK_PLUGIN_CFLAGS) $(KALLOCSTAT_PLUGIN_CFLAGS) ++GCC_PLUGINS_CFLAGS += $(KERNEXEC_PLUGIN_CFLAGS) $(CHECKER_PLUGIN_CFLAGS) $(COLORIZE_PLUGIN_CFLAGS) ++GCC_PLUGINS_CFLAGS += $(SIZE_OVERFLOW_PLUGIN_CFLAGS) $(LATENT_ENTROPY_PLUGIN_CFLAGS) $(STRUCTLEAK_PLUGIN_CFLAGS) ++GCC_PLUGINS_CFLAGS += $(INITIFY_PLUGIN_CFLAGS) ++GCC_PLUGINS_CFLAGS += $(RANDSTRUCT_PLUGIN_CFLAGS) ++GCC_PLUGINS_AFLAGS := $(KERNEXEC_PLUGIN_AFLAGS) ++export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGINS_AFLAGS CONSTIFY_PLUGIN LATENT_ENTROPY_PLUGIN_CFLAGS ++ifeq ($(KBUILD_EXTMOD),) ++gcc-plugins: ++ $(Q)$(MAKE) $(build)=tools/gcc ++else ++gcc-plugins: ; ++endif ++else ++gcc-plugins: ++ifeq ($(call cc-ifversion, -ge, 0405, y), y) ++ $(error Your gcc installation does not support plugins. If the necessary headers for plugin support are missing, they should be installed. On Debian, apt-get install gcc--plugin-dev. If you choose to ignore this error and lessen the improvements provided by this patch, re-run make with the DISABLE_PAX_PLUGINS=y argument.)) ++else ++ $(Q)echo "warning, your gcc version does not support plugins, you should upgrade it to gcc 4.5 at least" ++endif ++ $(Q)echo "PAX_MEMORY_STACKLEAK, constification, PAX_LATENT_ENTROPY and other features will be less secure. PAX_SIZE_OVERFLOW will not be active." ++endif ++endif ++ + ifdef CONFIG_READABLE_ASM + # Disable optimizations that make assembler listings hard to read. + # reorder blocks reorders the control in the function +@@ -714,7 +784,7 @@ KBUILD_CFLAGS += $(call cc-option, -gsplit-dwarf, -g) + else + KBUILD_CFLAGS += -g + endif +-KBUILD_AFLAGS += -Wa,-gdwarf-2 ++KBUILD_AFLAGS += -Wa,--gdwarf-2 + endif + ifdef CONFIG_DEBUG_INFO_DWARF4 + KBUILD_CFLAGS += $(call cc-option, -gdwarf-4,) +@@ -886,7 +956,7 @@ export mod_sign_cmd + + + ifeq ($(KBUILD_EXTMOD),) +-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ ++core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/ + + vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ + $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ +@@ -936,6 +1006,8 @@ endif + + # The actual objects are generated when descending, + # make sure no implicit rule kicks in ++$(filter-out $(init-y),$(vmlinux-deps)): KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++$(filter-out $(init-y),$(vmlinux-deps)): KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) + $(sort $(vmlinux-deps)): $(vmlinux-dirs) ; + + # Handle descending into subdirectories listed in $(vmlinux-dirs) +@@ -945,7 +1017,7 @@ $(sort $(vmlinux-deps)): $(vmlinux-dirs) ; + # Error messages still appears in the original language + + PHONY += $(vmlinux-dirs) +-$(vmlinux-dirs): prepare scripts ++$(vmlinux-dirs): gcc-plugins prepare scripts + $(Q)$(MAKE) $(build)=$@ + + define filechk_kernel.release +@@ -988,10 +1060,13 @@ prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ + + archprepare: archheaders archscripts prepare1 scripts_basic + ++prepare0: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++prepare0: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) + prepare0: archprepare FORCE + $(Q)$(MAKE) $(build)=. + + # All the preparing.. ++prepare: KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) + prepare: prepare0 + + # Generate some files +@@ -1099,6 +1174,8 @@ all: modules + # using awk while concatenating to the final file. + + PHONY += modules ++modules: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++modules: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) + 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.'; +@@ -1114,7 +1191,7 @@ modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) + + # Target to prepare building external modules + PHONY += modules_prepare +-modules_prepare: prepare scripts ++modules_prepare: gcc-plugins prepare scripts + + # Target to install modules + PHONY += modules_install +@@ -1180,7 +1257,10 @@ MRPROPER_FILES += .config .config.old .version .old_version \ + Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ + signing_key.priv signing_key.x509 x509.genkey \ + extra_certificates signing_key.x509.keyid \ +- signing_key.x509.signer vmlinux-gdb.py ++ signing_key.x509.signer vmlinux-gdb.py \ ++ tools/gcc/size_overflow_plugin/size_overflow_hash_aux.h \ ++ tools/gcc/size_overflow_plugin/size_overflow_hash.h \ ++ tools/gcc/randomize_layout_seed.h + + # clean - Delete most, but leave enough to build external modules + # +@@ -1219,7 +1299,7 @@ distclean: mrproper + @find $(srctree) $(RCS_FIND_IGNORE) \ + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ +- -o -name '.*.rej' -o -name '*%' -o -name 'core' \) \ ++ -o -name '.*.rej' -o -name '*.so' -o -name '*%' -o -name 'core' \) \ + -type f -print | xargs rm -f + + +@@ -1385,6 +1465,8 @@ PHONY += $(module-dirs) modules + $(module-dirs): crmodverdir $(objtree)/Module.symvers + $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) + ++modules: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++modules: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) + modules: $(module-dirs) + @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost +@@ -1525,17 +1607,21 @@ else + target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@)) + endif + +-%.s: %.c prepare scripts FORCE ++%.s: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++%.s: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) ++%.s: %.c gcc-plugins prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + %.i: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +-%.o: %.c prepare scripts FORCE ++%.o: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++%.o: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) ++%.o: %.c gcc-plugins prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + %.lst: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +-%.s: %.S prepare scripts FORCE ++%.s: %.S gcc-plugins prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +-%.o: %.S prepare scripts FORCE ++%.o: %.S gcc-plugins prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + %.symtypes: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +@@ -1547,11 +1633,15 @@ endif + $(build)=$(build-dir) + # Make sure the latest headers are built for Documentation + Documentation/: headers_install +-%/: prepare scripts FORCE ++%/: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++%/: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) ++%/: gcc-plugins prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +-%.ko: prepare scripts FORCE ++%.ko: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) ++%.ko: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) ++%.ko: gcc-plugins prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) $(@:.ko=.o) +diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h +index 8f8eafb..3405f46 100644 +--- a/arch/alpha/include/asm/atomic.h ++++ b/arch/alpha/include/asm/atomic.h +@@ -239,4 +239,14 @@ static inline long atomic64_dec_if_positive(atomic64_t *v) + #define atomic_dec(v) atomic_sub(1,(v)) + #define atomic64_dec(v) atomic64_sub(1,(v)) + ++#define atomic64_read_unchecked(v) atomic64_read(v) ++#define atomic64_set_unchecked(v, i) atomic64_set((v), (i)) ++#define atomic64_add_unchecked(a, v) atomic64_add((a), (v)) ++#define atomic64_add_return_unchecked(a, v) atomic64_add_return((a), (v)) ++#define atomic64_sub_unchecked(a, v) atomic64_sub((a), (v)) ++#define atomic64_inc_unchecked(v) atomic64_inc(v) ++#define atomic64_inc_return_unchecked(v) atomic64_inc_return(v) ++#define atomic64_dec_unchecked(v) atomic64_dec(v) ++#define atomic64_cmpxchg_unchecked(v, o, n) atomic64_cmpxchg((v), (o), (n)) ++ + #endif /* _ALPHA_ATOMIC_H */ +diff --git a/arch/alpha/include/asm/cache.h b/arch/alpha/include/asm/cache.h +index ad368a9..fbe0f25 100644 +--- a/arch/alpha/include/asm/cache.h ++++ b/arch/alpha/include/asm/cache.h +@@ -4,19 +4,19 @@ + #ifndef __ARCH_ALPHA_CACHE_H + #define __ARCH_ALPHA_CACHE_H + ++#include + + /* Bytes per L1 (data) cache line. */ + #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV6) +-# define L1_CACHE_BYTES 64 + # define L1_CACHE_SHIFT 6 + #else + /* Both EV4 and EV5 are write-through, read-allocate, + direct-mapped, physical. + */ +-# define L1_CACHE_BYTES 32 + # define L1_CACHE_SHIFT 5 + #endif + ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + #define SMP_CACHE_BYTES L1_CACHE_BYTES + + #endif +diff --git a/arch/alpha/include/asm/elf.h b/arch/alpha/include/asm/elf.h +index 968d999..d36b2df 100644 +--- a/arch/alpha/include/asm/elf.h ++++ b/arch/alpha/include/asm/elf.h +@@ -91,6 +91,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + + #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) + ++#ifdef CONFIG_PAX_ASLR ++#define PAX_ELF_ET_DYN_BASE (current->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL) ++ ++#define PAX_DELTA_MMAP_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 28) ++#define PAX_DELTA_STACK_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 19) ++#endif ++ + /* $0 is set by ld.so to a pointer to a function which might be + registered using atexit. This provides a mean for the dynamic + linker to call DT_FINI functions for shared libraries that have +diff --git a/arch/alpha/include/asm/pgalloc.h b/arch/alpha/include/asm/pgalloc.h +index aab14a0..b4fa3e7 100644 +--- a/arch/alpha/include/asm/pgalloc.h ++++ b/arch/alpha/include/asm/pgalloc.h +@@ -29,6 +29,12 @@ pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) + pgd_set(pgd, pmd); + } + ++static inline void ++pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) ++{ ++ pgd_populate(mm, pgd, pmd); ++} ++ + extern pgd_t *pgd_alloc(struct mm_struct *mm); + + static inline void +diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h +index a9a1195..e9b8417 100644 +--- a/arch/alpha/include/asm/pgtable.h ++++ b/arch/alpha/include/asm/pgtable.h +@@ -101,6 +101,17 @@ struct vm_area_struct; + #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) + #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) + #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE) ++# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) ++# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) ++#else ++# define PAGE_SHARED_NOEXEC PAGE_SHARED ++# define PAGE_COPY_NOEXEC PAGE_COPY ++# define PAGE_READONLY_NOEXEC PAGE_READONLY ++#endif ++ + #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) + + #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) +diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c +index 2fd00b7..cfd5069 100644 +--- a/arch/alpha/kernel/module.c ++++ b/arch/alpha/kernel/module.c +@@ -160,7 +160,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, + + /* The small sections were sorted to the end of the segment. + The following should definitely cover them. */ +- gp = (u64)me->module_core + me->core_size - 0x8000; ++ gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000; + got = sechdrs[me->arch.gotsecindex].sh_addr; + + for (i = 0; i < n; i++) { +diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c +index 36dc91a..6769cb0 100644 +--- a/arch/alpha/kernel/osf_sys.c ++++ b/arch/alpha/kernel/osf_sys.c +@@ -1295,10 +1295,11 @@ SYSCALL_DEFINE1(old_adjtimex, struct timex32 __user *, txc_p) + generic version except that we know how to honor ADDR_LIMIT_32BIT. */ + + static unsigned long +-arch_get_unmapped_area_1(unsigned long addr, unsigned long len, +- unsigned long limit) ++arch_get_unmapped_area_1(struct file *filp, unsigned long addr, unsigned long len, ++ unsigned long limit, unsigned long flags) + { + struct vm_unmapped_area_info info; ++ unsigned long offset = gr_rand_threadstack_offset(current->mm, filp, flags); + + info.flags = 0; + info.length = len; +@@ -1306,6 +1307,7 @@ arch_get_unmapped_area_1(unsigned long addr, unsigned long len, + info.high_limit = limit; + info.align_mask = 0; + info.align_offset = 0; ++ info.threadstack_offset = offset; + return vm_unmapped_area(&info); + } + +@@ -1338,20 +1340,24 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + merely specific addresses, but regions of memory -- perhaps + this feature should be incorporated into all ports? */ + ++#ifdef CONFIG_PAX_RANDMMAP ++ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) ++#endif ++ + if (addr) { +- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); ++ addr = arch_get_unmapped_area_1 (filp, PAGE_ALIGN(addr), len, limit, flags); + if (addr != (unsigned long) -ENOMEM) + return addr; + } + + /* Next, try allocating at TASK_UNMAPPED_BASE. */ +- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE), +- len, limit); ++ addr = arch_get_unmapped_area_1 (filp, PAGE_ALIGN(current->mm->mmap_base), len, limit, flags); ++ + if (addr != (unsigned long) -ENOMEM) + return addr; + + /* Finally, try allocating in low memory. */ +- addr = arch_get_unmapped_area_1 (PAGE_SIZE, len, limit); ++ addr = arch_get_unmapped_area_1 (filp, PAGE_SIZE, len, limit, flags); + + return addr; + } +diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c +index 4a905bd..0a4da53 100644 +--- a/arch/alpha/mm/fault.c ++++ b/arch/alpha/mm/fault.c +@@ -52,6 +52,124 @@ __load_new_mm_context(struct mm_struct *next_mm) + __reload_thread(pcb); + } + ++#ifdef CONFIG_PAX_PAGEEXEC ++/* ++ * PaX: decide what to do with offenders (regs->pc = fault address) ++ * ++ * returns 1 when task should be killed ++ * 2 when patched PLT trampoline was detected ++ * 3 when unpatched PLT trampoline was detected ++ */ ++static int pax_handle_fetch_fault(struct pt_regs *regs) ++{ ++ ++#ifdef CONFIG_PAX_EMUPLT ++ int err; ++ ++ do { /* PaX: patched PLT emulation #1 */ ++ unsigned int ldah, ldq, jmp; ++ ++ err = get_user(ldah, (unsigned int *)regs->pc); ++ err |= get_user(ldq, (unsigned int *)(regs->pc+4)); ++ err |= get_user(jmp, (unsigned int *)(regs->pc+8)); ++ ++ if (err) ++ break; ++ ++ if ((ldah & 0xFFFF0000U) == 0x277B0000U && ++ (ldq & 0xFFFF0000U) == 0xA77B0000U && ++ jmp == 0x6BFB0000U) ++ { ++ unsigned long r27, addr; ++ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; ++ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL; ++ ++ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); ++ err = get_user(r27, (unsigned long *)addr); ++ if (err) ++ break; ++ ++ regs->r27 = r27; ++ regs->pc = r27; ++ return 2; ++ } ++ } while (0); ++ ++ do { /* PaX: patched PLT emulation #2 */ ++ unsigned int ldah, lda, br; ++ ++ err = get_user(ldah, (unsigned int *)regs->pc); ++ err |= get_user(lda, (unsigned int *)(regs->pc+4)); ++ err |= get_user(br, (unsigned int *)(regs->pc+8)); ++ ++ if (err) ++ break; ++ ++ if ((ldah & 0xFFFF0000U) == 0x277B0000U && ++ (lda & 0xFFFF0000U) == 0xA77B0000U && ++ (br & 0xFFE00000U) == 0xC3E00000U) ++ { ++ unsigned long addr = br | 0xFFFFFFFFFFE00000UL; ++ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; ++ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL; ++ ++ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); ++ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); ++ return 2; ++ } ++ } while (0); ++ ++ do { /* PaX: unpatched PLT emulation */ ++ unsigned int br; ++ ++ err = get_user(br, (unsigned int *)regs->pc); ++ ++ if (!err && (br & 0xFFE00000U) == 0xC3800000U) { ++ unsigned int br2, ldq, nop, jmp; ++ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver; ++ ++ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); ++ err = get_user(br2, (unsigned int *)addr); ++ err |= get_user(ldq, (unsigned int *)(addr+4)); ++ err |= get_user(nop, (unsigned int *)(addr+8)); ++ err |= get_user(jmp, (unsigned int *)(addr+12)); ++ err |= get_user(resolver, (unsigned long *)(addr+16)); ++ ++ if (err) ++ break; ++ ++ if (br2 == 0xC3600000U && ++ ldq == 0xA77B000CU && ++ nop == 0x47FF041FU && ++ jmp == 0x6B7B0000U) ++ { ++ regs->r28 = regs->pc+4; ++ regs->r27 = addr+16; ++ regs->pc = resolver; ++ return 3; ++ } ++ } ++ } while (0); ++#endif ++ ++ return 1; ++} ++ ++void pax_report_insns(struct pt_regs *regs, void *pc, void *sp) ++{ ++ unsigned long i; ++ ++ printk(KERN_ERR "PAX: bytes at PC: "); ++ for (i = 0; i < 5; i++) { ++ unsigned int c; ++ if (get_user(c, (unsigned int *)pc+i)) ++ printk(KERN_CONT "???????? "); ++ else ++ printk(KERN_CONT "%08x ", c); ++ } ++ printk("\n"); ++} ++#endif + + /* + * This routine handles page faults. It determines the address, +@@ -132,8 +250,29 @@ retry: + good_area: + si_code = SEGV_ACCERR; + if (cause < 0) { +- if (!(vma->vm_flags & VM_EXEC)) ++ if (!(vma->vm_flags & VM_EXEC)) { ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc) ++ goto bad_area; ++ ++ up_read(&mm->mmap_sem); ++ switch (pax_handle_fetch_fault(regs)) { ++ ++#ifdef CONFIG_PAX_EMUPLT ++ case 2: ++ case 3: ++ return; ++#endif ++ ++ } ++ pax_report_fault(regs, (void *)regs->pc, (void *)rdusp()); ++ do_group_exit(SIGKILL); ++#else + goto bad_area; ++#endif ++ ++ } + } else if (!cause) { + /* Allow reads even for write-only mappings */ + if (!(vma->vm_flags & (VM_READ | VM_WRITE))) +diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig +index bd4670d..920c97a 100644 +--- a/arch/arc/Kconfig ++++ b/arch/arc/Kconfig +@@ -485,6 +485,7 @@ config ARC_DBG_TLB_MISS_COUNT + bool "Profile TLB Misses" + default n + select DEBUG_FS ++ depends on !GRKERNSEC_KMEM + help + Counts number of I and D TLB Misses and exports them via Debugfs + The counters can be cleared via Debugfs as well +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index ede2526..9e12300 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1770,7 +1770,7 @@ config ALIGNMENT_TRAP + + config UACCESS_WITH_MEMCPY + bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user()" +- depends on MMU ++ depends on MMU && !PAX_MEMORY_UDEREF + default y if CPU_FEROCEON + help + Implement faster copy_to_user and clear_user methods for CPU +@@ -2006,6 +2006,7 @@ config KEXEC + bool "Kexec system call (EXPERIMENTAL)" + depends on (!SMP || PM_SLEEP_SMP) + depends on !CPU_V7M ++ depends on !GRKERNSEC_KMEM + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot +diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug +index a2e16f9..b26e911 100644 +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -7,6 +7,7 @@ config ARM_PTDUMP + depends on DEBUG_KERNEL + depends on MMU + select DEBUG_FS ++ depends on !GRKERNSEC_KMEM + ---help--- + Say Y here if you want to show the kernel pagetable layout in a + debugfs file. This information is only useful for kernel developers +diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h +index e22c119..abe7041 100644 +--- a/arch/arm/include/asm/atomic.h ++++ b/arch/arm/include/asm/atomic.h +@@ -18,17 +18,41 @@ + #include + #include + ++#ifdef CONFIG_GENERIC_ATOMIC64 ++#include ++#endif ++ + #define ATOMIC_INIT(i) { (i) } + + #ifdef __KERNEL__ + ++#ifdef CONFIG_THUMB2_KERNEL ++#define REFCOUNT_TRAP_INSN "bkpt 0xf1" ++#else ++#define REFCOUNT_TRAP_INSN "bkpt 0xf103" ++#endif ++ ++#define _ASM_EXTABLE(from, to) \ ++" .pushsection __ex_table,\"a\"\n"\ ++" .align 3\n" \ ++" .long " #from ", " #to"\n" \ ++" .popsection" ++ + /* + * On ARM, ordinary assignment (str instruction) doesn't clear the local + * strex/ldrex monitor on some implementations. The reason we can use it for + * atomic_set() is the clrex or dummy strex done on every exception return. + */ + #define atomic_read(v) ACCESS_ONCE((v)->counter) ++static inline int atomic_read_unchecked(const atomic_unchecked_t *v) ++{ ++ return ACCESS_ONCE(v->counter); ++} + #define atomic_set(v,i) (((v)->counter) = (i)) ++static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i) ++{ ++ v->counter = i; ++} + + #if __LINUX_ARM_ARCH__ >= 6 + +@@ -38,26 +62,50 @@ + * to ensure that the update happens. + */ + +-#define ATOMIC_OP(op, c_op, asm_op) \ +-static inline void atomic_##op(int i, atomic_t *v) \ ++#ifdef CONFIG_PAX_REFCOUNT ++#define __OVERFLOW_POST \ ++ " bvc 3f\n" \ ++ "2: " REFCOUNT_TRAP_INSN "\n"\ ++ "3:\n" ++#define __OVERFLOW_POST_RETURN \ ++ " bvc 3f\n" \ ++" mov %0, %1\n" \ ++ "2: " REFCOUNT_TRAP_INSN "\n"\ ++ "3:\n" ++#define __OVERFLOW_EXTABLE \ ++ "4:\n" \ ++ _ASM_EXTABLE(2b, 4b) ++#else ++#define __OVERFLOW_POST ++#define __OVERFLOW_POST_RETURN ++#define __OVERFLOW_EXTABLE ++#endif ++ ++#define __ATOMIC_OP(op, suffix, c_op, asm_op, post_op, extable) \ ++static inline void atomic_##op##suffix(int i, atomic##suffix##_t *v) \ + { \ + unsigned long tmp; \ + int result; \ + \ + prefetchw(&v->counter); \ +- __asm__ __volatile__("@ atomic_" #op "\n" \ ++ __asm__ __volatile__("@ atomic_" #op #suffix "\n" \ + "1: ldrex %0, [%3]\n" \ + " " #asm_op " %0, %0, %4\n" \ ++ post_op \ + " strex %1, %0, [%3]\n" \ + " teq %1, #0\n" \ +-" bne 1b" \ ++" bne 1b\n" \ ++ extable \ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) \ + : "r" (&v->counter), "Ir" (i) \ + : "cc"); \ + } \ + +-#define ATOMIC_OP_RETURN(op, c_op, asm_op) \ +-static inline int atomic_##op##_return(int i, atomic_t *v) \ ++#define ATOMIC_OP(op, c_op, asm_op) __ATOMIC_OP(op, _unchecked, c_op, asm_op, , )\ ++ __ATOMIC_OP(op, , c_op, asm_op##s, __OVERFLOW_POST, __OVERFLOW_EXTABLE) ++ ++#define __ATOMIC_OP_RETURN(op, suffix, c_op, asm_op, post_op, extable) \ ++static inline int atomic_##op##_return##suffix(int i, atomic##suffix##_t *v)\ + { \ + unsigned long tmp; \ + int result; \ +@@ -65,12 +113,14 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ + smp_mb(); \ + prefetchw(&v->counter); \ + \ +- __asm__ __volatile__("@ atomic_" #op "_return\n" \ ++ __asm__ __volatile__("@ atomic_" #op "_return" #suffix "\n" \ + "1: ldrex %0, [%3]\n" \ + " " #asm_op " %0, %0, %4\n" \ ++ post_op \ + " strex %1, %0, [%3]\n" \ + " teq %1, #0\n" \ +-" bne 1b" \ ++" bne 1b\n" \ ++ extable \ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) \ + : "r" (&v->counter), "Ir" (i) \ + : "cc"); \ +@@ -80,6 +130,9 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ + return result; \ + } + ++#define ATOMIC_OP_RETURN(op, c_op, asm_op) __ATOMIC_OP_RETURN(op, _unchecked, c_op, asm_op, , )\ ++ __ATOMIC_OP_RETURN(op, , c_op, asm_op##s, __OVERFLOW_POST_RETURN, __OVERFLOW_EXTABLE) ++ + static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) + { + int oldval; +@@ -115,12 +168,24 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) + __asm__ __volatile__ ("@ atomic_add_unless\n" + "1: ldrex %0, [%4]\n" + " teq %0, %5\n" +-" beq 2f\n" +-" add %1, %0, %6\n" ++" beq 4f\n" ++" adds %1, %0, %6\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++"2: " REFCOUNT_TRAP_INSN "\n" ++"3:\n" ++#endif ++ + " strex %2, %1, [%4]\n" + " teq %2, #0\n" + " bne 1b\n" +-"2:" ++"4:" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ + : "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter) + : "r" (&v->counter), "r" (u), "r" (a) + : "cc"); +@@ -131,14 +196,36 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) + return oldval; + } + ++static inline int atomic_cmpxchg_unchecked(atomic_unchecked_t *ptr, int old, int new) ++{ ++ unsigned long oldval, res; ++ ++ smp_mb(); ++ ++ do { ++ __asm__ __volatile__("@ atomic_cmpxchg_unchecked\n" ++ "ldrex %1, [%3]\n" ++ "mov %0, #0\n" ++ "teq %1, %4\n" ++ "strexeq %0, %5, [%3]\n" ++ : "=&r" (res), "=&r" (oldval), "+Qo" (ptr->counter) ++ : "r" (&ptr->counter), "Ir" (old), "r" (new) ++ : "cc"); ++ } while (res); ++ ++ smp_mb(); ++ ++ return oldval; ++} ++ + #else /* ARM_ARCH_6 */ + + #ifdef CONFIG_SMP + #error SMP not supported on pre-ARMv6 CPUs + #endif + +-#define ATOMIC_OP(op, c_op, asm_op) \ +-static inline void atomic_##op(int i, atomic_t *v) \ ++#define __ATOMIC_OP(op, suffix, c_op, asm_op) \ ++static inline void atomic_##op##suffix(int i, atomic##suffix##_t *v) \ + { \ + unsigned long flags; \ + \ +@@ -147,8 +234,11 @@ static inline void atomic_##op(int i, atomic_t *v) \ + raw_local_irq_restore(flags); \ + } \ + +-#define ATOMIC_OP_RETURN(op, c_op, asm_op) \ +-static inline int atomic_##op##_return(int i, atomic_t *v) \ ++#define ATOMIC_OP(op, c_op, asm_op) __ATOMIC_OP(op, , c_op, asm_op) \ ++ __ATOMIC_OP(op, _unchecked, c_op, asm_op) ++ ++#define __ATOMIC_OP_RETURN(op, suffix, c_op, asm_op) \ ++static inline int atomic_##op##_return##suffix(int i, atomic##suffix##_t *v)\ + { \ + unsigned long flags; \ + int val; \ +@@ -161,6 +251,9 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ + return val; \ + } + ++#define ATOMIC_OP_RETURN(op, c_op, asm_op) __ATOMIC_OP_RETURN(op, , c_op, asm_op)\ ++ __ATOMIC_OP_RETURN(op, _unchecked, c_op, asm_op) ++ + static inline int atomic_cmpxchg(atomic_t *v, int old, int new) + { + int ret; +@@ -175,6 +268,11 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new) + return ret; + } + ++static inline int atomic_cmpxchg_unchecked(atomic_unchecked_t *v, int old, int new) ++{ ++ return atomic_cmpxchg((atomic_t *)v, old, new); ++} ++ + static inline int __atomic_add_unless(atomic_t *v, int a, int u) + { + int c, old; +@@ -196,16 +294,38 @@ ATOMIC_OPS(sub, -=, sub) + + #undef ATOMIC_OPS + #undef ATOMIC_OP_RETURN ++#undef __ATOMIC_OP_RETURN + #undef ATOMIC_OP ++#undef __ATOMIC_OP + + #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) ++static inline int atomic_xchg_unchecked(atomic_unchecked_t *v, int new) ++{ ++ return xchg(&v->counter, new); ++} + + #define atomic_inc(v) atomic_add(1, v) ++static inline void atomic_inc_unchecked(atomic_unchecked_t *v) ++{ ++ atomic_add_unchecked(1, v); ++} + #define atomic_dec(v) atomic_sub(1, v) ++static inline void atomic_dec_unchecked(atomic_unchecked_t *v) ++{ ++ atomic_sub_unchecked(1, v); ++} + + #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) ++static inline int atomic_inc_and_test_unchecked(atomic_unchecked_t *v) ++{ ++ return atomic_add_return_unchecked(1, v) == 0; ++} + #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) + #define atomic_inc_return(v) (atomic_add_return(1, v)) ++static inline int atomic_inc_return_unchecked(atomic_unchecked_t *v) ++{ ++ return atomic_add_return_unchecked(1, v); ++} + #define atomic_dec_return(v) (atomic_sub_return(1, v)) + #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) + +@@ -216,6 +336,14 @@ typedef struct { + long long counter; + } atomic64_t; + ++#ifdef CONFIG_PAX_REFCOUNT ++typedef struct { ++ long long counter; ++} atomic64_unchecked_t; ++#else ++typedef atomic64_t atomic64_unchecked_t; ++#endif ++ + #define ATOMIC64_INIT(i) { (i) } + + #ifdef CONFIG_ARM_LPAE +@@ -232,6 +360,19 @@ static inline long long atomic64_read(const atomic64_t *v) + return result; + } + ++static inline long long atomic64_read_unchecked(const atomic64_unchecked_t *v) ++{ ++ long long result; ++ ++ __asm__ __volatile__("@ atomic64_read_unchecked\n" ++" ldrd %0, %H0, [%1]" ++ : "=&r" (result) ++ : "r" (&v->counter), "Qo" (v->counter) ++ ); ++ ++ return result; ++} ++ + static inline void atomic64_set(atomic64_t *v, long long i) + { + __asm__ __volatile__("@ atomic64_set\n" +@@ -240,6 +381,15 @@ static inline void atomic64_set(atomic64_t *v, long long i) + : "r" (&v->counter), "r" (i) + ); + } ++ ++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long long i) ++{ ++ __asm__ __volatile__("@ atomic64_set_unchecked\n" ++" strd %2, %H2, [%1]" ++ : "=Qo" (v->counter) ++ : "r" (&v->counter), "r" (i) ++ ); ++} + #else + static inline long long atomic64_read(const atomic64_t *v) + { +@@ -254,6 +404,19 @@ static inline long long atomic64_read(const atomic64_t *v) + return result; + } + ++static inline long long atomic64_read_unchecked(const atomic64_unchecked_t *v) ++{ ++ long long result; ++ ++ __asm__ __volatile__("@ atomic64_read_unchecked\n" ++" ldrexd %0, %H0, [%1]" ++ : "=&r" (result) ++ : "r" (&v->counter), "Qo" (v->counter) ++ ); ++ ++ return result; ++} ++ + static inline void atomic64_set(atomic64_t *v, long long i) + { + long long tmp; +@@ -268,29 +431,57 @@ static inline void atomic64_set(atomic64_t *v, long long i) + : "r" (&v->counter), "r" (i) + : "cc"); + } ++ ++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long long i) ++{ ++ long long tmp; ++ ++ prefetchw(&v->counter); ++ __asm__ __volatile__("@ atomic64_set_unchecked\n" ++"1: ldrexd %0, %H0, [%2]\n" ++" strexd %0, %3, %H3, [%2]\n" ++" teq %0, #0\n" ++" bne 1b" ++ : "=&r" (tmp), "=Qo" (v->counter) ++ : "r" (&v->counter), "r" (i) ++ : "cc"); ++} + #endif + +-#define ATOMIC64_OP(op, op1, op2) \ +-static inline void atomic64_##op(long long i, atomic64_t *v) \ ++#undef __OVERFLOW_POST_RETURN ++#define __OVERFLOW_POST_RETURN \ ++ " bvc 3f\n" \ ++" mov %0, %1\n" \ ++" mov %H0, %H1\n" \ ++ "2: " REFCOUNT_TRAP_INSN "\n"\ ++ "3:\n" ++ ++#define __ATOMIC64_OP(op, suffix, op1, op2, post_op, extable) \ ++static inline void atomic64_##op##suffix(long long i, atomic64##suffix##_t *v)\ + { \ + long long result; \ + unsigned long tmp; \ + \ + prefetchw(&v->counter); \ +- __asm__ __volatile__("@ atomic64_" #op "\n" \ ++ __asm__ __volatile__("@ atomic64_" #op #suffix "\n" \ + "1: ldrexd %0, %H0, [%3]\n" \ + " " #op1 " %Q0, %Q0, %Q4\n" \ + " " #op2 " %R0, %R0, %R4\n" \ ++ post_op \ + " strexd %1, %0, %H0, [%3]\n" \ + " teq %1, #0\n" \ +-" bne 1b" \ ++" bne 1b\n" \ ++ extable \ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) \ + : "r" (&v->counter), "r" (i) \ + : "cc"); \ + } \ + +-#define ATOMIC64_OP_RETURN(op, op1, op2) \ +-static inline long long atomic64_##op##_return(long long i, atomic64_t *v) \ ++#define ATOMIC64_OP(op, op1, op2) __ATOMIC64_OP(op, _unchecked, op1, op2, , ) \ ++ __ATOMIC64_OP(op, , op1, op2##s, __OVERFLOW_POST, __OVERFLOW_EXTABLE) ++ ++#define __ATOMIC64_OP_RETURN(op, suffix, op1, op2, post_op, extable) \ ++static inline long long atomic64_##op##_return##suffix(long long i, atomic64##suffix##_t *v) \ + { \ + long long result; \ + unsigned long tmp; \ +@@ -298,13 +489,15 @@ static inline long long atomic64_##op##_return(long long i, atomic64_t *v) \ + smp_mb(); \ + prefetchw(&v->counter); \ + \ +- __asm__ __volatile__("@ atomic64_" #op "_return\n" \ ++ __asm__ __volatile__("@ atomic64_" #op "_return" #suffix "\n" \ + "1: ldrexd %0, %H0, [%3]\n" \ + " " #op1 " %Q0, %Q0, %Q4\n" \ + " " #op2 " %R0, %R0, %R4\n" \ ++ post_op \ + " strexd %1, %0, %H0, [%3]\n" \ + " teq %1, #0\n" \ +-" bne 1b" \ ++" bne 1b\n" \ ++ extable \ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) \ + : "r" (&v->counter), "r" (i) \ + : "cc"); \ +@@ -314,6 +507,9 @@ static inline long long atomic64_##op##_return(long long i, atomic64_t *v) \ + return result; \ + } + ++#define ATOMIC64_OP_RETURN(op, op1, op2) __ATOMIC64_OP_RETURN(op, _unchecked, op1, op2, , ) \ ++ __ATOMIC64_OP_RETURN(op, , op1, op2##s, __OVERFLOW_POST_RETURN, __OVERFLOW_EXTABLE) ++ + #define ATOMIC64_OPS(op, op1, op2) \ + ATOMIC64_OP(op, op1, op2) \ + ATOMIC64_OP_RETURN(op, op1, op2) +@@ -323,7 +519,12 @@ ATOMIC64_OPS(sub, subs, sbc) + + #undef ATOMIC64_OPS + #undef ATOMIC64_OP_RETURN ++#undef __ATOMIC64_OP_RETURN + #undef ATOMIC64_OP ++#undef __ATOMIC64_OP ++#undef __OVERFLOW_EXTABLE ++#undef __OVERFLOW_POST_RETURN ++#undef __OVERFLOW_POST + + static inline long long atomic64_cmpxchg(atomic64_t *ptr, long long old, + long long new) +@@ -351,6 +552,31 @@ static inline long long atomic64_cmpxchg(atomic64_t *ptr, long long old, + return oldval; + } + ++static inline long long atomic64_cmpxchg_unchecked(atomic64_unchecked_t *ptr, long long old, ++ long long new) ++{ ++ long long oldval; ++ unsigned long res; ++ ++ smp_mb(); ++ ++ do { ++ __asm__ __volatile__("@ atomic64_cmpxchg_unchecked\n" ++ "ldrexd %1, %H1, [%3]\n" ++ "mov %0, #0\n" ++ "teq %1, %4\n" ++ "teqeq %H1, %H4\n" ++ "strexdeq %0, %5, %H5, [%3]" ++ : "=&r" (res), "=&r" (oldval), "+Qo" (ptr->counter) ++ : "r" (&ptr->counter), "r" (old), "r" (new) ++ : "cc"); ++ } while (res); ++ ++ smp_mb(); ++ ++ return oldval; ++} ++ + static inline long long atomic64_xchg(atomic64_t *ptr, long long new) + { + long long result; +@@ -376,21 +602,35 @@ static inline long long atomic64_xchg(atomic64_t *ptr, long long new) + static inline long long atomic64_dec_if_positive(atomic64_t *v) + { + long long result; +- unsigned long tmp; ++ u64 tmp; + + smp_mb(); + prefetchw(&v->counter); + + __asm__ __volatile__("@ atomic64_dec_if_positive\n" +-"1: ldrexd %0, %H0, [%3]\n" +-" subs %Q0, %Q0, #1\n" +-" sbc %R0, %R0, #0\n" ++"1: ldrexd %1, %H1, [%3]\n" ++" subs %Q0, %Q1, #1\n" ++" sbcs %R0, %R1, #0\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++" mov %Q0, %Q1\n" ++" mov %R0, %R1\n" ++"2: " REFCOUNT_TRAP_INSN "\n" ++"3:\n" ++#endif ++ + " teq %R0, #0\n" +-" bmi 2f\n" ++" bmi 4f\n" + " strexd %1, %0, %H0, [%3]\n" + " teq %1, #0\n" + " bne 1b\n" +-"2:" ++"4:\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) + : "r" (&v->counter) + : "cc"); +@@ -414,13 +654,25 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) + " teq %0, %5\n" + " teqeq %H0, %H5\n" + " moveq %1, #0\n" +-" beq 2f\n" ++" beq 4f\n" + " adds %Q0, %Q0, %Q6\n" +-" adc %R0, %R0, %R6\n" ++" adcs %R0, %R0, %R6\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++"2: " REFCOUNT_TRAP_INSN "\n" ++"3:\n" ++#endif ++ + " strexd %2, %0, %H0, [%4]\n" + " teq %2, #0\n" + " bne 1b\n" +-"2:" ++"4:\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ + : "=&r" (val), "+r" (ret), "=&r" (tmp), "+Qo" (v->counter) + : "r" (&v->counter), "r" (u), "r" (a) + : "cc"); +@@ -433,10 +685,13 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) + + #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) + #define atomic64_inc(v) atomic64_add(1LL, (v)) ++#define atomic64_inc_unchecked(v) atomic64_add_unchecked(1LL, (v)) + #define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) ++#define atomic64_inc_return_unchecked(v) atomic64_add_return_unchecked(1LL, (v)) + #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) + #define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) + #define atomic64_dec(v) atomic64_sub(1LL, (v)) ++#define atomic64_dec_unchecked(v) atomic64_sub_unchecked(1LL, (v)) + #define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) + #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) + #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) +diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h +index 6c2327e..85beac4 100644 +--- a/arch/arm/include/asm/barrier.h ++++ b/arch/arm/include/asm/barrier.h +@@ -67,7 +67,7 @@ + do { \ + compiletime_assert_atomic_type(*p); \ + smp_mb(); \ +- ACCESS_ONCE(*p) = (v); \ ++ ACCESS_ONCE_RW(*p) = (v); \ + } while (0) + + #define smp_load_acquire(p) \ +diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h +index 75fe66b..ba3dee4 100644 +--- a/arch/arm/include/asm/cache.h ++++ b/arch/arm/include/asm/cache.h +@@ -4,8 +4,10 @@ + #ifndef __ASMARM_CACHE_H + #define __ASMARM_CACHE_H + ++#include ++ + #define L1_CACHE_SHIFT CONFIG_ARM_L1_CACHE_SHIFT +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + /* + * Memory returned by kmalloc() may be used for DMA, so we must make +@@ -24,5 +26,6 @@ + #endif + + #define __read_mostly __attribute__((__section__(".data..read_mostly"))) ++#define __read_only __attribute__ ((__section__(".data..read_only"))) + + #endif +diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h +index 4812cda..9da8116 100644 +--- a/arch/arm/include/asm/cacheflush.h ++++ b/arch/arm/include/asm/cacheflush.h +@@ -116,7 +116,7 @@ struct cpu_cache_fns { + void (*dma_unmap_area)(const void *, size_t, int); + + void (*dma_flush_range)(const void *, const void *); +-}; ++} __no_const; + + /* + * Select the calling method +diff --git a/arch/arm/include/asm/checksum.h b/arch/arm/include/asm/checksum.h +index 5233151..87a71fa 100644 +--- a/arch/arm/include/asm/checksum.h ++++ b/arch/arm/include/asm/checksum.h +@@ -37,7 +37,19 @@ __wsum + csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); + + __wsum +-csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr); ++__csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr); ++ ++static inline __wsum ++csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) ++{ ++ __wsum ret; ++ pax_open_userland(); ++ ret = __csum_partial_copy_from_user(src, dst, len, sum, err_ptr); ++ pax_close_userland(); ++ return ret; ++} ++ ++ + + /* + * Fold a partial checksum without adding pseudo headers +diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h +index 1692a05..1835802 100644 +--- a/arch/arm/include/asm/cmpxchg.h ++++ b/arch/arm/include/asm/cmpxchg.h +@@ -107,6 +107,10 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size + (__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), \ + sizeof(*(ptr))); \ + }) ++#define xchg_unchecked(ptr, x) ({ \ ++ (__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), \ ++ sizeof(*(ptr))); \ ++}) + + #include + +diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h +index 0f84249..8e83c55 100644 +--- a/arch/arm/include/asm/cpuidle.h ++++ b/arch/arm/include/asm/cpuidle.h +@@ -32,7 +32,7 @@ struct device_node; + struct cpuidle_ops { + int (*suspend)(int cpu, unsigned long arg); + int (*init)(struct device_node *, int cpu); +-}; ++} __no_const; + + struct of_cpuidle_method { + const char *method; +diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h +index 6ddbe44..b5e38b1a 100644 +--- a/arch/arm/include/asm/domain.h ++++ b/arch/arm/include/asm/domain.h +@@ -48,18 +48,37 @@ + * Domain types + */ + #define DOMAIN_NOACCESS 0 +-#define DOMAIN_CLIENT 1 + #ifdef CONFIG_CPU_USE_DOMAINS ++#define DOMAIN_USERCLIENT 1 ++#define DOMAIN_KERNELCLIENT 1 + #define DOMAIN_MANAGER 3 ++#define DOMAIN_VECTORS DOMAIN_USER + #else ++ ++#ifdef CONFIG_PAX_KERNEXEC + #define DOMAIN_MANAGER 1 ++#define DOMAIN_KERNEXEC 3 ++#else ++#define DOMAIN_MANAGER 1 ++#endif ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++#define DOMAIN_USERCLIENT 0 ++#define DOMAIN_UDEREF 1 ++#define DOMAIN_VECTORS DOMAIN_KERNEL ++#else ++#define DOMAIN_USERCLIENT 1 ++#define DOMAIN_VECTORS DOMAIN_USER ++#endif ++#define DOMAIN_KERNELCLIENT 1 ++ + #endif + + #define domain_val(dom,type) ((type) << (2*(dom))) + + #ifndef __ASSEMBLY__ + +-#ifdef CONFIG_CPU_USE_DOMAINS ++#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + static inline void set_domain(unsigned val) + { + asm volatile( +@@ -68,15 +87,7 @@ static inline void set_domain(unsigned val) + isb(); + } + +-#define modify_domain(dom,type) \ +- do { \ +- struct thread_info *thread = current_thread_info(); \ +- unsigned int domain = thread->cpu_domain; \ +- domain &= ~domain_val(dom, DOMAIN_MANAGER); \ +- thread->cpu_domain = domain | domain_val(dom, type); \ +- set_domain(thread->cpu_domain); \ +- } while (0) +- ++extern void modify_domain(unsigned int dom, unsigned int type); + #else + static inline void set_domain(unsigned val) { } + static inline void modify_domain(unsigned dom, unsigned type) { } +diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h +index d2315ff..f60b47b 100644 +--- a/arch/arm/include/asm/elf.h ++++ b/arch/arm/include/asm/elf.h +@@ -117,7 +117,14 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +-#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) ++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) ++ ++#ifdef CONFIG_PAX_ASLR ++#define PAX_ELF_ET_DYN_BASE 0x00008000UL ++ ++#define PAX_DELTA_MMAP_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10) ++#define PAX_DELTA_STACK_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10) ++#endif + + /* When the program starts, a1 contains a pointer to a function to be + registered with atexit, as per the SVR4 ABI. A value of 0 means we +diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h +index de53547..52b9a28 100644 +--- a/arch/arm/include/asm/fncpy.h ++++ b/arch/arm/include/asm/fncpy.h +@@ -81,7 +81,9 @@ + BUG_ON((uintptr_t)(dest_buf) & (FNCPY_ALIGN - 1) || \ + (__funcp_address & ~(uintptr_t)1 & (FNCPY_ALIGN - 1))); \ + \ ++ pax_open_kernel(); \ + memcpy(dest_buf, (void const *)(__funcp_address & ~1), size); \ ++ pax_close_kernel(); \ + flush_icache_range((unsigned long)(dest_buf), \ + (unsigned long)(dest_buf) + (size)); \ + \ +diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h +index 5eed828..365e018 100644 +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -46,6 +46,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + ++ pax_open_userland(); ++ + smp_mb(); + /* Prefetching cannot fault */ + prefetchw(uaddr); +@@ -63,6 +65,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + : "cc", "memory"); + smp_mb(); + ++ pax_close_userland(); ++ + *uval = val; + return ret; + } +@@ -94,6 +98,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + return -EFAULT; + + preempt_disable(); ++ pax_open_userland(); ++ + __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" + "1: " TUSER(ldr) " %1, [%4]\n" + " teq %1, %2\n" +@@ -104,6 +110,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT) + : "cc", "memory"); + ++ pax_close_userland(); ++ + *uval = val; + preempt_enable(); + +@@ -131,6 +139,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + preempt_disable(); + #endif + pagefault_disable(); ++ pax_open_userland(); + + switch (op) { + case FUTEX_OP_SET: +@@ -152,6 +161,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + ret = -ENOSYS; + } + ++ pax_close_userland(); + pagefault_enable(); + #ifndef CONFIG_SMP + preempt_enable(); +diff --git a/arch/arm/include/asm/kmap_types.h b/arch/arm/include/asm/kmap_types.h +index 83eb2f7..ed77159 100644 +--- a/arch/arm/include/asm/kmap_types.h ++++ b/arch/arm/include/asm/kmap_types.h +@@ -4,6 +4,6 @@ + /* + * This is the "bare minimum". AIO seems to require this. + */ +-#define KM_TYPE_NR 16 ++#define KM_TYPE_NR 17 + + #endif +diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h +index 9e614a1..3302cca 100644 +--- a/arch/arm/include/asm/mach/dma.h ++++ b/arch/arm/include/asm/mach/dma.h +@@ -22,7 +22,7 @@ struct dma_ops { + int (*residue)(unsigned int, dma_t *); /* optional */ + int (*setspeed)(unsigned int, dma_t *, int); /* optional */ + const char *type; +-}; ++} __do_const; + + struct dma_struct { + void *addr; /* single DMA address */ +diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h +index f98c7f3..e5c626d 100644 +--- a/arch/arm/include/asm/mach/map.h ++++ b/arch/arm/include/asm/mach/map.h +@@ -23,17 +23,19 @@ struct map_desc { + + /* types 0-3 are defined in asm/io.h */ + enum { +- MT_UNCACHED = 4, +- MT_CACHECLEAN, +- MT_MINICLEAN, ++ MT_UNCACHED_RW = 4, ++ MT_CACHECLEAN_RO, ++ MT_MINICLEAN_RO, + MT_LOW_VECTORS, + MT_HIGH_VECTORS, +- MT_MEMORY_RWX, ++ __MT_MEMORY_RWX, + MT_MEMORY_RW, +- MT_ROM, +- MT_MEMORY_RWX_NONCACHED, ++ MT_MEMORY_RX, ++ MT_ROM_RX, ++ MT_MEMORY_RW_NONCACHED, ++ MT_MEMORY_RX_NONCACHED, + MT_MEMORY_RW_DTCM, +- MT_MEMORY_RWX_ITCM, ++ MT_MEMORY_RX_ITCM, + MT_MEMORY_RW_SO, + MT_MEMORY_DMA_READY, + }; +diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h +index 563b92f..689d58e 100644 +--- a/arch/arm/include/asm/outercache.h ++++ b/arch/arm/include/asm/outercache.h +@@ -39,7 +39,7 @@ struct outer_cache_fns { + /* This is an ARM L2C thing */ + void (*write_sec)(unsigned long, unsigned); + void (*configure)(const struct l2x0_regs *); +-}; ++} __no_const; + + extern struct outer_cache_fns outer_cache; + +diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h +index 4355f0e..cd9168e 100644 +--- a/arch/arm/include/asm/page.h ++++ b/arch/arm/include/asm/page.h +@@ -23,6 +23,7 @@ + + #else + ++#include + #include + + /* +@@ -114,7 +115,7 @@ struct cpu_user_fns { + void (*cpu_clear_user_highpage)(struct page *page, unsigned long vaddr); + void (*cpu_copy_user_highpage)(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +-}; ++} __no_const; + + #ifdef MULTI_USER + extern struct cpu_user_fns cpu_user; +diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h +index 19cfab5..3f5c7e9 100644 +--- a/arch/arm/include/asm/pgalloc.h ++++ b/arch/arm/include/asm/pgalloc.h +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #define check_pgt_cache() do { } while (0) + +@@ -43,6 +44,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) + set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); + } + ++static inline void pud_populate_kernel(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) ++{ ++ pud_populate(mm, pud, pmd); ++} ++ + #else /* !CONFIG_ARM_LPAE */ + + /* +@@ -51,6 +57,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) + #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); }) + #define pmd_free(mm, pmd) do { } while (0) + #define pud_populate(mm,pmd,pte) BUG() ++#define pud_populate_kernel(mm,pmd,pte) BUG() + + #endif /* CONFIG_ARM_LPAE */ + +@@ -128,6 +135,19 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte) + __free_page(pte); + } + ++static inline void __section_update(pmd_t *pmdp, unsigned long addr, pmdval_t prot) ++{ ++#ifdef CONFIG_ARM_LPAE ++ pmdp[0] = __pmd(pmd_val(pmdp[0]) | prot); ++#else ++ if (addr & SECTION_SIZE) ++ pmdp[1] = __pmd(pmd_val(pmdp[1]) | prot); ++ else ++ pmdp[0] = __pmd(pmd_val(pmdp[0]) | prot); ++#endif ++ flush_pmd_entry(pmdp); ++} ++ + static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, + pmdval_t prot) + { +diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h +index 5e68278..1869bae 100644 +--- a/arch/arm/include/asm/pgtable-2level-hwdef.h ++++ b/arch/arm/include/asm/pgtable-2level-hwdef.h +@@ -27,7 +27,7 @@ + /* + * - section + */ +-#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */ ++#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */ + #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) + #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) + #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ +@@ -39,6 +39,7 @@ + #define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */ + #define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */ + #define PMD_SECT_AF (_AT(pmdval_t, 0)) ++#define PMD_SECT_RDONLY (_AT(pmdval_t, 0)) + + #define PMD_SECT_UNCACHED (_AT(pmdval_t, 0)) + #define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE) +@@ -68,6 +69,7 @@ + * - extended small page/tiny page + */ + #define PTE_EXT_XN (_AT(pteval_t, 1) << 0) /* v6 */ ++#define PTE_EXT_PXN (_AT(pteval_t, 1) << 2) /* v7 */ + #define PTE_EXT_AP_MASK (_AT(pteval_t, 3) << 4) + #define PTE_EXT_AP0 (_AT(pteval_t, 1) << 4) + #define PTE_EXT_AP1 (_AT(pteval_t, 2) << 4) +diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h +index aeddd28..207745c 100644 +--- a/arch/arm/include/asm/pgtable-2level.h ++++ b/arch/arm/include/asm/pgtable-2level.h +@@ -127,6 +127,9 @@ + #define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ + #define L_PTE_NONE (_AT(pteval_t, 1) << 11) + ++/* Two-level page tables only have PXN in the PGD, not in the PTE. */ ++#define L_PTE_PXN (_AT(pteval_t, 0)) ++ + /* + * These are the memory types, defined to be compatible with + * pre-ARMv6 CPUs cacheable and bufferable bits: n/a,n/a,C,B +diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h +index a745a2a..481350a 100644 +--- a/arch/arm/include/asm/pgtable-3level.h ++++ b/arch/arm/include/asm/pgtable-3level.h +@@ -80,6 +80,7 @@ + #define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ + #define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ + #define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ ++#define L_PTE_PXN (_AT(pteval_t, 1) << 53) /* PXN */ + #define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ + #define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) + #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) +@@ -91,10 +92,12 @@ + #define L_PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) + #define L_PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) + #define L_PMD_SECT_RDONLY (_AT(pteval_t, 1) << 58) ++#define PMD_SECT_RDONLY PMD_SECT_AP2 + + /* + * To be used in assembly code with the upper page attributes. + */ ++#define L_PTE_PXN_HIGH (1 << (53 - 32)) + #define L_PTE_XN_HIGH (1 << (54 - 32)) + #define L_PTE_DIRTY_HIGH (1 << (55 - 32)) + +diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h +index f403541..b10df68 100644 +--- a/arch/arm/include/asm/pgtable.h ++++ b/arch/arm/include/asm/pgtable.h +@@ -33,6 +33,9 @@ + #include + #endif + ++#define ktla_ktva(addr) (addr) ++#define ktva_ktla(addr) (addr) ++ + /* + * Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the +@@ -48,6 +51,9 @@ + #define LIBRARY_TEXT_START 0x0c000000 + + #ifndef __ASSEMBLY__ ++extern pteval_t __supported_pte_mask; ++extern pmdval_t __supported_pmd_mask; ++ + extern void __pte_error(const char *file, int line, pte_t); + extern void __pmd_error(const char *file, int line, pmd_t); + extern void __pgd_error(const char *file, int line, pgd_t); +@@ -56,6 +62,48 @@ extern void __pgd_error(const char *file, int line, pgd_t); + #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) + #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) + ++#define __HAVE_ARCH_PAX_OPEN_KERNEL ++#define __HAVE_ARCH_PAX_CLOSE_KERNEL ++ ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++#include ++#include ++#include ++ ++static inline int test_domain(int domain, int domaintype) ++{ ++ return ((current_thread_info()->cpu_domain) & domain_val(domain, 3)) == domain_val(domain, domaintype); ++} ++#endif ++ ++#ifdef CONFIG_PAX_KERNEXEC ++static inline unsigned long pax_open_kernel(void) { ++#ifdef CONFIG_ARM_LPAE ++ /* TODO */ ++#else ++ preempt_disable(); ++ BUG_ON(test_domain(DOMAIN_KERNEL, DOMAIN_KERNEXEC)); ++ modify_domain(DOMAIN_KERNEL, DOMAIN_KERNEXEC); ++#endif ++ return 0; ++} ++ ++static inline unsigned long pax_close_kernel(void) { ++#ifdef CONFIG_ARM_LPAE ++ /* TODO */ ++#else ++ BUG_ON(test_domain(DOMAIN_KERNEL, DOMAIN_MANAGER)); ++ /* DOMAIN_MANAGER = "client" under KERNEXEC */ ++ modify_domain(DOMAIN_KERNEL, DOMAIN_MANAGER); ++ preempt_enable_no_resched(); ++#endif ++ return 0; ++} ++#else ++static inline unsigned long pax_open_kernel(void) { return 0; } ++static inline unsigned long pax_close_kernel(void) { return 0; } ++#endif ++ + /* + * This is the lowest virtual address we can permit any user space + * mapping to be mapped at. This is particularly important for +@@ -75,8 +123,8 @@ extern void __pgd_error(const char *file, int line, pgd_t); + /* + * The pgprot_* and protection_map entries will be fixed up in runtime + * to include the cachable and bufferable bits based on memory policy, +- * as well as any architecture dependent bits like global/ASID and SMP +- * shared mapping bits. ++ * as well as any architecture dependent bits like global/ASID, PXN, ++ * and SMP shared mapping bits. + */ + #define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG + +@@ -307,7 +355,7 @@ static inline pte_t pte_mknexec(pte_t pte) + static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) + { + const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER | +- L_PTE_NONE | L_PTE_VALID; ++ L_PTE_NONE | L_PTE_VALID | __supported_pte_mask; + pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); + return pte; + } +diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h +index c25ef3e..735f14b 100644 +--- a/arch/arm/include/asm/psci.h ++++ b/arch/arm/include/asm/psci.h +@@ -32,7 +32,7 @@ struct psci_operations { + int (*affinity_info)(unsigned long target_affinity, + unsigned long lowest_affinity_level); + int (*migrate_info_type)(void); +-}; ++} __no_const; + + extern struct psci_operations psci_ops; + extern struct smp_operations psci_smp_ops; +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 2f3ac1b..67182ae0 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -108,7 +108,7 @@ struct smp_operations { + int (*cpu_disable)(unsigned int cpu); + #endif + #endif +-}; ++} __no_const; + + struct of_cpu_method { + const char *method; +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index bd32ede..bd90a0b 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -74,9 +74,9 @@ struct thread_info { + .flags = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .addr_limit = KERNEL_DS, \ +- .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ +- domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ +- domain_val(DOMAIN_IO, DOMAIN_CLIENT), \ ++ .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_USERCLIENT) | \ ++ domain_val(DOMAIN_KERNEL, DOMAIN_KERNELCLIENT) | \ ++ domain_val(DOMAIN_IO, DOMAIN_KERNELCLIENT), \ + } + + #define init_thread_info (init_thread_union.thread_info) +@@ -152,7 +152,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, + #define TIF_SYSCALL_AUDIT 9 + #define TIF_SYSCALL_TRACEPOINT 10 + #define TIF_SECCOMP 11 /* seccomp syscall filtering active */ +-#define TIF_NOHZ 12 /* in adaptive nohz mode */ ++/* within 8 bits of TIF_SYSCALL_TRACE ++ * to meet flexible second operand requirements ++ */ ++#define TIF_GRSEC_SETXID 12 ++#define TIF_NOHZ 13 /* in adaptive nohz mode */ + #define TIF_USING_IWMMXT 17 + #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ + #define TIF_RESTORE_SIGMASK 20 +@@ -166,10 +170,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, + #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) + #define _TIF_SECCOMP (1 << TIF_SECCOMP) + #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) ++#define _TIF_GRSEC_SETXID (1 << TIF_GRSEC_SETXID) + + /* Checks for any syscall work in entry-common.S */ + #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ +- _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP) ++ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | _TIF_GRSEC_SETXID) + + /* + * Change these and you break ASM code in entry-common.S +diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h +index 5f833f7..76e6644 100644 +--- a/arch/arm/include/asm/tls.h ++++ b/arch/arm/include/asm/tls.h +@@ -3,6 +3,7 @@ + + #include + #include ++#include + + #ifdef __ASSEMBLY__ + #include +@@ -89,7 +90,9 @@ static inline void set_tls(unsigned long val) + * at 0xffff0fe0 must be used instead. (see + * entry-armv.S for details) + */ ++ pax_open_kernel(); + *((unsigned int *)0xffff0ff0) = val; ++ pax_close_kernel(); + #endif + } + +diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h +index 74b17d0..7e6da4b 100644 +--- a/arch/arm/include/asm/uaccess.h ++++ b/arch/arm/include/asm/uaccess.h +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + #include +@@ -70,11 +71,38 @@ extern int __put_user_bad(void); + static inline void set_fs(mm_segment_t fs) + { + current_thread_info()->addr_limit = fs; +- modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); ++ modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_KERNELCLIENT : DOMAIN_MANAGER); + } + + #define segment_eq(a, b) ((a) == (b)) + ++#define __HAVE_ARCH_PAX_OPEN_USERLAND ++#define __HAVE_ARCH_PAX_CLOSE_USERLAND ++ ++static inline void pax_open_userland(void) ++{ ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ if (segment_eq(get_fs(), USER_DS)) { ++ BUG_ON(test_domain(DOMAIN_USER, DOMAIN_UDEREF)); ++ modify_domain(DOMAIN_USER, DOMAIN_UDEREF); ++ } ++#endif ++ ++} ++ ++static inline void pax_close_userland(void) ++{ ++ ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ if (segment_eq(get_fs(), USER_DS)) { ++ BUG_ON(test_domain(DOMAIN_USER, DOMAIN_NOACCESS)); ++ modify_domain(DOMAIN_USER, DOMAIN_NOACCESS); ++ } ++#endif ++ ++} ++ + #define __addr_ok(addr) ({ \ + unsigned long flag; \ + __asm__("cmp %2, %0; movlo %0, #0" \ +@@ -198,8 +226,12 @@ extern int __get_user_64t_4(void *); + + #define get_user(x, p) \ + ({ \ ++ int __e; \ + might_fault(); \ +- __get_user_check(x, p); \ ++ pax_open_userland(); \ ++ __e = __get_user_check((x), (p)); \ ++ pax_close_userland(); \ ++ __e; \ + }) + + extern int __put_user_1(void *, unsigned int); +@@ -244,8 +276,12 @@ extern int __put_user_8(void *, unsigned long long); + + #define put_user(x, p) \ + ({ \ ++ int __e; \ + might_fault(); \ +- __put_user_check(x, p); \ ++ pax_open_userland(); \ ++ __e = __put_user_check((x), (p)); \ ++ pax_close_userland(); \ ++ __e; \ + }) + + #else /* CONFIG_MMU */ +@@ -269,6 +305,7 @@ static inline void set_fs(mm_segment_t fs) + + #endif /* CONFIG_MMU */ + ++#define access_ok_noprefault(type, addr, size) access_ok((type), (addr), (size)) + #define access_ok(type, addr, size) (__range_ok(addr, size) == 0) + + #define user_addr_max() \ +@@ -286,13 +323,17 @@ static inline void set_fs(mm_segment_t fs) + #define __get_user(x, ptr) \ + ({ \ + long __gu_err = 0; \ ++ pax_open_userland(); \ + __get_user_err((x), (ptr), __gu_err); \ ++ pax_close_userland(); \ + __gu_err; \ + }) + + #define __get_user_error(x, ptr, err) \ + ({ \ ++ pax_open_userland(); \ + __get_user_err((x), (ptr), err); \ ++ pax_close_userland(); \ + (void) 0; \ + }) + +@@ -368,13 +409,17 @@ do { \ + #define __put_user(x, ptr) \ + ({ \ + long __pu_err = 0; \ ++ pax_open_userland(); \ + __put_user_err((x), (ptr), __pu_err); \ ++ pax_close_userland(); \ + __pu_err; \ + }) + + #define __put_user_error(x, ptr, err) \ + ({ \ ++ pax_open_userland(); \ + __put_user_err((x), (ptr), err); \ ++ pax_close_userland(); \ + (void) 0; \ + }) + +@@ -474,11 +519,44 @@ do { \ + + + #ifdef CONFIG_MMU +-extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n); +-extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n); +-extern unsigned long __must_check __copy_to_user_std(void __user *to, const void *from, unsigned long n); +-extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); +-extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned long n); ++extern unsigned long __must_check __size_overflow(3) ___copy_from_user(void *to, const void __user *from, unsigned long n); ++extern unsigned long __must_check __size_overflow(3) ___copy_to_user(void __user *to, const void *from, unsigned long n); ++ ++static inline unsigned long __must_check __size_overflow(3) __copy_from_user(void *to, const void __user *from, unsigned long n) ++{ ++ unsigned long ret; ++ ++ check_object_size(to, n, false); ++ pax_open_userland(); ++ ret = ___copy_from_user(to, from, n); ++ pax_close_userland(); ++ return ret; ++} ++ ++static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) ++{ ++ unsigned long ret; ++ ++ check_object_size(from, n, true); ++ pax_open_userland(); ++ ret = ___copy_to_user(to, from, n); ++ pax_close_userland(); ++ return ret; ++} ++ ++extern unsigned long __must_check __size_overflow(3) __copy_to_user_std(void __user *to, const void *from, unsigned long n); ++extern unsigned long __must_check __size_overflow(2) ___clear_user(void __user *addr, unsigned long n); ++extern unsigned long __must_check __size_overflow(2) __clear_user_std(void __user *addr, unsigned long n); ++ ++static inline unsigned long __must_check __clear_user(void __user *addr, unsigned long n) ++{ ++ unsigned long ret; ++ pax_open_userland(); ++ ret = ___clear_user(addr, n); ++ pax_close_userland(); ++ return ret; ++} ++ + #else + #define __copy_from_user(to, from, n) (memcpy(to, (void __force *)from, n), 0) + #define __copy_to_user(to, from, n) (memcpy((void __force *)to, from, n), 0) +@@ -487,6 +565,9 @@ extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned l + + static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) + { ++ if ((long)n < 0) ++ return n; ++ + if (access_ok(VERIFY_READ, from, n)) + n = __copy_from_user(to, from, n); + else /* security hole - plug it */ +@@ -496,6 +577,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u + + static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) + { ++ if ((long)n < 0) ++ return n; ++ + if (access_ok(VERIFY_WRITE, to, n)) + n = __copy_to_user(to, from, n); + return n; +diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h +index 5af0ed1..cea83883 100644 +--- a/arch/arm/include/uapi/asm/ptrace.h ++++ b/arch/arm/include/uapi/asm/ptrace.h +@@ -92,7 +92,7 @@ + * ARMv7 groups of PSR bits + */ + #define APSR_MASK 0xf80f0000 /* N, Z, C, V, Q and GE flags */ +-#define PSR_ISET_MASK 0x01000010 /* ISA state (J, T) mask */ ++#define PSR_ISET_MASK 0x01000020 /* ISA state (J, T) mask */ + #define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ + #define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */ + +diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c +index 5e5a51a..b21eeef 100644 +--- a/arch/arm/kernel/armksyms.c ++++ b/arch/arm/kernel/armksyms.c +@@ -58,7 +58,7 @@ EXPORT_SYMBOL(arm_delay_ops); + + /* networking */ + EXPORT_SYMBOL(csum_partial); +-EXPORT_SYMBOL(csum_partial_copy_from_user); ++EXPORT_SYMBOL(__csum_partial_copy_from_user); + EXPORT_SYMBOL(csum_partial_copy_nocheck); + EXPORT_SYMBOL(__csum_ipv6_magic); + +@@ -97,9 +97,9 @@ EXPORT_SYMBOL(mmiocpy); + #ifdef CONFIG_MMU + EXPORT_SYMBOL(copy_page); + +-EXPORT_SYMBOL(__copy_from_user); +-EXPORT_SYMBOL(__copy_to_user); +-EXPORT_SYMBOL(__clear_user); ++EXPORT_SYMBOL(___copy_from_user); ++EXPORT_SYMBOL(___copy_to_user); ++EXPORT_SYMBOL(___clear_user); + + EXPORT_SYMBOL(__get_user_1); + EXPORT_SYMBOL(__get_user_2); +diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c +index 318da33..373689f 100644 +--- a/arch/arm/kernel/cpuidle.c ++++ b/arch/arm/kernel/cpuidle.c +@@ -19,7 +19,7 @@ extern struct of_cpuidle_method __cpuidle_method_of_table[]; + static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel + __used __section(__cpuidle_method_of_table_end); + +-static struct cpuidle_ops cpuidle_ops[NR_CPUS]; ++static struct cpuidle_ops cpuidle_ops[NR_CPUS] __read_only; + + /** + * arm_cpuidle_simple_enter() - a wrapper to cpu_do_idle() +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index cb4fb1e..dc7fcaf 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -50,6 +50,87 @@ + 9997: + .endm + ++ .macro pax_enter_kernel ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++ @ make aligned space for saved DACR ++ sub sp, sp, #8 ++ @ save regs ++ stmdb sp!, {r1, r2} ++ @ read DACR from cpu_domain into r1 ++ mov r2, sp ++ @ assume 8K pages, since we have to split the immediate in two ++ bic r2, r2, #(0x1fc0) ++ bic r2, r2, #(0x3f) ++ ldr r1, [r2, #TI_CPU_DOMAIN] ++ @ store old DACR on stack ++ str r1, [sp, #8] ++#ifdef CONFIG_PAX_KERNEXEC ++ @ set type of DOMAIN_KERNEL to DOMAIN_KERNELCLIENT ++ bic r1, r1, #(domain_val(DOMAIN_KERNEL, 3)) ++ orr r1, r1, #(domain_val(DOMAIN_KERNEL, DOMAIN_KERNELCLIENT)) ++#endif ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ @ set current DOMAIN_USER to DOMAIN_NOACCESS ++ bic r1, r1, #(domain_val(DOMAIN_USER, 3)) ++#endif ++ @ write r1 to current_thread_info()->cpu_domain ++ str r1, [r2, #TI_CPU_DOMAIN] ++ @ write r1 to DACR ++ mcr p15, 0, r1, c3, c0, 0 ++ @ instruction sync ++ instr_sync ++ @ restore regs ++ ldmia sp!, {r1, r2} ++#endif ++ .endm ++ ++ .macro pax_open_userland ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ @ save regs ++ stmdb sp!, {r0, r1} ++ @ read DACR from cpu_domain into r1 ++ mov r0, sp ++ @ assume 8K pages, since we have to split the immediate in two ++ bic r0, r0, #(0x1fc0) ++ bic r0, r0, #(0x3f) ++ ldr r1, [r0, #TI_CPU_DOMAIN] ++ @ set current DOMAIN_USER to DOMAIN_CLIENT ++ bic r1, r1, #(domain_val(DOMAIN_USER, 3)) ++ orr r1, r1, #(domain_val(DOMAIN_USER, DOMAIN_UDEREF)) ++ @ write r1 to current_thread_info()->cpu_domain ++ str r1, [r0, #TI_CPU_DOMAIN] ++ @ write r1 to DACR ++ mcr p15, 0, r1, c3, c0, 0 ++ @ instruction sync ++ instr_sync ++ @ restore regs ++ ldmia sp!, {r0, r1} ++#endif ++ .endm ++ ++ .macro pax_close_userland ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ @ save regs ++ stmdb sp!, {r0, r1} ++ @ read DACR from cpu_domain into r1 ++ mov r0, sp ++ @ assume 8K pages, since we have to split the immediate in two ++ bic r0, r0, #(0x1fc0) ++ bic r0, r0, #(0x3f) ++ ldr r1, [r0, #TI_CPU_DOMAIN] ++ @ set current DOMAIN_USER to DOMAIN_NOACCESS ++ bic r1, r1, #(domain_val(DOMAIN_USER, 3)) ++ @ write r1 to current_thread_info()->cpu_domain ++ str r1, [r0, #TI_CPU_DOMAIN] ++ @ write r1 to DACR ++ mcr p15, 0, r1, c3, c0, 0 ++ @ instruction sync ++ instr_sync ++ @ restore regs ++ ldmia sp!, {r0, r1} ++#endif ++ .endm ++ + .macro pabt_helper + @ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5 + #ifdef MULTI_PABORT +@@ -92,11 +173,15 @@ + * Invalid mode handlers + */ + .macro inv_entry, reason ++ ++ pax_enter_kernel ++ + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - lr} ) + THUMB( stmia sp, {r0 - r12} ) + THUMB( str sp, [sp, #S_SP] ) + THUMB( str lr, [sp, #S_LR] ) ++ + mov r1, #\reason + .endm + +@@ -152,7 +237,11 @@ ENDPROC(__und_invalid) + .macro svc_entry, stack_hole=0, trace=1 + UNWIND(.fnstart ) + UNWIND(.save {r0 - pc} ) ++ ++ pax_enter_kernel ++ + sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) ++ + #ifdef CONFIG_THUMB2_KERNEL + SPFIX( str r0, [sp] ) @ temporarily saved + SPFIX( mov r0, sp ) +@@ -167,7 +256,12 @@ ENDPROC(__und_invalid) + ldmia r0, {r3 - r5} + add r7, sp, #S_SP - 4 @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++ @ offset sp by 8 as done in pax_enter_kernel ++ add r2, sp, #(S_FRAME_SIZE + \stack_hole + 4) ++#else + add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) ++#endif + SPFIX( addeq r2, r2, #4 ) + str r3, [sp, #-4]! @ save the "real" r0 copied + @ from the exception stack +@@ -371,6 +465,9 @@ ENDPROC(__fiq_abt) + .macro usr_entry, trace=1 + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space ++ ++ pax_enter_kernel_user ++ + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) +@@ -481,7 +578,9 @@ __und_usr: + tst r3, #PSR_T_BIT @ Thumb mode? + bne __und_usr_thumb + sub r4, r2, #4 @ ARM instr at LR - 4 ++ pax_open_userland + 1: ldrt r0, [r4] ++ pax_close_userland + ARM_BE8(rev r0, r0) @ little endian instruction + + @ r0 = 32-bit ARM instruction which caused the exception +@@ -515,11 +614,15 @@ __und_usr_thumb: + */ + .arch armv6t2 + #endif ++ pax_open_userland + 2: ldrht r5, [r4] ++ pax_close_userland + ARM_BE8(rev16 r5, r5) @ little endian instruction + cmp r5, #0xe800 @ 32bit instruction if xx != 0 + blo __und_usr_fault_16 @ 16bit undefined instruction ++ pax_open_userland + 3: ldrht r0, [r2] ++ pax_close_userland + ARM_BE8(rev16 r0, r0) @ little endian instruction + add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 + str r2, [sp, #S_PC] @ it's a 2x16bit instr, update +@@ -549,7 +652,8 @@ ENDPROC(__und_usr) + */ + .pushsection .text.fixup, "ax" + .align 2 +-4: str r4, [sp, #S_PC] @ retry current instruction ++4: pax_close_userland ++ str r4, [sp, #S_PC] @ retry current instruction + ret r9 + .popsection + .pushsection __ex_table,"a" +@@ -769,7 +873,7 @@ ENTRY(__switch_to) + THUMB( str lr, [ip], #4 ) + ldr r4, [r2, #TI_TP_VALUE] + ldr r5, [r2, #TI_TP_VALUE + 4] +-#ifdef CONFIG_CPU_USE_DOMAINS ++#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + ldr r6, [r2, #TI_CPU_DOMAIN] + #endif + switch_tls r1, r4, r5, r3, r7 +@@ -778,7 +882,7 @@ ENTRY(__switch_to) + ldr r8, =__stack_chk_guard + ldr r7, [r7, #TSK_STACK_CANARY] + #endif +-#ifdef CONFIG_CPU_USE_DOMAINS ++#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + mcr p15, 0, r6, c3, c0, 0 @ Set domain register + #endif + mov r5, r0 +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index b48dd4f..9f9a72f 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -11,18 +11,46 @@ + #include + #include + #include ++#include + #include + ++#include "entry-header.S" ++ + #ifdef CONFIG_NEED_RET_TO_USER + #include + #else + .macro arch_ret_to_user, tmp1, tmp2 ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++ @ save regs ++ stmdb sp!, {r1, r2} ++ @ read DACR from cpu_domain into r1 ++ mov r2, sp ++ @ assume 8K pages, since we have to split the immediate in two ++ bic r2, r2, #(0x1fc0) ++ bic r2, r2, #(0x3f) ++ ldr r1, [r2, #TI_CPU_DOMAIN] ++#ifdef CONFIG_PAX_KERNEXEC ++ @ set type of DOMAIN_KERNEL to DOMAIN_KERNELCLIENT ++ bic r1, r1, #(domain_val(DOMAIN_KERNEL, 3)) ++ orr r1, r1, #(domain_val(DOMAIN_KERNEL, DOMAIN_KERNELCLIENT)) ++#endif ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ @ set current DOMAIN_USER to DOMAIN_UDEREF ++ bic r1, r1, #(domain_val(DOMAIN_USER, 3)) ++ orr r1, r1, #(domain_val(DOMAIN_USER, DOMAIN_UDEREF)) ++#endif ++ @ write r1 to current_thread_info()->cpu_domain ++ str r1, [r2, #TI_CPU_DOMAIN] ++ @ write r1 to DACR ++ mcr p15, 0, r1, c3, c0, 0 ++ @ instruction sync ++ instr_sync ++ @ restore regs ++ ldmia sp!, {r1, r2} ++#endif + .endm + #endif + +-#include "entry-header.S" +- +- + .align 5 + /* + * This is the fast syscall return path. We do as little as +@@ -174,6 +202,12 @@ ENTRY(vector_swi) + USER( ldr scno, [lr, #-4] ) @ get SWI instruction + #endif + ++ /* ++ * do this here to avoid a performance hit of wrapping the code above ++ * that directly dereferences userland to parse the SWI instruction ++ */ ++ pax_enter_kernel_user ++ + adr tbl, sys_call_table @ load syscall table pointer + + #if defined(CONFIG_OABI_COMPAT) +diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S +index 1a0045a..9b4f34d 100644 +--- a/arch/arm/kernel/entry-header.S ++++ b/arch/arm/kernel/entry-header.S +@@ -196,6 +196,60 @@ + msr cpsr_c, \rtemp @ switch back to the SVC mode + .endm + ++ .macro pax_enter_kernel_user ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++ @ save regs ++ stmdb sp!, {r0, r1} ++ @ read DACR from cpu_domain into r1 ++ mov r0, sp ++ @ assume 8K pages, since we have to split the immediate in two ++ bic r0, r0, #(0x1fc0) ++ bic r0, r0, #(0x3f) ++ ldr r1, [r0, #TI_CPU_DOMAIN] ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ @ set current DOMAIN_USER to DOMAIN_NOACCESS ++ bic r1, r1, #(domain_val(DOMAIN_USER, 3)) ++#endif ++#ifdef CONFIG_PAX_KERNEXEC ++ @ set current DOMAIN_KERNEL to DOMAIN_KERNELCLIENT ++ bic r1, r1, #(domain_val(DOMAIN_KERNEL, 3)) ++ orr r1, r1, #(domain_val(DOMAIN_KERNEL, DOMAIN_KERNELCLIENT)) ++#endif ++ @ write r1 to current_thread_info()->cpu_domain ++ str r1, [r0, #TI_CPU_DOMAIN] ++ @ write r1 to DACR ++ mcr p15, 0, r1, c3, c0, 0 ++ @ instruction sync ++ instr_sync ++ @ restore regs ++ ldmia sp!, {r0, r1} ++#endif ++ .endm ++ ++ .macro pax_exit_kernel ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++ @ save regs ++ stmdb sp!, {r0, r1} ++ @ read old DACR from stack into r1 ++ ldr r1, [sp, #(8 + S_SP)] ++ sub r1, r1, #8 ++ ldr r1, [r1] ++ ++ @ write r1 to current_thread_info()->cpu_domain ++ mov r0, sp ++ @ assume 8K pages, since we have to split the immediate in two ++ bic r0, r0, #(0x1fc0) ++ bic r0, r0, #(0x3f) ++ str r1, [r0, #TI_CPU_DOMAIN] ++ @ write r1 to DACR ++ mcr p15, 0, r1, c3, c0, 0 ++ @ instruction sync ++ instr_sync ++ @ restore regs ++ ldmia sp!, {r0, r1} ++#endif ++ .endm ++ + #ifndef CONFIG_THUMB2_KERNEL + .macro svc_exit, rpsr, irq = 0 + .if \irq != 0 +@@ -215,6 +269,9 @@ + blne trace_hardirqs_off + #endif + .endif ++ ++ pax_exit_kernel ++ + msr spsr_cxsf, \rpsr + #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) + @ We must avoid clrex due to Cortex-A15 erratum #830321 +@@ -291,6 +348,9 @@ + blne trace_hardirqs_off + #endif + .endif ++ ++ pax_exit_kernel ++ + ldr lr, [sp, #S_SP] @ top of the stack + ldrd r0, r1, [sp, #S_LR] @ calling lr and pc + +diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c +index 059c3da..8e45cfc 100644 +--- a/arch/arm/kernel/fiq.c ++++ b/arch/arm/kernel/fiq.c +@@ -95,7 +95,10 @@ void set_fiq_handler(void *start, unsigned int length) + void *base = vectors_page; + unsigned offset = FIQ_OFFSET; + ++ pax_open_kernel(); + memcpy(base + offset, start, length); ++ pax_close_kernel(); ++ + if (!cache_is_vipt_nonaliasing()) + flush_icache_range((unsigned long)base + offset, offset + + length); +diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S +index 29e2991..7bc5757 100644 +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -467,7 +467,7 @@ __enable_mmu: + mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ +- domain_val(DOMAIN_IO, DOMAIN_CLIENT)) ++ domain_val(DOMAIN_IO, DOMAIN_KERNELCLIENT)) + mcr p15, 0, r5, c3, c0, 0 @ load domain access register + mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + #endif +diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c +index 097e2e2..3927085 100644 +--- a/arch/arm/kernel/module-plts.c ++++ b/arch/arm/kernel/module-plts.c +@@ -30,17 +30,12 @@ struct plt_entries { + u32 lit[PLT_ENT_COUNT]; + }; + +-static bool in_init(const struct module *mod, u32 addr) +-{ +- return addr - (u32)mod->module_init < mod->init_size; +-} +- + u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) + { + struct plt_entries *plt, *plt_end; + int c, *count; + +- if (in_init(mod, loc)) { ++ if (within_module_init(loc, mod)) { + plt = (void *)mod->arch.init_plt->sh_addr; + plt_end = (void *)plt + mod->arch.init_plt->sh_size; + count = &mod->arch.init_plt_count; +diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c +index efdddcb..35e58f6 100644 +--- a/arch/arm/kernel/module.c ++++ b/arch/arm/kernel/module.c +@@ -38,17 +38,47 @@ + #endif + + #ifdef CONFIG_MMU +-void *module_alloc(unsigned long size) ++static inline void *__module_alloc(unsigned long size, pgprot_t prot) + { +- void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, +- GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, ++ void *p; ++ ++ if (!size || (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) && PAGE_ALIGN(size) > MODULES_END - MODULES_VADDR)) ++ return NULL; ++ ++ p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, ++ GFP_KERNEL, prot, 0, NUMA_NO_NODE, + __builtin_return_address(0)); + if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p) + return p; + return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END, +- GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, ++ GFP_KERNEL, prot, 0, NUMA_NO_NODE, + __builtin_return_address(0)); + } ++ ++void *module_alloc(unsigned long size) ++{ ++ ++#ifdef CONFIG_PAX_KERNEXEC ++ return __module_alloc(size, PAGE_KERNEL); ++#else ++ return __module_alloc(size, PAGE_KERNEL_EXEC); ++#endif ++ ++} ++ ++#ifdef CONFIG_PAX_KERNEXEC ++void module_memfree_exec(void *module_region) ++{ ++ module_memfree(module_region); ++} ++EXPORT_SYMBOL(module_memfree_exec); ++ ++void *module_alloc_exec(unsigned long size) ++{ ++ return __module_alloc(size, PAGE_KERNEL_EXEC); ++} ++EXPORT_SYMBOL(module_alloc_exec); ++#endif + #endif + + int +diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c +index 69bda1a..755113a 100644 +--- a/arch/arm/kernel/patch.c ++++ b/arch/arm/kernel/patch.c +@@ -66,6 +66,7 @@ void __kprobes __patch_text_real(void *addr, unsigned int insn, bool remap) + else + __acquire(&patch_lock); + ++ pax_open_kernel(); + if (thumb2 && __opcode_is_thumb16(insn)) { + *(u16 *)waddr = __opcode_to_mem_thumb16(insn); + size = sizeof(u16); +@@ -97,6 +98,7 @@ void __kprobes __patch_text_real(void *addr, unsigned int insn, bool remap) + *(u32 *)waddr = insn; + size = sizeof(u32); + } ++ pax_close_kernel(); + + if (waddr != addr) { + flush_kernel_vmap_range(waddr, twopage ? size / 2 : size); +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index f192a2a..1a40523 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -105,8 +105,8 @@ void __show_regs(struct pt_regs *regs) + + show_regs_print_info(KERN_DEFAULT); + +- print_symbol("PC is at %s\n", instruction_pointer(regs)); +- print_symbol("LR is at %s\n", regs->ARM_lr); ++ printk("PC is at %pA\n", (void *)instruction_pointer(regs)); ++ printk("LR is at %pA\n", (void *)regs->ARM_lr); + printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, +@@ -283,12 +283,6 @@ unsigned long get_wchan(struct task_struct *p) + return 0; + } + +-unsigned long arch_randomize_brk(struct mm_struct *mm) +-{ +- unsigned long range_end = mm->brk + 0x02000000; +- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; +-} +- + #ifdef CONFIG_MMU + #ifdef CONFIG_KUSER_HELPERS + /* +@@ -304,7 +298,7 @@ static struct vm_area_struct gate_vma = { + + static int __init gate_vma_init(void) + { +- gate_vma.vm_page_prot = PAGE_READONLY_EXEC; ++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); + return 0; + } + arch_initcall(gate_vma_init); +@@ -333,91 +327,13 @@ const char *arch_vma_name(struct vm_area_struct *vma) + return is_gate_vma(vma) ? "[vectors]" : NULL; + } + +-/* If possible, provide a placement hint at a random offset from the +- * stack for the sigpage and vdso pages. +- */ +-static unsigned long sigpage_addr(const struct mm_struct *mm, +- unsigned int npages) +-{ +- unsigned long offset; +- unsigned long first; +- unsigned long last; +- unsigned long addr; +- unsigned int slots; +- +- first = PAGE_ALIGN(mm->start_stack); +- +- last = TASK_SIZE - (npages << PAGE_SHIFT); +- +- /* No room after stack? */ +- if (first > last) +- return 0; +- +- /* Just enough room? */ +- if (first == last) +- return first; +- +- slots = ((last - first) >> PAGE_SHIFT) + 1; +- +- offset = get_random_int() % slots; +- +- addr = first + (offset << PAGE_SHIFT); +- +- return addr; +-} +- +-static struct page *signal_page; +-extern struct page *get_signal_page(void); +- +-static const struct vm_special_mapping sigpage_mapping = { +- .name = "[sigpage]", +- .pages = &signal_page, +-}; +- + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) + { + struct mm_struct *mm = current->mm; +- struct vm_area_struct *vma; +- unsigned long npages; +- unsigned long addr; +- unsigned long hint; +- int ret = 0; +- +- if (!signal_page) +- signal_page = get_signal_page(); +- if (!signal_page) +- return -ENOMEM; +- +- npages = 1; /* for sigpage */ +- npages += vdso_total_pages; + + down_write(&mm->mmap_sem); +- hint = sigpage_addr(mm, npages); +- addr = get_unmapped_area(NULL, hint, npages << PAGE_SHIFT, 0, 0); +- if (IS_ERR_VALUE(addr)) { +- ret = addr; +- goto up_fail; +- } +- +- vma = _install_special_mapping(mm, addr, PAGE_SIZE, +- VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, +- &sigpage_mapping); +- +- if (IS_ERR(vma)) { +- ret = PTR_ERR(vma); +- goto up_fail; +- } +- +- mm->context.sigpage = addr; +- +- /* Unlike the sigpage, failure to install the vdso is unlikely +- * to be fatal to the process, so no error check needed +- * here. +- */ +- arm_install_vdso(mm, addr + PAGE_SIZE); +- +- up_fail: ++ mm->context.sigpage = (PAGE_OFFSET + (get_random_int() % 0x3FFEFFE0)) & 0xFFFFFFFC; + up_write(&mm->mmap_sem); +- return ret; ++ return 0; + } + #endif +diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c +index f90fdf4..24e8c84 100644 +--- a/arch/arm/kernel/psci.c ++++ b/arch/arm/kernel/psci.c +@@ -26,7 +26,7 @@ + #include + #include + +-struct psci_operations psci_ops; ++struct psci_operations psci_ops __read_only; + + static int (*invoke_psci_fn)(u32, u32, u32, u32); + typedef int (*psci_initcall_t)(const struct device_node *); +diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c +index ef9119f..31995a3 100644 +--- a/arch/arm/kernel/ptrace.c ++++ b/arch/arm/kernel/ptrace.c +@@ -928,10 +928,19 @@ static void tracehook_report_syscall(struct pt_regs *regs, + regs->ARM_ip = ip; + } + ++#ifdef CONFIG_GRKERNSEC_SETXID ++extern void gr_delayed_cred_worker(void); ++#endif ++ + asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) + { + current_thread_info()->syscall = scno; + ++#ifdef CONFIG_GRKERNSEC_SETXID ++ if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) ++ gr_delayed_cred_worker(); ++#endif ++ + /* Do the secure computing check first; failures should be fast. */ + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + if (secure_computing() == -1) +diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c +index 3826935..8ed63ed 100644 +--- a/arch/arm/kernel/reboot.c ++++ b/arch/arm/kernel/reboot.c +@@ -122,6 +122,7 @@ void machine_power_off(void) + + if (pm_power_off) + pm_power_off(); ++ while (1); + } + + /* +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index 36c18b7..0d78292 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -108,21 +108,23 @@ EXPORT_SYMBOL(elf_hwcap); + unsigned int elf_hwcap2 __read_mostly; + EXPORT_SYMBOL(elf_hwcap2); + ++pteval_t __supported_pte_mask __read_only; ++pmdval_t __supported_pmd_mask __read_only; + + #ifdef MULTI_CPU +-struct processor processor __read_mostly; ++struct processor processor __read_only; + #endif + #ifdef MULTI_TLB +-struct cpu_tlb_fns cpu_tlb __read_mostly; ++struct cpu_tlb_fns cpu_tlb __read_only; + #endif + #ifdef MULTI_USER +-struct cpu_user_fns cpu_user __read_mostly; ++struct cpu_user_fns cpu_user __read_only; + #endif + #ifdef MULTI_CACHE +-struct cpu_cache_fns cpu_cache __read_mostly; ++struct cpu_cache_fns cpu_cache __read_only; + #endif + #ifdef CONFIG_OUTER_CACHE +-struct outer_cache_fns outer_cache __read_mostly; ++struct outer_cache_fns outer_cache __read_only; + EXPORT_SYMBOL(outer_cache); + #endif + +@@ -253,9 +255,13 @@ static int __get_cpu_architecture(void) + * Register 0 and check for VMSAv7 or PMSAv7 */ + unsigned int mmfr0 = read_cpuid_ext(CPUID_EXT_MMFR0); + if ((mmfr0 & 0x0000000f) >= 0x00000003 || +- (mmfr0 & 0x000000f0) >= 0x00000030) ++ (mmfr0 & 0x000000f0) >= 0x00000030) { + cpu_arch = CPU_ARCH_ARMv7; +- else if ((mmfr0 & 0x0000000f) == 0x00000002 || ++ if ((mmfr0 & 0x0000000f) == 0x00000005 || (mmfr0 & 0x0000000f) == 0x00000004) { ++ __supported_pte_mask |= L_PTE_PXN; ++ __supported_pmd_mask |= PMD_PXNTABLE; ++ } ++ } else if ((mmfr0 & 0x0000000f) == 0x00000002 || + (mmfr0 & 0x000000f0) == 0x00000020) + cpu_arch = CPU_ARCH_ARMv6; + else +diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c +index 586eef2..61aabd4 100644 +--- a/arch/arm/kernel/signal.c ++++ b/arch/arm/kernel/signal.c +@@ -24,8 +24,6 @@ + + extern const unsigned long sigreturn_codes[7]; + +-static unsigned long signal_return_offset; +- + #ifdef CONFIG_CRUNCH + static int preserve_crunch_context(struct crunch_sigframe __user *frame) + { +@@ -390,8 +388,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, + * except when the MPU has protected the vectors + * page from PL0 + */ +- retcode = mm->context.sigpage + signal_return_offset + +- (idx << 2) + thumb; ++ retcode = mm->context.sigpage + (idx << 2) + thumb; + } else + #endif + { +@@ -597,33 +594,3 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) + } while (thread_flags & _TIF_WORK_MASK); + return 0; + } +- +-struct page *get_signal_page(void) +-{ +- unsigned long ptr; +- unsigned offset; +- struct page *page; +- void *addr; +- +- page = alloc_pages(GFP_KERNEL, 0); +- +- if (!page) +- return NULL; +- +- addr = page_address(page); +- +- /* Give the signal return code some randomness */ +- offset = 0x200 + (get_random_int() & 0x7fc); +- signal_return_offset = offset; +- +- /* +- * Copy signal return handlers into the vector page, and +- * set sigreturn to be a pointer to these. +- */ +- memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes)); +- +- ptr = (unsigned long)addr + offset; +- flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); +- +- return page; +-} +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 3d6b782..8b3baeb 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -76,7 +76,7 @@ enum ipi_msg_type { + + static DECLARE_COMPLETION(cpu_running); + +-static struct smp_operations smp_ops; ++static struct smp_operations smp_ops __read_only; + + void __init smp_set_ops(struct smp_operations *ops) + { +diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c +index b10e136..cb5edf9 100644 +--- a/arch/arm/kernel/tcm.c ++++ b/arch/arm/kernel/tcm.c +@@ -64,7 +64,7 @@ static struct map_desc itcm_iomap[] __initdata = { + .virtual = ITCM_OFFSET, + .pfn = __phys_to_pfn(ITCM_OFFSET), + .length = 0, +- .type = MT_MEMORY_RWX_ITCM, ++ .type = MT_MEMORY_RX_ITCM, + } + }; + +@@ -362,7 +362,9 @@ no_dtcm: + start = &__sitcm_text; + end = &__eitcm_text; + ram = &__itcm_start; ++ pax_open_kernel(); + memcpy(start, ram, itcm_code_sz); ++ pax_close_kernel(); + pr_debug("CPU ITCM: copied code from %p - %p\n", + start, end); + itcm_present = true; +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index d358226..bfd4019 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -65,7 +65,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long); + void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) + { + #ifdef CONFIG_KALLSYMS +- printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); ++ printk("[<%08lx>] (%pA) from [<%08lx>] (%pA)\n", where, (void *)where, from, (void *)from); + #else + printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); + #endif +@@ -267,6 +267,8 @@ static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; + static int die_owner = -1; + static unsigned int die_nest_count; + ++extern void gr_handle_kernel_exploit(void); ++ + static unsigned long oops_begin(void) + { + int cpu; +@@ -309,6 +311,9 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) + panic("Fatal exception in interrupt"); + if (panic_on_oops) + panic("Fatal exception"); ++ ++ gr_handle_kernel_exploit(); ++ + if (signr) + do_exit(signr); + } +@@ -870,7 +875,11 @@ void __init early_trap_init(void *vectors_base) + kuser_init(vectors_base); + + flush_icache_range(vectors, vectors + PAGE_SIZE * 2); +- modify_domain(DOMAIN_USER, DOMAIN_CLIENT); ++ ++#ifndef CONFIG_PAX_MEMORY_UDEREF ++ modify_domain(DOMAIN_USER, DOMAIN_USERCLIENT); ++#endif ++ + #else /* ifndef CONFIG_CPU_V7M */ + /* + * on V7-M there is no need to copy the vector table to a dedicated +diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S +index 8b60fde..8d986dd 100644 +--- a/arch/arm/kernel/vmlinux.lds.S ++++ b/arch/arm/kernel/vmlinux.lds.S +@@ -37,7 +37,7 @@ + #endif + + #if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ +- defined(CONFIG_GENERIC_BUG) ++ defined(CONFIG_GENERIC_BUG) || defined(CONFIG_PAX_REFCOUNT) + #define ARM_EXIT_KEEP(x) x + #define ARM_EXIT_DISCARD(x) + #else +@@ -120,6 +120,8 @@ SECTIONS + #ifdef CONFIG_DEBUG_RODATA + . = ALIGN(1<arch.vmid_gen != atomic64_read(&kvm_vmid_gen)); ++ return unlikely(kvm->arch.vmid_gen != atomic64_read_unchecked(&kvm_vmid_gen)); + } + + /** +@@ -405,7 +405,7 @@ static void update_vttbr(struct kvm *kvm) + + /* First user of a new VMID generation? */ + if (unlikely(kvm_next_vmid == 0)) { +- atomic64_inc(&kvm_vmid_gen); ++ atomic64_inc_unchecked(&kvm_vmid_gen); + kvm_next_vmid = 1; + + /* +@@ -422,7 +422,7 @@ static void update_vttbr(struct kvm *kvm) + kvm_call_hyp(__kvm_flush_vm_context); + } + +- kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen); ++ kvm->arch.vmid_gen = atomic64_read_unchecked(&kvm_vmid_gen); + kvm->arch.vmid = kvm_next_vmid; + kvm_next_vmid++; + +@@ -1110,7 +1110,7 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) + /** + * Initialize Hyp-mode and memory mappings on all CPUs. + */ +-int kvm_arch_init(void *opaque) ++int kvm_arch_init(const void *opaque) + { + int err; + int ret, cpu; +diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S +index 1710fd7..ec3e014 100644 +--- a/arch/arm/lib/clear_user.S ++++ b/arch/arm/lib/clear_user.S +@@ -12,14 +12,14 @@ + + .text + +-/* Prototype: int __clear_user(void *addr, size_t sz) ++/* Prototype: int ___clear_user(void *addr, size_t sz) + * Purpose : clear some user memory + * Params : addr - user memory address to clear + * : sz - number of bytes to clear + * Returns : number of bytes NOT cleared + */ + ENTRY(__clear_user_std) +-WEAK(__clear_user) ++WEAK(___clear_user) + stmfd sp!, {r1, lr} + mov r2, #0 + cmp r1, #4 +@@ -44,7 +44,7 @@ WEAK(__clear_user) + USER( strnebt r2, [r0]) + mov r0, #0 + ldmfd sp!, {r1, pc} +-ENDPROC(__clear_user) ++ENDPROC(___clear_user) + ENDPROC(__clear_user_std) + + .pushsection .text.fixup,"ax" +diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S +index 7a235b9..73a0556 100644 +--- a/arch/arm/lib/copy_from_user.S ++++ b/arch/arm/lib/copy_from_user.S +@@ -17,7 +17,7 @@ + /* + * Prototype: + * +- * size_t __copy_from_user(void *to, const void *from, size_t n) ++ * size_t ___copy_from_user(void *to, const void *from, size_t n) + * + * Purpose: + * +@@ -89,11 +89,11 @@ + + .text + +-ENTRY(__copy_from_user) ++ENTRY(___copy_from_user) + + #include "copy_template.S" + +-ENDPROC(__copy_from_user) ++ENDPROC(___copy_from_user) + + .pushsection .fixup,"ax" + .align 0 +diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S +index 6ee2f67..d1cce76 100644 +--- a/arch/arm/lib/copy_page.S ++++ b/arch/arm/lib/copy_page.S +@@ -10,6 +10,7 @@ + * ASM optimised string functions + */ + #include ++#include + #include + #include + #include +diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S +index 9648b06..19c333c 100644 +--- a/arch/arm/lib/copy_to_user.S ++++ b/arch/arm/lib/copy_to_user.S +@@ -17,7 +17,7 @@ + /* + * Prototype: + * +- * size_t __copy_to_user(void *to, const void *from, size_t n) ++ * size_t ___copy_to_user(void *to, const void *from, size_t n) + * + * Purpose: + * +@@ -93,11 +93,11 @@ + .text + + ENTRY(__copy_to_user_std) +-WEAK(__copy_to_user) ++WEAK(___copy_to_user) + + #include "copy_template.S" + +-ENDPROC(__copy_to_user) ++ENDPROC(___copy_to_user) + ENDPROC(__copy_to_user_std) + + .pushsection .text.fixup,"ax" +diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S +index 1d0957e..f708846 100644 +--- a/arch/arm/lib/csumpartialcopyuser.S ++++ b/arch/arm/lib/csumpartialcopyuser.S +@@ -57,8 +57,8 @@ + * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT + */ + +-#define FN_ENTRY ENTRY(csum_partial_copy_from_user) +-#define FN_EXIT ENDPROC(csum_partial_copy_from_user) ++#define FN_ENTRY ENTRY(__csum_partial_copy_from_user) ++#define FN_EXIT ENDPROC(__csum_partial_copy_from_user) + + #include "csumpartialcopygeneric.S" + +diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c +index 8044591..c9b2609 100644 +--- a/arch/arm/lib/delay.c ++++ b/arch/arm/lib/delay.c +@@ -29,7 +29,7 @@ + /* + * Default to the loop-based delay implementation. + */ +-struct arm_delay_ops arm_delay_ops = { ++struct arm_delay_ops arm_delay_ops __read_only = { + .delay = __loop_delay, + .const_udelay = __loop_const_udelay, + .udelay = __loop_udelay, +diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c +index 4b39af2..9ae747d 100644 +--- a/arch/arm/lib/uaccess_with_memcpy.c ++++ b/arch/arm/lib/uaccess_with_memcpy.c +@@ -85,7 +85,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) + return 1; + } + +-static unsigned long noinline ++static unsigned long noinline __size_overflow(3) + __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) + { + int atomic; +@@ -136,7 +136,7 @@ out: + } + + unsigned long +-__copy_to_user(void __user *to, const void *from, unsigned long n) ++___copy_to_user(void __user *to, const void *from, unsigned long n) + { + /* + * This test is stubbed out of the main function above to keep +@@ -150,7 +150,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) + return __copy_to_user_memcpy(to, from, n); + } + +-static unsigned long noinline ++static unsigned long noinline __size_overflow(2) + __clear_user_memset(void __user *addr, unsigned long n) + { + if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { +@@ -190,7 +190,7 @@ out: + return n; + } + +-unsigned long __clear_user(void __user *addr, unsigned long n) ++unsigned long ___clear_user(void __user *addr, unsigned long n) + { + /* See rational for this in __copy_to_user() above. */ + if (n < 64) +diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c +index f572219..2cf36d5 100644 +--- a/arch/arm/mach-exynos/suspend.c ++++ b/arch/arm/mach-exynos/suspend.c +@@ -732,8 +732,10 @@ void __init exynos_pm_init(void) + tmp |= pm_data->wake_disable_mask; + pmu_raw_writel(tmp, S5P_WAKEUP_MASK); + +- exynos_pm_syscore_ops.suspend = pm_data->pm_suspend; +- exynos_pm_syscore_ops.resume = pm_data->pm_resume; ++ pax_open_kernel(); ++ *(void **)&exynos_pm_syscore_ops.suspend = pm_data->pm_suspend; ++ *(void **)&exynos_pm_syscore_ops.resume = pm_data->pm_resume; ++ pax_close_kernel(); + + register_syscore_ops(&exynos_pm_syscore_ops); + suspend_set_ops(&exynos_suspend_ops); +diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c +index e46e9ea..9141c83 100644 +--- a/arch/arm/mach-mvebu/coherency.c ++++ b/arch/arm/mach-mvebu/coherency.c +@@ -117,7 +117,7 @@ static void __init armada_370_coherency_init(struct device_node *np) + + /* + * This ioremap hook is used on Armada 375/38x to ensure that PCIe +- * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This ++ * memory areas are mapped as MT_UNCACHED_RW instead of MT_DEVICE. This + * is needed as a workaround for a deadlock issue between the PCIe + * interface and the cache controller. + */ +@@ -130,7 +130,7 @@ armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size, + mvebu_mbus_get_pcie_mem_aperture(&pcie_mem); + + if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end) +- mtype = MT_UNCACHED; ++ mtype = MT_UNCACHED_RW; + + return __arm_ioremap_caller(phys_addr, size, mtype, caller); + } +diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c +index b6443a4..20a0b74 100644 +--- a/arch/arm/mach-omap2/board-n8x0.c ++++ b/arch/arm/mach-omap2/board-n8x0.c +@@ -569,7 +569,7 @@ static int n8x0_menelaus_late_init(struct device *dev) + } + #endif + +-struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = { ++struct menelaus_platform_data n8x0_menelaus_platform_data __initconst = { + .late_init = n8x0_menelaus_late_init, + }; + +diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c +index 79f49d9..70bf184 100644 +--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c ++++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c +@@ -86,7 +86,7 @@ struct cpu_pm_ops { + void (*resume)(void); + void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state); + void (*hotplug_restart)(void); +-}; ++} __no_const; + + static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); + static struct powerdomain *mpuss_pd; +@@ -105,7 +105,7 @@ static void dummy_cpu_resume(void) + static void dummy_scu_prepare(unsigned int cpu_id, unsigned int cpu_state) + {} + +-struct cpu_pm_ops omap_pm_ops = { ++static struct cpu_pm_ops omap_pm_ops __read_only = { + .finish_suspend = default_finish_suspend, + .resume = dummy_cpu_resume, + .scu_prepare = dummy_scu_prepare, +diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c +index 5305ec7..6d74045 100644 +--- a/arch/arm/mach-omap2/omap-smp.c ++++ b/arch/arm/mach-omap2/omap-smp.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + + #include +diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c +index e1d2e99..d9b3177 100644 +--- a/arch/arm/mach-omap2/omap-wakeupgen.c ++++ b/arch/arm/mach-omap2/omap-wakeupgen.c +@@ -330,7 +330,7 @@ static int irq_cpu_hotplug_notify(struct notifier_block *self, + return NOTIFY_OK; + } + +-static struct notifier_block __refdata irq_hotplug_notifier = { ++static struct notifier_block irq_hotplug_notifier = { + .notifier_call = irq_cpu_hotplug_notify, + }; + +diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c +index 4cb8fd9..5ce65bc 100644 +--- a/arch/arm/mach-omap2/omap_device.c ++++ b/arch/arm/mach-omap2/omap_device.c +@@ -504,7 +504,7 @@ void omap_device_delete(struct omap_device *od) + struct platform_device __init *omap_device_build(const char *pdev_name, + int pdev_id, + struct omap_hwmod *oh, +- void *pdata, int pdata_len) ++ const void *pdata, int pdata_len) + { + struct omap_hwmod *ohs[] = { oh }; + +@@ -532,7 +532,7 @@ struct platform_device __init *omap_device_build(const char *pdev_name, + struct platform_device __init *omap_device_build_ss(const char *pdev_name, + int pdev_id, + struct omap_hwmod **ohs, +- int oh_cnt, void *pdata, ++ int oh_cnt, const void *pdata, + int pdata_len) + { + int ret = -ENOMEM; +diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h +index 78c02b3..c94109a 100644 +--- a/arch/arm/mach-omap2/omap_device.h ++++ b/arch/arm/mach-omap2/omap_device.h +@@ -72,12 +72,12 @@ int omap_device_idle(struct platform_device *pdev); + /* Core code interface */ + + struct platform_device *omap_device_build(const char *pdev_name, int pdev_id, +- struct omap_hwmod *oh, void *pdata, ++ struct omap_hwmod *oh, const void *pdata, + int pdata_len); + + struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id, + struct omap_hwmod **oh, int oh_cnt, +- void *pdata, int pdata_len); ++ const void *pdata, int pdata_len); + + struct omap_device *omap_device_alloc(struct platform_device *pdev, + struct omap_hwmod **ohs, int oh_cnt); +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 486cc4d..8d1a0b7 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -199,10 +199,10 @@ struct omap_hwmod_soc_ops { + int (*init_clkdm)(struct omap_hwmod *oh); + void (*update_context_lost)(struct omap_hwmod *oh); + int (*get_context_lost)(struct omap_hwmod *oh); +-}; ++} __no_const; + + /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ +-static struct omap_hwmod_soc_ops soc_ops; ++static struct omap_hwmod_soc_ops soc_ops __read_only; + + /* omap_hwmod_list contains all registered struct omap_hwmods */ + static LIST_HEAD(omap_hwmod_list); +diff --git a/arch/arm/mach-omap2/powerdomains43xx_data.c b/arch/arm/mach-omap2/powerdomains43xx_data.c +index 95fee54..cfa9cf1 100644 +--- a/arch/arm/mach-omap2/powerdomains43xx_data.c ++++ b/arch/arm/mach-omap2/powerdomains43xx_data.c +@@ -10,6 +10,7 @@ + + #include + #include ++#include + + #include "powerdomain.h" + +@@ -129,7 +130,9 @@ static int am43xx_check_vcvp(void) + + void __init am43xx_powerdomains_init(void) + { +- omap4_pwrdm_operations.pwrdm_has_voltdm = am43xx_check_vcvp; ++ pax_open_kernel(); ++ *(void **)&omap4_pwrdm_operations.pwrdm_has_voltdm = am43xx_check_vcvp; ++ pax_close_kernel(); + pwrdm_register_platform_funcs(&omap4_pwrdm_operations); + pwrdm_register_pwrdms(powerdomains_am43xx); + pwrdm_complete_init(); +diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c +index ff0a68c..b312aa0 100644 +--- a/arch/arm/mach-omap2/wd_timer.c ++++ b/arch/arm/mach-omap2/wd_timer.c +@@ -110,7 +110,9 @@ static int __init omap_init_wdt(void) + struct omap_hwmod *oh; + char *oh_name = "wd_timer2"; + char *dev_name = "omap_wdt"; +- struct omap_wd_timer_platform_data pdata; ++ static struct omap_wd_timer_platform_data pdata = { ++ .read_reset_sources = prm_read_reset_sources ++ }; + + if (!cpu_class_is_omap2() || of_have_populated_dt()) + return 0; +@@ -121,8 +123,6 @@ static int __init omap_init_wdt(void) + return -EINVAL; + } + +- pdata.read_reset_sources = prm_read_reset_sources; +- + pdev = omap_device_build(dev_name, id, oh, &pdata, + sizeof(struct omap_wd_timer_platform_data)); + WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n", +diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c +index b0790fc..71eb21f 100644 +--- a/arch/arm/mach-shmobile/platsmp-apmu.c ++++ b/arch/arm/mach-shmobile/platsmp-apmu.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include "common.h" + #include "platsmp-apmu.h" + +@@ -233,6 +234,8 @@ static int shmobile_smp_apmu_enter_suspend(suspend_state_t state) + + void __init shmobile_smp_apmu_suspend_init(void) + { +- shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend; ++ pax_open_kernel(); ++ *(void **)&shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend; ++ pax_close_kernel(); + } + #endif +diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c +index 34608fc..344d7c0 100644 +--- a/arch/arm/mach-shmobile/pm-r8a7740.c ++++ b/arch/arm/mach-shmobile/pm-r8a7740.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "common.h" + #include "pm-rmobile.h" +@@ -117,7 +118,9 @@ static int r8a7740_enter_suspend(suspend_state_t suspend_state) + + static void r8a7740_suspend_init(void) + { +- shmobile_suspend_ops.enter = r8a7740_enter_suspend; ++ pax_open_kernel(); ++ *(void **)&shmobile_suspend_ops.enter = r8a7740_enter_suspend; ++ pax_close_kernel(); + } + #else + static void r8a7740_suspend_init(void) {} +diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c +index a7e4668..83334f33 100644 +--- a/arch/arm/mach-shmobile/pm-sh73a0.c ++++ b/arch/arm/mach-shmobile/pm-sh73a0.c +@@ -9,6 +9,7 @@ + */ + + #include ++#include + #include "common.h" + + #ifdef CONFIG_SUSPEND +@@ -20,7 +21,9 @@ static int sh73a0_enter_suspend(suspend_state_t suspend_state) + + static void sh73a0_suspend_init(void) + { +- shmobile_suspend_ops.enter = sh73a0_enter_suspend; ++ pax_open_kernel(); ++ *(void **)&shmobile_suspend_ops.enter = sh73a0_enter_suspend; ++ pax_close_kernel(); + } + #else + static void sh73a0_suspend_init(void) {} +diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c +index 7469347..1ecc350 100644 +--- a/arch/arm/mach-tegra/cpuidle-tegra20.c ++++ b/arch/arm/mach-tegra/cpuidle-tegra20.c +@@ -177,7 +177,7 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev, + bool entered_lp2 = false; + + if (tegra_pending_sgi()) +- ACCESS_ONCE(abort_flag) = true; ++ ACCESS_ONCE_RW(abort_flag) = true; + + cpuidle_coupled_parallel_barrier(dev, &abort_barrier); + +diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c +index 3b9098d..15b390f 100644 +--- a/arch/arm/mach-tegra/irq.c ++++ b/arch/arm/mach-tegra/irq.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/arch/arm/mach-ux500/pm.c b/arch/arm/mach-ux500/pm.c +index 8538910..2f39bc4 100644 +--- a/arch/arm/mach-ux500/pm.c ++++ b/arch/arm/mach-ux500/pm.c +@@ -10,6 +10,7 @@ + */ + + #include ++#include + #include + #include + #include +diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c +index f66816c..228b951 100644 +--- a/arch/arm/mach-zynq/platsmp.c ++++ b/arch/arm/mach-zynq/platsmp.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include "common.h" + +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 7c6b976..055db09 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -446,6 +446,7 @@ config CPU_32v5 + + config CPU_32v6 + bool ++ select CPU_USE_DOMAINS if CPU_V6 && MMU && !PAX_KERNEXEC && !PAX_MEMORY_UDEREF + select TLS_REG_EMUL if !CPU_32v6K && !MMU + + config CPU_32v6K +@@ -600,6 +601,7 @@ config CPU_CP15_MPU + + config CPU_USE_DOMAINS + bool ++ depends on !ARM_LPAE && !PAX_KERNEXEC && !PAX_MEMORY_UDEREF + help + This option enables or disables the use of domain switching + via the set_fs() function. +@@ -818,7 +820,7 @@ config NEED_KUSER_HELPERS + + config KUSER_HELPERS + bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS +- depends on MMU ++ depends on MMU && (!(CPU_V6 || CPU_V6K || CPU_V7) || GRKERNSEC_OLD_ARM_USERLAND) + default y + help + Warning: disabling this option may break user programs. +@@ -832,7 +834,7 @@ config KUSER_HELPERS + See Documentation/arm/kernel_user_helpers.txt for details. + + However, the fixed address nature of these helpers can be used +- by ROP (return orientated programming) authors when creating ++ by ROP (Return Oriented Programming) authors when creating + exploits. + + If all of the binaries and libraries which run on your platform +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index 9769f1e..16aaa55 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -216,10 +216,12 @@ union offset_union { + #define __get16_unaligned_check(ins,val,addr) \ + do { \ + unsigned int err = 0, v, a = addr; \ ++ pax_open_userland(); \ + __get8_unaligned_check(ins,v,a,err); \ + val = v << ((BE) ? 8 : 0); \ + __get8_unaligned_check(ins,v,a,err); \ + val |= v << ((BE) ? 0 : 8); \ ++ pax_close_userland(); \ + if (err) \ + goto fault; \ + } while (0) +@@ -233,6 +235,7 @@ union offset_union { + #define __get32_unaligned_check(ins,val,addr) \ + do { \ + unsigned int err = 0, v, a = addr; \ ++ pax_open_userland(); \ + __get8_unaligned_check(ins,v,a,err); \ + val = v << ((BE) ? 24 : 0); \ + __get8_unaligned_check(ins,v,a,err); \ +@@ -241,6 +244,7 @@ union offset_union { + val |= v << ((BE) ? 8 : 16); \ + __get8_unaligned_check(ins,v,a,err); \ + val |= v << ((BE) ? 0 : 24); \ ++ pax_close_userland(); \ + if (err) \ + goto fault; \ + } while (0) +@@ -254,6 +258,7 @@ union offset_union { + #define __put16_unaligned_check(ins,val,addr) \ + do { \ + unsigned int err = 0, v = val, a = addr; \ ++ pax_open_userland(); \ + __asm__( FIRST_BYTE_16 \ + ARM( "1: "ins" %1, [%2], #1\n" ) \ + THUMB( "1: "ins" %1, [%2]\n" ) \ +@@ -273,6 +278,7 @@ union offset_union { + " .popsection\n" \ + : "=r" (err), "=&r" (v), "=&r" (a) \ + : "0" (err), "1" (v), "2" (a)); \ ++ pax_close_userland(); \ + if (err) \ + goto fault; \ + } while (0) +@@ -286,6 +292,7 @@ union offset_union { + #define __put32_unaligned_check(ins,val,addr) \ + do { \ + unsigned int err = 0, v = val, a = addr; \ ++ pax_open_userland(); \ + __asm__( FIRST_BYTE_32 \ + ARM( "1: "ins" %1, [%2], #1\n" ) \ + THUMB( "1: "ins" %1, [%2]\n" ) \ +@@ -315,6 +322,7 @@ union offset_union { + " .popsection\n" \ + : "=r" (err), "=&r" (v), "=&r" (a) \ + : "0" (err), "1" (v), "2" (a)); \ ++ pax_close_userland(); \ + if (err) \ + goto fault; \ + } while (0) +diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c +index 71b3d33..8af9ade 100644 +--- a/arch/arm/mm/cache-l2x0.c ++++ b/arch/arm/mm/cache-l2x0.c +@@ -44,7 +44,7 @@ struct l2c_init_data { + void (*configure)(void __iomem *); + void (*unlock)(void __iomem *, unsigned); + struct outer_cache_fns outer_cache; +-}; ++} __do_const; + + #define CACHE_LINE_SIZE 32 + +diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c +index 845769e..4278fd7 100644 +--- a/arch/arm/mm/context.c ++++ b/arch/arm/mm/context.c +@@ -43,7 +43,7 @@ + #define NUM_USER_ASIDS ASID_FIRST_VERSION + + static DEFINE_RAW_SPINLOCK(cpu_asid_lock); +-static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION); ++static atomic64_unchecked_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION); + static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS); + + static DEFINE_PER_CPU(atomic64_t, active_asids); +@@ -178,7 +178,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) + { + static u32 cur_idx = 1; + u64 asid = atomic64_read(&mm->context.id); +- u64 generation = atomic64_read(&asid_generation); ++ u64 generation = atomic64_read_unchecked(&asid_generation); + + if (asid != 0) { + /* +@@ -208,7 +208,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) + */ + asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); + if (asid == NUM_USER_ASIDS) { +- generation = atomic64_add_return(ASID_FIRST_VERSION, ++ generation = atomic64_add_return_unchecked(ASID_FIRST_VERSION, + &asid_generation); + flush_context(cpu); + asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); +@@ -240,14 +240,14 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) + cpu_set_reserved_ttbr0(); + + asid = atomic64_read(&mm->context.id); +- if (!((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) ++ if (!((asid ^ atomic64_read_unchecked(&asid_generation)) >> ASID_BITS) + && atomic64_xchg(&per_cpu(active_asids, cpu), asid)) + goto switch_mm_fastpath; + + raw_spin_lock_irqsave(&cpu_asid_lock, flags); + /* Check that our ASID belongs to the current generation. */ + asid = atomic64_read(&mm->context.id); +- if ((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) { ++ if ((asid ^ atomic64_read_unchecked(&asid_generation)) >> ASID_BITS) { + asid = new_context(mm, cpu); + atomic64_set(&mm->context.id, asid); + } +diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c +index 0d629b8..01867c8 100644 +--- a/arch/arm/mm/fault.c ++++ b/arch/arm/mm/fault.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "fault.h" + +@@ -138,6 +139,31 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, + if (fixup_exception(regs)) + return; + ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ if (addr < TASK_SIZE) { ++ if (current->signal->curr_ip) ++ printk(KERN_EMERG "PAX: From %pI4: %s:%d, uid/euid: %u/%u, attempted to access userland memory at %08lx\n", ¤t->signal->curr_ip, current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), addr); ++ else ++ printk(KERN_EMERG "PAX: %s:%d, uid/euid: %u/%u, attempted to access userland memory at %08lx\n", current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), addr); ++ } ++#endif ++ ++#ifdef CONFIG_PAX_KERNEXEC ++ if ((fsr & FSR_WRITE) && ++ (((unsigned long)_stext <= addr && addr < init_mm.end_code) || ++ (MODULES_VADDR <= addr && addr < MODULES_END))) ++ { ++ if (current->signal->curr_ip) ++ printk(KERN_EMERG "PAX: From %pI4: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n", ¤t->signal->curr_ip, current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid())); ++ else ++ printk(KERN_EMERG "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n", current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid())); ++ } ++#endif ++ + /* + * No handler, we'll have to terminate things with extreme prejudice. + */ +@@ -173,6 +199,13 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, + } + #endif + ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (fsr & FSR_LNX_PF) { ++ pax_report_fault(regs, (void *)regs->ARM_pc, (void *)regs->ARM_sp); ++ do_group_exit(SIGKILL); ++ } ++#endif ++ + tsk->thread.address = addr; + tsk->thread.error_code = fsr; + tsk->thread.trap_no = 14; +@@ -400,6 +433,33 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + } + #endif /* CONFIG_MMU */ + ++#ifdef CONFIG_PAX_PAGEEXEC ++void pax_report_insns(struct pt_regs *regs, void *pc, void *sp) ++{ ++ long i; ++ ++ printk(KERN_ERR "PAX: bytes at PC: "); ++ for (i = 0; i < 20; i++) { ++ unsigned char c; ++ if (get_user(c, (__force unsigned char __user *)pc+i)) ++ printk(KERN_CONT "?? "); ++ else ++ printk(KERN_CONT "%02x ", c); ++ } ++ printk("\n"); ++ ++ printk(KERN_ERR "PAX: bytes at SP-4: "); ++ for (i = -1; i < 20; i++) { ++ unsigned long c; ++ if (get_user(c, (__force unsigned long __user *)sp+i)) ++ printk(KERN_CONT "???????? "); ++ else ++ printk(KERN_CONT "%08lx ", c); ++ } ++ printk("\n"); ++} ++#endif ++ + /* + * First Level Translation Fault Handler + * +@@ -547,9 +607,22 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + const struct fsr_info *inf = fsr_info + fsr_fs(fsr); + struct siginfo info; + ++#ifdef CONFIG_PAX_MEMORY_UDEREF ++ if (addr < TASK_SIZE && is_domain_fault(fsr)) { ++ if (current->signal->curr_ip) ++ printk(KERN_EMERG "PAX: From %pI4: %s:%d, uid/euid: %u/%u, attempted to access userland memory at %08lx\n", ¤t->signal->curr_ip, current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), addr); ++ else ++ printk(KERN_EMERG "PAX: %s:%d, uid/euid: %u/%u, attempted to access userland memory at %08lx\n", current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), addr); ++ goto die; ++ } ++#endif ++ + if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) + return; + ++die: + pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n", + inf->name, fsr, addr); + show_pte(current->mm, addr); +@@ -574,15 +647,104 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs * + ifsr_info[nr].name = name; + } + ++asmlinkage int sys_sigreturn(struct pt_regs *regs); ++asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); ++ + asmlinkage void __exception + do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) + { + const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); + struct siginfo info; ++ unsigned long pc = instruction_pointer(regs); ++ ++ if (user_mode(regs)) { ++ unsigned long sigpage = current->mm->context.sigpage; ++ ++ if (sigpage <= pc && pc < sigpage + 7*4) { ++ if (pc < sigpage + 3*4) ++ sys_sigreturn(regs); ++ else ++ sys_rt_sigreturn(regs); ++ return; ++ } ++ if (pc == 0xffff0f60UL) { ++ /* ++ * PaX: __kuser_cmpxchg64 emulation ++ */ ++ // TODO ++ //regs->ARM_pc = regs->ARM_lr; ++ //return; ++ } ++ if (pc == 0xffff0fa0UL) { ++ /* ++ * PaX: __kuser_memory_barrier emulation ++ */ ++ // dmb(); implied by the exception ++ regs->ARM_pc = regs->ARM_lr; ++ return; ++ } ++ if (pc == 0xffff0fc0UL) { ++ /* ++ * PaX: __kuser_cmpxchg emulation ++ */ ++ // TODO ++ //long new; ++ //int op; ++ ++ //op = FUTEX_OP_SET << 28; ++ //new = futex_atomic_op_inuser(op, regs->ARM_r2); ++ //regs->ARM_r0 = old != new; ++ //regs->ARM_pc = regs->ARM_lr; ++ //return; ++ } ++ if (pc == 0xffff0fe0UL) { ++ /* ++ * PaX: __kuser_get_tls emulation ++ */ ++ regs->ARM_r0 = current_thread_info()->tp_value[0]; ++ regs->ARM_pc = regs->ARM_lr; ++ return; ++ } ++ } ++ ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++ else if (is_domain_fault(ifsr) || is_xn_fault(ifsr)) { ++ if (current->signal->curr_ip) ++ printk(KERN_EMERG "PAX: From %pI4: %s:%d, uid/euid: %u/%u, attempted to execute %s memory at %08lx\n", ¤t->signal->curr_ip, current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), ++ pc >= TASK_SIZE ? "non-executable kernel" : "userland", pc); ++ else ++ printk(KERN_EMERG "PAX: %s:%d, uid/euid: %u/%u, attempted to execute %s memory at %08lx\n", current->comm, task_pid_nr(current), ++ from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), ++ pc >= TASK_SIZE ? "non-executable kernel" : "userland", pc); ++ goto die; ++ } ++#endif ++ ++#ifdef CONFIG_PAX_REFCOUNT ++ if (fsr_fs(ifsr) == FAULT_CODE_DEBUG) { ++#ifdef CONFIG_THUMB2_KERNEL ++ unsigned short bkpt; ++ ++ if (!probe_kernel_address(pc, bkpt) && cpu_to_le16(bkpt) == 0xbef1) { ++#else ++ unsigned int bkpt; ++ ++ if (!probe_kernel_address(pc, bkpt) && cpu_to_le32(bkpt) == 0xe12f1073) { ++#endif ++ current->thread.error_code = ifsr; ++ current->thread.trap_no = 0; ++ pax_report_refcount_overflow(regs); ++ fixup_exception(regs); ++ return; ++ } ++ } ++#endif + + if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) + return; + ++die: + pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", + inf->name, ifsr, addr); + +diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h +index cf08bdf..772656c 100644 +--- a/arch/arm/mm/fault.h ++++ b/arch/arm/mm/fault.h +@@ -3,6 +3,7 @@ + + /* + * Fault status register encodings. We steal bit 31 for our own purposes. ++ * Set when the FSR value is from an instruction fault. + */ + #define FSR_LNX_PF (1 << 31) + #define FSR_WRITE (1 << 11) +@@ -22,6 +23,17 @@ static inline int fsr_fs(unsigned int fsr) + } + #endif + ++/* valid for LPAE and !LPAE */ ++static inline int is_xn_fault(unsigned int fsr) ++{ ++ return ((fsr_fs(fsr) & 0x3c) == 0xc); ++} ++ ++static inline int is_domain_fault(unsigned int fsr) ++{ ++ return ((fsr_fs(fsr) & 0xD) == 0x9); ++} ++ + void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs); + unsigned long search_exception_table(unsigned long addr); + +diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c +index 8a63b4c..6b04370 100644 +--- a/arch/arm/mm/init.c ++++ b/arch/arm/mm/init.c +@@ -710,7 +710,46 @@ void free_tcmmem(void) + { + #ifdef CONFIG_HAVE_TCM + extern char __tcm_start, __tcm_end; ++#endif + ++#ifdef CONFIG_PAX_KERNEXEC ++ unsigned long addr; ++ pgd_t *pgd; ++ pud_t *pud; ++ pmd_t *pmd; ++ int cpu_arch = cpu_architecture(); ++ unsigned int cr = get_cr(); ++ ++ if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { ++ /* make pages tables, etc before .text NX */ ++ for (addr = PAGE_OFFSET; addr < (unsigned long)_stext; addr += SECTION_SIZE) { ++ pgd = pgd_offset_k(addr); ++ pud = pud_offset(pgd, addr); ++ pmd = pmd_offset(pud, addr); ++ __section_update(pmd, addr, PMD_SECT_XN); ++ } ++ /* make init NX */ ++ for (addr = (unsigned long)__init_begin; addr < (unsigned long)_sdata; addr += SECTION_SIZE) { ++ pgd = pgd_offset_k(addr); ++ pud = pud_offset(pgd, addr); ++ pmd = pmd_offset(pud, addr); ++ __section_update(pmd, addr, PMD_SECT_XN); ++ } ++ /* make kernel code/rodata RX */ ++ for (addr = (unsigned long)_stext; addr < (unsigned long)__init_begin; addr += SECTION_SIZE) { ++ pgd = pgd_offset_k(addr); ++ pud = pud_offset(pgd, addr); ++ pmd = pmd_offset(pud, addr); ++#ifdef CONFIG_ARM_LPAE ++ __section_update(pmd, addr, PMD_SECT_RDONLY); ++#else ++ __section_update(pmd, addr, PMD_SECT_APX|PMD_SECT_AP_WRITE); ++#endif ++ } ++ } ++#endif ++ ++#ifdef CONFIG_HAVE_TCM + poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); + free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); + #endif +diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c +index 0c81056..97279f7 100644 +--- a/arch/arm/mm/ioremap.c ++++ b/arch/arm/mm/ioremap.c +@@ -405,9 +405,9 @@ __arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached) + unsigned int mtype; + + if (cached) +- mtype = MT_MEMORY_RWX; ++ mtype = MT_MEMORY_RX; + else +- mtype = MT_MEMORY_RWX_NONCACHED; ++ mtype = MT_MEMORY_RX_NONCACHED; + + return __arm_ioremap_caller(phys_addr, size, mtype, + __builtin_return_address(0)); +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 407dc78..047ce9d 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -59,6 +59,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + struct vm_area_struct *vma; + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); ++ unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); + struct vm_unmapped_area_info info; + + /* +@@ -81,6 +82,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + if (len > TASK_SIZE) + return -ENOMEM; + ++#ifdef CONFIG_PAX_RANDMMAP ++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) ++#endif ++ + if (addr) { + if (do_align) + addr = COLOUR_ALIGN(addr, pgoff); +@@ -88,8 +93,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len, offset)) + return addr; + } + +@@ -99,6 +103,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + info.high_limit = TASK_SIZE; + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_offset = pgoff << PAGE_SHIFT; ++ info.threadstack_offset = offset; + return vm_unmapped_area(&info); + } + +@@ -112,6 +117,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + unsigned long addr = addr0; + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); ++ unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); + struct vm_unmapped_area_info info; + + /* +@@ -132,6 +138,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + return addr; + } + ++#ifdef CONFIG_PAX_RANDMMAP ++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) ++#endif ++ + /* requesting a specific address */ + if (addr) { + if (do_align) +@@ -139,8 +149,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + else + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len, offset)) + return addr; + } + +@@ -150,6 +159,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + info.high_limit = mm->mmap_base; + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_offset = pgoff << PAGE_SHIFT; ++ info.threadstack_offset = offset; + addr = vm_unmapped_area(&info); + + /* +@@ -183,14 +193,30 @@ void arch_pick_mmap_layout(struct mm_struct *mm) + { + unsigned long random_factor = 0UL; + ++#ifdef CONFIG_PAX_RANDMMAP ++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) ++#endif ++ + if (current->flags & PF_RANDOMIZE) + random_factor = arch_mmap_rnd(); + + if (mmap_is_legacy()) { + mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; ++ ++#ifdef CONFIG_PAX_RANDMMAP ++ if (mm->pax_flags & MF_PAX_RANDMMAP) ++ mm->mmap_base += mm->delta_mmap; ++#endif ++ + mm->get_unmapped_area = arch_get_unmapped_area; + } else { + mm->mmap_base = mmap_base(random_factor); ++ ++#ifdef CONFIG_PAX_RANDMMAP ++ if (mm->pax_flags & MF_PAX_RANDMMAP) ++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack; ++#endif ++ + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + } + } +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index 870838a..070df1d 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -41,6 +41,22 @@ + #include "mm.h" + #include "tcm.h" + ++#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) ++void modify_domain(unsigned int dom, unsigned int type) ++{ ++ struct thread_info *thread = current_thread_info(); ++ unsigned int domain = thread->cpu_domain; ++ /* ++ * DOMAIN_MANAGER might be defined to some other value, ++ * use the arch-defined constant ++ */ ++ domain &= ~domain_val(dom, 3); ++ thread->cpu_domain = domain | domain_val(dom, type); ++ set_domain(thread->cpu_domain); ++} ++EXPORT_SYMBOL(modify_domain); ++#endif ++ + /* + * empty_zero_page is a special page that is used for + * zero-initialized data and COW. +@@ -242,7 +258,15 @@ __setup("noalign", noalign_setup); + #define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE + #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE + +-static struct mem_type mem_types[] = { ++#ifdef CONFIG_PAX_KERNEXEC ++#define L_PTE_KERNEXEC L_PTE_RDONLY ++#define PMD_SECT_KERNEXEC PMD_SECT_RDONLY ++#else ++#define L_PTE_KERNEXEC L_PTE_DIRTY ++#define PMD_SECT_KERNEXEC PMD_SECT_AP_WRITE ++#endif ++ ++static struct mem_type mem_types[] __read_only = { + [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */ + .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED | + L_PTE_SHARED, +@@ -271,19 +295,19 @@ static struct mem_type mem_types[] = { + .prot_sect = PROT_SECT_DEVICE, + .domain = DOMAIN_IO, + }, +- [MT_UNCACHED] = { ++ [MT_UNCACHED_RW] = { + .prot_pte = PROT_PTE_DEVICE, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, + .domain = DOMAIN_IO, + }, +- [MT_CACHECLEAN] = { +- .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, ++ [MT_CACHECLEAN_RO] = { ++ .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_RDONLY, + .domain = DOMAIN_KERNEL, + }, + #ifndef CONFIG_ARM_LPAE +- [MT_MINICLEAN] = { +- .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE, ++ [MT_MINICLEAN_RO] = { ++ .prot_sect = PMD_TYPE_SECT | PMD_SECT_MINICACHE | PMD_SECT_XN | PMD_SECT_RDONLY, + .domain = DOMAIN_KERNEL, + }, + #endif +@@ -291,15 +315,15 @@ static struct mem_type mem_types[] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_RDONLY, + .prot_l1 = PMD_TYPE_TABLE, +- .domain = DOMAIN_USER, ++ .domain = DOMAIN_VECTORS, + }, + [MT_HIGH_VECTORS] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_USER | L_PTE_RDONLY, + .prot_l1 = PMD_TYPE_TABLE, +- .domain = DOMAIN_USER, ++ .domain = DOMAIN_VECTORS, + }, +- [MT_MEMORY_RWX] = { ++ [__MT_MEMORY_RWX] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, +@@ -312,17 +336,30 @@ static struct mem_type mem_types[] = { + .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, + .domain = DOMAIN_KERNEL, + }, +- [MT_ROM] = { +- .prot_sect = PMD_TYPE_SECT, ++ [MT_MEMORY_RX] = { ++ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_KERNEXEC, ++ .prot_l1 = PMD_TYPE_TABLE, ++ .prot_sect = PMD_TYPE_SECT | PMD_SECT_KERNEXEC, ++ .domain = DOMAIN_KERNEL, ++ }, ++ [MT_ROM_RX] = { ++ .prot_sect = PMD_TYPE_SECT | PMD_SECT_RDONLY, + .domain = DOMAIN_KERNEL, + }, +- [MT_MEMORY_RWX_NONCACHED] = { ++ [MT_MEMORY_RW_NONCACHED] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_MT_BUFFERABLE, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, + .domain = DOMAIN_KERNEL, + }, ++ [MT_MEMORY_RX_NONCACHED] = { ++ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_KERNEXEC | ++ L_PTE_MT_BUFFERABLE, ++ .prot_l1 = PMD_TYPE_TABLE, ++ .prot_sect = PMD_TYPE_SECT | PMD_SECT_KERNEXEC, ++ .domain = DOMAIN_KERNEL, ++ }, + [MT_MEMORY_RW_DTCM] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_XN, +@@ -330,9 +367,10 @@ static struct mem_type mem_types[] = { + .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, + .domain = DOMAIN_KERNEL, + }, +- [MT_MEMORY_RWX_ITCM] = { +- .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, ++ [MT_MEMORY_RX_ITCM] = { ++ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_KERNEXEC, + .prot_l1 = PMD_TYPE_TABLE, ++ .prot_sect = PMD_TYPE_SECT | PMD_SECT_KERNEXEC, + .domain = DOMAIN_KERNEL, + }, + [MT_MEMORY_RW_SO] = { +@@ -544,9 +582,14 @@ static void __init build_mem_type_table(void) + * Mark cache clean areas and XIP ROM read only + * from SVC mode and no access from userspace. + */ +- mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; +- mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; +- mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; ++ mem_types[MT_ROM_RX].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; ++#ifdef CONFIG_PAX_KERNEXEC ++ mem_types[MT_MEMORY_RX].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; ++ mem_types[MT_MEMORY_RX_ITCM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; ++#endif ++ mem_types[MT_MINICLEAN_RO].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; ++ mem_types[MT_CACHECLEAN_RO].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; + #endif + + /* +@@ -563,13 +606,17 @@ static void __init build_mem_type_table(void) + mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; + mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; +- mem_types[MT_MEMORY_RWX].prot_sect |= PMD_SECT_S; +- mem_types[MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED; ++ mem_types[__MT_MEMORY_RWX].prot_sect |= PMD_SECT_S; ++ mem_types[__MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_RW].prot_pte |= L_PTE_SHARED; ++ mem_types[MT_MEMORY_RX].prot_sect |= PMD_SECT_S; ++ mem_types[MT_MEMORY_RX].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED; +- mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_S; +- mem_types[MT_MEMORY_RWX_NONCACHED].prot_pte |= L_PTE_SHARED; ++ mem_types[MT_MEMORY_RW_NONCACHED].prot_sect |= PMD_SECT_S; ++ mem_types[MT_MEMORY_RW_NONCACHED].prot_pte |= L_PTE_SHARED; ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_sect |= PMD_SECT_S; ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_pte |= L_PTE_SHARED; + } + } + +@@ -580,15 +627,20 @@ static void __init build_mem_type_table(void) + if (cpu_arch >= CPU_ARCH_ARMv6) { + if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { + /* Non-cacheable Normal is XCB = 001 */ +- mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ++ mem_types[MT_MEMORY_RW_NONCACHED].prot_sect |= ++ PMD_SECT_BUFFERED; ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_sect |= + PMD_SECT_BUFFERED; + } else { + /* For both ARMv6 and non-TEX-remapping ARMv7 */ +- mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ++ mem_types[MT_MEMORY_RW_NONCACHED].prot_sect |= ++ PMD_SECT_TEX(1); ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_sect |= + PMD_SECT_TEX(1); + } + } else { +- mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; ++ mem_types[MT_MEMORY_RW_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; + } + + #ifdef CONFIG_ARM_LPAE +@@ -609,6 +661,8 @@ static void __init build_mem_type_table(void) + user_pgprot |= PTE_EXT_PXN; + #endif + ++ user_pgprot |= __supported_pte_mask; ++ + for (i = 0; i < 16; i++) { + pteval_t v = pgprot_val(protection_map[i]); + protection_map[i] = __pgprot(v | user_pgprot); +@@ -626,21 +680,24 @@ static void __init build_mem_type_table(void) + + mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; + mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; +- mem_types[MT_MEMORY_RWX].prot_sect |= ecc_mask | cp->pmd; +- mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot; ++ mem_types[__MT_MEMORY_RWX].prot_sect |= ecc_mask | cp->pmd; ++ mem_types[__MT_MEMORY_RWX].prot_pte |= kern_pgprot; + mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot; ++ mem_types[MT_MEMORY_RX].prot_sect |= ecc_mask | cp->pmd; ++ mem_types[MT_MEMORY_RX].prot_pte |= kern_pgprot; + mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot; +- mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask; +- mem_types[MT_ROM].prot_sect |= cp->pmd; ++ mem_types[MT_MEMORY_RW_NONCACHED].prot_sect |= ecc_mask; ++ mem_types[MT_MEMORY_RX_NONCACHED].prot_sect |= ecc_mask; ++ mem_types[MT_ROM_RX].prot_sect |= cp->pmd; + + switch (cp->pmd) { + case PMD_SECT_WT: +- mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; ++ mem_types[MT_CACHECLEAN_RO].prot_sect |= PMD_SECT_WT; + break; + case PMD_SECT_WB: + case PMD_SECT_WBWA: +- mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB; ++ mem_types[MT_CACHECLEAN_RO].prot_sect |= PMD_SECT_WB; + break; + } + pr_info("Memory policy: %sData cache %s\n", +@@ -854,7 +911,7 @@ static void __init create_mapping(struct map_desc *md) + return; + } + +- if ((md->type == MT_DEVICE || md->type == MT_ROM) && ++ if ((md->type == MT_DEVICE || md->type == MT_ROM_RX) && + md->virtual >= PAGE_OFFSET && + (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { + pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n", +@@ -1224,18 +1281,15 @@ void __init arm_mm_memblock_reserve(void) + * called function. This means you can't use any function or debugging + * method which may touch any device, otherwise the kernel _will_ crash. + */ ++ ++static char vectors[PAGE_SIZE * 2] __read_only __aligned(PAGE_SIZE); ++ + static void __init devicemaps_init(const struct machine_desc *mdesc) + { + struct map_desc map; + unsigned long addr; +- void *vectors; + +- /* +- * Allocate the vector page early. +- */ +- vectors = early_alloc(PAGE_SIZE * 2); +- +- early_trap_init(vectors); ++ early_trap_init(&vectors); + + for (addr = VMALLOC_START; addr; addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); +@@ -1248,7 +1302,7 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) + map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); + map.virtual = MODULES_VADDR; + map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; +- map.type = MT_ROM; ++ map.type = MT_ROM_RX; + create_mapping(&map); + #endif + +@@ -1259,14 +1313,14 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) + map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS); + map.virtual = FLUSH_BASE; + map.length = SZ_1M; +- map.type = MT_CACHECLEAN; ++ map.type = MT_CACHECLEAN_RO; + create_mapping(&map); + #endif + #ifdef FLUSH_BASE_MINICACHE + map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M); + map.virtual = FLUSH_BASE_MINICACHE; + map.length = SZ_1M; +- map.type = MT_MINICLEAN; ++ map.type = MT_MINICLEAN_RO; + create_mapping(&map); + #endif + +@@ -1275,7 +1329,7 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) + * location (0xffff0000). If we aren't using high-vectors, also + * create a mapping at the low-vectors virtual address. + */ +- map.pfn = __phys_to_pfn(virt_to_phys(vectors)); ++ map.pfn = __phys_to_pfn(virt_to_phys(&vectors)); + map.virtual = 0xffff0000; + map.length = PAGE_SIZE; + #ifdef CONFIG_KUSER_HELPERS +@@ -1335,8 +1389,10 @@ static void __init kmap_init(void) + static void __init map_lowmem(void) + { + struct memblock_region *reg; ++#ifndef CONFIG_PAX_KERNEXEC + phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE); + phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); ++#endif + + /* Map all the lowmem memory banks. */ + for_each_memblock(memory, reg) { +@@ -1349,11 +1405,48 @@ static void __init map_lowmem(void) + if (start >= end) + break; + ++#ifdef CONFIG_PAX_KERNEXEC ++ map.pfn = __phys_to_pfn(start); ++ map.virtual = __phys_to_virt(start); ++ map.length = end - start; ++ ++ if (map.virtual <= (unsigned long)_stext && ((unsigned long)_end < (map.virtual + map.length))) { ++ struct map_desc kernel; ++ struct map_desc initmap; ++ ++ /* when freeing initmem we will make this RW */ ++ initmap.pfn = __phys_to_pfn(__pa(__init_begin)); ++ initmap.virtual = (unsigned long)__init_begin; ++ initmap.length = _sdata - __init_begin; ++ initmap.type = __MT_MEMORY_RWX; ++ create_mapping(&initmap); ++ ++ /* when freeing initmem we will make this RX */ ++ kernel.pfn = __phys_to_pfn(__pa(_stext)); ++ kernel.virtual = (unsigned long)_stext; ++ kernel.length = __init_begin - _stext; ++ kernel.type = __MT_MEMORY_RWX; ++ create_mapping(&kernel); ++ ++ if (map.virtual < (unsigned long)_stext) { ++ map.length = (unsigned long)_stext - map.virtual; ++ map.type = __MT_MEMORY_RWX; ++ create_mapping(&map); ++ } ++ ++ map.pfn = __phys_to_pfn(__pa(_sdata)); ++ map.virtual = (unsigned long)_sdata; ++ map.length = end - __pa(_sdata); ++ } ++ ++ map.type = MT_MEMORY_RW; ++ create_mapping(&map); ++#else + if (end < kernel_x_start) { + map.pfn = __phys_to_pfn(start); + map.virtual = __phys_to_virt(start); + map.length = end - start; +- map.type = MT_MEMORY_RWX; ++ map.type = __MT_MEMORY_RWX; + + create_mapping(&map); + } else if (start >= kernel_x_end) { +@@ -1377,7 +1470,7 @@ static void __init map_lowmem(void) + map.pfn = __phys_to_pfn(kernel_x_start); + map.virtual = __phys_to_virt(kernel_x_start); + map.length = kernel_x_end - kernel_x_start; +- map.type = MT_MEMORY_RWX; ++ map.type = __MT_MEMORY_RWX; + + create_mapping(&map); + +@@ -1390,6 +1483,7 @@ static void __init map_lowmem(void) + create_mapping(&map); + } + } ++#endif + } + } + +diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c +index c011e22..92a0260 100644 +--- a/arch/arm/net/bpf_jit_32.c ++++ b/arch/arm/net/bpf_jit_32.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include "bpf_jit_32.h" + +@@ -72,54 +73,38 @@ struct jit_ctx { + #endif + }; + ++#ifdef CONFIG_GRKERNSEC_BPF_HARDEN ++int bpf_jit_enable __read_only; ++#else + int bpf_jit_enable __read_mostly; ++#endif + +-static inline int call_neg_helper(struct sk_buff *skb, int offset, void *ret, +- unsigned int size) +-{ +- void *ptr = bpf_internal_load_pointer_neg_helper(skb, offset, size); +- +- if (!ptr) +- return -EFAULT; +- memcpy(ret, ptr, size); +- return 0; +-} +- +-static u64 jit_get_skb_b(struct sk_buff *skb, int offset) ++static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) + { + u8 ret; + int err; + +- if (offset < 0) +- err = call_neg_helper(skb, offset, &ret, 1); +- else +- err = skb_copy_bits(skb, offset, &ret, 1); ++ err = skb_copy_bits(skb, offset, &ret, 1); + + return (u64)err << 32 | ret; + } + +-static u64 jit_get_skb_h(struct sk_buff *skb, int offset) ++static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) + { + u16 ret; + int err; + +- if (offset < 0) +- err = call_neg_helper(skb, offset, &ret, 2); +- else +- err = skb_copy_bits(skb, offset, &ret, 2); ++ err = skb_copy_bits(skb, offset, &ret, 2); + + return (u64)err << 32 | ntohs(ret); + } + +-static u64 jit_get_skb_w(struct sk_buff *skb, int offset) ++static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) + { + u32 ret; + int err; + +- if (offset < 0) +- err = call_neg_helper(skb, offset, &ret, 4); +- else +- err = skb_copy_bits(skb, offset, &ret, 4); ++ err = skb_copy_bits(skb, offset, &ret, 4); + + return (u64)err << 32 | ntohl(ret); + } +@@ -199,8 +184,10 @@ static void jit_fill_hole(void *area, unsigned int size) + { + u32 *ptr; + /* We are guaranteed to have aligned memory. */ ++ pax_open_kernel(); + for (ptr = area; size >= sizeof(u32); size -= sizeof(u32)) + *ptr++ = __opcode_to_mem_arm(ARM_INST_UDF); ++ pax_close_kernel(); + } + + static void build_prologue(struct jit_ctx *ctx) +@@ -556,6 +543,9 @@ static int build_body(struct jit_ctx *ctx) + case BPF_LD | BPF_B | BPF_ABS: + load_order = 0; + load: ++ /* the interpreter will deal with the negative K */ ++ if ((int)k < 0) ++ return -ENOTSUPP; + emit_mov_i(r_off, k, ctx); + load_common: + ctx->seen |= SEEN_DATA | SEEN_CALL; +@@ -570,18 +560,6 @@ load_common: + condt = ARM_COND_HI; + } + +- /* +- * test for negative offset, only if we are +- * currently scheduled to take the fast +- * path. this will update the flags so that +- * the slowpath instruction are ignored if the +- * offset is negative. +- * +- * for loard_order == 0 the HI condition will +- * make loads at offset 0 take the slow path too. +- */ +- _emit(condt, ARM_CMP_I(r_off, 0), ctx); +- + _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data), + ctx); + +diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c +index 5b217f4..c23f40e 100644 +--- a/arch/arm/plat-iop/setup.c ++++ b/arch/arm/plat-iop/setup.c +@@ -24,7 +24,7 @@ static struct map_desc iop3xx_std_desc[] __initdata = { + .virtual = IOP3XX_PERIPHERAL_VIRT_BASE, + .pfn = __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE), + .length = IOP3XX_PERIPHERAL_SIZE, +- .type = MT_UNCACHED, ++ .type = MT_UNCACHED_RW, + }, + }; + +diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c +index a5bc92d..0bb4730 100644 +--- a/arch/arm/plat-omap/sram.c ++++ b/arch/arm/plat-omap/sram.c +@@ -93,6 +93,8 @@ void __init omap_map_sram(unsigned long start, unsigned long size, + * Looks like we need to preserve some bootloader code at the + * beginning of SRAM for jumping to flash for reboot to work... + */ ++ pax_open_kernel(); + memset_io(omap_sram_base + omap_sram_skip, 0, + omap_sram_size - omap_sram_skip); ++ pax_close_kernel(); + } +diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug +index d6285ef..b684dac 100644 +--- a/arch/arm64/Kconfig.debug ++++ b/arch/arm64/Kconfig.debug +@@ -10,6 +10,7 @@ config ARM64_PTDUMP + bool "Export kernel pagetable layout to userspace via debugfs" + depends on DEBUG_KERNEL + select DEBUG_FS ++ depends on !GRKERNSEC_KMEM + help + Say Y here if you want to show the kernel pagetable layout in a + debugfs file. This information is only useful for kernel developers +diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h +index 7047051..44e8675 100644 +--- a/arch/arm64/include/asm/atomic.h ++++ b/arch/arm64/include/asm/atomic.h +@@ -252,5 +252,15 @@ static inline int atomic64_add_unless(atomic64_t *v, long a, long u) + #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) + #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) + ++#define atomic64_read_unchecked(v) atomic64_read(v) ++#define atomic64_set_unchecked(v, i) atomic64_set((v), (i)) ++#define atomic64_add_unchecked(a, v) atomic64_add((a), (v)) ++#define atomic64_add_return_unchecked(a, v) atomic64_add_return((a), (v)) ++#define atomic64_sub_unchecked(a, v) atomic64_sub((a), (v)) ++#define atomic64_inc_unchecked(v) atomic64_inc(v) ++#define atomic64_inc_return_unchecked(v) atomic64_inc_return(v) ++#define atomic64_dec_unchecked(v) atomic64_dec(v) ++#define atomic64_cmpxchg_unchecked(v, o, n) atomic64_cmpxchg((v), (o), (n)) ++ + #endif + #endif +diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h +index 0fa47c4..b167938 100644 +--- a/arch/arm64/include/asm/barrier.h ++++ b/arch/arm64/include/asm/barrier.h +@@ -44,7 +44,7 @@ + do { \ + compiletime_assert_atomic_type(*p); \ + barrier(); \ +- ACCESS_ONCE(*p) = (v); \ ++ ACCESS_ONCE_RW(*p) = (v); \ + } while (0) + + #define smp_load_acquire(p) \ +diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h +index 4fde8c1..441f84f 100644 +--- a/arch/arm64/include/asm/percpu.h ++++ b/arch/arm64/include/asm/percpu.h +@@ -135,16 +135,16 @@ static inline void __percpu_write(void *ptr, unsigned long val, int size) + { + switch (size) { + case 1: +- ACCESS_ONCE(*(u8 *)ptr) = (u8)val; ++ ACCESS_ONCE_RW(*(u8 *)ptr) = (u8)val; + break; + case 2: +- ACCESS_ONCE(*(u16 *)ptr) = (u16)val; ++ ACCESS_ONCE_RW(*(u16 *)ptr) = (u16)val; + break; + case 4: +- ACCESS_ONCE(*(u32 *)ptr) = (u32)val; ++ ACCESS_ONCE_RW(*(u32 *)ptr) = (u32)val; + break; + case 8: +- ACCESS_ONCE(*(u64 *)ptr) = (u64)val; ++ ACCESS_ONCE_RW(*(u64 *)ptr) = (u64)val; + break; + default: + BUILD_BUG(); +diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h +index 7642056..bffc904 100644 +--- a/arch/arm64/include/asm/pgalloc.h ++++ b/arch/arm64/include/asm/pgalloc.h +@@ -46,6 +46,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) + set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); + } + ++static inline void pud_populate_kernel(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) ++{ ++ pud_populate(mm, pud, pmd); ++} ++ + #endif /* CONFIG_PGTABLE_LEVELS > 2 */ + + #if CONFIG_PGTABLE_LEVELS > 3 +diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h +index 07e1ba44..ec8cbbb 100644 +--- a/arch/arm64/include/asm/uaccess.h ++++ b/arch/arm64/include/asm/uaccess.h +@@ -99,6 +99,7 @@ static inline void set_fs(mm_segment_t fs) + flag; \ + }) + ++#define access_ok_noprefault(type, addr, size) access_ok((type), (addr), (size)) + #define access_ok(type, addr, size) __range_ok(addr, size) + #define user_addr_max get_fs + +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index d16a1ce..a5acc60 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -134,7 +134,7 @@ static void __dma_free_coherent(struct device *dev, size_t size, + phys_to_page(paddr), + size >> PAGE_SHIFT); + if (!freed) +- swiotlb_free_coherent(dev, size, vaddr, dma_handle); ++ swiotlb_free_coherent(dev, size, vaddr, dma_handle, attrs); + } + + static void *__dma_alloc(struct device *dev, size_t size, +diff --git a/arch/avr32/include/asm/cache.h b/arch/avr32/include/asm/cache.h +index c3a58a1..78fbf54 100644 +--- a/arch/avr32/include/asm/cache.h ++++ b/arch/avr32/include/asm/cache.h +@@ -1,8 +1,10 @@ + #ifndef __ASM_AVR32_CACHE_H + #define __ASM_AVR32_CACHE_H + ++#include ++ + #define L1_CACHE_SHIFT 5 +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + /* + * Memory returned by kmalloc() may be used for DMA, so we must make +diff --git a/arch/avr32/include/asm/elf.h b/arch/avr32/include/asm/elf.h +index 0388ece..87c8df1 100644 +--- a/arch/avr32/include/asm/elf.h ++++ b/arch/avr32/include/asm/elf.h +@@ -84,8 +84,14 @@ typedef struct user_fpu_struct elf_fpregset_t; + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +-#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) ++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) + ++#ifdef CONFIG_PAX_ASLR ++#define PAX_ELF_ET_DYN_BASE 0x00001000UL ++ ++#define PAX_DELTA_MMAP_LEN 15 ++#define PAX_DELTA_STACK_LEN 15 ++#endif + + /* This yields a mask that user programs can use to figure out what + instruction set this CPU supports. This could be done in user space, +diff --git a/arch/avr32/include/asm/kmap_types.h b/arch/avr32/include/asm/kmap_types.h +index 479330b..53717a8 100644 +--- a/arch/avr32/include/asm/kmap_types.h ++++ b/arch/avr32/include/asm/kmap_types.h +@@ -2,9 +2,9 @@ + #define __ASM_AVR32_KMAP_TYPES_H + + #ifdef CONFIG_DEBUG_HIGHMEM +-# define KM_TYPE_NR 29 ++# define KM_TYPE_NR 30 + #else +-# define KM_TYPE_NR 14 ++# define KM_TYPE_NR 15 + #endif + + #endif /* __ASM_AVR32_KMAP_TYPES_H */ +diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c +index c035339..e1fa594 100644 +--- a/arch/avr32/mm/fault.c ++++ b/arch/avr32/mm/fault.c +@@ -41,6 +41,23 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap) + + int exception_trace = 1; + ++#ifdef CONFIG_PAX_PAGEEXEC ++void pax_report_insns(struct pt_regs *regs, void *pc, void *sp) ++{ ++ unsigned long i; ++ ++ printk(KERN_ERR "PAX: bytes at PC: "); ++ for (i = 0; i < 20; i++) { ++ unsigned char c; ++ if (get_user(c, (unsigned char *)pc+i)) ++ printk(KERN_CONT "???????? "); ++ else ++ printk(KERN_CONT "%02x ", c); ++ } ++ printk("\n"); ++} ++#endif ++ + /* + * This routine handles page faults. It determines the address and the + * problem, and then passes it off to one of the appropriate routines. +@@ -178,6 +195,16 @@ bad_area: + up_read(&mm->mmap_sem); + + if (user_mode(regs)) { ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (mm->pax_flags & MF_PAX_PAGEEXEC) { ++ if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) { ++ pax_report_fault(regs, (void *)regs->pc, (void *)regs->sp); ++ do_group_exit(SIGKILL); ++ } ++ } ++#endif ++ + if (exception_trace && printk_ratelimit()) + printk("%s%s[%d]: segfault at %08lx pc %08lx " + "sp %08lx ecr %lu\n", +diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug +index f3337ee..15b6f8d 100644 +--- a/arch/blackfin/Kconfig.debug ++++ b/arch/blackfin/Kconfig.debug +@@ -18,6 +18,7 @@ config DEBUG_VERBOSE + config DEBUG_MMRS + tristate "Generate Blackfin MMR tree" + select DEBUG_FS ++ depends on !GRKERNSEC_KMEM + help + Create a tree of Blackfin MMRs via the debugfs tree. If + you enable this, you will find all MMRs laid out in the +diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h +index 568885a..f8008df 100644 +--- a/arch/blackfin/include/asm/cache.h ++++ b/arch/blackfin/include/asm/cache.h +@@ -7,6 +7,7 @@ + #ifndef __ARCH_BLACKFIN_CACHE_H + #define __ARCH_BLACKFIN_CACHE_H + ++#include + #include /* for asmlinkage */ + + /* +@@ -14,7 +15,7 @@ + * Blackfin loads 32 bytes for cache + */ + #define L1_CACHE_SHIFT 5 +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + #define SMP_CACHE_BYTES L1_CACHE_BYTES + + #define ARCH_DMA_MINALIGN L1_CACHE_BYTES +diff --git a/arch/cris/include/arch-v10/arch/cache.h b/arch/cris/include/arch-v10/arch/cache.h +index aea2718..3639a60 100644 +--- a/arch/cris/include/arch-v10/arch/cache.h ++++ b/arch/cris/include/arch-v10/arch/cache.h +@@ -1,8 +1,9 @@ + #ifndef _ASM_ARCH_CACHE_H + #define _ASM_ARCH_CACHE_H + ++#include + /* Etrax 100LX have 32-byte cache-lines. */ +-#define L1_CACHE_BYTES 32 + #define L1_CACHE_SHIFT 5 ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #endif /* _ASM_ARCH_CACHE_H */ +diff --git a/arch/cris/include/arch-v32/arch/cache.h b/arch/cris/include/arch-v32/arch/cache.h +index 7caf25d..ee65ac5 100644 +--- a/arch/cris/include/arch-v32/arch/cache.h ++++ b/arch/cris/include/arch-v32/arch/cache.h +@@ -1,11 +1,12 @@ + #ifndef _ASM_CRIS_ARCH_CACHE_H + #define _ASM_CRIS_ARCH_CACHE_H + ++#include + #include + + /* A cache-line is 32 bytes. */ +-#define L1_CACHE_BYTES 32 + #define L1_CACHE_SHIFT 5 ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #define __read_mostly __attribute__((__section__(".data..read_mostly"))) + +diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h +index 102190a..5334cea 100644 +--- a/arch/frv/include/asm/atomic.h ++++ b/arch/frv/include/asm/atomic.h +@@ -181,6 +181,16 @@ static inline void atomic64_dec(atomic64_t *v) + #define atomic64_cmpxchg(v, old, new) (__cmpxchg_64(old, new, &(v)->counter)) + #define atomic64_xchg(v, new) (__xchg_64(new, &(v)->counter)) + ++#define atomic64_read_unchecked(v) atomic64_read(v) ++#define atomic64_set_unchecked(v, i) atomic64_set((v), (i)) ++#define atomic64_add_unchecked(a, v) atomic64_add((a), (v)) ++#define atomic64_add_return_unchecked(a, v) atomic64_add_return((a), (v)) ++#define atomic64_sub_unchecked(a, v) atomic64_sub((a), (v)) ++#define atomic64_inc_unchecked(v) atomic64_inc(v) ++#define atomic64_inc_return_unchecked(v) atomic64_inc_return(v) ++#define atomic64_dec_unchecked(v) atomic64_dec(v) ++#define atomic64_cmpxchg_unchecked(v, o, n) atomic64_cmpxchg((v), (o), (n)) ++ + static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + { + int c, old; +diff --git a/arch/frv/include/asm/cache.h b/arch/frv/include/asm/cache.h +index 2797163..c2a401df9 100644 +--- a/arch/frv/include/asm/cache.h ++++ b/arch/frv/include/asm/cache.h +@@ -12,10 +12,11 @@ + #ifndef __ASM_CACHE_H + #define __ASM_CACHE_H + ++#include + + /* bytes per L1 cache line */ + #define L1_CACHE_SHIFT (CONFIG_FRV_L1_CACHE_SHIFT) +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #define __cacheline_aligned __attribute__((aligned(L1_CACHE_BYTES))) + #define ____cacheline_aligned __attribute__((aligned(L1_CACHE_BYTES))) +diff --git a/arch/frv/include/asm/kmap_types.h b/arch/frv/include/asm/kmap_types.h +index 43901f2..0d8b865 100644 +--- a/arch/frv/include/asm/kmap_types.h ++++ b/arch/frv/include/asm/kmap_types.h +@@ -2,6 +2,6 @@ + #ifndef _ASM_KMAP_TYPES_H + #define _ASM_KMAP_TYPES_H + +-#define KM_TYPE_NR 17 ++#define KM_TYPE_NR 18 + + #endif +diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c +index 836f147..4cf23f5 100644 +--- a/arch/frv/mm/elf-fdpic.c ++++ b/arch/frv/mm/elf-fdpic.c +@@ -61,6 +61,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + { + struct vm_area_struct *vma; + struct vm_unmapped_area_info info; ++ unsigned long offset = gr_rand_threadstack_offset(current->mm, filp, flags); + + if (len > TASK_SIZE) + return -ENOMEM; +@@ -73,8 +74,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(current->mm, addr); +- if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len, offset)) + goto success; + } + +@@ -85,6 +85,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + info.high_limit = (current->mm->start_stack - 0x00200000); + info.align_mask = 0; + info.align_offset = 0; ++ info.threadstack_offset = offset; + addr = vm_unmapped_area(&info); + if (!(addr & ~PAGE_MASK)) + goto success; +diff --git a/arch/hexagon/include/asm/cache.h b/arch/hexagon/include/asm/cache.h +index 69952c18..4fa2908 100644 +--- a/arch/hexagon/include/asm/cache.h ++++ b/arch/hexagon/include/asm/cache.h +@@ -21,9 +21,11 @@ + #ifndef __ASM_CACHE_H + #define __ASM_CACHE_H + ++#include ++ + /* Bytes per L1 cache line */ +-#define L1_CACHE_SHIFT (5) +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_SHIFT 5 ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig +index 42a91a7..29d446e 100644 +--- a/arch/ia64/Kconfig ++++ b/arch/ia64/Kconfig +@@ -518,6 +518,7 @@ source "drivers/sn/Kconfig" + config KEXEC + bool "kexec system call" + depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) ++ depends on !GRKERNSEC_KMEM + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot +diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile +index 970d0bd..e750b9b 100644 +--- a/arch/ia64/Makefile ++++ b/arch/ia64/Makefile +@@ -98,5 +98,6 @@ endef + archprepare: make_nr_irqs_h FORCE + PHONY += make_nr_irqs_h FORCE + ++make_nr_irqs_h: KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) + make_nr_irqs_h: FORCE + $(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h +diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h +index 0bf0350..2ad1957 100644 +--- a/arch/ia64/include/asm/atomic.h ++++ b/arch/ia64/include/asm/atomic.h +@@ -193,4 +193,14 @@ atomic64_add_negative (__s64 i, atomic64_t *v) + #define atomic64_inc(v) atomic64_add(1, (v)) + #define atomic64_dec(v) atomic64_sub(1, (v)) + ++#define atomic64_read_unchecked(v) atomic64_read(v) ++#define atomic64_set_unchecked(v, i) atomic64_set((v), (i)) ++#define atomic64_add_unchecked(a, v) atomic64_add((a), (v)) ++#define atomic64_add_return_unchecked(a, v) atomic64_add_return((a), (v)) ++#define atomic64_sub_unchecked(a, v) atomic64_sub((a), (v)) ++#define atomic64_inc_unchecked(v) atomic64_inc(v) ++#define atomic64_inc_return_unchecked(v) atomic64_inc_return(v) ++#define atomic64_dec_unchecked(v) atomic64_dec(v) ++#define atomic64_cmpxchg_unchecked(v, o, n) atomic64_cmpxchg((v), (o), (n)) ++ + #endif /* _ASM_IA64_ATOMIC_H */ +diff --git a/arch/ia64/include/asm/barrier.h b/arch/ia64/include/asm/barrier.h +index 843ba43..fa118fb 100644 +--- a/arch/ia64/include/asm/barrier.h ++++ b/arch/ia64/include/asm/barrier.h +@@ -66,7 +66,7 @@ + do { \ + compiletime_assert_atomic_type(*p); \ + barrier(); \ +- ACCESS_ONCE(*p) = (v); \ ++ ACCESS_ONCE_RW(*p) = (v); \ + } while (0) + + #define smp_load_acquire(p) \ +diff --git a/arch/ia64/include/asm/cache.h b/arch/ia64/include/asm/cache.h +index 988254a..e1ee885 100644 +--- a/arch/ia64/include/asm/cache.h ++++ b/arch/ia64/include/asm/cache.h +@@ -1,6 +1,7 @@ + #ifndef _ASM_IA64_CACHE_H + #define _ASM_IA64_CACHE_H + ++#include + + /* + * Copyright (C) 1998-2000 Hewlett-Packard Co +@@ -9,7 +10,7 @@ + + /* Bytes per L1 (data) cache line. */ + #define L1_CACHE_SHIFT CONFIG_IA64_L1_CACHE_SHIFT +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #ifdef CONFIG_SMP + # define SMP_CACHE_SHIFT L1_CACHE_SHIFT +diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h +index 5a83c5c..4d7f553 100644 +--- a/arch/ia64/include/asm/elf.h ++++ b/arch/ia64/include/asm/elf.h +@@ -42,6 +42,13 @@ + */ + #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x800000000UL) + ++#ifdef CONFIG_PAX_ASLR ++#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) ++ ++#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) ++#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) ++#endif ++ + #define PT_IA_64_UNWIND 0x70000001 + + /* IA-64 relocations: */ +diff --git a/arch/ia64/include/asm/pgalloc.h b/arch/ia64/include/asm/pgalloc.h +index f5e70e9..624fad5 100644 +--- a/arch/ia64/include/asm/pgalloc.h ++++ b/arch/ia64/include/asm/pgalloc.h +@@ -39,6 +39,12 @@ pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud) + pgd_val(*pgd_entry) = __pa(pud); + } + ++static inline void ++pgd_populate_kernel(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud) ++{ ++ pgd_populate(mm, pgd_entry, pud); ++} ++ + static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) + { + return quicklist_alloc(0, GFP_KERNEL, NULL); +@@ -57,6 +63,12 @@ pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) + pud_val(*pud_entry) = __pa(pmd); + } + ++static inline void ++pud_populate_kernel(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd) ++{ ++ pud_populate(mm, pud_entry, pmd); ++} ++ + static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) + { + return quicklist_alloc(0, GFP_KERNEL, NULL); +diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h +index 9f3ed9e..c99b418 100644 +--- a/arch/ia64/include/asm/pgtable.h ++++ b/arch/ia64/include/asm/pgtable.h +@@ -12,7 +12,7 @@ + * David Mosberger-Tang + */ + +- ++#include + #include + #include + #include +@@ -139,6 +139,17 @@ + #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) + #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) + #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX) ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW) ++# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) ++# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) ++#else ++# define PAGE_SHARED_NOEXEC PAGE_SHARED ++# define PAGE_READONLY_NOEXEC PAGE_READONLY ++# define PAGE_COPY_NOEXEC PAGE_COPY ++#endif ++ + #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX) + #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX) + #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX) +diff --git a/arch/ia64/include/asm/spinlock.h b/arch/ia64/include/asm/spinlock.h +index 45698cd..e8e2dbc 100644 +--- a/arch/ia64/include/asm/spinlock.h ++++ b/arch/ia64/include/asm/spinlock.h +@@ -71,7 +71,7 @@ static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock) + unsigned short *p = (unsigned short *)&lock->lock + 1, tmp; + + asm volatile ("ld2.bias %0=[%1]" : "=r"(tmp) : "r"(p)); +- ACCESS_ONCE(*p) = (tmp + 2) & ~1; ++ ACCESS_ONCE_RW(*p) = (tmp + 2) & ~1; + } + + static __always_inline void __ticket_spin_unlock_wait(arch_spinlock_t *lock) +diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h +index 4f3fb6cc..254055e 100644 +--- a/arch/ia64/include/asm/uaccess.h ++++ b/arch/ia64/include/asm/uaccess.h +@@ -70,6 +70,7 @@ + && ((segment).seg == KERNEL_DS.seg \ + || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT))); \ + }) ++#define access_ok_noprefault(type, addr, size) access_ok((type), (addr), (size)) + #define access_ok(type, addr, size) __access_ok((addr), (size), get_fs()) + + /* +@@ -241,12 +242,24 @@ extern unsigned long __must_check __copy_user (void __user *to, const void __use + static inline unsigned long + __copy_to_user (void __user *to, const void *from, unsigned long count) + { ++ if (count > INT_MAX) ++ return count; ++ ++ if (!__builtin_constant_p(count)) ++ check_object_size(from, count, true); ++ + return __copy_user(to, (__force void __user *) from, count); + } + + static inline unsigned long + __copy_from_user (void *to, const void __user *from, unsigned long count) + { ++ if (count > INT_MAX) ++ return count; ++ ++ if (!__builtin_constant_p(count)) ++ check_object_size(to, count, false); ++ + return __copy_user((__force void __user *) to, from, count); + } + +@@ -256,10 +269,13 @@ __copy_from_user (void *to, const void __user *from, unsigned long count) + ({ \ + void __user *__cu_to = (to); \ + const void *__cu_from = (from); \ +- long __cu_len = (n); \ ++ unsigned long __cu_len = (n); \ + \ +- if (__access_ok(__cu_to, __cu_len, get_fs())) \ ++ if (__cu_len <= INT_MAX && __access_ok(__cu_to, __cu_len, get_fs())) { \ ++ if (!__builtin_constant_p(n)) \ ++ check_object_size(__cu_from, __cu_len, true); \ + __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \ ++ } \ + __cu_len; \ + }) + +@@ -267,11 +283,14 @@ __copy_from_user (void *to, const void __user *from, unsigned long count) + ({ \ + void *__cu_to = (to); \ + const void __user *__cu_from = (from); \ +- long __cu_len = (n); \ ++ unsigned long __cu_len = (n); \ + \ + __chk_user_ptr(__cu_from); \ +- if (__access_ok(__cu_from, __cu_len, get_fs())) \ ++ if (__cu_len <= INT_MAX && __access_ok(__cu_from, __cu_len, get_fs())) { \ ++ if (!__builtin_constant_p(n)) \ ++ check_object_size(__cu_to, __cu_len, false); \ + __cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \ ++ } \ + __cu_len; \ + }) + +diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c +index b15933c..098b1c8 100644 +--- a/arch/ia64/kernel/module.c ++++ b/arch/ia64/kernel/module.c +@@ -484,15 +484,39 @@ module_frob_arch_sections (Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings, + } + + static inline int ++in_init_rx (const struct module *mod, uint64_t addr) ++{ ++ return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx; ++} ++ ++static inline int ++in_init_rw (const struct module *mod, uint64_t addr) ++{ ++ return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw; ++} ++ ++static inline int + in_init (const struct module *mod, uint64_t addr) + { +- return addr - (uint64_t) mod->module_init < mod->init_size; ++ return in_init_rx(mod, addr) || in_init_rw(mod, addr); ++} ++ ++static inline int ++in_core_rx (const struct module *mod, uint64_t addr) ++{ ++ return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx; ++} ++ ++static inline int ++in_core_rw (const struct module *mod, uint64_t addr) ++{ ++ return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw; + } + + static inline int + in_core (const struct module *mod, uint64_t addr) + { +- return addr - (uint64_t) mod->module_core < mod->core_size; ++ return in_core_rx(mod, addr) || in_core_rw(mod, addr); + } + + static inline int +@@ -675,7 +699,14 @@ do_reloc (struct module *mod, uint8_t r_type, Elf64_Sym *sym, uint64_t addend, + break; + + case RV_BDREL: +- val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core); ++ if (in_init_rx(mod, val)) ++ val -= (uint64_t) mod->module_init_rx; ++ else if (in_init_rw(mod, val)) ++ val -= (uint64_t) mod->module_init_rw; ++ else if (in_core_rx(mod, val)) ++ val -= (uint64_t) mod->module_core_rx; ++ else if (in_core_rw(mod, val)) ++ val -= (uint64_t) mod->module_core_rw; + break; + + case RV_LTV: +@@ -810,15 +841,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symind + * addresses have been selected... + */ + uint64_t gp; +- if (mod->core_size > MAX_LTOFF) ++ if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF) + /* + * This takes advantage of fact that SHF_ARCH_SMALL gets allocated + * at the end of the module. + */ +- gp = mod->core_size - MAX_LTOFF / 2; ++ gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2; + else +- gp = mod->core_size / 2; +- gp = (uint64_t) mod->module_core + ((gp + 7) & -8); ++ gp = (mod->core_size_rx + mod->core_size_rw) / 2; ++ gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8); + mod->arch.gp = gp; + DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp); + } +diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c +index c39c3cd..3c77738 100644 +--- a/arch/ia64/kernel/palinfo.c ++++ b/arch/ia64/kernel/palinfo.c +@@ -980,7 +980,7 @@ static int palinfo_cpu_callback(struct notifier_block *nfb, + return NOTIFY_OK; + } + +-static struct notifier_block __refdata palinfo_cpu_notifier = ++static struct notifier_block palinfo_cpu_notifier = + { + .notifier_call = palinfo_cpu_callback, + .priority = 0, +diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c +index 41e33f8..65180b2a 100644 +--- a/arch/ia64/kernel/sys_ia64.c ++++ b/arch/ia64/kernel/sys_ia64.c +@@ -28,6 +28,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len + unsigned long align_mask = 0; + struct mm_struct *mm = current->mm; + struct vm_unmapped_area_info info; ++ unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); + + if (len > RGN_MAP_LIMIT) + return -ENOMEM; +@@ -43,6 +44,13 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len + if (REGION_NUMBER(addr) == RGN_HPAGE) + addr = 0; + #endif ++ ++#ifdef CONFIG_PAX_RANDMMAP ++ if (mm->pax_flags & MF_PAX_RANDMMAP) ++ addr = mm->free_area_cache; ++ else ++#endif ++ + if (!addr) + addr = TASK_UNMAPPED_BASE; + +@@ -61,6 +69,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len + info.high_limit = TASK_SIZE; + info.align_mask = align_mask; + info.align_offset = 0; ++ info.threadstack_offset = offset; + return vm_unmapped_area(&info); + } + +diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S +index dc506b0..39baade 100644 +--- a/arch/ia64/kernel/vmlinux.lds.S ++++ b/arch/ia64/kernel/vmlinux.lds.S +@@ -171,7 +171,7 @@ SECTIONS { + /* Per-cpu data: */ + . = ALIGN(PERCPU_PAGE_SIZE); + PERCPU_VADDR(SMP_CACHE_BYTES, PERCPU_ADDR, :percpu) +- __phys_per_cpu_start = __per_cpu_load; ++ __phys_per_cpu_start = per_cpu_load; + /* + * ensure percpu data fits + * into percpu page size +diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c +index 70b40d1..01a9a28 100644 +--- a/arch/ia64/mm/fault.c ++++ b/arch/ia64/mm/fault.c +@@ -72,6 +72,23 @@ mapped_kernel_page_is_present (unsigned long address) + return pte_present(pte); + } + ++#ifdef CONFIG_PAX_PAGEEXEC ++void pax_report_insns(struct pt_regs *regs, void *pc, void *sp) ++{ ++ unsigned long i; ++ ++ printk(KERN_ERR "PAX: bytes at PC: "); ++ for (i = 0; i < 8; i++) { ++ unsigned int c; ++ if (get_user(c, (unsigned int *)pc+i)) ++ printk(KERN_CONT "???????? "); ++ else ++ printk(KERN_CONT "%08x ", c); ++ } ++ printk("\n"); ++} ++#endif ++ + # define VM_READ_BIT 0 + # define VM_WRITE_BIT 1 + # define VM_EXEC_BIT 2 +@@ -151,8 +168,21 @@ retry: + if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE)))) + goto bad_area; + +- if ((vma->vm_flags & mask) != mask) ++ if ((vma->vm_flags & mask) != mask) { ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) { ++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip) ++ goto bad_area; ++ ++ up_read(&mm->mmap_sem); ++ pax_report_fault(regs, (void *)regs->cr_iip, (void *)regs->r12); ++ do_group_exit(SIGKILL); ++ } ++#endif ++ + goto bad_area; ++ } + + /* + * If for any reason at all we couldn't handle the fault, make +diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c +index f50d4b3..c7975ee 100644 +--- a/arch/ia64/mm/hugetlbpage.c ++++ b/arch/ia64/mm/hugetlbpage.c +@@ -138,6 +138,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u + unsigned long pgoff, unsigned long flags) + { + struct vm_unmapped_area_info info; ++ unsigned long offset = gr_rand_threadstack_offset(current->mm, file, flags); + + if (len > RGN_MAP_LIMIT) + return -ENOMEM; +@@ -161,6 +162,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u + info.high_limit = HPAGE_REGION_BASE + RGN_MAP_LIMIT; + info.align_mask = PAGE_MASK & (HPAGE_SIZE - 1); + info.align_offset = 0; ++ info.threadstack_offset = offset; + return vm_unmapped_area(&info); + } + +diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c +index 97e48b0..fc59c36 100644 +--- a/arch/ia64/mm/init.c ++++ b/arch/ia64/mm/init.c +@@ -119,6 +119,19 @@ ia64_init_addr_space (void) + vma->vm_start = current->thread.rbs_bot & PAGE_MASK; + vma->vm_end = vma->vm_start + PAGE_SIZE; + vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT; ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (current->mm->pax_flags & MF_PAX_PAGEEXEC) { ++ vma->vm_flags &= ~VM_EXEC; ++ ++#ifdef CONFIG_PAX_MPROTECT ++ if (current->mm->pax_flags & MF_PAX_MPROTECT) ++ vma->vm_flags &= ~VM_MAYEXEC; ++#endif ++ ++ } ++#endif ++ + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + down_write(¤t->mm->mmap_sem); + if (insert_vm_struct(current->mm, vma)) { +@@ -279,7 +292,7 @@ static int __init gate_vma_init(void) + gate_vma.vm_start = FIXADDR_USER_START; + gate_vma.vm_end = FIXADDR_USER_END; + gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; +- gate_vma.vm_page_prot = __P101; ++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); + + return 0; + } +diff --git a/arch/m32r/include/asm/cache.h b/arch/m32r/include/asm/cache.h +index 40b3ee98..8c2c112 100644 +--- a/arch/m32r/include/asm/cache.h ++++ b/arch/m32r/include/asm/cache.h +@@ -1,8 +1,10 @@ + #ifndef _ASM_M32R_CACHE_H + #define _ASM_M32R_CACHE_H + ++#include ++ + /* L1 cache line size */ + #define L1_CACHE_SHIFT 4 +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #endif /* _ASM_M32R_CACHE_H */ +diff --git a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c +index 82abd15..d95ae5d 100644 +--- a/arch/m32r/lib/usercopy.c ++++ b/arch/m32r/lib/usercopy.c +@@ -14,6 +14,9 @@ + unsigned long + __generic_copy_to_user(void __user *to, const void *from, unsigned long n) + { ++ if ((long)n < 0) ++ return n; ++ + prefetch(from); + if (access_ok(VERIFY_WRITE, to, n)) + __copy_user(to,from,n); +@@ -23,6 +26,9 @@ __generic_copy_to_user(void __user *to, const void *from, unsigned long n) + unsigned long + __generic_copy_from_user(void *to, const void __user *from, unsigned long n) + { ++ if ((long)n < 0) ++ return n; ++ + prefetchw(to); + if (access_ok(VERIFY_READ, from, n)) + __copy_user_zeroing(to,from,n); +diff --git a/arch/m68k/include/asm/cache.h b/arch/m68k/include/asm/cache.h +index 0395c51..5f26031 100644 +--- a/arch/m68k/include/asm/cache.h ++++ b/arch/m68k/include/asm/cache.h +@@ -4,9 +4,11 @@ + #ifndef __ARCH_M68K_CACHE_H + #define __ARCH_M68K_CACHE_H + ++#include ++ + /* bytes per L1 cache line */ + #define L1_CACHE_SHIFT 4 +-#define L1_CACHE_BYTES (1<< L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +diff --git a/arch/metag/include/asm/barrier.h b/arch/metag/include/asm/barrier.h +index 5a696e5..070490d 100644 +--- a/arch/metag/include/asm/barrier.h ++++ b/arch/metag/include/asm/barrier.h +@@ -90,7 +90,7 @@ static inline void fence(void) + do { \ + compiletime_assert_atomic_type(*p); \ + smp_mb(); \ +- ACCESS_ONCE(*p) = (v); \ ++ ACCESS_ONCE_RW(*p) = (v); \ + } while (0) + + #define smp_load_acquire(p) \ +diff --git a/arch/metag/mm/hugetlbpage.c b/arch/metag/mm/hugetlbpage.c +index 53f0f6c..2dc07fd 100644 +--- a/arch/metag/mm/hugetlbpage.c ++++ b/arch/metag/mm/hugetlbpage.c +@@ -189,6 +189,7 @@ hugetlb_get_unmapped_area_new_pmd(unsigned long len) + info.high_limit = TASK_SIZE; + info.align_mask = PAGE_MASK & HUGEPT_MASK; + info.align_offset = 0; ++ info.threadstack_offset = 0; + return vm_unmapped_area(&info); + } + +diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h +index 4efe96a..60e8699 100644 +--- a/arch/microblaze/include/asm/cache.h ++++ b/arch/microblaze/include/asm/cache.h +@@ -13,11 +13,12 @@ + #ifndef _ASM_MICROBLAZE_CACHE_H + #define _ASM_MICROBLAZE_CACHE_H + ++#include + #include + + #define L1_CACHE_SHIFT 5 + /* word-granular cache in microblaze */ +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #define SMP_CACHE_BYTES L1_CACHE_BYTES + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 199a835..822b487 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -2591,6 +2591,7 @@ source "kernel/Kconfig.preempt" + + config KEXEC + bool "Kexec system call" ++ depends on !GRKERNSEC_KMEM + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot +diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c +index d8960d4..77dbd31 100644 +--- a/arch/mips/cavium-octeon/dma-octeon.c ++++ b/arch/mips/cavium-octeon/dma-octeon.c +@@ -199,7 +199,7 @@ static void octeon_dma_free_coherent(struct device *dev, size_t size, + if (dma_release_from_coherent(dev, order, vaddr)) + return; + +- swiotlb_free_coherent(dev, size, vaddr, dma_handle); ++ swiotlb_free_coherent(dev, size, vaddr, dma_handle, attrs); + } + + static dma_addr_t octeon_unity_phys_to_dma(struct device *dev, phys_addr_t paddr) +diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h +index 26d4363..3c9a82e 100644 +--- a/arch/mips/include/asm/atomic.h ++++ b/arch/mips/include/asm/atomic.h +@@ -22,15 +22,39 @@ + #include + #include + ++#ifdef CONFIG_GENERIC_ATOMIC64 ++#include ++#endif ++ + #define ATOMIC_INIT(i) { (i) } + ++#ifdef CONFIG_64BIT ++#define _ASM_EXTABLE(from, to) \ ++" .section __ex_table,\"a\"\n" \ ++" .dword " #from ", " #to"\n" \ ++" .previous\n" ++#else ++#define _ASM_EXTABLE(from, to) \ ++" .section __ex_table,\"a\"\n" \ ++" .word " #from ", " #to"\n" \ ++" .previous\n" ++#endif ++ + /* + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. + */ +-#define atomic_read(v) ACCESS_ONCE((v)->counter) ++static inline int atomic_read(const atomic_t *v) ++{ ++ return ACCESS_ONCE(v->counter); ++} ++ ++static inline int atomic_read_unchecked(const atomic_unchecked_t *v) ++{ ++ return ACCESS_ONCE(v->counter); ++} + + /* + * atomic_set - set atomic variable +@@ -39,47 +63,77 @@ + * + * Atomically sets the value of @v to @i. + */ +-#define atomic_set(v, i) ((v)->counter = (i)) ++static inline void atomic_set(atomic_t *v, int i) ++{ ++ v->counter = i; ++} + +-#define ATOMIC_OP(op, c_op, asm_op) \ +-static __inline__ void atomic_##op(int i, atomic_t * v) \ ++static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i) ++{ ++ v->counter = i; ++} ++ ++#ifdef CONFIG_PAX_REFCOUNT ++#define __OVERFLOW_POST \ ++ " b 4f \n" \ ++ " .set noreorder \n" \ ++ "3: b 5f \n" \ ++ " move %0, %1 \n" \ ++ " .set reorder \n" ++#define __OVERFLOW_EXTABLE \ ++ "3:\n" \ ++ _ASM_EXTABLE(2b, 3b) ++#else ++#define __OVERFLOW_POST ++#define __OVERFLOW_EXTABLE ++#endif ++ ++#define __ATOMIC_OP(op, suffix, asm_op, extable) \ ++static inline void atomic_##op##suffix(int i, atomic##suffix##_t * v) \ + { \ + if (kernel_uses_llsc && R10000_LLSC_WAR) { \ + int temp; \ + \ + __asm__ __volatile__( \ +- " .set arch=r4000 \n" \ +- "1: ll %0, %1 # atomic_" #op " \n" \ +- " " #asm_op " %0, %2 \n" \ ++ " .set mips3 \n" \ ++ "1: ll %0, %1 # atomic_" #op #suffix "\n" \ ++ "2: " #asm_op " %0, %2 \n" \ + " sc %0, %1 \n" \ + " beqzl %0, 1b \n" \ ++ extable \ + " .set mips0 \n" \ + : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ + : "Ir" (i)); \ + } else if (kernel_uses_llsc) { \ + int temp; \ + \ +- do { \ +- __asm__ __volatile__( \ +- " .set "MIPS_ISA_LEVEL" \n" \ +- " ll %0, %1 # atomic_" #op "\n" \ +- " " #asm_op " %0, %2 \n" \ +- " sc %0, %1 \n" \ +- " .set mips0 \n" \ +- : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ +- : "Ir" (i)); \ +- } while (unlikely(!temp)); \ ++ __asm__ __volatile__( \ ++ " .set "MIPS_ISA_LEVEL" \n" \ ++ "1: ll %0, %1 # atomic_" #op #suffix "\n" \ ++ "2: " #asm_op " %0, %2 \n" \ ++ " sc %0, %1 \n" \ ++ " beqz %0, 1b \n" \ ++ extable \ ++ " .set mips0 \n" \ ++ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "Ir" (i)); \ + } else { \ + unsigned long flags; \ + \ + raw_local_irq_save(flags); \ +- v->counter c_op i; \ ++ __asm__ __volatile__( \ ++ "2: " #asm_op " %0, %1 \n" \ ++ extable \ ++ : "+r" (v->counter) : "Ir" (i)); \ + raw_local_irq_restore(flags); \ + } \ + } + +-#define ATOMIC_OP_RETURN(op, c_op, asm_op) \ +-static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ ++#define ATOMIC_OP(op, asm_op) __ATOMIC_OP(op, _unchecked, asm_op##u, ) \ ++ __ATOMIC_OP(op, , asm_op, __OVERFLOW_EXTABLE) ++ ++#define __ATOMIC_OP_RETURN(op, suffix, asm_op, post_op, extable) \ ++static inline int atomic_##op##_return##suffix(int i, atomic##suffix##_t * v) \ + { \ + int result; \ + \ +@@ -89,12 +143,15 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ + int temp; \ + \ + __asm__ __volatile__( \ +- " .set arch=r4000 \n" \ +- "1: ll %1, %2 # atomic_" #op "_return \n" \ +- " " #asm_op " %0, %1, %3 \n" \ ++ " .set mips3 \n" \ ++ "1: ll %1, %2 # atomic_" #op "_return" #suffix"\n" \ ++ "2: " #asm_op " %0, %1, %3 \n" \ + " sc %0, %2 \n" \ + " beqzl %0, 1b \n" \ +- " " #asm_op " %0, %1, %3 \n" \ ++ post_op \ ++ extable \ ++ "4: " #asm_op " %0, %1, %3 \n" \ ++ "5: \n" \ + " .set mips0 \n" \ + : "=&r" (result), "=&r" (temp), \ + "+" GCC_OFF_SMALL_ASM() (v->counter) \ +@@ -102,26 +159,33 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ + } else if (kernel_uses_llsc) { \ + int temp; \ + \ +- do { \ +- __asm__ __volatile__( \ +- " .set "MIPS_ISA_LEVEL" \n" \ +- " ll %1, %2 # atomic_" #op "_return \n" \ +- " " #asm_op " %0, %1, %3 \n" \ +- " sc %0, %2 \n" \ +- " .set mips0 \n" \ +- : "=&r" (result), "=&r" (temp), \ +- "+" GCC_OFF_SMALL_ASM() (v->counter) \ +- : "Ir" (i)); \ +- } while (unlikely(!result)); \ ++ __asm__ __volatile__( \ ++ " .set "MIPS_ISA_LEVEL" \n" \ ++ "1: ll %1, %2 # atomic_" #op "_return" #suffix "\n" \ ++ "2: " #asm_op " %0, %1, %3 \n" \ ++ " sc %0, %2 \n" \ ++ post_op \ ++ extable \ ++ "4: " #asm_op " %0, %1, %3 \n" \ ++ "5: \n" \ ++ " .set mips0 \n" \ ++ : "=&r" (result), "=&r" (temp), \ ++ "+" GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "Ir" (i)); \ + \ + result = temp; result c_op i; \ + } else { \ + unsigned long flags; \ + \ + raw_local_irq_save(flags); \ +- result = v->counter; \ +- result c_op i; \ +- v->counter = result; \ ++ __asm__ __volatile__( \ ++ " lw %0, %1 \n" \ ++ "2: " #asm_op " %0, %1, %2 \n" \ ++ " sw %0, %1 \n" \ ++ "3: \n" \ ++ extable \ ++ : "=&r" (result), "+" GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "Ir" (i)); \ + raw_local_irq_restore(flags); \ + } \ + \ +@@ -130,16 +194,21 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ + return result; \ + } + +-#define ATOMIC_OPS(op, c_op, asm_op) \ +- ATOMIC_OP(op, c_op, asm_op) \ +- ATOMIC_OP_RETURN(op, c_op, asm_op) ++#define ATOMIC_OP_RETURN(op, asm_op) __ATOMIC_OP_RETURN(op, _unchecked, asm_op##u, , ) \ ++ __ATOMIC_OP_RETURN(op, , asm_op, __OVERFLOW_POST, __OVERFLOW_EXTABLE) + +-ATOMIC_OPS(add, +=, addu) +-ATOMIC_OPS(sub, -=, subu) ++#define ATOMIC_OPS(op, asm_op) \ ++ ATOMIC_OP(op, asm_op) \ ++ ATOMIC_OP_RETURN(op, asm_op) ++ ++ATOMIC_OPS(add, add) ++ATOMIC_OPS(sub, sub) + + #undef ATOMIC_OPS + #undef ATOMIC_OP_RETURN ++#undef __ATOMIC_OP_RETURN + #undef ATOMIC_OP ++#undef __ATOMIC_OP + + /* + * atomic_sub_if_positive - conditionally subtract integer from atomic variable +@@ -149,7 +218,7 @@ ATOMIC_OPS(sub, -=, subu) + * Atomically test @v and subtract @i if @v is greater or equal than @i. + * The function returns the old value of @v minus @i. + */ +-static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) ++static __inline__ int atomic_sub_if_positive(int i, atomic_t *v) + { + int result; + +@@ -159,7 +228,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) + int temp; + + __asm__ __volatile__( +- " .set arch=r4000 \n" ++ " .set "MIPS_ISA_LEVEL" \n" + "1: ll %1, %2 # atomic_sub_if_positive\n" + " subu %0, %1, %3 \n" + " bltz %0, 1f \n" +@@ -208,8 +277,26 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) + return result; + } + +-#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) +-#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) ++static inline int atomic_cmpxchg(atomic_t *v, int old, int new) ++{ ++ return cmpxchg(&v->counter, old, new); ++} ++ ++static inline int atomic_cmpxchg_unchecked(atomic_unchecked_t *v, int old, ++ int new) ++{ ++ return cmpxchg(&(v->counter), old, new); ++} ++ ++static inline int atomic_xchg(atomic_t *v, int new) ++{ ++ return xchg(&v->counter, new); ++} ++ ++static inline int atomic_xchg_unchecked(atomic_unchecked_t *v, int new) ++{ ++ return xchg(&(v->counter), new); ++} + + /** + * __atomic_add_unless - add unless the number is a given value +@@ -237,6 +324,10 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + + #define atomic_dec_return(v) atomic_sub_return(1, (v)) + #define atomic_inc_return(v) atomic_add_return(1, (v)) ++static __inline__ int atomic_inc_return_unchecked(atomic_unchecked_t *v) ++{ ++ return atomic_add_return_unchecked(1, v); ++} + + /* + * atomic_sub_and_test - subtract value from variable and test result +@@ -258,6 +349,10 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * other cases. + */ + #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) ++static __inline__ int atomic_inc_and_test_unchecked(atomic_unchecked_t *v) ++{ ++ return atomic_add_return_unchecked(1, v) == 0; ++} + + /* + * atomic_dec_and_test - decrement by 1 and test +@@ -282,6 +377,10 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * Atomically increments @v by 1. + */ + #define atomic_inc(v) atomic_add(1, (v)) ++static __inline__ void atomic_inc_unchecked(atomic_unchecked_t *v) ++{ ++ atomic_add_unchecked(1, v); ++} + + /* + * atomic_dec - decrement and test +@@ -290,6 +389,10 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * Atomically decrements @v by 1. + */ + #define atomic_dec(v) atomic_sub(1, (v)) ++static __inline__ void atomic_dec_unchecked(atomic_unchecked_t *v) ++{ ++ atomic_sub_unchecked(1, v); ++} + + /* + * atomic_add_negative - add and test if negative +@@ -311,54 +414,77 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * @v: pointer of type atomic64_t + * + */ +-#define atomic64_read(v) ACCESS_ONCE((v)->counter) ++static inline long atomic64_read(const atomic64_t *v) ++{ ++ return ACCESS_ONCE(v->counter); ++} ++ ++static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v) ++{ ++ return ACCESS_ONCE(v->counter); ++} + + /* + * atomic64_set - set atomic variable + * @v: pointer of type atomic64_t + * @i: required value + */ +-#define atomic64_set(v, i) ((v)->counter = (i)) ++static inline void atomic64_set(atomic64_t *v, long i) ++{ ++ v->counter = i; ++} + +-#define ATOMIC64_OP(op, c_op, asm_op) \ +-static __inline__ void atomic64_##op(long i, atomic64_t * v) \ ++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i) ++{ ++ v->counter = i; ++} ++ ++#define __ATOMIC64_OP(op, suffix, asm_op, extable) \ ++static inline void atomic64_##op##suffix(long i, atomic64##suffix##_t * v) \ + { \ + if (kernel_uses_llsc && R10000_LLSC_WAR) { \ + long temp; \ + \ + __asm__ __volatile__( \ +- " .set arch=r4000 \n" \ +- "1: lld %0, %1 # atomic64_" #op " \n" \ +- " " #asm_op " %0, %2 \n" \ ++ " .set "MIPS_ISA_LEVEL" \n" \ ++ "1: lld %0, %1 # atomic64_" #op #suffix "\n" \ ++ "2: " #asm_op " %0, %2 \n" \ + " scd %0, %1 \n" \ + " beqzl %0, 1b \n" \ ++ extable \ + " .set mips0 \n" \ + : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ + : "Ir" (i)); \ + } else if (kernel_uses_llsc) { \ + long temp; \ + \ +- do { \ +- __asm__ __volatile__( \ +- " .set "MIPS_ISA_LEVEL" \n" \ +- " lld %0, %1 # atomic64_" #op "\n" \ +- " " #asm_op " %0, %2 \n" \ +- " scd %0, %1 \n" \ +- " .set mips0 \n" \ +- : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ +- : "Ir" (i)); \ +- } while (unlikely(!temp)); \ ++ __asm__ __volatile__( \ ++ " .set "MIPS_ISA_LEVEL" \n" \ ++ "1: lld %0, %1 # atomic64_" #op #suffix "\n" \ ++ "2: " #asm_op " %0, %2 \n" \ ++ " scd %0, %1 \n" \ ++ " beqz %0, 1b \n" \ ++ extable \ ++ " .set mips0 \n" \ ++ : "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "Ir" (i)); \ + } else { \ + unsigned long flags; \ + \ + raw_local_irq_save(flags); \ +- v->counter c_op i; \ ++ __asm__ __volatile__( \ ++ "2: " #asm_op " %0, %1 \n" \ ++ extable \ ++ : "+" GCC_OFF_SMALL_ASM() (v->counter) : "Ir" (i)); \ + raw_local_irq_restore(flags); \ + } \ + } + +-#define ATOMIC64_OP_RETURN(op, c_op, asm_op) \ +-static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ ++#define ATOMIC64_OP(op, asm_op) __ATOMIC64_OP(op, _unchecked, asm_op##u, ) \ ++ __ATOMIC64_OP(op, , asm_op, __OVERFLOW_EXTABLE) ++ ++#define __ATOMIC64_OP_RETURN(op, suffix, asm_op, post_op, extable) \ ++static inline long atomic64_##op##_return##suffix(long i, atomic64##suffix##_t * v)\ + { \ + long result; \ + \ +@@ -368,12 +494,15 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ + long temp; \ + \ + __asm__ __volatile__( \ +- " .set arch=r4000 \n" \ ++ " .set mips3 \n" \ + "1: lld %1, %2 # atomic64_" #op "_return\n" \ +- " " #asm_op " %0, %1, %3 \n" \ ++ "2: " #asm_op " %0, %1, %3 \n" \ + " scd %0, %2 \n" \ + " beqzl %0, 1b \n" \ +- " " #asm_op " %0, %1, %3 \n" \ ++ post_op \ ++ extable \ ++ "4: " #asm_op " %0, %1, %3 \n" \ ++ "5: \n" \ + " .set mips0 \n" \ + : "=&r" (result), "=&r" (temp), \ + "+" GCC_OFF_SMALL_ASM() (v->counter) \ +@@ -381,27 +510,35 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ + } else if (kernel_uses_llsc) { \ + long temp; \ + \ +- do { \ +- __asm__ __volatile__( \ +- " .set "MIPS_ISA_LEVEL" \n" \ +- " lld %1, %2 # atomic64_" #op "_return\n" \ +- " " #asm_op " %0, %1, %3 \n" \ +- " scd %0, %2 \n" \ +- " .set mips0 \n" \ +- : "=&r" (result), "=&r" (temp), \ +- "=" GCC_OFF_SMALL_ASM() (v->counter) \ +- : "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter) \ +- : "memory"); \ +- } while (unlikely(!result)); \ ++ __asm__ __volatile__( \ ++ " .set "MIPS_ISA_LEVEL" \n" \ ++ "1: lld %1, %2 # atomic64_" #op "_return" #suffix "\n"\ ++ "2: " #asm_op " %0, %1, %3 \n" \ ++ " scd %0, %2 \n" \ ++ " beqz %0, 1b \n" \ ++ post_op \ ++ extable \ ++ "4: " #asm_op " %0, %1, %3 \n" \ ++ "5: \n" \ ++ " .set mips0 \n" \ ++ : "=&r" (result), "=&r" (temp), \ ++ "=" GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "Ir" (i), GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "memory"); \ + \ + result = temp; result c_op i; \ + } else { \ + unsigned long flags; \ + \ + raw_local_irq_save(flags); \ +- result = v->counter; \ +- result c_op i; \ +- v->counter = result; \ ++ __asm__ __volatile__( \ ++ " ld %0, %1 \n" \ ++ "2: " #asm_op " %0, %1, %2 \n" \ ++ " sd %0, %1 \n" \ ++ "3: \n" \ ++ extable \ ++ : "=&r" (result), "+" GCC_OFF_SMALL_ASM() (v->counter) \ ++ : "Ir" (i)); \ + raw_local_irq_restore(flags); \ + } \ + \ +@@ -410,16 +547,23 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ + return result; \ + } + +-#define ATOMIC64_OPS(op, c_op, asm_op) \ +- ATOMIC64_OP(op, c_op, asm_op) \ +- ATOMIC64_OP_RETURN(op, c_op, asm_op) ++#define ATOMIC64_OP_RETURN(op, asm_op) __ATOMIC64_OP_RETURN(op, _unchecked, asm_op##u, , ) \ ++ __ATOMIC64_OP_RETURN(op, , asm_op, __OVERFLOW_POST, __OVERFLOW_EXTABLE) + +-ATOMIC64_OPS(add, +=, daddu) +-ATOMIC64_OPS(sub, -=, dsubu) ++#define ATOMIC64_OPS(op, asm_op) \ ++ ATOMIC64_OP(op, asm_op) \ ++ ATOMIC64_OP_RETURN(op, asm_op) ++ ++ATOMIC64_OPS(add, dadd) ++ATOMIC64_OPS(sub, dsub) + + #undef ATOMIC64_OPS + #undef ATOMIC64_OP_RETURN ++#undef __ATOMIC64_OP_RETURN + #undef ATOMIC64_OP ++#undef __ATOMIC64_OP ++#undef __OVERFLOW_EXTABLE ++#undef __OVERFLOW_POST + + /* + * atomic64_sub_if_positive - conditionally subtract integer from atomic +@@ -430,7 +574,7 @@ ATOMIC64_OPS(sub, -=, dsubu) + * Atomically test @v and subtract @i if @v is greater or equal than @i. + * The function returns the old value of @v minus @i. + */ +-static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) ++static __inline__ long atomic64_sub_if_positive(long i, atomic64_t *v) + { + long result; + +@@ -440,7 +584,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) + long temp; + + __asm__ __volatile__( +- " .set arch=r4000 \n" ++ " .set "MIPS_ISA_LEVEL" \n" + "1: lld %1, %2 # atomic64_sub_if_positive\n" + " dsubu %0, %1, %3 \n" + " bltz %0, 1f \n" +@@ -489,9 +633,26 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) + return result; + } + +-#define atomic64_cmpxchg(v, o, n) \ +- ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) +-#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new))) ++static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) ++{ ++ return cmpxchg(&v->counter, old, new); ++} ++ ++static inline long atomic64_cmpxchg_unchecked(atomic64_unchecked_t *v, long old, ++ long new) ++{ ++ return cmpxchg(&(v->counter), old, new); ++} ++ ++static inline long atomic64_xchg(atomic64_t *v, long new) ++{ ++ return xchg(&v->counter, new); ++} ++ ++static inline long atomic64_xchg_unchecked(atomic64_unchecked_t *v, long new) ++{ ++ return xchg(&(v->counter), new); ++} + + /** + * atomic64_add_unless - add unless the number is a given value +@@ -521,6 +682,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + + #define atomic64_dec_return(v) atomic64_sub_return(1, (v)) + #define atomic64_inc_return(v) atomic64_add_return(1, (v)) ++#define atomic64_inc_return_unchecked(v) atomic64_add_return_unchecked(1, (v)) + + /* + * atomic64_sub_and_test - subtract value from variable and test result +@@ -542,6 +704,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * other cases. + */ + #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) ++#define atomic64_inc_and_test_unchecked(v) atomic64_add_return_unchecked(1, (v)) == 0) + + /* + * atomic64_dec_and_test - decrement by 1 and test +@@ -566,6 +729,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * Atomically increments @v by 1. + */ + #define atomic64_inc(v) atomic64_add(1, (v)) ++#define atomic64_inc_unchecked(v) atomic64_add_unchecked(1, (v)) + + /* + * atomic64_dec - decrement and test +@@ -574,6 +738,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * Atomically decrements @v by 1. + */ + #define atomic64_dec(v) atomic64_sub(1, (v)) ++#define atomic64_dec_unchecked(v) atomic64_sub_unchecked(1, (v)) + + /* + * atomic64_add_negative - add and test if negative +diff --git a/arch/mips/include/asm/barrier.h b/arch/mips/include/asm/barrier.h +index 7ecba84..21774af 100644 +--- a/arch/mips/include/asm/barrier.h ++++ b/arch/mips/include/asm/barrier.h +@@ -133,7 +133,7 @@ + do { \ + compiletime_assert_atomic_type(*p); \ + smp_mb(); \ +- ACCESS_ONCE(*p) = (v); \ ++ ACCESS_ONCE_RW(*p) = (v); \ + } while (0) + + #define smp_load_acquire(p) \ +diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h +index b4db69f..8f3b093 100644 +--- a/arch/mips/include/asm/cache.h ++++ b/arch/mips/include/asm/cache.h +@@ -9,10 +9,11 @@ + #ifndef _ASM_CACHE_H + #define _ASM_CACHE_H + ++#include + #include + + #define L1_CACHE_SHIFT CONFIG_MIPS_L1_CACHE_SHIFT +-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) ++#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + + #define SMP_CACHE_SHIFT L1_CACHE_SHIFT + #define SMP_CACHE_BYTES L1_CACHE_BYTES +diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h +index f19e890..a4f8177 100644 +--- a/arch/mips/include/asm/elf.h ++++ b/arch/mips/include/asm/elf.h +@@ -417,6 +417,13 @@ extern const char *__elf_platform; + #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) + #endif + ++#ifdef CONFIG_PAX_ASLR ++#define PAX_ELF_ET_DYN_BASE (TASK_IS_32BIT_ADDR ? 0x00400000UL : 0x00400000UL) ++ ++#define PAX_DELTA_MMAP_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) ++#define PAX_DELTA_STACK_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) ++#endif ++ + #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 + struct linux_binprm; + extern int arch_setup_additional_pages(struct linux_binprm *bprm, +diff --git a/arch/mips/include/asm/exec.h b/arch/mips/include/asm/exec.h +index c1f6afa..38cc6e9 100644 +--- a/arch/mips/include/asm/exec.h ++++ b/arch/mips/include/asm/exec.h +@@ -12,6 +12,6 @@ + #ifndef _ASM_EXEC_H + #define _ASM_EXEC_H + +-extern unsigned long arch_align_stack(unsigned long sp); ++#define arch_align_stack(x) ((x) & ~0xfUL) + + #endif /* _ASM_EXEC_H */ +diff --git a/arch/mips/include/asm/hw_irq.h b/arch/mips/include/asm/hw_irq.h +index 9e8ef59..1139d6b 100644 +--- a/arch/mips/include/asm/hw_irq.h ++++ b/arch/mips/include/asm/hw_irq.h +@@ -10,7 +10,7 @@ + + #include + +-extern atomic_t irq_err_count; ++extern atomic_unchecked_t irq_err_count; + + /* + * interrupt-retrigger: NOP for now. This may not be appropriate for all +diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h +index 8feaed6..1bd8a64 100644 +--- a/arch/mips/include/asm/local.h ++++ b/arch/mips/include/asm/local.h +@@ -13,15 +13,25 @@ typedef struct + atomic_long_t a; + } local_t; + ++typedef struct { ++ atomic_long_unchecked_t a; ++} local_unchecked_t; ++ + #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } + + #define local_read(l) atomic_long_read(&(l)->a) ++#define local_read_unchecked(l) atomic_long_read_unchecked(&(l)->a) + #define local_set(l, i) atomic_long_set(&(l)->a, (i)) ++#define local_set_unchecked(l, i) atomic_long_set_unchecked(&(l)->a, (i)) + + #define local_add(i, l) atomic_long_add((i), (&(l)->a)) ++#define local_add_unchecked(i, l) atomic_long_add_unchecked((i), (&(l)->a)) + #define local_sub(i, l) atomic_long_sub((i), (&(l)->a)) ++#define local_sub_unchecked(i, l) atomic_long_sub_unchecked((i), (&(l)->a)) + #define local_inc(l) atomic_long_inc(&(l)->a) ++#define local_inc_unchecked(l) atomic_long_inc_unchecked(&(l)->a) + #define local_dec(l) atomic_long_dec(&(l)->a) ++#define local_dec_unchecked(l) atomic_long_dec_unchecked(&(l)->a) + + /* + * Same as above, but return the result value +@@ -71,6 +81,51 @@ static __inline__ long local_add_return(long i, local_t * l) + return result; + } + ++static __inline__ long local_add_return_unchecked(long i, local_unchecked_t * l) ++{ ++ unsigned long result; ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ unsigned long temp; ++ ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1:" __LL "%1, %2 # local_add_return \n" ++ " addu %0, %1, %3 \n" ++ __SC "%0, %2 \n" ++ " beqzl %0, 1b \n" ++ " addu %0, %1, %3 \n" ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) ++ : "Ir" (i), "m" (l->a.counter) ++ : "memory"); ++ } else if (kernel_uses_llsc) { ++ unsigned long temp; ++ ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1:" __LL "%1, %2 # local_add_return \n" ++ " addu %0, %1, %3 \n" ++ __SC "%0, %2 \n" ++ " beqz %0, 1b \n" ++ " addu %0, %1, %3 \n" ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) ++ : "Ir" (i), "m" (l->a.counter) ++ : "memory"); ++ } else { ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ result = l->a.counter; ++ result += i; ++ l->a.counter = result; ++ local_irq_restore(flags); ++ } ++ ++ return result; ++} ++ + static __inline__ long local_sub_return(long i, local_t * l) + { + unsigned long result; +@@ -118,6 +173,8 @@ static __inline__ long local_sub_return(long i, local_t * l) + + #define local_cmpxchg(l, o, n) \ + ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) ++#define local_cmpxchg_unchecked(l, o, n) \ ++ ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) + #define local_xchg(l, n) (atomic_long_xchg((&(l)->a), (n))) + + /** +diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h +index 89dd7fe..a123c97 100644 +--- a/arch/mips/include/asm/page.h ++++ b/arch/mips/include/asm/page.h +@@ -118,7 +118,7 @@ extern void copy_user_highpage(struct page *to, struct page *from, + #ifdef CONFIG_CPU_MIPS32 + typedef struct { unsigned long pte_low, pte_high; } pte_t; + #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) +- #define __pte(x) ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) ++ #define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte; }) + #else + typedef struct { unsigned long long pte; } pte_t; + #define pte_val(x) ((x).pte) +diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h +index b336037..5b874cc 100644 +--- a/arch/mips/include/asm/pgalloc.h ++++ b/arch/mips/include/asm/pgalloc.h +@@ -37,6 +37,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) + { + set_pud(pud, __pud((unsigned long)pmd)); + } ++ ++static inline void pud_populate_kernel(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) ++{ ++ pud_populate(mm, pud, pmd); ++} + #endif + + /* +diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h +index ae85694..4cdbba8 100644 +--- a/arch/mips/include/asm/pgtable.h ++++ b/arch/mips/include/asm/pgtable.h +@@ -20,6 +20,9 @@ + #include + #include + ++#define ktla_ktva(addr) (addr) ++#define ktva_ktla(addr) (addr) ++ + struct mm_struct; + struct vm_area_struct; + +diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h +index 9c0014e..5101ef5 100644 +--- a/arch/mips/include/asm/thread_info.h ++++ b/arch/mips/include/asm/thread_info.h +@@ -100,6 +100,9 @@ static inline struct thread_info *current_thread_info(void) + #define TIF_SECCOMP 4 /* secure computing */ + #define TIF_NOTIFY_RESUME 5 /* callback before returning to user */ + #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ ++/* li takes a 32bit immediate */ ++#define TIF_GRSEC_SETXID 10 /* update credentials on syscall entry/exit */ ++ + #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ + #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ + #define TIF_NOHZ 19 /* in adaptive nohz mode */ +@@ -135,14 +138,16 @@ static inline struct thread_info *current_thread_info(void) + #define _TIF_USEDMSA (1< + #include + #include +diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c +index 9287678..f870e47 100644 +--- a/arch/mips/kernel/binfmt_elfo32.c ++++ b/arch/mips/kernel/binfmt_elfo32.c +@@ -70,6 +70,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + #undef ELF_ET_DYN_BASE + #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) + ++#ifdef CONFIG_PAX_ASLR ++#define PAX_ELF_ET_DYN_BASE (TASK_IS_32BIT_ADDR ? 0x00400000UL : 0x00400000UL) ++ ++#define PAX_DELTA_MMAP_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) ++#define PAX_DELTA_STACK_LEN (TASK_IS_32BIT_ADDR ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) ++#endif ++ + #include + + #include +diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c +index 74f6752..f3d7a47 100644 +--- a/arch/mips/kernel/i8259.c ++++ b/arch/mips/kernel/i8259.c +@@ -205,7 +205,7 @@ spurious_8259A_irq: + printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq); + spurious_irq_mask |= irqmask; + } +- atomic_inc(&irq_err_count); ++ atomic_inc_unchecked(&irq_err_count); + /* + * Theoretically we do not have to handle this IRQ, + * but in Linux this does not cause problems and is +diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c +index 44a1f79..2bd6aa3 100644 +--- a/arch/mips/kernel/irq-gt641xx.c ++++ b/arch/mips/kernel/irq-gt641xx.c +@@ -110,7 +110,7 @@ void gt641xx_irq_dispatch(void) + } + } + +- atomic_inc(&irq_err_count); ++ atomic_inc_unchecked(&irq_err_count); + } + + void __init gt641xx_irq_init(void) +diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c +index 8eb5af8..2baf465 100644 +--- a/arch/mips/kernel/irq.c ++++ b/arch/mips/kernel/irq.c +@@ -34,17 +34,17 @@ void ack_bad_irq(unsigned int irq) + printk("unexpected IRQ # %d\n", irq); + } + +-atomic_t irq_err_count; ++atomic_unchecked_t irq_err_count; + + int arch_show_interrupts(struct seq_file *p, int prec) + { +- seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); ++ seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read_unchecked(&irq_err_count)); + return 0; + } + + asmlinkage void spurious_interrupt(void) + { +- atomic_inc(&irq_err_count); ++ atomic_inc_unchecked(&irq_err_count); + } + + void __init init_IRQ(void) +@@ -58,6 +58,8 @@ void __init init_IRQ(void) + } + + #ifdef CONFIG_DEBUG_STACKOVERFLOW ++ ++extern void gr_handle_kernel_exploit(void); + static inline void check_stack_overflow(void) + { + unsigned long sp; +@@ -73,6 +75,7 @@ static inline void check_stack_overflow(void) + printk("do_IRQ: stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); ++ gr_handle_kernel_exploit(); + } + } + #else +diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c +index 0614717..002fa43 100644 +--- a/arch/mips/kernel/pm-cps.c ++++ b/arch/mips/kernel/pm-cps.c +@@ -172,7 +172,7 @@ int cps_pm_enter_state(enum cps_pm_state state) + nc_core_ready_count = nc_addr; + + /* Ensure ready_count is zero-initialised before the assembly runs */ +- ACCESS_ONCE(*nc_core_ready_count) = 0; ++ ACCESS_ONCE_RW(*nc_core_ready_count) = 0; + coupled_barrier(&per_cpu(pm_barrier, core), online); + + /* Run the generated entry code */ +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index f2975d4..f61d355 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -541,18 +541,6 @@ out: + return pc; + } + +-/* +- * Don't forget that the stack pointer must be aligned on a 8 bytes +- * boundary for 32-bits ABI and 16 bytes for 64-bits ABI. +- */ +-unsigned long arch_align_stack(unsigned long sp) +-{ +- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) +- sp -= get_random_int() & ~PAGE_MASK; +- +- return sp & ALMASK; +-} +- + static void arch_dump_stack(void *info) + { + struct pt_regs *regs; +diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c +index e933a30..0d02625 100644 +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -785,6 +785,10 @@ long arch_ptrace(struct task_struct *child, long request, + return ret; + } + ++#ifdef CONFIG_GRKERNSEC_SETXID ++extern void gr_delayed_cred_worker(void); ++#endif ++ + /* + * Notification of system call entry/exit + * - triggered by current->work.syscall_trace +@@ -803,6 +807,11 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) + tracehook_report_syscall_entry(regs)) + ret = -1; + ++#ifdef CONFIG_GRKERNSEC_SETXID ++ if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) ++ gr_delayed_cred_worker(); ++#endif ++ + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + trace_sys_enter(regs, regs->regs[2]); + +diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c +index 2242bdd..b284048 100644 +--- a/arch/mips/kernel/sync-r4k.c ++++ b/arch/mips/kernel/sync-r4k.c +@@ -18,8 +18,8 @@ + #include + + static atomic_t count_start_flag = ATOMIC_INIT(0); +-static atomic_t count_count_start = ATOMIC_INIT(0); +-static atomic_t count_count_stop = ATOMIC_INIT(0); ++static atomic_unchecked_t count_count_start = ATOMIC_INIT(0); ++static atomic_unchecked_t count_count_stop = ATOMIC_INIT(0); + static atomic_t count_reference = ATOMIC_INIT(0); + + #define COUNTON 100 +@@ -58,13 +58,13 @@ void synchronise_count_master(int cpu) + + for (i = 0; i < NR_LOOPS; i++) { + /* slaves loop on '!= 2' */ +- while (atomic_read(&count_count_start) != 1) ++ while (atomic_read_unchecked(&count_count_start) != 1) + mb(); +- atomic_set(&count_count_stop, 0); ++ atomic_set_unchecked(&count_count_stop, 0); + smp_wmb(); + + /* this lets the slaves write their count register */ +- atomic_inc(&count_count_start); ++ atomic_inc_unchecked(&count_count_start); + + /* + * Everyone initialises count in the last loop: +@@ -75,11 +75,11 @@ void synchronise_count_master(int cpu) + /* + * Wait for all slaves to leave the synchronization point: + */ +- while (atomic_read(&count_count_stop) != 1) ++ while (atomic_read_unchecked(&count_count_stop) != 1) + mb(); +- atomic_set(&count_count_start, 0); ++ atomic_set_unchecked(&count_count_start, 0); + smp_wmb(); +- atomic_inc(&count_count_stop); ++ atomic_inc_unchecked(&count_count_stop); + } + /* Arrange for an interrupt in a short while */ + write_c0_compare(read_c0_count() + COUNTON); +@@ -112,8 +112,8 @@ void synchronise_count_slave(int cpu) + initcount = atomic_read(&count_reference); + + for (i = 0; i < NR_LOOPS; i++) { +- atomic_inc(&count_count_start); +- while (atomic_read(&count_count_start) != 2) ++ atomic_inc_unchecked(&count_count_start); ++ while (atomic_read_unchecked(&count_count_start) != 2) + mb(); + + /* +@@ -122,8 +122,8 @@ void synchronise_count_slave(int cpu) + if (i == NR_LOOPS-1) + write_c0_count(initcount); + +- atomic_inc(&count_count_stop); +- while (atomic_read(&count_count_stop) != 2) ++ atomic_inc_unchecked(&count_count_stop); ++ while (atomic_read_unchecked(&count_count_stop) != 2) + mb(); + } + /* Arrange for an interrupt in a short while */ +diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c +index 8ea28e6..c8873d5 100644 +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -697,7 +697,18 @@ asmlinkage void do_ov(struct pt_regs *regs) + siginfo_t info; + + prev_state = exception_enter(); +- die_if_kernel("Integer overflow", regs); ++ if (unlikely(!user_mode(regs))) { ++ ++#ifdef CONFIG_PAX_REFCOUNT ++ if (fixup_exception(regs)) { ++ pax_report_refcount_overflow(regs); ++ exception_exit(prev_state); ++ return; ++ } ++#endif ++ ++ die("Integer overflow", regs); ++ } + + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; +diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c +index cd4c129..290c518 100644 +--- a/arch/mips/kvm/mips.c ++++ b/arch/mips/kvm/mips.c +@@ -1016,7 +1016,7 @@ long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) + return r; + } + +-int kvm_arch_init(void *opaque) ++int kvm_arch_init(const void *opaque) + { + if (kvm_mips_callbacks) { + kvm_err("kvm: module already exists\n"); +diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c +index 852a41c..75b9d38 100644 +--- a/arch/mips/mm/fault.c ++++ b/arch/mips/mm/fault.c +@@ -31,6 +31,23 @@ + + int show_unhandled_signals = 1; + ++#ifdef CONFIG_PAX_PAGEEXEC ++void pax_report_insns(struct pt_regs *regs, void *pc, void *sp) ++{ ++ unsigned long i; ++ ++ printk(KERN_ERR "PAX: bytes at PC: "); ++ for (i = 0; i < 5; i++) { ++ unsigned int c; ++ if (get_user(c, (unsigned int *)pc+i)) ++ printk(KERN_CONT "???????? "); ++ else ++ printk(KERN_CONT "%08x ", c); ++ } ++ printk("\n"); ++} ++#endif ++ + /* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate +@@ -207,6 +224,14 @@ bad_area: + bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ + if (user_mode(regs)) { ++ ++#ifdef CONFIG_PAX_PAGEEXEC ++ if (cpu_has_rixi && (mm->pax_flags & MF_PAX_PAGEEXEC) && !write && address == instruction_pointer(regs)) { ++ pax_report_fault(regs, (void *)address, (void *)user_stack_pointer(regs)); ++ do_group_exit(SIGKILL); ++ } ++#endif ++ + tsk->thread.cp0_badvaddr = address; + tsk->thread.error_code = write; + if (show_unhandled_signals && +diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c +index 5c81fdd..db158d3 100644 +--- a/arch/mips/mm/mmap.c ++++ b/arch/mips/mm/mmap.c +@@ -59,6 +59,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + struct vm_area_struct *vma; + unsigned long addr = addr0; + int do_color_align; ++ unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); + struct vm_unmapped_area_info info; + + if (unlikely(len > TASK_SIZE)) +@@ -84,6 +85,11 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + do_color_align = 1; + + /* requesting a specific address */ ++ ++#ifdef CONFIG_PAX_RANDMMAP ++ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) ++#endif ++ + if (addr) { + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); +@@ -91,14 +97,14 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); +- if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ if (TASK_SIZE - len >= addr && check_heap_stack_gap(vma, addr, len, offset)) + return addr; + } + + info.length = len; + info.align_mask = do_color_align ? (PAGE_MASK & shm_align_mask) : 0; + info.align_offset = pgoff << PAGE_SHIFT; ++ info.threadstack_offset = offset; + + if (dir == DOWN) { + info.flags = VM_UNMAPPED_AREA_TOPDOWN; +@@ -160,45 +166,34 @@ void arch_pic \ No newline at end of file diff --git a/test/grsecurity-3.1-4.2.6-201511092040.patch.sig b/test/grsecurity-3.1-4.2.6-201511092040.patch.sig new file mode 100644 index 0000000..076b7fd Binary files /dev/null and b/test/grsecurity-3.1-4.2.6-201511092040.patch.sig differ