From 8396727d78764e2372344ff2323c1704cc532c53 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sat, 24 May 2014 13:10:57 +0200 Subject: add some experimental kernel patches for security and multipath tcp --- target/linux/config/Config.in.addons | 17 + target/linux/patches/3.14.4/grsecurity.grsec | 121457 +++++++++++++++++++++ target/linux/patches/3.14.4/multipath-tcp.mptcp | 17203 +++ 3 files changed, 138677 insertions(+) create mode 100644 target/linux/config/Config.in.addons create mode 100644 target/linux/patches/3.14.4/grsecurity.grsec create mode 100644 target/linux/patches/3.14.4/multipath-tcp.mptcp (limited to 'target/linux') diff --git a/target/linux/config/Config.in.addons b/target/linux/config/Config.in.addons new file mode 100644 index 000000000..5c020812d --- /dev/null +++ b/target/linux/config/Config.in.addons @@ -0,0 +1,17 @@ +menu "Kernel addons" + +config ADK_KERNEL_ADDON_GRSEC + prompt "Enable Grsecurity addon" + boolean + depends on ADK_KERNEL_VERSION_3_14 + help + http://www.grsecurity.net + +config ADK_KERNEL_ADDON_MPTCP + prompt "Enable Multipath TCP addon" + boolean + depends on ADK_KERNEL_VERSION_3_14 + help + http://www.multipath-tcp.org + +endmenu diff --git a/target/linux/patches/3.14.4/grsecurity.grsec b/target/linux/patches/3.14.4/grsecurity.grsec new file mode 100644 index 000000000..9d846b96f --- /dev/null +++ b/target/linux/patches/3.14.4/grsecurity.grsec @@ -0,0 +1,121457 @@ +diff --git a/Documentation/dontdiff b/Documentation/dontdiff +index b89a739..e289b9b 100644 +--- a/Documentation/dontdiff ++++ b/Documentation/dontdiff +@@ -2,9 +2,11 @@ + *.aux + *.bin + *.bz2 ++*.c.[012]*.* + *.cis + *.cpio + *.csp ++*.dbg + *.dsp + *.dvi + *.elf +@@ -14,6 +16,7 @@ + *.gcov + *.gen.S + *.gif ++*.gmo + *.grep + *.grp + *.gz +@@ -48,14 +51,17 @@ + *.tab.h + *.tex + *.ver ++*.vim + *.xml + *.xz + *_MODULES ++*_reg_safe.h + *_vga16.c + *~ + \#*# + *.9 +-.* ++.[^g]* ++.gen* + .*.d + .mm + 53c700_d.h +@@ -69,9 +75,11 @@ Image + Module.markers + Module.symvers + PENDING ++PERF* + SCCS + System.map* + TAGS ++TRACEEVENT-CFLAGS + aconf + af_names.h + aic7*reg.h* +@@ -80,6 +88,7 @@ aic7*seq.h* + aicasm + aicdb.h* + altivec*.c ++ashldi3.S + asm-offsets.h + asm_offsets.h + autoconf.h* +@@ -92,32 +101,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 +@@ -125,12 +142,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 +@@ -145,14 +165,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 +@@ -162,14 +182,15 @@ mach-types.h + machtypes.h + map + map_hugetlb +-media + mconf ++mdp + miboot* + mk_elfconfig + mkboot + mkbugboot + mkcpustr + mkdep ++mkpiggy + mkprep + mkregtable + mktables +@@ -185,6 +206,8 @@ oui.c* + page-types + parse.c + parse.h ++parse-events* ++pasyms.h + patches* + pca200e.bin + pca200e_ecd.bin2 +@@ -194,6 +217,7 @@ perf-archive + piggyback + piggy.gzip + piggy.S ++pmu-* + pnmtologo + ppc_defs.h* + pss_boot.h +@@ -203,7 +227,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 +@@ -213,8 +242,12 @@ series + setup + setup.bin + setup.elf ++signing_key* ++size_overflow_hash.h + sImage ++slabinfo + sm_tbl* ++sortextable + split-include + syscalltab.h + tables.c +@@ -224,6 +257,7 @@ tftpboot.img + timeconst.h + times.h* + trix_boot.h ++user_constants.h + utsrelease.h* + vdso-syms.lds + vdso.lds +@@ -235,13 +269,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 +@@ -249,9 +287,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/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 7116fda..d8ed6e8 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1084,6 +1084,10 @@ 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 ++ ++ + hashdist= [KNL,NUMA] Large hashes allocated during boot + are distributed across NUMA nodes. Defaults on + for 64-bit NUMA, off otherwise. +@@ -2080,6 +2084,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. +@@ -2347,6 +2355,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + the specified number of seconds. This is to be used if + your oopses keep scrolling off the screen. + ++ 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= ++ 0/1 to disable/enable slab object sanitization (enabled by ++ default). ++ ++ 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/Makefile b/Makefile +index d7c07fd..d6d4bfa 100644 +--- a/Makefile ++++ b/Makefile +@@ -244,8 +244,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + + HOSTCC = gcc + HOSTCXX = g++ +-HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer +-HOSTCXXFLAGS = -O2 ++HOSTCFLAGS = -Wall -W -Wmissing-prototypes -Wstrict-prototypes -Wno-unused-parameter -Wno-missing-field-initializers -O2 -fomit-frame-pointer -fno-delete-null-pointer-checks ++HOSTCFLAGS += $(call cc-option, -Wno-empty-body) ++HOSTCXXFLAGS = -O2 -Wall -W -Wno-array-bounds + + # Decide whether to build built-in, modular, or both. + # Normally, just do built-in. +@@ -423,8 +424,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 + +@@ -585,6 +586,72 @@ else + KBUILD_CFLAGS += -O2 + endif + ++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 ++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 += $(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 ++ + include $(srctree)/arch/$(SRCARCH)/Makefile + + ifdef CONFIG_READABLE_ASM +@@ -779,7 +846,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) \ +@@ -828,6 +895,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) +@@ -837,7 +906,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 +@@ -880,10 +949,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 +@@ -991,6 +1063,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.'; +@@ -1006,7 +1080,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 +@@ -1072,7 +1146,8 @@ MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \ + 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 ++ signing_key.x509.signer tools/gcc/size_overflow_hash.h \ ++ tools/gcc/randomize_layout_seed.h + + # clean - Delete most, but leave enough to build external modules + # +@@ -1112,6 +1187,7 @@ distclean: mrproper + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ + -o -name '.*.rej' \ ++ -o -name '.*.rej' -o -name '*.so' \ + -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ + -type f -print | xargs rm -f + +@@ -1273,6 +1349,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 +@@ -1412,17 +1490,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 $@) +@@ -1432,11 +1514,15 @@ endif + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +-%/: 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 78b03ef..da28a51 100644 +--- a/arch/alpha/include/asm/atomic.h ++++ b/arch/alpha/include/asm/atomic.h +@@ -292,6 +292,16 @@ 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)) ++ + #define smp_mb__before_atomic_dec() smp_mb() + #define smp_mb__after_atomic_dec() smp_mb() + #define smp_mb__before_atomic_inc() smp_mb() +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 d8f9b7e..f6222fa 100644 +--- a/arch/alpha/include/asm/pgtable.h ++++ b/arch/alpha/include/asm/pgtable.h +@@ -102,6 +102,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 1402fcc..0b1abd2 100644 +--- a/arch/alpha/kernel/osf_sys.c ++++ b/arch/alpha/kernel/osf_sys.c +@@ -1298,10 +1298,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; +@@ -1309,6 +1310,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); + } + +@@ -1341,20 +1343,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 98838a0..b304fb4 100644 +--- a/arch/alpha/mm/fault.c ++++ b/arch/alpha/mm/fault.c +@@ -53,6 +53,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, +@@ -133,8 +251,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/arm/Kconfig b/arch/arm/Kconfig +index 44298ad..29a20c0 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1862,7 +1862,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 +@@ -2125,6 +2125,7 @@ config XIP_PHYS_ADDR + config KEXEC + bool "Kexec system call (EXPERIMENTAL)" + depends on (!SMP || PM_SLEEP_SMP) ++ 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/include/asm/atomic.h b/arch/arm/include/asm/atomic.h +index 62d2cb5..09d45e3 100644 +--- a/arch/arm/include/asm/atomic.h ++++ b/arch/arm/include/asm/atomic.h +@@ -18,17 +18,35 @@ + #include + #include + ++#ifdef CONFIG_GENERIC_ATOMIC64 ++#include ++#endif ++ + #define ATOMIC_INIT(i) { (i) } + + #ifdef __KERNEL__ + ++#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) (*(volatile int *)&(v)->counter) ++static inline int atomic_read_unchecked(const atomic_unchecked_t *v) ++{ ++ return 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 + +@@ -44,6 +62,36 @@ static inline void atomic_add(int i, atomic_t *v) + + prefetchw(&v->counter); + __asm__ __volatile__("@ atomic_add\n" ++"1: ldrex %1, [%3]\n" ++" adds %0, %1, %4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ ++" strex %1, %0, [%3]\n" ++" teq %1, #0\n" ++" bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ ++ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) ++ : "r" (&v->counter), "Ir" (i) ++ : "cc"); ++} ++ ++static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ prefetchw(&v->counter); ++ __asm__ __volatile__("@ atomic_add_unchecked\n" + "1: ldrex %0, [%3]\n" + " add %0, %0, %4\n" + " strex %1, %0, [%3]\n" +@@ -62,6 +110,42 @@ static inline int atomic_add_return(int i, atomic_t *v) + smp_mb(); + + __asm__ __volatile__("@ atomic_add_return\n" ++"1: ldrex %1, [%3]\n" ++" adds %0, %1, %4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++" mov %0, %1\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ ++" strex %1, %0, [%3]\n" ++" teq %1, #0\n" ++" bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ ++ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) ++ : "r" (&v->counter), "Ir" (i) ++ : "cc"); ++ ++ smp_mb(); ++ ++ return result; ++} ++ ++static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ smp_mb(); ++ ++ __asm__ __volatile__("@ atomic_add_return_unchecked\n" + "1: ldrex %0, [%3]\n" + " add %0, %0, %4\n" + " strex %1, %0, [%3]\n" +@@ -83,6 +167,36 @@ static inline void atomic_sub(int i, atomic_t *v) + + prefetchw(&v->counter); + __asm__ __volatile__("@ atomic_sub\n" ++"1: ldrex %1, [%3]\n" ++" subs %0, %1, %4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ ++" strex %1, %0, [%3]\n" ++" teq %1, #0\n" ++" bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ ++ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) ++ : "r" (&v->counter), "Ir" (i) ++ : "cc"); ++} ++ ++static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ prefetchw(&v->counter); ++ __asm__ __volatile__("@ atomic_sub_unchecked\n" + "1: ldrex %0, [%3]\n" + " sub %0, %0, %4\n" + " strex %1, %0, [%3]\n" +@@ -101,11 +215,25 @@ static inline int atomic_sub_return(int i, atomic_t *v) + smp_mb(); + + __asm__ __volatile__("@ atomic_sub_return\n" +-"1: ldrex %0, [%3]\n" +-" sub %0, %0, %4\n" ++"1: ldrex %1, [%3]\n" ++" subs %0, %1, %4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++" mov %0, %1\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ + " strex %1, %0, [%3]\n" + " teq %1, #0\n" + " bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) + : "r" (&v->counter), "Ir" (i) + : "cc"); +@@ -138,6 +266,28 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) + 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 +@@ -156,7 +306,17 @@ static inline int atomic_add_return(int i, atomic_t *v) + + return val; + } ++ ++static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) ++{ ++ return atomic_add_return(i, v); ++} ++ + #define atomic_add(i, v) (void) atomic_add_return(i, v) ++static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) ++{ ++ (void) atomic_add_return(i, v); ++} + + static inline int atomic_sub_return(int i, atomic_t *v) + { +@@ -171,6 +331,10 @@ static inline int atomic_sub_return(int i, atomic_t *v) + return val; + } + #define atomic_sub(i, v) (void) atomic_sub_return(i, v) ++static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) ++{ ++ (void) atomic_sub_return(i, v); ++} + + static inline int atomic_cmpxchg(atomic_t *v, int old, int new) + { +@@ -186,9 +350,18 @@ 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(v, old, new); ++} ++ + #endif /* __LINUX_ARM_ARCH__ */ + + #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); ++} + + static inline int __atomic_add_unless(atomic_t *v, int a, int u) + { +@@ -201,11 +374,27 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) + } + + #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) + +@@ -221,6 +410,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 +@@ -237,6 +434,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" +@@ -245,6 +455,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) + { +@@ -259,6 +478,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; +@@ -273,6 +505,21 @@ 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 + + static inline void atomic64_add(long long i, atomic64_t *v) +@@ -284,6 +531,37 @@ static inline void atomic64_add(long long i, atomic64_t *v) + __asm__ __volatile__("@ atomic64_add\n" + "1: ldrexd %0, %H0, [%3]\n" + " adds %Q0, %Q0, %Q4\n" ++" adcs %R0, %R0, %R4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ ++" strexd %1, %0, %H0, [%3]\n" ++" teq %1, #0\n" ++" bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ ++ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) ++ : "r" (&v->counter), "r" (i) ++ : "cc"); ++} ++ ++static inline void atomic64_add_unchecked(long long i, atomic64_unchecked_t *v) ++{ ++ long long result; ++ unsigned long tmp; ++ ++ prefetchw(&v->counter); ++ __asm__ __volatile__("@ atomic64_add_unchecked\n" ++"1: ldrexd %0, %H0, [%3]\n" ++" adds %Q0, %Q0, %Q4\n" + " adc %R0, %R0, %R4\n" + " strexd %1, %0, %H0, [%3]\n" + " teq %1, #0\n" +@@ -303,6 +581,44 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v) + __asm__ __volatile__("@ atomic64_add_return\n" + "1: ldrexd %0, %H0, [%3]\n" + " adds %Q0, %Q0, %Q4\n" ++" adcs %R0, %R0, %R4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++" mov %0, %1\n" ++" mov %H0, %H1\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ ++" strexd %1, %0, %H0, [%3]\n" ++" teq %1, #0\n" ++" bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ ++ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) ++ : "r" (&v->counter), "r" (i) ++ : "cc"); ++ ++ smp_mb(); ++ ++ return result; ++} ++ ++static inline long long atomic64_add_return_unchecked(long long i, atomic64_unchecked_t *v) ++{ ++ long long result; ++ unsigned long tmp; ++ ++ smp_mb(); ++ ++ __asm__ __volatile__("@ atomic64_add_return_unchecked\n" ++"1: ldrexd %0, %H0, [%3]\n" ++" adds %Q0, %Q0, %Q4\n" + " adc %R0, %R0, %R4\n" + " strexd %1, %0, %H0, [%3]\n" + " teq %1, #0\n" +@@ -325,6 +641,37 @@ static inline void atomic64_sub(long long i, atomic64_t *v) + __asm__ __volatile__("@ atomic64_sub\n" + "1: ldrexd %0, %H0, [%3]\n" + " subs %Q0, %Q0, %Q4\n" ++" sbcs %R0, %R0, %R4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ ++" strexd %1, %0, %H0, [%3]\n" ++" teq %1, #0\n" ++" bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ ++ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) ++ : "r" (&v->counter), "r" (i) ++ : "cc"); ++} ++ ++static inline void atomic64_sub_unchecked(long long i, atomic64_unchecked_t *v) ++{ ++ long long result; ++ unsigned long tmp; ++ ++ prefetchw(&v->counter); ++ __asm__ __volatile__("@ atomic64_sub_unchecked\n" ++"1: ldrexd %0, %H0, [%3]\n" ++" subs %Q0, %Q0, %Q4\n" + " sbc %R0, %R0, %R4\n" + " strexd %1, %0, %H0, [%3]\n" + " teq %1, #0\n" +@@ -344,16 +691,29 @@ static inline long long atomic64_sub_return(long long i, atomic64_t *v) + __asm__ __volatile__("@ atomic64_sub_return\n" + "1: ldrexd %0, %H0, [%3]\n" + " subs %Q0, %Q0, %Q4\n" +-" sbc %R0, %R0, %R4\n" ++" sbcs %R0, %R0, %R4\n" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++" bvc 3f\n" ++" mov %0, %1\n" ++" mov %H0, %H1\n" ++"2: bkpt 0xf103\n" ++"3:\n" ++#endif ++ + " strexd %1, %0, %H0, [%3]\n" + " teq %1, #0\n" + " bne 1b" ++ ++#ifdef CONFIG_PAX_REFCOUNT ++"\n4:\n" ++ _ASM_EXTABLE(2b, 4b) ++#endif ++ + : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) + : "r" (&v->counter), "r" (i) + : "cc"); + +- smp_mb(); +- + return result; + } + +@@ -382,6 +742,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; +@@ -406,20 +791,34 @@ 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(); + + __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: bkpt 0xf103\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"); +@@ -442,13 +841,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: bkpt 0xf103\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"); +@@ -461,10 +872,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/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 8b8b616..d973d24 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 df2fbba..63fe3e1 100644 +--- a/arch/arm/include/asm/cmpxchg.h ++++ b/arch/arm/include/asm/cmpxchg.h +@@ -102,6 +102,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size + + #define xchg(ptr,x) \ + ((__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/domain.h b/arch/arm/include/asm/domain.h +index 6ddbe44..b5e38b1 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 f4b46d3..abc9b2b 100644 +--- a/arch/arm/include/asm/elf.h ++++ b/arch/arm/include/asm/elf.h +@@ -114,7 +114,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 (2 * TASK_SIZE / 3) ++#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 +@@ -124,10 +131,6 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); + extern void elf_set_personality(const struct elf32_hdr *); + #define SET_PERSONALITY(ex) elf_set_personality(&(ex)) + +-struct mm_struct; +-extern unsigned long arch_randomize_brk(struct mm_struct *mm); +-#define arch_randomize_brk arch_randomize_brk +- + #ifdef CONFIG_MMU + #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 + struct linux_binprm; +diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h +index de53547..52b9a28 100644 +--- a/arch/arm/include/asm/fncpy.h ++++ 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 2aff798..099eb15 100644 +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -45,6 +45,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(); + __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" + "1: ldrex %1, [%4]\n" +@@ -60,6 +62,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + : "cc", "memory"); + smp_mb(); + ++ pax_close_userland(); ++ + *uval = val; + return ret; + } +@@ -90,6 +94,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + ++ pax_open_userland(); ++ + __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" + "1: " TUSER(ldr) " %1, [%4]\n" + " teq %1, %2\n" +@@ -100,6 +106,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; + return ret; + } +@@ -122,6 +130,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + return -EFAULT; + + pagefault_disable(); /* implies preempt_disable() */ ++ pax_open_userland(); + + switch (op) { + case FUTEX_OP_SET: +@@ -143,6 +152,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + ret = -ENOSYS; + } + ++ pax_close_userland(); + pagefault_enable(); /* subsumes preempt_enable() */ + + if (!ret) { +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 f94784f..9a09a4a 100644 +--- a/arch/arm/include/asm/outercache.h ++++ b/arch/arm/include/asm/outercache.h +@@ -35,7 +35,7 @@ struct outer_cache_fns { + #endif + void (*set_debug)(unsigned long); + void (*resume)(void); +-}; ++} __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 78a7793..e3dc06c 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) + { +@@ -157,7 +177,7 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) + static inline void + pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) + { +- __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE); ++ __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE | __supported_pmd_mask); + } + #define pmd_pgtable(pmd) pmd_page(pmd) + +diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h +index 5cfba15..f415e1a 100644 +--- a/arch/arm/include/asm/pgtable-2level-hwdef.h ++++ b/arch/arm/include/asm/pgtable-2level-hwdef.h +@@ -20,12 +20,15 @@ + #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) + #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) + #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) ++#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */ + #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) + #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) + #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ ++ + /* + * - section + */ ++#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 */ +@@ -37,6 +40,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) +@@ -66,6 +70,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 219ac88..73ec32a 100644 +--- a/arch/arm/include/asm/pgtable-2level.h ++++ b/arch/arm/include/asm/pgtable-2level.h +@@ -126,6 +126,9 @@ + #define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ + #define L_PTE_NONE (_AT(pteval_t, 1) << 11) + ++/* Two-level page tables only have PXN in the PGD, not in the PTE. */ ++#define L_PTE_PXN (_AT(pteval_t, 0)) ++ + /* + * These are the memory types, defined to be compatible with + * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB +diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h +index 626989f..9d67a33 100644 +--- a/arch/arm/include/asm/pgtable-3level-hwdef.h ++++ b/arch/arm/include/asm/pgtable-3level-hwdef.h +@@ -75,6 +75,7 @@ + #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ + #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ + #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ ++#define PTE_EXT_PXN (_AT(pteval_t, 1) << 53) /* PXN */ + #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ + + /* +diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h +index 85c60ad..b0bbd7e 100644 +--- a/arch/arm/include/asm/pgtable-3level.h ++++ b/arch/arm/include/asm/pgtable-3level.h +@@ -82,6 +82,7 @@ + #define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ + #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) /* unused */ + #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ +@@ -95,6 +96,7 @@ + /* + * 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 7d59b52..27a12f8 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 + +@@ -262,7 +310,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return 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 c4ae171..ea0c0c2 100644 +--- a/arch/arm/include/asm/psci.h ++++ b/arch/arm/include/asm/psci.h +@@ -29,7 +29,7 @@ struct psci_operations { + int (*cpu_off)(struct psci_power_state state); + int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); + int (*migrate)(unsigned long cpuid); +-}; ++} __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 22a3b9b..7f214ee 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -112,7 +112,7 @@ struct smp_operations { + int (*cpu_disable)(unsigned int cpu); + #endif + #endif +-}; ++} __no_const; + + /* + * set platform specific SMP operations +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index 71a06b2..8bb9ae1 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -88,9 +88,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), \ + .restart_block = { \ + .