diff --git a/Documentation/dontdiff b/Documentation/dontdiff index b89a739..79768fb 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,19 +101,24 @@ 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 @@ -115,9 +129,11 @@ 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 +141,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 +164,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 +181,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 +205,8 @@ oui.c* page-types parse.c parse.h +parse-events* +pasyms.h patches* pca200e.bin pca200e_ecd.bin2 @@ -194,6 +216,7 @@ perf-archive piggyback piggy.gzip piggy.S +pmu-* pnmtologo ppc_defs.h* pss_boot.h @@ -203,7 +226,10 @@ r200_reg_safe.h r300_reg_safe.h r420_reg_safe.h r600_reg_safe.h +realmode.lds +realmode.relocs recordmcount +regdb.c relocs rlim_names.h rn50_reg_safe.h @@ -213,8 +239,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 +254,7 @@ tftpboot.img timeconst.h times.h* trix_boot.h +user_constants.h utsrelease.h* vdso-syms.lds vdso.lds @@ -235,13 +266,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 +284,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 2fe6e76..889ee23 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -976,6 +976,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. 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. @@ -1928,6 +1932,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. noexec=on: enable non-executable mappings (default) noexec=off: disable non-executable mappings + nopcid [X86-64] + Disable PCID (Process-Context IDentifier) even if it + is supported by the processor. + nosmap [X86] Disable SMAP (Supervisor Mode Access Prevention) even if it is supported by processor. @@ -2195,6 +2203,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted. the specified number of seconds. This is to be used if your oopses keep scrolling off the screen. + 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 25d38b7..7582631 100644 --- a/Makefile +++ b/Makefile @@ -241,8 +241,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 -fno-delete-null-pointer-checks # Decide whether to build built-in, modular, or both. # Normally, just do built-in. @@ -414,8 +415,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 @@ -576,6 +577,65 @@ 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_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.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_AFLAGS := $(KERNEXEC_PLUGIN_AFLAGS) +export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGINS_AFLAGS CONSTIFY_PLUGIN +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 @@ -733,7 +793,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) \ @@ -782,6 +842,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) @@ -791,7 +853,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)=$@ # Store (new) KERNELRELASE string in include/config/kernel.release @@ -835,6 +897,7 @@ prepare0: archprepare FORCE $(Q)$(MAKE) $(build)=. # All the preparing.. +prepare: KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) prepare: prepare0 # Generate some files @@ -942,6 +1005,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.'; @@ -957,7 +1022,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 @@ -1023,7 +1088,7 @@ 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 # clean - Delete most, but leave enough to build external modules # @@ -1063,6 +1128,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 @@ -1223,6 +1289,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 @@ -1359,17 +1427,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 $@) @@ -1379,11 +1451,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 c2cbe4f..f7264b4 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -250,6 +250,16 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) #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 bc2a0da..8ad11ee 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 81a4342..348b927 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 b9e37ad..44c24e7 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1297,10 +1297,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; @@ -1308,6 +1309,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); } @@ -1340,20 +1342,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 0c4132d..88f0d53 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 18a9f5e..ca910b7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1766,7 +1766,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 diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index da1c77d..2ee6056 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -17,17 +17,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 @@ -42,6 +60,35 @@ static inline void atomic_add(int i, atomic_t *v) int result; __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; + + __asm__ __volatile__("@ atomic_add_unchecked\n" "1: ldrex %0, [%3]\n" " add %0, %0, %4\n" " strex %1, %0, [%3]\n" @@ -60,6 +107,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" @@ -80,6 +163,35 @@ static inline void atomic_sub(int i, atomic_t *v) int result; __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; + + __asm__ __volatile__("@ atomic_sub_unchecked\n" "1: ldrex %0, [%3]\n" " sub %0, %0, %4\n" " strex %1, %0, [%3]\n" @@ -98,11 +210,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"); @@ -134,6 +260,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; +} + static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) { unsigned long tmp, tmp2; @@ -167,7 +315,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) { @@ -182,6 +340,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) { @@ -197,6 +359,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(v, old, new); +} + static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) { unsigned long flags; @@ -209,6 +376,10 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) #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) { @@ -221,11 +392,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) @@ -241,6 +428,14 @@ typedef struct { u64 __aligned(8) counter; } atomic64_t; +#ifdef CONFIG_PAX_REFCOUNT +typedef struct { + u64 __aligned(8) counter; +} atomic64_unchecked_t; +#else +typedef atomic64_t atomic64_unchecked_t; +#endif + #define ATOMIC64_INIT(i) { (i) } #ifdef CONFIG_ARM_LPAE @@ -257,6 +452,19 @@ static inline u64 atomic64_read(const atomic64_t *v) return result; } +static inline u64 atomic64_read_unchecked(const atomic64_unchecked_t *v) +{ + u64 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, u64 i) { __asm__ __volatile__("@ atomic64_set\n" @@ -265,6 +473,15 @@ static inline void atomic64_set(atomic64_t *v, u64 i) : "r" (&v->counter), "r" (i) ); } + +static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, u64 i) +{ + __asm__ __volatile__("@ atomic64_set_unchecked\n" +" strd %2, %H2, [%1]" + : "=Qo" (v->counter) + : "r" (&v->counter), "r" (i) + ); +} #else static inline u64 atomic64_read(const atomic64_t *v) { @@ -279,6 +496,19 @@ static inline u64 atomic64_read(const atomic64_t *v) return result; } +static inline u64 atomic64_read_unchecked(atomic64_unchecked_t *v) +{ + u64 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, u64 i) { u64 tmp; @@ -292,6 +522,21 @@ static inline void atomic64_set(atomic64_t *v, u64 i) : "r" (&v->counter), "r" (i) : "cc"); } + +static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, u64 i) +{ + u64 tmp; + + __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(u64 i, atomic64_t *v) @@ -302,6 +547,36 @@ static inline void atomic64_add(u64 i, atomic64_t *v) __asm__ __volatile__("@ atomic64_add\n" "1: ldrexd %0, %H0, [%3]\n" " adds %0, %0, %4\n" +" adcs %H0, %H0, %H4\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(u64 i, atomic64_unchecked_t *v) +{ + u64 result; + unsigned long tmp; + + __asm__ __volatile__("@ atomic64_add_unchecked\n" +"1: ldrexd %0, %H0, [%3]\n" +" adds %0, %0, %4\n" " adc %H0, %H0, %H4\n" " strexd %1, %0, %H0, [%3]\n" " teq %1, #0\n" @@ -313,12 +588,49 @@ static inline void atomic64_add(u64 i, atomic64_t *v) static inline u64 atomic64_add_return(u64 i, atomic64_t *v) { + u64 result, tmp; + + smp_mb(); + + __asm__ __volatile__("@ atomic64_add_return\n" +"1: ldrexd %1, %H1, [%3]\n" +" adds %0, %1, %4\n" +" adcs %H0, %H1, %H4\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 u64 atomic64_add_return_unchecked(u64 i, atomic64_unchecked_t *v) +{ u64 result; unsigned long tmp; smp_mb(); - __asm__ __volatile__("@ atomic64_add_return\n" + __asm__ __volatile__("@ atomic64_add_return_unchecked\n" "1: ldrexd %0, %H0, [%3]\n" " adds %0, %0, %4\n" " adc %H0, %H0, %H4\n" @@ -342,23 +654,34 @@ static inline void atomic64_sub(u64 i, atomic64_t *v) __asm__ __volatile__("@ atomic64_sub\n" "1: ldrexd %0, %H0, [%3]\n" " subs %0, %0, %4\n" -" sbc %H0, %H0, %H4\n" +" sbcs %H0, %H0, %H4\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 u64 atomic64_sub_return(u64 i, atomic64_t *v) +static inline void atomic64_sub_unchecked(u64 i, atomic64_unchecked_t *v) { u64 result; unsigned long tmp; - smp_mb(); - - __asm__ __volatile__("@ atomic64_sub_return\n" + __asm__ __volatile__("@ atomic64_sub_unchecked\n" "1: ldrexd %0, %H0, [%3]\n" " subs %0, %0, %4\n" " sbc %H0, %H0, %H4\n" @@ -368,6 +691,39 @@ static inline u64 atomic64_sub_return(u64 i, atomic64_t *v) : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) : "r" (&v->counter), "r" (i) : "cc"); +} + +static inline u64 atomic64_sub_return(u64 i, atomic64_t *v) +{ + u64 result, tmp; + + smp_mb(); + + __asm__ __volatile__("@ atomic64_sub_return\n" +"1: ldrexd %1, %H1, [%3]\n" +" subs %0, %1, %4\n" +" sbcs %H0, %H1, %H4\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(); @@ -398,6 +754,30 @@ static inline u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old, u64 new) return oldval; } +static inline u64 atomic64_cmpxchg_unchecked(atomic64_unchecked_t *ptr, u64 old, u64 new) +{ + u64 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 u64 atomic64_xchg(atomic64_t *ptr, u64 new) { u64 result; @@ -421,21 +801,34 @@ static inline u64 atomic64_xchg(atomic64_t *ptr, u64 new) static inline u64 atomic64_dec_if_positive(atomic64_t *v) { - u64 result; - unsigned long tmp; + u64 result, tmp; smp_mb(); __asm__ __volatile__("@ atomic64_dec_if_positive\n" -"1: ldrexd %0, %H0, [%3]\n" -" subs %0, %0, #1\n" -" sbc %H0, %H0, #0\n" +"1: ldrexd %1, %H1, [%3]\n" +" subs %0, %1, #1\n" +" sbcs %H0, %H1, #0\n" + +#ifdef CONFIG_PAX_REFCOUNT +" bvc 3f\n" +" mov %0, %1\n" +" mov %H0, %H1\n" +"2: bkpt 0xf103\n" +"3:\n" +#endif + " teq %H0, #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"); @@ -458,13 +851,25 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u) " teq %0, %5\n" " teqeq %H0, %H5\n" " moveq %1, #0\n" -" beq 2f\n" +" beq 4f\n" " adds %0, %0, %6\n" -" adc %H0, %H0, %H6\n" +" adcs %H0, %H0, %H6\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"); @@ -477,10 +882,13 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 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 17d0ae8..014e350 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 6dcc164..b14d917 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 4f009c1..466c59b 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 56211f2..17e8a25 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -116,7 +116,14 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); 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 @@ -126,10 +133,6 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); extern void elf_set_personality(const struct elf32_hdr *); #define SET_PERSONALITY(ex) elf_set_personality(&(ex)) -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 e42cf59..7b94b8f 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -50,6 +50,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" @@ -65,6 +67,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, : "cc", "memory"); smp_mb(); + pax_close_userland(); + *uval = val; return ret; } @@ -95,6 +99,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" @@ -105,6 +111,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; } @@ -127,6 +135,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: @@ -148,6 +157,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 2fe141f..192dc01 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -27,13 +27,16 @@ struct map_desc { #define MT_MINICLEAN 6 #define MT_LOW_VECTORS 7 #define MT_HIGH_VECTORS 8 -#define MT_MEMORY 9 +#define MT_MEMORY_RWX 9 #define MT_ROM 10 -#define MT_MEMORY_NONCACHED 11 +#define MT_MEMORY_NONCACHED_RX 11 #define MT_MEMORY_DTCM 12 #define MT_MEMORY_ITCM 13 #define MT_MEMORY_SO 14 #define MT_MEMORY_DMA_READY 15 +#define MT_MEMORY_RW 16 +#define MT_MEMORY_RX 17 +#define MT_MEMORY_NONCACHED_RW 18 #ifdef CONFIG_MMU extern void iotable_init(struct map_desc *, int); diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 12f71a1..04e063c 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; #ifdef CONFIG_OUTER_CACHE diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index cbdc7a2..32f44fe 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h @@ -114,7 +114,7 @@ struct cpu_user_fns { 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 943504f..c37a730 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 */ @@ -126,6 +133,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) { @@ -155,7 +175,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 f97ee02..cc9fe9e 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 18f5cef..25b8f43 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -41,6 +41,7 @@ */ #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) +#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) @@ -71,6 +72,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 86b8fe3..e25f975 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h @@ -74,6 +74,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 */ @@ -82,6 +83,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 9bcd262..1ff999b 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -30,6 +30,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 @@ -45,6 +48,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); @@ -53,6 +59,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 @@ -72,8 +120,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 @@ -257,7 +305,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/proc-fns.h b/arch/arm/include/asm/proc-fns.h index f3628fb..a0672dd 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -75,7 +75,7 @@ extern struct processor { unsigned int suspend_size; void (*do_suspend)(void *); void (*do_resume)(void *); -} processor; +} __do_const processor; #ifndef MULTI_CPU extern void cpu_proc_init(void); diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h index ce0dbe7..c085b6f 100644 --- a/arch/arm/include/asm/psci.h +++ 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; diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index d3a22be..3a69ad5 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -107,7 +107,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 f00b569..aa5bb41 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -77,9 +77,9 @@ struct thread_info { .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 = { \ .fn = do_no_restart_syscall, \ }, \ @@ -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 @@ -165,10 +169,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) +#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/uaccess.h b/arch/arm/include/asm/uaccess.h index 7e1f760..de33b13 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -18,6 +18,7 @@ #include #include #include +#include #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -63,11 +64,38 @@ extern int __put_user_bad(void); static inline void set_fs(mm_segment_t fs) { current_thread_info()->addr_limit = fs; - 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" \ @@ -143,8 +171,12 @@ extern int __get_user_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); @@ -188,8 +220,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 */ @@ -230,13 +266,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; \ }) @@ -312,13 +352,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; \ }) @@ -418,11 +462,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_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); + +static inline unsigned long __must_check __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 __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(void __user *addr, unsigned long n); extern unsigned long __must_check __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) @@ -431,6 +508,9 @@ extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned l static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { + 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 */ @@ -440,6 +520,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { + 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 96ee092..37f1844 100644 --- a/arch/arm/include/uapi/asm/ptrace.h +++ b/arch/arm/include/uapi/asm/ptrace.h @@ -73,7 +73,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 60d3b73..e5a0f22 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -53,7 +53,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); @@ -89,9 +89,9 @@ EXPORT_SYMBOL(__memzero); #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/entry-armv.S b/arch/arm/kernel/entry-armv.S index d43c7e5..257c050 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -47,6 +47,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 @@ -89,11 +170,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 @@ -149,7 +234,11 @@ ENDPROC(__und_invalid) .macro svc_entry, stack_hole=0 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 ) @@ -164,7 +253,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 @@ -316,6 +410,9 @@ ENDPROC(__pabt_svc) .macro usr_entry 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} ) @@ -357,7 +454,8 @@ ENDPROC(__pabt_svc) .endm .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) #ifndef CONFIG_MMU #warning "NPTL on non MMU needs fixing" #else @@ -414,7 +512,9 @@ __und_usr: tst r3, #PSR_T_BIT @ Thumb mode? bne __und_usr_thumb sub r4, r2, #4 @ ARM instr at LR - 4 + pax_open_userland 1: ldrt r0, [r4] + pax_close_userland #ifdef CONFIG_CPU_ENDIAN_BE8 rev r0, r0 @ little endian instruction #endif @@ -449,10 +549,14 @@ __und_usr_thumb: */ .arch armv6t2 #endif + pax_open_userland 2: ldrht r5, [r4] + pax_close_userland 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 add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 str r2, [sp, #S_PC] @ it's a 2x16bit instr, update orr r0, r0, r5, lsl #16 @@ -481,7 +585,8 @@ ENDPROC(__und_usr) */ .pushsection .fixup, "ax" .align 2 -4: mov pc, r9 +4: pax_close_userland + mov pc, r9 .popsection .pushsection __ex_table,"a" .long 1b, 4b @@ -690,7 +795,7 @@ ENTRY(__switch_to) THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack THUMB( str sp, [ip], #4 ) THUMB( str lr, [ip], #4 ) -#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 set_tls r3, r4, r5 @@ -699,7 +804,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 bc5bc0a..d0998ca 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -10,18 +10,46 @@ #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 @@ -350,6 +378,7 @@ ENDPROC(ftrace_stub) .align 5 ENTRY(vector_swi) + sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 ARM( add r8, sp, #S_PC ) @@ -399,6 +428,12 @@ ENTRY(vector_swi) 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 + #ifdef CONFIG_ALIGNMENT_TRAP ldr ip, __cr_alignment ldr ip, [ip] diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 160f337..db67ee4 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -73,6 +73,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 @@ -92,6 +146,9 @@ blne trace_hardirqs_off #endif .endif + + pax_exit_kernel + msr spsr_cxsf, \rpsr #if defined(CONFIG_CPU_V6) ldr r0, [sp] @@ -155,6 +212,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 clrex @ clear the exclusive monitor diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 25442f4..d4948fc 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -84,17 +84,16 @@ int show_fiq_list(struct seq_file *p, int prec) void set_fiq_handler(void *start, unsigned int length) { -#if defined(CONFIG_CPU_USE_DOMAINS) - void *base = (void *)0xffff0000; -#else void *base = vectors_page; -#endif unsigned offset = FIQ_OFFSET; + pax_open_kernel(); memcpy(base + offset, start, length); + pax_close_kernel(); + + if (!cache_is_vipt_nonaliasing()) + flush_icache_range(base + offset, offset + length); flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); - if (!vectors_high()) - flush_icache_range(offset, offset + length); } int claim_fiq(struct fiq_handler *f) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 8bac553..caee108 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -52,7 +52,9 @@ .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE .macro pgtbl, rd, phys - add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE + mov \rd, #TEXT_OFFSET + sub \rd, #PG_DIR_SIZE + add \rd, \rd, \phys .endm /* @@ -434,7 +436,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/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 1fd749e..47adb08 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -1029,7 +1029,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata dbg_reset_nb = { +static struct notifier_block dbg_reset_nb = { .notifier_call = dbg_reset_notify, }; diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 1e9be5d..03edbc2 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -37,12 +37,37 @@ #endif #ifdef CONFIG_MMU -void *module_alloc(unsigned long size) +static inline void *__module_alloc(unsigned long size, pgprot_t prot) { + if (!size || PAGE_ALIGN(size) > MODULES_END - MODULES_VADDR) + return NULL; return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, - GFP_KERNEL, PAGE_KERNEL_EXEC, -1, + GFP_KERNEL, prot, -1, __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_free_exec(struct module *mod, void *module_region) +{ + module_free(mod, module_region); +} + +void *module_alloc_exec(unsigned long size) +{ + return __module_alloc(size, PAGE_KERNEL_EXEC); +} +#endif #endif int diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c index 07314af..c46655c 100644 --- a/arch/arm/kernel/patch.c +++ b/arch/arm/kernel/patch.c @@ -18,6 +18,7 @@ void __kprobes __patch_text(void *addr, unsigned int insn) bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); int size; + pax_open_kernel(); if (thumb2 && __opcode_is_thumb16(insn)) { *(u16 *)addr = __opcode_to_mem_thumb16(insn); size = sizeof(u16); @@ -39,6 +40,7 @@ void __kprobes __patch_text(void *addr, unsigned int insn) *(u32 *)addr = insn; size = sizeof(u32); } + pax_close_kernel(); flush_icache_range((uintptr_t)(addr), (uintptr_t)(addr) + size); diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index e19edc6..e186ee1 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -56,7 +56,7 @@ armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) int mapping; if (config >= PERF_COUNT_HW_MAX) - return -ENOENT; + return -EINVAL; mapping = (*event_map)[config]; return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 1f2740e..b36e225 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -171,7 +171,7 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = { +static struct notifier_block cpu_pmu_hotplug_notifier = { .notifier_call = cpu_pmu_notify, }; diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 5bc2615..dcd439f 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -223,6 +223,7 @@ void machine_power_off(void) if (pm_power_off) pm_power_off(); + BUG(); } /* @@ -236,7 +237,7 @@ void machine_power_off(void) * executing pre-reset code, and using RAM that the primary CPU's code wishes * to use. Implementing such co-ordination would be essentially impossible. */ -void machine_restart(char *cmd) +__noreturn void machine_restart(char *cmd) { smp_send_stop(); @@ -258,8 +259,8 @@ void __show_regs(struct pt_regs *regs) show_regs_print_info(KERN_DEFAULT); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - print_symbol("LR is at %s\n", regs->ARM_lr); + printk("PC is at %pA\n", (void *)instruction_pointer(regs)); + printk("LR is at %pA\n", (void *)regs->ARM_lr); printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" "sp : %08lx ip : %08lx fp : %08lx\n", regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, @@ -426,12 +427,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 /* @@ -447,7 +442,7 @@ static struct vm_area_struct gate_vma = { static int __init gate_vma_init(void) { - gate_vma.vm_page_prot = PAGE_READONLY_EXEC; + gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); return 0; } arch_initcall(gate_vma_init); @@ -466,48 +461,23 @@ int in_gate_area_no_mm(unsigned long addr) { return in_gate_area(NULL, addr); } -#define is_gate_vma(vma) ((vma) = &gate_vma) +#define is_gate_vma(vma) ((vma) == &gate_vma) #else #define is_gate_vma(vma) 0 #endif const char *arch_vma_name(struct vm_area_struct *vma) { - return is_gate_vma(vma) ? "[vectors]" : - (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ? - "[sigpage]" : NULL; + return is_gate_vma(vma) ? "[vectors]" : NULL; } -static struct page *signal_page; -extern struct page *get_signal_page(void); - int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; - unsigned long addr; - int ret; - - if (!signal_page) - signal_page = get_signal_page(); - if (!signal_page) - return -ENOMEM; down_write(&mm->mmap_sem); - addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); - if (IS_ERR_VALUE(addr)) { - ret = addr; - goto up_fail; - } - - ret = install_special_mapping(mm, addr, PAGE_SIZE, - VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, - &signal_page); - - if (ret == 0) - mm->context.sigpage = addr; - - up_fail: + mm->context.sigpage = (PAGE_OFFSET + (get_random_int() % 0x3FFEFFE0)) & 0xFFFFFFFC; up_write(&mm->mmap_sem); - return ret; + return 0; } #endif diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c index 3653164..d83e55d 100644 --- a/arch/arm/kernel/psci.c +++ b/arch/arm/kernel/psci.c @@ -24,7 +24,7 @@ #include #include -struct psci_operations psci_ops; +struct psci_operations psci_ops __read_only; static int (*invoke_psci_fn)(u32, u32, u32, u32); diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 03deeff..741ce88 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -937,10 +937,19 @@ static int tracehook_report_syscall(struct pt_regs *regs, return current_thread_info()->syscall; } +#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. */ if (secure_computing(scno) == -1) return -1; diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b4b1d39..efdc9be 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -97,21 +97,23 @@ EXPORT_SYMBOL(system_serial_high); unsigned int elf_hwcap __read_mostly; EXPORT_SYMBOL(elf_hwcap); +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; #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 @@ -236,9 +238,13 @@ static int __get_cpu_architecture(void) asm("mrc p15, 0, %0, c0, c1, 4" : "=r" (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 @@ -479,7 +485,7 @@ static void __init setup_processor(void) __cpu_architecture = __get_cpu_architecture(); #ifdef MULTI_CPU - processor = *list->proc; + memcpy((void *)&processor, list->proc, sizeof processor); #endif #ifdef MULTI_TLB cpu_tlb = *list->tlb; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 5a42c12..a2bb7c6 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -45,8 +45,6 @@ static const unsigned long sigreturn_codes[7] = { MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, }; -static unsigned long signal_return_offset; - #ifdef CONFIG_CRUNCH static int preserve_crunch_context(struct crunch_sigframe __user *frame) { @@ -406,8 +404,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, * except when the MPU has protected the vectors * page from PL0 */ - retcode = mm->context.sigpage + signal_return_offset + - (idx << 2) + thumb; + retcode = mm->context.sigpage + (idx << 2) + thumb; } else #endif { @@ -611,33 +608,3 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) } while (thread_flags & _TIF_WORK_MASK); return 0; } - -struct page *get_signal_page(void) -{ - unsigned long ptr; - unsigned offset; - struct page *page; - void *addr; - - page = alloc_pages(GFP_KERNEL, 0); - - if (!page) - return NULL; - - addr = page_address(page); - - /* Give the signal return code some randomness */ - offset = 0x200 + (get_random_int() & 0x7fc); - signal_return_offset = offset; - - /* - * Copy signal return handlers into the vector page, and - * set sigreturn to be a pointer to these. - */ - memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes)); - - ptr = (unsigned long)addr + offset; - flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); - - return page; -} diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 5919eb4..b5d6dfe 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -70,7 +70,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/traps.c b/arch/arm/kernel/traps.c index 6b9567e..b8af2d6 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -55,7 +55,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long); void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS - 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 @@ -257,6 +257,8 @@ static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; static int die_owner = -1; static unsigned int die_nest_count; +extern void gr_handle_kernel_exploit(void); + static unsigned long oops_begin(void) { int cpu; @@ -299,6 +301,9 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); + + gr_handle_kernel_exploit(); + if (signr) do_exit(signr); } @@ -592,7 +597,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) * The user helper at 0xffff0fe0 must be used instead. * (see entry-armv.S for details) */ + pax_open_kernel(); *((unsigned int *)0xffff0ff0) = regs->ARM_r0; + pax_close_kernel(); } return 0; @@ -848,5 +855,9 @@ 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 + } diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 33f2ea3..0b91824 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -8,7 +8,11 @@ #include #include #include - + +#ifdef CONFIG_PAX_KERNEXEC +#include +#endif + #define PROC_INFO \ . = ALIGN(4); \ VMLINUX_SYMBOL(__proc_info_begin) = .; \ @@ -94,6 +98,11 @@ SECTIONS _text = .; HEAD_TEXT } + +#ifdef CONFIG_PAX_KERNEXEC + . = ALIGN(1<arch.vmid_gen != atomic64_read(&kvm_vmid_gen)); + return unlikely(kvm->arch.vmid_gen != atomic64_read_unchecked(&kvm_vmid_gen)); } /** @@ -425,7 +425,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; /* @@ -442,7 +442,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++; diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S index 14a0d98..7771a7d 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 .fixup,"ax" diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 66a477a..bee61d3 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -16,7 +16,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: * @@ -84,11 +84,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 d066df6..df28194 100644 --- a/arch/arm/lib/copy_to_user.S +++ b/arch/arm/lib/copy_to_user.S @@ -16,7 +16,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: * @@ -88,11 +88,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 .fixup,"ax" diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S index 7d08b43..f7ca7ea 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 64dbfa5..84a3fd9 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -28,7 +28,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 025f742..8432b08 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -104,7 +104,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 diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index f389228..592ef66 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -149,7 +149,16 @@ static void clk_gate_fn_disable(struct clk_hw *hw) clk_gate_ops.disable(hw); } -static struct clk_ops clk_gate_fn_ops; +static int clk_gate_fn_is_enabled(struct clk_hw *hw) +{ + return clk_gate_ops.is_enabled(hw); +} + +static struct clk_ops clk_gate_fn_ops = { + .enable = clk_gate_fn_enable, + .disable = clk_gate_fn_disable, + .is_enabled = clk_gate_fn_is_enabled, +}; static struct clk __init *clk_register_gate_fn(struct device *dev, const char *name, @@ -183,14 +192,6 @@ static struct clk __init *clk_register_gate_fn(struct device *dev, gate_fn->fn_en = fn_en; gate_fn->fn_dis = fn_dis; - /* ops is the gate ops, but with our enable/disable functions */ - if (clk_gate_fn_ops.enable != clk_gate_fn_enable || - clk_gate_fn_ops.disable != clk_gate_fn_disable) { - clk_gate_fn_ops = clk_gate_ops; - clk_gate_fn_ops.enable = clk_gate_fn_enable; - clk_gate_fn_ops.disable = clk_gate_fn_disable; - } - clk = clk_register(dev, &gate_fn->gate.hw); if (IS_ERR(clk)) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index f6eeb87..cc90868 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -631,7 +631,7 @@ static int n8x0_menelaus_late_init(struct device *dev) } #endif -static struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = { +static struct menelaus_platform_data n8x0_menelaus_platform_data __initconst = { .late_init = n8x0_menelaus_late_init, }; diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 6c4da12..d9ca72d 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -147,7 +147,6 @@ struct omap3_gpmc_regs { }; static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; -static struct irq_chip gpmc_irq_chip; static unsigned gpmc_irq_start; static struct resource gpmc_mem_root; @@ -711,6 +710,18 @@ static void gpmc_irq_noop(struct irq_data *data) { } static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } +static struct irq_chip gpmc_irq_chip = { + .name = "gpmc", + .irq_startup = gpmc_irq_noop_ret, + .irq_enable = gpmc_irq_enable, + .irq_disable = gpmc_irq_disable, + .irq_shutdown = gpmc_irq_noop, + .irq_ack = gpmc_irq_noop, + .irq_mask = gpmc_irq_noop, + .irq_unmask = gpmc_irq_noop, + +}; + static int gpmc_setup_irq(void) { int i; @@ -725,15 +736,6 @@ static int gpmc_setup_irq(void) return gpmc_irq_start; } - gpmc_irq_chip.name = "gpmc"; - gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; - gpmc_irq_chip.irq_enable = gpmc_irq_enable; - gpmc_irq_chip.irq_disable = gpmc_irq_disable; - gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; - gpmc_irq_chip.irq_ack = gpmc_irq_noop; - gpmc_irq_chip.irq_mask = gpmc_irq_noop; - gpmc_irq_chip.irq_unmask = gpmc_irq_noop; - gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE; gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT; diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index f8bb3b9..831e7b8 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -339,7 +339,7 @@ static int __cpuinit 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 e6d2307..d057195 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -499,7 +499,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 }; @@ -527,7 +527,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 044c31d..2ee0861 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 7341eff..fd75e34 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -194,10 +194,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/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c index d15c7bb..b2d1f0c 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-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index 0cdba8d..297993e 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -181,7 +181,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-ux500/setup.h b/arch/arm/mach-ux500/setup.h index cad3ca8..1d79e0f 100644 --- a/arch/arm/mach-ux500/setup.h +++ b/arch/arm/mach-ux500/setup.h @@ -37,13 +37,6 @@ extern void ux500_timer_init(void); .type = MT_DEVICE, \ } -#define __MEM_DEV_DESC(x, sz) { \ - .virtual = IO_ADDRESS(x), \ - .pfn = __phys_to_pfn(x), \ - .length = sz, \ - .type = MT_MEMORY, \ -} - extern struct smp_operations ux500_smp_ops; extern void ux500_cpu_die(unsigned int cpu); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 08c9fe9..191320c 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -436,7 +436,7 @@ config CPU_32v5 config CPU_32v6 bool - select CPU_USE_DOMAINS if CPU_V6 && MMU + select CPU_USE_DOMAINS if CPU_V6 && MMU && !PAX_KERNEXEC && !PAX_MEMORY_UDEREF select TLS_REG_EMUL if !CPU_32v6K && !MMU config CPU_32v6K @@ -585,6 +585,7 @@ config CPU_CP15_MPU config CPU_USE_DOMAINS bool + depends on !ARM_LPAE && !PAX_KERNEXEC help This option enables or disables the use of domain switching via the set_fs() function. @@ -780,6 +781,7 @@ config NEED_KUSER_HELPERS config KUSER_HELPERS bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS default y + depends on !(CPU_V6 || CPU_V6K || CPU_V7) help Warning: disabling this option may break user programs. @@ -792,7 +794,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 6f4585b..7b6f52b 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -211,10 +211,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) @@ -228,6 +230,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); \ @@ -236,6 +239,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) @@ -249,6 +253,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" ) \ @@ -268,6 +273,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) @@ -281,6 +287,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" ) \ @@ -310,6 +317,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/context.c b/arch/arm/mm/context.c index eeab06e..2638dc2 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -42,7 +42,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); @@ -188,7 +188,7 @@ static int is_reserved_asid(u64 asid) static u64 new_context(struct mm_struct *mm, unsigned int cpu) { u64 asid = atomic64_read(&mm->context.id); - u64 generation = atomic64_read(&asid_generation); + u64 generation = atomic64_read_unchecked(&asid_generation); if (asid != 0 && is_reserved_asid(asid)) { /* @@ -206,7 +206,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) */ asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); 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); @@ -235,14 +235,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 5dbf13f..a2d1876 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,20 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, if (fixup_exception(regs)) return; +#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_ERR "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_ERR "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. */ @@ -174,6 +189,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; @@ -398,6 +420,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 * @@ -543,9 +592,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_ERR "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_ERR "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: printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); @@ -569,15 +631,68 @@ 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 == 0xffff0fe0UL) { + /* + * PaX: __kuser_get_tls emulation + */ + regs->ARM_r0 = current_thread_info()->tp_value; + 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_ERR "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_ERR "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) { + unsigned int bkpt; + + if (!probe_kernel_address((unsigned int *)pc, bkpt) && cpu_to_le32(bkpt) == 0xe12f1073) { + 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: printk(KERN_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 0ecc43f..190b956 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -726,7 +728,46 @@ void free_initmem(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, 0, "TCM link"); #endif diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 04d9006..c547d85 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -392,9 +392,9 @@ __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached) unsigned int mtype; if (cached) - mtype = MT_MEMORY; + mtype = MT_MEMORY_RX; else - mtype = MT_MEMORY_NONCACHED; + mtype = MT_MEMORY_NONCACHED_RX; 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 10062ce..8695745 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); /* @@ -173,6 +183,10 @@ 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 + /* 8 bits of randomness in 20 address space bits */ if ((current->flags & PF_RANDOMIZE) && !(current->personality & ADDR_NO_RANDOMIZE)) @@ -180,10 +194,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm) 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; mm->unmap_area = arch_unmap_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; mm->unmap_area = arch_unmap_area_topdown; } diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index daf336f..4e6392c 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -36,6 +36,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. @@ -228,10 +244,18 @@ __setup("noalign", noalign_setup); #endif /* ifdef CONFIG_CPU_CP15 / else */ -#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN +#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY #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, @@ -260,16 +284,16 @@ static struct mem_type mem_types[] = { [MT_UNCACHED] = { .prot_pte = PROT_PTE_DEVICE, .prot_l1 = PMD_TYPE_TABLE, - .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, + .prot_sect = PROT_SECT_DEVICE, .domain = DOMAIN_IO, }, [MT_CACHECLEAN] = { - .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_RDONLY, .domain = DOMAIN_KERNEL, }, #ifndef CONFIG_ARM_LPAE [MT_MINICLEAN] = { - .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_MINICACHE | PMD_SECT_RDONLY, .domain = DOMAIN_KERNEL, }, #endif @@ -277,36 +301,54 @@ static struct mem_type mem_types[] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_RDONLY, .prot_l1 = PMD_TYPE_TABLE, - .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] = { + [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, .domain = DOMAIN_KERNEL, }, + [MT_MEMORY_RW] = { + .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, + .domain = DOMAIN_KERNEL, + }, + [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] = { - .prot_sect = PMD_TYPE_SECT, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_RDONLY, .domain = DOMAIN_KERNEL, }, - [MT_MEMORY_NONCACHED] = { + [MT_MEMORY_NONCACHED_RW] = { .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_NONCACHED_RX] = { + .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_DTCM] = { - .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_XN, + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, .prot_l1 = PMD_TYPE_TABLE, - .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_RDONLY, .domain = DOMAIN_KERNEL, }, [MT_MEMORY_ITCM] = { @@ -316,10 +358,10 @@ static struct mem_type mem_types[] = { }, [MT_MEMORY_SO] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | - L_PTE_MT_UNCACHED | L_PTE_XN, + L_PTE_MT_UNCACHED, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S | - PMD_SECT_UNCACHED | PMD_SECT_XN, + PMD_SECT_UNCACHED, .domain = DOMAIN_KERNEL, }, [MT_MEMORY_DMA_READY] = { @@ -405,9 +447,35 @@ static void __init build_mem_type_table(void) * to prevent speculative instruction fetches. */ mem_types[MT_DEVICE].prot_sect |= PMD_SECT_XN; + mem_types[MT_DEVICE].prot_pte |= L_PTE_XN; mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN; + mem_types[MT_DEVICE_NONSHARED].prot_pte |= L_PTE_XN; mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN; + mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_XN; mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN; + mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_XN; + + /* Mark other regions on ARMv6+ as execute-never */ + +#ifdef CONFIG_PAX_KERNEXEC + mem_types[MT_UNCACHED].prot_sect |= PMD_SECT_XN; + mem_types[MT_UNCACHED].prot_pte |= L_PTE_XN; + mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_XN; + mem_types[MT_CACHECLEAN].prot_pte |= L_PTE_XN; +#ifndef CONFIG_ARM_LPAE + mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_XN; + mem_types[MT_MINICLEAN].prot_pte |= L_PTE_XN; +#endif + mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_XN; + mem_types[MT_MEMORY_RW].prot_pte |= L_PTE_XN; + mem_types[MT_MEMORY_NONCACHED_RW].prot_sect |= PMD_SECT_XN; + mem_types[MT_MEMORY_NONCACHED_RW].prot_pte |= PMD_SECT_XN; + mem_types[MT_MEMORY_DTCM].prot_sect |= PMD_SECT_XN; + mem_types[MT_MEMORY_DTCM].prot_pte |= L_PTE_XN; +#endif + + mem_types[MT_MEMORY_SO].prot_sect |= PMD_SECT_XN; + mem_types[MT_MEMORY_SO].prot_pte |= L_PTE_XN; } if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { /* @@ -468,6 +536,9 @@ static void __init build_mem_type_table(void) * from SVC mode and no access from userspace. */ mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; +#ifdef CONFIG_PAX_KERNEXEC + mem_types[MT_MEMORY_RX].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; +#endif mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; #endif @@ -485,11 +556,17 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY].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_NONCACHED].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_NONCACHED_RW].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED_RW].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_NONCACHED_RX].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_NONCACHED_RX].prot_pte |= L_PTE_SHARED; } } @@ -500,15 +577,20 @@ static void __init build_mem_type_table(void) if (cpu_arch >= CPU_ARCH_ARMv6) { if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { /* Non-cacheable Normal is XCB = 001 */ - mem_types[MT_MEMORY_NONCACHED].prot_sect |= + mem_types[MT_MEMORY_NONCACHED_RW].prot_sect |= + PMD_SECT_BUFFERED; + mem_types[MT_MEMORY_NONCACHED_RX].prot_sect |= PMD_SECT_BUFFERED; } else { /* For both ARMv6 and non-TEX-remapping ARMv7 */ - mem_types[MT_MEMORY_NONCACHED].prot_sect |= + mem_types[MT_MEMORY_NONCACHED_RW].prot_sect |= + PMD_SECT_TEX(1); + mem_types[MT_MEMORY_NONCACHED_RX].prot_sect |= PMD_SECT_TEX(1); } } else { - mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; + mem_types[MT_MEMORY_NONCACHED_RW].prot_sect |= PMD_SECT_BUFFERABLE; + mem_types[MT_MEMORY_NONCACHED_RX].prot_sect |= PMD_SECT_BUFFERABLE; } #ifdef CONFIG_ARM_LPAE @@ -524,6 +606,8 @@ static void __init build_mem_type_table(void) vecs_pgprot |= PTE_EXT_AF; #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); @@ -541,10 +625,15 @@ static void __init build_mem_type_table(void) mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; - mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; - mem_types[MT_MEMORY].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_NONCACHED].prot_sect |= ecc_mask; + mem_types[MT_MEMORY_NONCACHED_RW].prot_sect |= ecc_mask; + mem_types[MT_MEMORY_NONCACHED_RX].prot_sect |= ecc_mask; mem_types[MT_ROM].prot_sect |= cp->pmd; switch (cp->pmd) { @@ -1166,18 +1255,15 @@ void __init arm_mm_memblock_reserve(void) * called function. This means you can't use any function or debugging * method which may touch any device, otherwise the kernel _will_ crash. */ + +static char vectors[PAGE_SIZE * 2] __read_only __aligned(PAGE_SIZE); + static void __init devicemaps_init(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)); @@ -1217,7 +1303,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) * location (0xffff0000). If we aren't using high-vectors, also * create a mapping at the low-vectors virtual address. */ - 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 @@ -1287,8 +1373,39 @@ static void __init map_lowmem(void) map.pfn = __phys_to_pfn(start); map.virtual = __phys_to_virt(start); map.length = end - start; - map.type = MT_MEMORY; +#ifdef CONFIG_PAX_KERNEXEC + 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); + } +#endif + + map.type = MT_MEMORY_RW; create_mapping(&map); } } 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/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h index ce6d763..cfea917 100644 --- a/arch/arm/plat-samsung/include/plat/dma-ops.h +++ b/arch/arm/plat-samsung/include/plat/dma-ops.h @@ -47,7 +47,7 @@ struct samsung_dma_ops { int (*started)(unsigned ch); int (*flush)(unsigned ch); int (*stop)(unsigned ch); -}; +} __no_const; extern void *samsung_dmadev_get_ops(void); extern void *s3c_dma_get_ops(void); diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index f4726dc..39ed646 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -149,7 +149,7 @@ static int __cpuinit os_lock_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata os_lock_nb = { +static struct notifier_block os_lock_nb = { .notifier_call = os_lock_notify, }; diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 5ab825c..96aaec8 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -831,7 +831,7 @@ static int __cpuinit hw_breakpoint_reset_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hw_breakpoint_reset_nb = { +static struct notifier_block hw_breakpoint_reset_nb = { .notifier_call = hw_breakpoint_reset_notify, }; 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 d232888..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 (2 * TASK_SIZE / 3) +#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 b2f2d2d..d1c85cb 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. @@ -174,6 +191,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/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 b86329d..6709906 100644 --- a/arch/frv/include/asm/atomic.h +++ b/arch/frv/include/asm/atomic.h @@ -186,6 +186,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..c2a401d 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 f4ca594..adc72fd6 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 __cacheline_aligned __aligned(L1_CACHE_BYTES) #define ____cacheline_aligned __aligned(L1_CACHE_BYTES) diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 6e6fe18..a6ae668 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -208,6 +208,16 @@ 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)) + /* Atomic operations are already serializing */ #define smp_mb__before_atomic_dec() barrier() #define smp_mb__after_atomic_dec() barrier() 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 96a8d92..617a1cf 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 815810c..d60bd4c 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 @@ -142,6 +142,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 54ff557..70c88b7 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 449c8c0..18965fb 100644 --- a/arch/ia64/include/asm/uaccess.h +++ b/arch/ia64/include/asm/uaccess.h @@ -240,12 +240,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); } @@ -255,10 +267,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; \ }) @@ -266,11 +281,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/err_inject.c b/arch/ia64/kernel/err_inject.c index 2d67317..07d8bfa 100644 --- a/arch/ia64/kernel/err_inject.c +++ b/arch/ia64/kernel/err_inject.c @@ -256,7 +256,7 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata err_inject_cpu_notifier = +static struct notifier_block err_inject_cpu_notifier = { .notifier_call = err_inject_cpu_callback, }; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index d7396db..b33e873 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1922,7 +1922,7 @@ static int __cpuinit mca_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block mca_cpu_notifier __cpuinitdata = { +static struct notifier_block mca_cpu_notifier = { .notifier_call = mca_cpu_callback }; diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 24603be..948052d 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -307,8 +307,7 @@ plt_target (struct plt_entry *plt) void module_free (struct module *mod, void *module_region) { - if (mod && mod->arch.init_unw_table && - module_region == mod->module_init) { + if (mod && mod->arch.init_unw_table && module_region == mod->module_init_rx) { unw_remove_unwind_table(mod->arch.init_unw_table); mod->arch.init_unw_table = NULL; } @@ -494,15 +493,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 @@ -685,7 +708,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: @@ -820,15 +850,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 2b3c2d7..a318d84 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -980,7 +980,7 @@ static int __cpuinit 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/salinfo.c b/arch/ia64/kernel/salinfo.c index 4bc580a..7767f24 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -609,7 +609,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu return NOTIFY_OK; } -static struct notifier_block salinfo_cpu_notifier __cpuinitdata = +static struct notifier_block salinfo_cpu_notifier = { .notifier_call = salinfo_cpu_callback, .priority = 0, diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 41e33f8..65180b2 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/topology.c b/arch/ia64/kernel/topology.c index dc00b2c..cce53c2 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -445,7 +445,7 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cache_cpu_notifier = +static struct notifier_block cache_cpu_notifier = { .notifier_call = cache_cpu_callback }; diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 0ccb28f..8992469 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -198,7 +198,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 6cf0341..d352594 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 @@ -149,8 +166,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 76069c1..c2aa816 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -149,6 +149,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; @@ -172,6 +173,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 d1fe4b4..2628f37 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -120,6 +120,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)) { diff --git a/arch/m32r/include/asm/cache.h b/arch/m32r/include/asm/cache.h index 40b3ee9..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/mm/hugetlbpage.c b/arch/metag/mm/hugetlbpage.c index 3c52fa6..11b2ad8 100644 --- a/arch/metag/mm/hugetlbpage.c +++ b/arch/metag/mm/hugetlbpage.c @@ -200,6 +200,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/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 08b6079..8b554d2 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -21,15 +21,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) (*(volatile int *)&(v)->counter) +static inline int atomic_read(const atomic_t *v) +{ + return (*(volatile const int *) &v->counter); +} + +static inline int atomic_read_unchecked(const atomic_unchecked_t *v) +{ + return (*(volatile const int *) &v->counter); +} /* * atomic_set - set atomic variable @@ -38,7 +62,15 @@ * * 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; +} + +static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i) +{ + v->counter = i; +} /* * atomic_add - add integer to atomic variable @@ -47,7 +79,67 @@ * * Atomically adds @i to @v. */ -static __inline__ void atomic_add(int i, atomic_t * v) +static __inline__ void atomic_add(int i, atomic_t *v) +{ + int temp; + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic_add \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: add %0, %2 \n" +#else + " addu %0, %2 \n" +#endif + " sc %0, %1 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic_add \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: add %0, %2 \n" +#else + " addu %0, %2 \n" +#endif + " sc %0, %1 \n" + " beqz %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: add %0, %1 \n" + "2: \n" + _ASM_EXTABLE(1b, 2b) +#else + " addu %0, %1 \n" +#endif + : "+r" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } +} + +static __inline__ void atomic_add_unchecked(int i, atomic_unchecked_t *v) { if (kernel_uses_llsc && R10000_LLSC_WAR) { int temp; @@ -90,7 +182,67 @@ static __inline__ void atomic_add(int i, atomic_t * v) * * Atomically subtracts @i from @v. */ -static __inline__ void atomic_sub(int i, atomic_t * v) +static __inline__ void atomic_sub(int i, atomic_t *v) +{ + int temp; + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic64_sub \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: sub %0, %2 \n" +#else + " subu %0, %2 \n" +#endif + " sc %0, %1 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %0, %1 # atomic64_sub \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: sub %0, %2 \n" +#else + " subu %0, %2 \n" +#endif + " sc %0, %1 \n" + " beqz %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: sub %0, %1 \n" + "2: \n" + _ASM_EXTABLE(1b, 2b) +#else + " subu %0, %1 \n" +#endif + : "+r" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } +} + +static __inline__ void atomic_sub_unchecked(long i, atomic_unchecked_t *v) { if (kernel_uses_llsc && R10000_LLSC_WAR) { int temp; @@ -129,7 +281,93 @@ static __inline__ void atomic_sub(int i, atomic_t * v) /* * Same as above, but return the result value */ -static __inline__ int atomic_add_return(int i, atomic_t * v) +static __inline__ int atomic_add_return(int i, atomic_t *v) +{ + int result; + int temp; + + smp_mb__before_llsc(); + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_add_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: add %0, %1, %3 \n" +#else + " addu %0, %1, %3 \n" +#endif + " sc %0, %2 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " b 4f \n" + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: addu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_add_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: add %0, %1, %3 \n" +#else + " addu %0, %1, %3 \n" +#endif + " sc %0, %2 \n" + " bnez %0, 4f \n" + " b 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: addu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( + " lw %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: add %0, %2 \n" +#else + " addu %0, %2 \n" +#endif + " sw %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Note: Dest reg is not modified on overflow */ + "2: \n" + _ASM_EXTABLE(1b, 2b) +#endif + : "=&r" (result), "+m" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +static __inline__ int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) { int result; @@ -178,7 +416,93 @@ static __inline__ int atomic_add_return(int i, atomic_t * v) return result; } -static __inline__ int atomic_sub_return(int i, atomic_t * v) +static __inline__ int atomic_sub_return(int i, atomic_t *v) +{ + int result; + int temp; + + smp_mb__before_llsc(); + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_sub_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: sub %0, %1, %3 \n" +#else + " subu %0, %1, %3 \n" +#endif + " sc %0, %2 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " b 4f \n" + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: subu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: ll %1, %2 # atomic_sub_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: sub %0, %1, %3 \n" +#else + " subu %0, %1, %3 \n" +#endif + " sc %0, %2 \n" + " bnez %0, 4f \n" + " b 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: subu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( + " lw %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: sub %0, %2 \n" +#else + " subu %0, %2 \n" +#endif + " sw %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Note: Dest reg is not modified on overflow */ + "2: \n" + _ASM_EXTABLE(1b, 2b) +#endif + : "=&r" (result), "+m" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} +static __inline__ int atomic_sub_return_unchecked(int i, atomic_unchecked_t *v) { int result; @@ -238,7 +562,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) * 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; @@ -295,8 +619,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 @@ -324,6 +666,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 @@ -345,6 +691,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 @@ -369,6 +719,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 @@ -377,6 +731,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 @@ -398,14 +756,30 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) * @v: pointer of type atomic64_t * */ -#define atomic64_read(v) (*(volatile long *)&(v)->counter) +static inline long atomic64_read(const atomic64_t *v) +{ + return (*(volatile const long *) &v->counter); +} + +static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v) +{ + return (*(volatile const long *) &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; +} + +static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i) +{ + v->counter = i; +} /* * atomic64_add - add integer to atomic variable @@ -414,7 +788,66 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) * * Atomically adds @i to @v. */ -static __inline__ void atomic64_add(long i, atomic64_t * v) +static __inline__ void atomic64_add(long i, atomic64_t *v) +{ + long temp; + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_add \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: dadd %0, %2 \n" +#else + " daddu %0, %2 \n" +#endif + " scd %0, %1 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_add \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: dadd %0, %2 \n" +#else + " daddu %0, %2 \n" +#endif + " scd %0, %1 \n" + " beqz %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: dadd %0, %1 \n" + "2: \n" + _ASM_EXTABLE(1b, 2b) +#else + " daddu %0, %1 \n" +#endif + : "+r" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } +} +static __inline__ void atomic64_add_unchecked(long i, atomic64_unchecked_t *v) { if (kernel_uses_llsc && R10000_LLSC_WAR) { long temp; @@ -457,7 +890,67 @@ static __inline__ void atomic64_add(long i, atomic64_t * v) * * Atomically subtracts @i from @v. */ -static __inline__ void atomic64_sub(long i, atomic64_t * v) +static __inline__ void atomic64_sub(long i, atomic64_t *v) +{ + long temp; + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_sub \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: dsub %0, %2 \n" +#else + " dsubu %0, %2 \n" +#endif + " scd %0, %1 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %0, %1 # atomic64_sub \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "2: dsub %0, %2 \n" +#else + " dsubu %0, %2 \n" +#endif + " scd %0, %1 \n" + " beqz %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + "3: \n" + _ASM_EXTABLE(2b, 3b) +#endif + " .set mips0 \n" + : "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: dsub %0, %1 \n" + "2: \n" + _ASM_EXTABLE(1b, 2b) +#else + " dsubu %0, %1 \n" +#endif + : "+r" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } +} + +static __inline__ void atomic64_sub_unchecked(long i, atomic64_unchecked_t *v) { if (kernel_uses_llsc && R10000_LLSC_WAR) { long temp; @@ -496,7 +989,93 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v) /* * Same as above, but return the result value */ -static __inline__ long atomic64_add_return(long i, atomic64_t * v) +static __inline__ long atomic64_add_return(long i, atomic64_t *v) +{ + long result; + long temp; + + smp_mb__before_llsc(); + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_add_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: dadd %0, %1, %3 \n" +#else + " daddu %0, %1, %3 \n" +#endif + " scd %0, %2 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " b 4f \n" + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: daddu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "+m" (v->counter) + : "Ir" (i)); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_add_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: dadd %0, %1, %3 \n" +#else + " daddu %0, %1, %3 \n" +#endif + " scd %0, %2 \n" + " bnez %0, 4f \n" + " b 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: daddu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( + " ld %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: dadd %0, %2 \n" +#else + " daddu %0, %2 \n" +#endif + " sd %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Note: Dest reg is not modified on overflow */ + "2: \n" + _ASM_EXTABLE(1b, 2b) +#endif + : "=&r" (result), "+m" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} +static __inline__ long atomic64_add_return_unchecked(long i, atomic64_unchecked_t *v) { long result; @@ -546,7 +1125,97 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v) return result; } -static __inline__ long atomic64_sub_return(long i, atomic64_t * v) +static __inline__ long atomic64_sub_return(long i, atomic64_t *v) +{ + long result; + long temp; + + smp_mb__before_llsc(); + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_sub_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: dsub %0, %1, %3 \n" +#else + " dsubu %0, %1, %3 \n" +#endif + " scd %0, %2 \n" + " beqzl %0, 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " b 4f \n" + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: dsubu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else if (kernel_uses_llsc) { + __asm__ __volatile__( + " .set mips3 \n" + "1: lld %1, %2 # atomic64_sub_return \n" +#ifdef CONFIG_PAX_REFCOUNT + "2: dsub %0, %1, %3 \n" +#else + " dsubu %0, %1, %3 \n" +#endif + " scd %0, %2 \n" + " bnez %0, 4f \n" + " b 1b \n" +#ifdef CONFIG_PAX_REFCOUNT + " .set noreorder \n" + "3: b 5f \n" + " move %0, %1 \n" + " .set reorder \n" + _ASM_EXTABLE(2b, 3b) +#endif + "4: dsubu %0, %1, %3 \n" +#ifdef CONFIG_PAX_REFCOUNT + "5: \n" +#endif + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + } else { + unsigned long flags; + + raw_local_irq_save(flags); + __asm__ __volatile__( + " ld %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Exception on overflow. */ + "1: dsub %0, %2 \n" +#else + " dsubu %0, %2 \n" +#endif + " sd %0, %1 \n" +#ifdef CONFIG_PAX_REFCOUNT + /* Note: Dest reg is not modified on overflow */ + "2: \n" + _ASM_EXTABLE(1b, 2b) +#endif + : "=&r" (result), "+m" (v->counter) : "Ir" (i)); + raw_local_irq_restore(flags); + } + + smp_llsc_mb(); + + return result; +} + +static __inline__ long atomic64_sub_return_unchecked(long i, atomic64_unchecked_t *v) { long result; @@ -605,7 +1274,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) * 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; @@ -662,9 +1331,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 @@ -694,6 +1380,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 @@ -715,6 +1402,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 @@ -739,6 +1427,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 @@ -747,6 +1436,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/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 cf3ae24..238d22f 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h @@ -372,13 +372,16 @@ 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, int uses_interp); -struct mm_struct; -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - #endif /* _ASM_ELF_H */ 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/local.h b/arch/mips/include/asm/local.h index d44622c..64990d2 100644 --- a/arch/mips/include/asm/local.h +++ b/arch/mips/include/asm/local.h @@ -12,15 +12,25 @@ typedef struct atomic_long_t a; } local_t; +typedef struct { + atomic_long_unchecked_t a; +} local_unchecked_t; + #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } #define local_read(l) atomic_long_read(&(l)->a) +#define local_read_unchecked(l) atomic_long_read_unchecked(&(l)->a) #define local_set(l, i) atomic_long_set(&(l)->a, (i)) +#define local_set_unchecked(l, i) atomic_long_set_unchecked(&(l)->a, (i)) #define local_add(i, l) atomic_long_add((i), (&(l)->a)) +#define local_add_unchecked(i, l) atomic_long_add_unchecked((i), (&(l)->a)) #define local_sub(i, l) atomic_long_sub((i), (&(l)->a)) +#define local_sub_unchecked(i, l) atomic_long_sub_unchecked((i), (&(l)->a)) #define local_inc(l) atomic_long_inc(&(l)->a) +#define local_inc_unchecked(l) atomic_long_inc_unchecked(&(l)->a) #define local_dec(l) atomic_long_dec(&(l)->a) +#define local_dec_unchecked(l) atomic_long_dec_unchecked(&(l)->a) /* * Same as above, but return the result value @@ -70,6 +80,51 @@ static __inline__ long local_add_return(long i, local_t * l) return result; } +static __inline__ long local_add_return_unchecked(long i, local_unchecked_t * l) +{ + unsigned long result; + + if (kernel_uses_llsc && R10000_LLSC_WAR) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1:" __LL "%1, %2 # local_add_return \n" + " addu %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqzl %0, 1b \n" + " addu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) + : "Ir" (i), "m" (l->a.counter) + : "memory"); + } else if (kernel_uses_llsc) { + unsigned long temp; + + __asm__ __volatile__( + " .set mips3 \n" + "1:" __LL "%1, %2 # local_add_return \n" + " addu %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqz %0, 1b \n" + " addu %0, %1, %3 \n" + " .set mips0 \n" + : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) + : "Ir" (i), "m" (l->a.counter) + : "memory"); + } else { + unsigned long flags; + + local_irq_save(flags); + result = l->a.counter; + result += i; + l->a.counter = result; + local_irq_restore(flags); + } + + return result; +} + static __inline__ long local_sub_return(long i, local_t * l) { unsigned long result; @@ -117,6 +172,8 @@ static __inline__ long local_sub_return(long i, local_t * l) #define local_cmpxchg(l, o, n) \ ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) +#define local_cmpxchg_unchecked(l, o, n) \ + ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) #define local_xchg(l, n) (atomic_long_xchg((&(l)->a), (n))) /** diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index f59552f..3abe9b9 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -95,7 +95,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 881d18b..cea38bc 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/thread_info.h b/arch/mips/include/asm/thread_info.h index 895320e..bf63e10 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -115,6 +115,8 @@ static inline struct thread_info *current_thread_info(void) #define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */ #define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */ #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ +/* li takes a 32bit immediate */ +#define TIF_GRSEC_SETXID 29 /* update credentials on syscall entry/exit */ #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ #define _TIF_SYSCALL_TRACE (1< #include #include diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index 202e581..689ca79 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -56,6 +56,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 /* diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index d1fea7a..45602ea 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -77,17 +77,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) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index c6a041d..b3e7318 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -563,15 +563,3 @@ unsigned long get_wchan(struct task_struct *task) 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; -} diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 9c6299c..2fb4c22 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -528,6 +528,10 @@ static inline int audit_arch(void) return arch; } +#ifdef CONFIG_GRKERNSEC_SETXID +extern void gr_delayed_cred_worker(void); +#endif + /* * Notification of system call entry/exit * - triggered by current->work.syscall_trace @@ -537,6 +541,11 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs) /* do the secure computing check first */ secure_computing_strict(regs->regs[2]); +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + if (!(current->ptrace & PT_PTRACED)) goto out; diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 9b36424..e7f4154 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -52,7 +52,7 @@ NESTED(handle_sys, PT_SIZE, sp) stack_done: lw t0, TI_FLAGS($28) # syscall tracing enabled? - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_SYSCALL_WORK and t0, t1 bnez t0, syscall_trace_entry # -> yes diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 97a5909..59622f8 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -54,7 +54,7 @@ NESTED(handle_sys64, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_SYSCALL_WORK LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, syscall_trace_entry diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index edcb659..fb2ab09 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -47,7 +47,7 @@ NESTED(handle_sysn32, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_SYSCALL_WORK LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, n32_syscall_trace_entry diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 74f485d..47d2c38 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -81,7 +81,7 @@ NESTED(handle_sys, PT_SIZE, sp) PTR 4b, bad_stack .previous - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_SYSCALL_WORK LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, trace_a_syscall diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 1ff43d5..96fec68 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -21,8 +21,8 @@ #include static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0); +static atomic_unchecked_t __cpuinitdata count_count_start = ATOMIC_INIT(0); +static atomic_unchecked_t __cpuinitdata count_count_stop = ATOMIC_INIT(0); static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); #define COUNTON 100 @@ -69,13 +69,13 @@ void __cpuinit 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: @@ -86,11 +86,11 @@ void __cpuinit 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); @@ -131,8 +131,8 @@ void __cpuinit 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(); /* @@ -141,8 +141,8 @@ void __cpuinit 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 a75ae40..0d0f56a 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -675,7 +675,17 @@ asmlinkage void do_ov(struct pt_regs *regs) { siginfo_t info; - die_if_kernel("Integer overflow", regs); + if (unlikely(!user_mode(regs))) { + +#ifdef CONFIG_PAX_REFCOUNT + if (fixup_exception(regs)) { + pax_report_refcount_overflow(regs); + return; + } +#endif + + die("Integer overflow", regs); + } info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 0fead53..eeb00a6 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -27,6 +27,23 @@ #include /* For VMALLOC_END */ #include +#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 @@ -196,6 +213,14 @@ bad_area: bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (cpu_has_rixi && (mm->pax_flags & MF_PAX_PAGEEXEC) && !write && address == instruction_pointer(regs)) { + pax_report_fault(regs, (void *)address, (void *)user_stack_pointer(regs)); + do_group_exit(SIGKILL); + } +#endif + tsk->thread.cp0_badvaddr = address; tsk->thread.error_code = write; #if 0 diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index 7e5fe27..9656513 100644 --- a/arch/mips/mm/mmap.c +++ 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(vmm, 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; @@ -146,6 +152,10 @@ 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 = get_random_int(); random_factor = random_factor << PAGE_SHIFT; @@ -157,42 +167,27 @@ void arch_pick_mmap_layout(struct mm_struct *mm) 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; mm->unmap_area = arch_unmap_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; mm->unmap_area = arch_unmap_area_topdown; } } -static inline unsigned long brk_rnd(void) -{ - unsigned long rnd = get_random_int(); - - rnd = rnd << PAGE_SHIFT; - /* 8MB for 32bit, 256MB for 64bit */ - if (TASK_IS_32BIT_ADDR) - rnd = rnd & 0x7ffffful; - else - rnd = rnd & 0xffffffful; - - return rnd; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long base = mm->brk; - unsigned long ret; - - ret = PAGE_ALIGN(base + brk_rnd()); - - if (ret < mm->brk) - return mm->brk; - - return ret; -} - int __virt_addr_valid(const volatile void *kaddr) { return pfn_valid(PFN_DOWN(virt_to_phys(kaddr))); diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c index a2358b4..7cead4f 100644 --- a/arch/mips/sgi-ip27/ip27-nmi.c +++ b/arch/mips/sgi-ip27/ip27-nmi.c @@ -187,9 +187,9 @@ void cont_nmi_dump(void) { #ifndef REAL_NMI_SIGNAL - static atomic_t nmied_cpus = ATOMIC_INIT(0); + static atomic_unchecked_t nmied_cpus = ATOMIC_INIT(0); - atomic_inc(&nmied_cpus); + atomic_inc_unchecked(&nmied_cpus); #endif /* * Only allow 1 cpu to proceed @@ -233,7 +233,7 @@ cont_nmi_dump(void) udelay(10000); } #else - while (atomic_read(&nmied_cpus) != num_online_cpus()); + while (atomic_read_unchecked(&nmied_cpus) != num_online_cpus()); #endif /* diff --git a/arch/mn10300/proc-mn103e010/include/proc/cache.h b/arch/mn10300/proc-mn103e010/include/proc/cache.h index 967d144..db12197 100644 --- a/arch/mn10300/proc-mn103e010/include/proc/cache.h +++ b/arch/mn10300/proc-mn103e010/include/proc/cache.h @@ -11,12 +11,14 @@ #ifndef _ASM_PROC_CACHE_H #define _ASM_PROC_CACHE_H +#include + /* L1 cache */ #define L1_CACHE_NWAYS 4 /* number of ways in caches */ #define L1_CACHE_NENTRIES 256 /* number of entries in each way */ -#define L1_CACHE_BYTES 16 /* bytes per entry */ #define L1_CACHE_SHIFT 4 /* shift for bytes per entry */ +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) /* bytes per entry */ #define L1_CACHE_WAYDISP 0x1000 /* displacement of one way from the next */ #define L1_CACHE_TAG_VALID 0x00000001 /* cache tag valid bit */ diff --git a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h index bcb5df2..84fabd2 100644 --- a/arch/mn10300/proc-mn2ws0050/include/proc/cache.h +++ b/arch/mn10300/proc-mn2ws0050/include/proc/cache.h @@ -16,13 +16,15 @@ #ifndef _ASM_PROC_CACHE_H #define _ASM_PROC_CACHE_H +#include + /* * L1 cache */ #define L1_CACHE_NWAYS 4 /* number of ways in caches */ #define L1_CACHE_NENTRIES 128 /* number of entries in each way */ -#define L1_CACHE_BYTES 32 /* bytes per entry */ #define L1_CACHE_SHIFT 5 /* shift for bytes per entry */ +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) /* bytes per entry */ #define L1_CACHE_WAYDISP 0x1000 /* distance from one way to the next */ #define L1_CACHE_TAG_VALID 0x00000001 /* cache tag valid bit */ diff --git a/arch/openrisc/include/asm/cache.h b/arch/openrisc/include/asm/cache.h index 4ce7a01..449202a 100644 --- a/arch/openrisc/include/asm/cache.h +++ b/arch/openrisc/include/asm/cache.h @@ -19,11 +19,13 @@ #ifndef __ASM_OPENRISC_CACHE_H #define __ASM_OPENRISC_CACHE_H +#include + /* FIXME: How can we replace these with values from the CPU... * they shouldn't be hard-coded! */ -#define L1_CACHE_BYTES 16 #define L1_CACHE_SHIFT 4 +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) #endif /* __ASM_OPENRISC_CACHE_H */ diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 472886c..00e7df9 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -252,6 +252,16 @@ static inline long atomic64_dec_if_positive(atomic64_t *v) return dec; } +#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 /* !CONFIG_64BIT */ diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 47f11c7..3420df2 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -5,6 +5,7 @@ #ifndef __ARCH_PARISC_CACHE_H #define __ARCH_PARISC_CACHE_H +#include /* * PA 2.0 processors have 64-byte cachelines; PA 1.1 processors have @@ -15,13 +16,13 @@ * just ruin performance. */ #ifdef CONFIG_PA20 -#define L1_CACHE_BYTES 64 #define L1_CACHE_SHIFT 6 #else -#define L1_CACHE_BYTES 32 #define L1_CACHE_SHIFT 5 #endif +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) + #ifndef __ASSEMBLY__ #define SMP_CACHE_BYTES L1_CACHE_BYTES diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h index ad2b503..bdf1651 100644 --- a/arch/parisc/include/asm/elf.h +++ b/arch/parisc/include/asm/elf.h @@ -342,6 +342,13 @@ struct pt_regs; /* forward declaration... */ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE 0x10000UL + +#define PAX_DELTA_MMAP_LEN 16 +#define PAX_DELTA_STACK_LEN 16 +#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, but it's not easy, and we've already done it here. */ diff --git a/arch/parisc/include/asm/pgalloc.h b/arch/parisc/include/asm/pgalloc.h index fc987a1..6e068ef 100644 --- a/arch/parisc/include/asm/pgalloc.h +++ b/arch/parisc/include/asm/pgalloc.h @@ -61,6 +61,11 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) (__u32)(__pa((unsigned long)pmd) >> PxD_VALUE_SHIFT)); } +static inline void pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd) +{ + pgd_populate(mm, pgd, pmd); +} + static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) { pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, @@ -93,6 +98,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) #define pmd_free(mm, x) do { } while (0) #define pgd_populate(mm, pmd, pte) BUG() +#define pgd_populate_kernel(mm, pmd, pte) BUG() #endif diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 1e40d7f..a3eb445 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -223,6 +223,17 @@ extern void purge_tlb_entries(struct mm_struct *, unsigned long); #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED) #define PAGE_COPY PAGE_EXECREAD #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) + +#ifdef CONFIG_PAX_PAGEEXEC +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED) +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) +#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_KERNEL) #define PAGE_KERNEL_EXEC __pgprot(_PAGE_KERNEL_EXEC) #define PAGE_KERNEL_RWX __pgprot(_PAGE_KERNEL_RWX) diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index e0a8235..ce2f1e1 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -245,10 +245,10 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { - int sz = __compiletime_object_size(to); + size_t sz = __compiletime_object_size(to); int ret = -EFAULT; - if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n)) + if (likely(sz == (size_t)-1 || !__builtin_constant_p(n) || sz >= n)) ret = __copy_from_user(to, from, n); else copy_from_user_overflow(); diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 2a625fb..9908930 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -98,16 +98,38 @@ /* three functions to determine where in the module core * or init pieces the location is */ +static inline int in_init_rx(struct module *me, void *loc) +{ + return (loc >= me->module_init_rx && + loc < (me->module_init_rx + me->init_size_rx)); +} + +static inline int in_init_rw(struct module *me, void *loc) +{ + return (loc >= me->module_init_rw && + loc < (me->module_init_rw + me->init_size_rw)); +} + static inline int in_init(struct module *me, void *loc) { - return (loc >= me->module_init && - loc <= (me->module_init + me->init_size)); + return in_init_rx(me, loc) || in_init_rw(me, loc); +} + +static inline int in_core_rx(struct module *me, void *loc) +{ + return (loc >= me->module_core_rx && + loc < (me->module_core_rx + me->core_size_rx)); +} + +static inline int in_core_rw(struct module *me, void *loc) +{ + return (loc >= me->module_core_rw && + loc < (me->module_core_rw + me->core_size_rw)); } static inline int in_core(struct module *me, void *loc) { - return (loc >= me->module_core && - loc <= (me->module_core + me->core_size)); + return in_core_rx(me, loc) || in_core_rw(me, loc); } static inline int in_local(struct module *me, void *loc) @@ -371,13 +393,13 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, } /* align things a bit */ - me->core_size = ALIGN(me->core_size, 16); - me->arch.got_offset = me->core_size; - me->core_size += gots * sizeof(struct got_entry); + me->core_size_rw = ALIGN(me->core_size_rw, 16); + me->arch.got_offset = me->core_size_rw; + me->core_size_rw += gots * sizeof(struct got_entry); - me->core_size = ALIGN(me->core_size, 16); - me->arch.fdesc_offset = me->core_size; - me->core_size += fdescs * sizeof(Elf_Fdesc); + me->core_size_rw = ALIGN(me->core_size_rw, 16); + me->arch.fdesc_offset = me->core_size_rw; + me->core_size_rw += fdescs * sizeof(Elf_Fdesc); me->arch.got_max = gots; me->arch.fdesc_max = fdescs; @@ -395,7 +417,7 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend) BUG_ON(value == 0); - got = me->module_core + me->arch.got_offset; + got = me->module_core_rw + me->arch.got_offset; for (i = 0; got[i].addr; i++) if (got[i].addr == value) goto out; @@ -413,7 +435,7 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend) #ifdef CONFIG_64BIT static Elf_Addr get_fdesc(struct module *me, unsigned long value) { - Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset; + Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset; if (!value) { printk(KERN_ERR "%s: zero OPD requested!\n", me->name); @@ -431,7 +453,7 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value) /* Create new one */ fdesc->addr = value; - fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; + fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; return (Elf_Addr)fdesc; } #endif /* CONFIG_64BIT */ @@ -843,7 +865,7 @@ register_unwind_table(struct module *me, table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; end = table + sechdrs[me->arch.unwind_section].sh_size; - gp = (Elf_Addr)me->module_core + me->arch.got_offset; + gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", me->arch.unwind_section, table, end, gp); diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 5dfd248..64914ac 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -33,9 +33,11 @@ #include #include -static unsigned long get_unshared_area(unsigned long addr, unsigned long len) +static unsigned long get_unshared_area(struct file *filp, unsigned long addr, unsigned long len, + 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; @@ -43,6 +45,7 @@ static unsigned long get_unshared_area(unsigned long addr, unsigned long len) info.high_limit = TASK_SIZE; info.align_mask = 0; info.align_offset = 0; + info.threadstack_offset = offset; return vm_unmapped_area(&info); } @@ -61,10 +64,11 @@ static int get_offset(struct address_space *mapping) return (unsigned long) mapping >> 8; } -static unsigned long get_shared_area(struct address_space *mapping, - unsigned long addr, unsigned long len, unsigned long pgoff) +static unsigned long get_shared_area(struct file *filp, struct address_space *mapping, + unsigned long addr, unsigned long len, unsigned long pgoff, 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; @@ -72,6 +76,7 @@ static unsigned long get_shared_area(struct address_space *mapping, info.high_limit = TASK_SIZE; info.align_mask = PAGE_MASK & (SHMLBA - 1); info.align_offset = (get_offset(mapping) + pgoff) << PAGE_SHIFT; + info.threadstack_offset = offset; return vm_unmapped_area(&info); } @@ -86,15 +91,22 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, return -EINVAL; return addr; } - if (!addr) + if (!addr) { addr = TASK_UNMAPPED_BASE; +#ifdef CONFIG_PAX_RANDMMAP + if (current->mm->pax_flags & MF_PAX_RANDMMAP) + addr += current->mm->delta_mmap; +#endif + + } + if (filp) { - addr = get_shared_area(filp->f_mapping, addr, len, pgoff); + addr = get_shared_area(filp, filp->f_mapping, addr, len, pgoff, flags); } else if(flags & MAP_SHARED) { - addr = get_shared_area(NULL, addr, len, pgoff); + addr = get_shared_area(filp, NULL, addr, len, pgoff, flags); } else { - addr = get_unshared_area(addr, len); + addr = get_unshared_area(filp, addr, len, flags); } return addr; } diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 04e47c6..7a8faf6 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -727,9 +727,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm,regs->iaoq[0]); - if (vma && (regs->iaoq[0] >= vma->vm_start) - && (vma->vm_flags & VM_EXEC)) { - + if (vma && (regs->iaoq[0] >= vma->vm_start)) { fault_address = regs->iaoq[0]; fault_space = regs->iasq[0]; diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index f247a34..dc0f219 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ DEFINE_PER_CPU(struct exception_data, exception_data); static unsigned long parisc_acctyp(unsigned long code, unsigned int inst) { - if (code == 6 || code == 16) + if (code == 6 || code == 7 || code == 16) return VM_EXEC; switch (inst & 0xf0000000) { @@ -138,6 +139,116 @@ parisc_acctyp(unsigned long code, unsigned int inst) } #endif +#ifdef CONFIG_PAX_PAGEEXEC +/* + * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address) + * + * returns 1 when task should be killed + * 2 when rt_sigreturn 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: unpatched PLT emulation */ + unsigned int bl, depwi; + + err = get_user(bl, (unsigned int *)instruction_pointer(regs)); + err |= get_user(depwi, (unsigned int *)(instruction_pointer(regs)+4)); + + if (err) + break; + + if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) { + unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12; + + err = get_user(ldw, (unsigned int *)addr); + err |= get_user(bv, (unsigned int *)(addr+4)); + err |= get_user(ldw2, (unsigned int *)(addr+8)); + + if (err) + break; + + if (ldw == 0x0E801096U && + bv == 0xEAC0C000U && + ldw2 == 0x0E881095U) + { + unsigned int resolver, map; + + err = get_user(resolver, (unsigned int *)(instruction_pointer(regs)+8)); + err |= get_user(map, (unsigned int *)(instruction_pointer(regs)+12)); + if (err) + break; + + regs->gr[20] = instruction_pointer(regs)+8; + regs->gr[21] = map; + regs->gr[22] = resolver; + regs->iaoq[0] = resolver | 3UL; + regs->iaoq[1] = regs->iaoq[0] + 4; + return 3; + } + } + } while (0); +#endif + +#ifdef CONFIG_PAX_EMUTRAMP + +#ifndef CONFIG_PAX_EMUSIGRT + if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP)) + return 1; +#endif + + do { /* PaX: rt_sigreturn emulation */ + unsigned int ldi1, ldi2, bel, nop; + + err = get_user(ldi1, (unsigned int *)instruction_pointer(regs)); + err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4)); + err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8)); + err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12)); + + if (err) + break; + + if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) && + ldi2 == 0x3414015AU && + bel == 0xE4008200U && + nop == 0x08000240U) + { + regs->gr[25] = (ldi1 & 2) >> 1; + regs->gr[20] = __NR_rt_sigreturn; + regs->gr[31] = regs->iaoq[1] + 16; + regs->sr[0] = regs->iasq[1]; + regs->iaoq[0] = 0x100UL; + regs->iaoq[1] = regs->iaoq[0] + 4; + regs->iasq[0] = regs->sr[2]; + regs->iasq[1] = regs->sr[2]; + return 2; + } + } 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 + int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fix; @@ -194,8 +305,33 @@ good_area: acc_type = parisc_acctyp(code,regs->iir); - if ((vma->vm_flags & acc_type) != acc_type) + if ((vma->vm_flags & acc_type) != acc_type) { + +#ifdef CONFIG_PAX_PAGEEXEC + if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) && + (address & ~3UL) == instruction_pointer(regs)) + { + up_read(&mm->mmap_sem); + switch (pax_handle_fetch_fault(regs)) { + +#ifdef CONFIG_PAX_EMUPLT + case 3: + return; +#endif + +#ifdef CONFIG_PAX_EMUTRAMP + case 2: + return; +#endif + + } + pax_report_fault(regs, (void *)instruction_pointer(regs), (void *)regs->gr[30]); + 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/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index e3b1d41..8e81edf 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -523,6 +523,16 @@ static __inline__ long atomic64_inc_not_zero(atomic64_t *v) return t1; } +#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 /* __powerpc64__ */ #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index 9e495c9..b6878e5 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h @@ -3,6 +3,7 @@ #ifdef __KERNEL__ +#include /* bytes per L1 cache line */ #if defined(CONFIG_8xx) || defined(CONFIG_403GCX) @@ -22,7 +23,7 @@ #define L1_CACHE_SHIFT 7 #endif -#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/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index cc0655a..13eac2e 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -28,8 +28,19 @@ 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. */ -extern unsigned long randomize_et_dyn(unsigned long base); -#define ELF_ET_DYN_BASE (randomize_et_dyn(0x20000000)) +#define ELF_ET_DYN_BASE (0x20000000) + +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (0x10000000UL) + +#ifdef __powerpc64__ +#define PAX_DELTA_MMAP_LEN (is_32bit_task() ? 16 : 28) +#define PAX_DELTA_STACK_LEN (is_32bit_task() ? 16 : 28) +#else +#define PAX_DELTA_MMAP_LEN 15 +#define PAX_DELTA_STACK_LEN 15 +#endif +#endif /* * Our registers are always unsigned longs, whether we're a 32 bit @@ -123,10 +134,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, (0x7ff >> (PAGE_SHIFT - 12)) : \ (0x3ffff >> (PAGE_SHIFT - 12))) -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - - #ifdef CONFIG_SPU_BASE /* Notes used in ET_CORE. Note name is "SPU//". */ #define NT_SPU 1 diff --git a/arch/powerpc/include/asm/exec.h b/arch/powerpc/include/asm/exec.h index 8196e9c..d83a9f3 100644 --- a/arch/powerpc/include/asm/exec.h +++ b/arch/powerpc/include/asm/exec.h @@ -4,6 +4,6 @@ #ifndef _ASM_POWERPC_EXEC_H #define _ASM_POWERPC_EXEC_H -extern unsigned long arch_align_stack(unsigned long sp); +#define arch_align_stack(x) ((x) & ~0xfUL) #endif /* _ASM_POWERPC_EXEC_H */ diff --git a/arch/powerpc/include/asm/kmap_types.h b/arch/powerpc/include/asm/kmap_types.h index 5acabbd..7ea14fa 100644 --- a/arch/powerpc/include/asm/kmap_types.h +++ b/arch/powerpc/include/asm/kmap_types.h @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. */ -#define KM_TYPE_NR 16 +#define KM_TYPE_NR 17 #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_KMAP_TYPES_H */ diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/mman.h index 8565c25..2865190 100644 --- a/arch/powerpc/include/asm/mman.h +++ b/arch/powerpc/include/asm/mman.h @@ -24,7 +24,7 @@ static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot) } #define arch_calc_vm_prot_bits(prot) arch_calc_vm_prot_bits(prot) -static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags) +static inline pgprot_t arch_vm_get_page_prot(vm_flags_t vm_flags) { return (vm_flags & VM_SAO) ? __pgprot(_PAGE_SAO) : __pgprot(0); } diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index b9f4262..dcf04f7 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -230,8 +230,9 @@ extern long long virt_phys_offset; * and needs to be executable. This means the whole heap ends * up being executable. */ -#define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define VM_DATA_DEFAULT_FLAGS32 \ + (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ + VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) #define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) @@ -259,6 +260,9 @@ extern long long virt_phys_offset; #define is_kernel_addr(x) ((x) >= PAGE_OFFSET) #endif +#define ktla_ktva(addr) (addr) +#define ktva_ktla(addr) (addr) + #ifndef CONFIG_PPC_BOOK3S_64 /* * Use the top bit of the higher-level page table entries to indicate whether diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index 88693ce..ac6f9ab 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h @@ -153,15 +153,18 @@ do { \ * stack by default, so in the absence of a PT_GNU_STACK program header * we turn execute permission off. */ -#define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#define VM_STACK_DEFAULT_FLAGS32 \ + (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ + VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) #define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#ifndef CONFIG_PAX_PAGEEXEC #define VM_STACK_DEFAULT_FLAGS \ (is_32bit_task() ? \ VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) +#endif #include diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index b66ae72..4a378cd 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h @@ -53,6 +53,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) #ifndef CONFIG_PPC_64K_PAGES #define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD) +#define pgd_populate_kernel(MM, PGD, PUD) pgd_populate((MM), (PGD), (PUD)) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { @@ -70,6 +71,11 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) pud_set(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); +} + #define pmd_populate(mm, pmd, pte_page) \ pmd_populate_kernel(mm, pmd, page_address(pte_page)) #define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte)) @@ -171,6 +177,7 @@ extern void __tlb_remove_table(void *_table); #endif #define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd) +#define pud_populate_kernel(mm, pud, pmd) pud_populate((mm), (pud), (pmd)) static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 7aeb955..19f748e 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -2,6 +2,7 @@ #define _ASM_POWERPC_PGTABLE_H #ifdef __KERNEL__ +#include #ifndef __ASSEMBLY__ #include /* For TASK_SIZE */ #include diff --git a/arch/powerpc/include/asm/pte-hash32.h b/arch/powerpc/include/asm/pte-hash32.h index 4aad413..85d86bf 100644 --- a/arch/powerpc/include/asm/pte-hash32.h +++ b/arch/powerpc/include/asm/pte-hash32.h @@ -21,6 +21,7 @@ #define _PAGE_FILE 0x004 /* when !present: nonlinear file mapping */ #define _PAGE_USER 0x004 /* usermode access allowed */ #define _PAGE_GUARDED 0x008 /* G: prohibit speculative access */ +#define _PAGE_EXEC _PAGE_GUARDED #define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */ #define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */ #define _PAGE_WRITETHRU 0x040 /* W: cache write-through */ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index e1fb161..2290d1d 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -234,6 +234,7 @@ #define SPRN_DBCR 0x136 /* e300 Data Breakpoint Control Reg */ #define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ #define DSISR_NOHPTE 0x40000000 /* no translation found */ +#define DSISR_GUARDED 0x10000000 /* fetch from guarded storage */ #define DSISR_PROTFAULT 0x08000000 /* protection fault */ #define DSISR_ISSTORE 0x02000000 /* access was a store */ #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 48cfc85..891382f 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -50,7 +50,7 @@ struct smp_ops_t { int (*cpu_disable)(void); void (*cpu_die)(unsigned int nr); int (*cpu_bootable)(unsigned int nr); -}; +} __no_const; extern void smp_send_debugger_break(void); extern void start_secondary_resume(void); diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index ba7b197..d292e26 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -93,7 +93,6 @@ static inline struct thread_info *current_thread_info(void) #define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_32BIT 4 /* 32 bit binary */ -#define TIF_PERFMON_WORK 5 /* work for pfm_handle_work() */ #define TIF_PERFMON_CTXSW 6 /* perfmon needs ctxsw calls */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_SINGLESTEP 8 /* singlestepping active */ @@ -107,6 +106,9 @@ static inline struct thread_info *current_thread_info(void) #define TIF_EMULATE_STACK_STORE 16 /* Is an instruction emulation for stack store? */ #define TIF_MEMDIE 17 /* is terminating due to OOM killer */ +#define TIF_PERFMON_WORK 18 /* work for pfm_handle_work() */ +/* mask must be expressable within 16 bits to satisfy 'andi' instruction reqs */ +#define TIF_GRSEC_SETXID 5 /* update credentials on syscall entry/exit */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1< INT_MAX) + return n; + + if (!__builtin_constant_p(n)) + check_object_size(to, n, false); + + if (likely(access_ok(VERIFY_READ, from, n))) + n = __copy_from_user(to, from, n); + else + memset(to, 0, n); + return n; +} + +static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) +{ + if ((long)n < 0 || n > INT_MAX) + return n; + + if (likely(access_ok(VERIFY_WRITE, to, n))) { + if (!__builtin_constant_p(n)) + check_object_size(from, n, true); + n = __copy_to_user(to, from, n); + } + return n; +} + +extern unsigned long copy_in_user(void __user *to, const void __user *from, + unsigned long n); + +#endif /* __powerpc64__ */ + extern unsigned long __clear_user(void __user *addr, unsigned long size); static inline unsigned long clear_user(void __user *addr, unsigned long size) diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 645170a..6cf0271 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -757,6 +757,7 @@ storage_fault_common: std r14,_DAR(r1) std r15,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD + bl .save_nvgprs mr r4,r14 mr r5,r15 ld r14,PACA_EXGEN+EX_R14(r13) @@ -765,8 +766,7 @@ storage_fault_common: cmpdi r3,0 bne- 1f b .ret_from_except_lite -1: bl .save_nvgprs - mr r5,r3 +1: mr r5,r3 addi r3,r1,STACK_FRAME_OVERHEAD ld r4,_DAR(r1) bl .bad_page_fault diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 902ca3c..e942155 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -1357,10 +1357,10 @@ handle_page_fault: 11: ld r4,_DAR(r1) ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD + bl .save_nvgprs bl .do_page_fault cmpdi r3,0 beq+ 12f - bl .save_nvgprs mr r5,r3 addi r3,r1,STACK_FRAME_OVERHEAD lwz r4,_DAR(r1) diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index 2e3200c..72095ce 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c @@ -162,7 +162,7 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr, me->arch.core_plt_section = i; } if (!me->arch.core_plt_section || !me->arch.init_plt_section) { - printk("Module doesn't contain .plt or .init.plt sections.\n"); + printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name); return -ENOEXEC; } @@ -192,11 +192,16 @@ static uint32_t do_plt_call(void *location, DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); /* Init, or core PLT? */ - if (location >= mod->module_core - && location < mod->module_core + mod->core_size) + if ((location >= mod->module_core_rx && location < mod->module_core_rx + mod->core_size_rx) || + (location >= mod->module_core_rw && location < mod->module_core_rw + mod->core_size_rw)) entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; - else + else if ((location >= mod->module_init_rx && location < mod->module_init_rx + mod->init_size_rx) || + (location >= mod->module_init_rw && location < mod->module_init_rw + mod->init_size_rw)) entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; + else { + printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name); + return ~0UL; + } /* Find this entry, or if that fails, the next avail. entry */ while (entry->jump[0]) { diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 7baa27b..f6b394a 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -884,8 +884,8 @@ void show_regs(struct pt_regs * regs) * Lookup NIP late so we have the best change of getting the * above info out without failing */ - printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip); - printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link); + printk("NIP ["REG"] %pA\n", regs->nip, (void *)regs->nip); + printk("LR ["REG"] %pA\n", regs->link, (void *)regs->link); #endif #ifdef CONFIG_PPC_TRANSACTIONAL_MEM printk("PACATMSCRATCH [%llx]\n", get_paca()->tm_scratch); @@ -1345,10 +1345,10 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) newsp = stack[0]; ip = stack[STACK_FRAME_LR_SAVE]; if (!firstframe || ip != lr) { - printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); + printk("["REG"] ["REG"] %pA", sp, ip, (void *)ip); #ifdef CONFIG_FUNCTION_GRAPH_TRACER if ((ip == rth || ip == mrth) && curr_frame >= 0) { - printk(" (%pS)", + printk(" (%pA)", (void *)current->ret_stack[curr_frame].ret); curr_frame--; } @@ -1368,7 +1368,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) struct pt_regs *regs = (struct pt_regs *) (sp + STACK_FRAME_OVERHEAD); lr = regs->link; - printk("--- Exception: %lx at %pS\n LR = %pS\n", + printk("--- Exception: %lx at %pA\n LR = %pA\n", regs->trap, (void *)regs->nip, (void *)lr); firstframe = 1; } @@ -1404,58 +1404,3 @@ void notrace __ppc64_runlatch_off(void) mtspr(SPRN_CTRLT, ctrl); } #endif /* CONFIG_PPC64 */ - -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 & ~0xf; -} - -static inline unsigned long brk_rnd(void) -{ - unsigned long rnd = 0; - - /* 8MB for 32bit, 1GB for 64bit */ - if (is_32bit_task()) - rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT))); - else - rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT))); - - return rnd << PAGE_SHIFT; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long base = mm->brk; - unsigned long ret; - -#ifdef CONFIG_PPC_STD_MMU_64 - /* - * If we are using 1TB segments and we are allowed to randomise - * the heap, we can put it above 1TB so it is backed by a 1TB - * segment. Otherwise the heap will be in the bottom 1TB - * which always uses 256MB segments and this may result in a - * performance penalty. - */ - if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T)) - base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T); -#endif - - ret = PAGE_ALIGN(base + brk_rnd()); - - if (ret < mm->brk) - return mm->brk; - - return ret; -} - -unsigned long randomize_et_dyn(unsigned long base) -{ - unsigned long ret = PAGE_ALIGN(base + brk_rnd()); - - if (ret < base) - return base; - - return ret; -} diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 64f7bd5..8dd550f 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -1783,6 +1783,10 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } +#ifdef CONFIG_GRKERNSEC_SETXID +extern void gr_delayed_cred_worker(void); +#endif + /* * We must return the syscall number to actually look up in the table. * This can be -1L to skip running any syscall at all. @@ -1795,6 +1799,11 @@ long do_syscall_trace_enter(struct pt_regs *regs) secure_computing_strict(regs->gpr[0]); +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + if (test_thread_flag(TIF_SYSCALL_TRACE) && tracehook_report_syscall_entry(regs)) /* @@ -1829,6 +1838,11 @@ void do_syscall_trace_leave(struct pt_regs *regs) { int step; +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + audit_syscall_exit(regs); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 0f83122..c0aca6a 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -987,7 +987,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; addr = frame; - if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { + if (vdso32_rt_sigtramp && current->mm->context.vdso_base != ~0UL) { sigret = 0; tramp = current->mm->context.vdso_base + vdso32_rt_sigtramp; } else { diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 887e99d..310bc11 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -751,7 +751,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, #endif /* Set up to return from userspace. */ - if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { + if (vdso64_rt_sigtramp && current->mm->context.vdso_base != ~0UL) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index e68a845..8b140e6 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -522,7 +522,7 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata sysfs_cpu_nb = { +static struct notifier_block sysfs_cpu_nb = { .notifier_call = sysfs_cpu_notify, }; diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 88929b1..bece8f8 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -141,6 +141,8 @@ static unsigned __kprobes long oops_begin(struct pt_regs *regs) return flags; } +extern void gr_handle_kernel_exploit(void); + static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) { @@ -190,6 +192,9 @@ static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); + + gr_handle_kernel_exploit(); + do_exit(signr); } diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index d4f463a..8fb7431 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "setup.h" @@ -222,7 +223,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) vdso_base = VDSO32_MBASE; #endif - current->mm->context.vdso_base = 0; + current->mm->context.vdso_base = ~0UL; /* vDSO has a problem and was disabled, just don't "enable" it for the * process @@ -242,7 +243,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) vdso_base = get_unmapped_area(NULL, vdso_base, (vdso_pages << PAGE_SHIFT) + ((VDSO_ALIGNMENT - 1) & PAGE_MASK), - 0, 0); + 0, MAP_PRIVATE | MAP_EXECUTABLE); if (IS_ERR_VALUE(vdso_base)) { rc = vdso_base; goto fail_mmapsem; diff --git a/arch/powerpc/lib/usercopy_64.c b/arch/powerpc/lib/usercopy_64.c index 5eea6f3..5d10396 100644 --- a/arch/powerpc/lib/usercopy_64.c +++ b/arch/powerpc/lib/usercopy_64.c @@ -9,22 +9,6 @@ #include #include -unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_READ, from, n))) - n = __copy_from_user(to, from, n); - else - memset(to, 0, n); - return n; -} - -unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) -{ - if (likely(access_ok(VERIFY_WRITE, to, n))) - n = __copy_to_user(to, from, n); - return n; -} - unsigned long copy_in_user(void __user *to, const void __user *from, unsigned long n) { @@ -35,7 +19,5 @@ unsigned long copy_in_user(void __user *to, const void __user *from, return n; } -EXPORT_SYMBOL(copy_from_user); -EXPORT_SYMBOL(copy_to_user); EXPORT_SYMBOL(copy_in_user); diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 8726779..a33c512 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -33,6 +33,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -69,6 +73,33 @@ static inline int notify_page_fault(struct pt_regs *regs) } #endif +#ifdef CONFIG_PAX_PAGEEXEC +/* + * PaX: decide what to do with offenders (regs->nip = fault address) + * + * returns 1 when task should be killed + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + 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 __user *)pc+i)) + printk(KERN_CONT "???????? "); + else + printk(KERN_CONT "%08x ", c); + } + printk("\n"); +} +#endif + /* * Check whether the instruction at regs->nip is a store using * an update addressing form which will update r1. @@ -216,7 +247,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, * indicate errors in DSISR but can validly be set in SRR1. */ if (trap == 0x400) - error_code &= 0x48200000; + error_code &= 0x58200000; else is_write = error_code & DSISR_ISSTORE; #else @@ -371,7 +402,7 @@ good_area: * "undefined". Of those that can be set, this is the only * one which seems bad. */ - if (error_code & 0x10000000) + if (error_code & DSISR_GUARDED) /* Guarded storage error. */ goto bad_area; #endif /* CONFIG_8xx */ @@ -386,7 +417,7 @@ good_area: * processors use the same I/D cache coherency mechanism * as embedded. */ - if (error_code & DSISR_PROTFAULT) + if (error_code & (DSISR_PROTFAULT | DSISR_GUARDED)) goto bad_area; #endif /* CONFIG_PPC_STD_MMU */ @@ -471,6 +502,23 @@ bad_area: bad_area_nosemaphore: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm->pax_flags & MF_PAX_PAGEEXEC) { +#ifdef CONFIG_PPC_STD_MMU + if (is_exec && (error_code & (DSISR_PROTFAULT | DSISR_GUARDED))) { +#else + if (is_exec && regs->nip == address) { +#endif + switch (pax_handle_fetch_fault(regs)) { + } + + pax_report_fault(regs, (void *)regs->nip, (void *)regs->gpr[PT_R1]); + do_group_exit(SIGKILL); + } + } +#endif + _exception(SIGSEGV, regs, code, address); goto bail; } diff --git a/arch/powerpc/mm/mmap_64.c b/arch/powerpc/mm/mmap_64.c index 67a42ed..cd463e0 100644 --- a/arch/powerpc/mm/mmap_64.c +++ b/arch/powerpc/mm/mmap_64.c @@ -57,6 +57,10 @@ static unsigned long mmap_rnd(void) { unsigned long rnd = 0; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (current->flags & PF_RANDOMIZE) { /* 8MB for 32bit, 1GB for 64bit */ if (is_32bit_task()) @@ -91,10 +95,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm) */ if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; + +#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; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); + +#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; mm->unmap_area = arch_unmap_area_topdown; } diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index e779642..e5bb889 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c @@ -363,7 +363,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata mmu_context_cpu_nb = { +static struct notifier_block mmu_context_cpu_nb = { .notifier_call = mmu_context_cpu_notify, }; diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index cafad40..9cbc0fc 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -920,7 +920,7 @@ static void __init *careful_zallocation(int nid, unsigned long size, return ret; } -static struct notifier_block __cpuinitdata ppc64_numa_nb = { +static struct notifier_block ppc64_numa_nb = { .notifier_call = cpu_numa_callback, .priority = 1 /* Must run before sched domains notifier. */ }; diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 3e99c14..f00953c 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c @@ -103,7 +103,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, if ((mm->task_size - len) < addr) return 0; vma = find_vma(mm, addr); - return (!vma || (addr + len) <= vma->vm_start); + return check_heap_stack_gap(vma, addr, len, 0); } static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice) @@ -277,6 +277,12 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm, info.align_offset = 0; addr = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + addr += mm->delta_mmap; +#endif + while (addr < TASK_SIZE) { info.low_limit = addr; if (!slice_scan_available(addr, available, 1, &addr)) @@ -410,6 +416,11 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, if (fixed && addr > (mm->task_size - len)) return -EINVAL; +#ifdef CONFIG_PAX_RANDMMAP + if (!fixed && (mm->pax_flags & MF_PAX_RANDMMAP)) + addr = 0; +#endif + /* If hint, make sure it matches our alignment restrictions */ if (!fixed && addr) { addr = _ALIGN_UP(addr, 1ul << pshift); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 9098692..3d54cd1 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -280,9 +280,9 @@ spufs_mem_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_NOPAGE; } -static int spufs_mem_mmap_access(struct vm_area_struct *vma, +static ssize_t spufs_mem_mmap_access(struct vm_area_struct *vma, unsigned long address, - void *buf, int len, int write) + void *buf, size_t len, int write) { struct spu_context *ctx = vma->vm_file->private_data; unsigned long offset = address - vma->vm_start; diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index bdb738a..49c9f95 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -885,7 +885,7 @@ static int smp_core99_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata smp_core99_cpu_nb = { +static struct notifier_block smp_core99_cpu_nb = { .notifier_call = smp_core99_cpu_notify, }; #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index c797832..ce575c8 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -326,6 +326,16 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v) #define atomic64_dec_and_test(_v) (atomic64_sub_return(1, _v) == 0) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +#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/s390/include/asm/cache.h b/arch/s390/include/asm/cache.h index 4d7ccac..d03d0ad 100644 --- a/arch/s390/include/asm/cache.h +++ b/arch/s390/include/asm/cache.h @@ -9,8 +9,10 @@ #ifndef __ARCH_S390_CACHE_H #define __ARCH_S390_CACHE_H -#define L1_CACHE_BYTES 256 +#include + #define L1_CACHE_SHIFT 8 +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) #define NET_SKB_PAD 32 #define __read_mostly __attribute__((__section__(".data..read_mostly"))) diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 78f4f87..598ce39 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -162,8 +162,14 @@ extern unsigned int vdso_enabled; 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. */ -extern unsigned long randomize_et_dyn(unsigned long base); -#define ELF_ET_DYN_BASE (randomize_et_dyn(STACK_TOP / 3 * 2)) +#define ELF_ET_DYN_BASE (STACK_TOP / 3 * 2) + +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_31BIT) ? 0x10000UL : 0x80000000UL) + +#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_31BIT) ? 15 : 26) +#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_31BIT) ? 15 : 26) +#endif /* This yields a mask that user programs can use to figure out what instruction set this CPU supports. */ @@ -222,9 +228,6 @@ struct linux_binprm; #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 int arch_setup_additional_pages(struct linux_binprm *, int); -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); #endif diff --git a/arch/s390/include/asm/exec.h b/arch/s390/include/asm/exec.h index c4a93d6..4d2a9b4 100644 --- a/arch/s390/include/asm/exec.h +++ b/arch/s390/include/asm/exec.h @@ -7,6 +7,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/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 9c33ed4..e40cbef 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -252,6 +252,10 @@ static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { might_fault(); + + if ((long)n < 0) + return n; + return __copy_to_user(to, from, n); } @@ -275,6 +279,9 @@ copy_to_user(void __user *to, const void *from, unsigned long n) 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 (__builtin_constant_p(n) && (n <= 256)) return uaccess.copy_from_user_small(n, from, to); else @@ -306,10 +313,14 @@ __compiletime_warning("copy_from_user() buffer size is not provably correct") static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { - unsigned int sz = __compiletime_object_size(to); + size_t sz = __compiletime_object_size(to); might_fault(); - if (unlikely(sz != -1 && sz < n)) { + + if ((long)n < 0) + return n; + + if (unlikely(sz != (size_t)-1 && sz < n)) { copy_from_user_overflow(); return n; } diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 7845e15..59c4353 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -169,11 +169,11 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, /* Increase core size by size of got & plt and set start offsets for got and plt. */ - me->core_size = ALIGN(me->core_size, 4); - me->arch.got_offset = me->core_size; - me->core_size += me->arch.got_size; - me->arch.plt_offset = me->core_size; - me->core_size += me->arch.plt_size; + me->core_size_rw = ALIGN(me->core_size_rw, 4); + me->arch.got_offset = me->core_size_rw; + me->core_size_rw += me->arch.got_size; + me->arch.plt_offset = me->core_size_rx; + me->core_size_rx += me->arch.plt_size; return 0; } @@ -289,7 +289,7 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, if (info->got_initialized == 0) { Elf_Addr *gotent; - gotent = me->module_core + me->arch.got_offset + + gotent = me->module_core_rw + me->arch.got_offset + info->got_offset; *gotent = val; info->got_initialized = 1; @@ -312,7 +312,7 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, rc = apply_rela_bits(loc, val, 0, 64, 0); else if (r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT) { - val += (Elf_Addr) me->module_core - loc; + val += (Elf_Addr) me->module_core_rw - loc; rc = apply_rela_bits(loc, val, 1, 32, 1); } break; @@ -325,7 +325,7 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */ if (info->plt_initialized == 0) { unsigned int *ip; - ip = me->module_core + me->arch.plt_offset + + ip = me->module_core_rx + me->arch.plt_offset + info->plt_offset; #ifndef CONFIG_64BIT ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */ @@ -350,7 +350,7 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, val - loc + 0xffffUL < 0x1ffffeUL) || (r_type == R_390_PLT32DBL && val - loc + 0xffffffffULL < 0x1fffffffeULL))) - val = (Elf_Addr) me->module_core + + val = (Elf_Addr) me->module_core_rx + me->arch.plt_offset + info->plt_offset; val += rela->r_addend - loc; @@ -372,7 +372,7 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, case R_390_GOTOFF32: /* 32 bit offset to GOT. */ case R_390_GOTOFF64: /* 64 bit offset to GOT. */ val = val + rela->r_addend - - ((Elf_Addr) me->module_core + me->arch.got_offset); + ((Elf_Addr) me->module_core_rw + me->arch.got_offset); if (r_type == R_390_GOTOFF16) rc = apply_rela_bits(loc, val, 0, 16, 0); else if (r_type == R_390_GOTOFF32) @@ -382,7 +382,7 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, break; case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */ - val = (Elf_Addr) me->module_core + me->arch.got_offset + + val = (Elf_Addr) me->module_core_rw + me->arch.got_offset + rela->r_addend - loc; if (r_type == R_390_GOTPC) rc = apply_rela_bits(loc, val, 1, 32, 0); diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 2bc3edd..ab9d598 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -236,39 +236,3 @@ unsigned long get_wchan(struct task_struct *p) } return 0; } - -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 & ~0xf; -} - -static inline unsigned long brk_rnd(void) -{ - /* 8MB for 32bit, 1GB for 64bit */ - if (is_32bit_task()) - return (get_random_int() & 0x7ffUL) << PAGE_SHIFT; - else - return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); - - if (ret < mm->brk) - return mm->brk; - return ret; -} - -unsigned long randomize_et_dyn(unsigned long base) -{ - unsigned long ret = PAGE_ALIGN(base + brk_rnd()); - - if (!(current->flags & PF_RANDOMIZE)) - return base; - if (ret < base) - return base; - return ret; -} diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 06bafec..2bca531 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -90,10 +90,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm) */ if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; + +#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; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); + +#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; mm->unmap_area = arch_unmap_area_topdown; } @@ -175,10 +187,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm) */ if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + mm->get_unmapped_area = s390_get_unmapped_area; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); + +#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 = s390_get_unmapped_area_topdown; mm->unmap_area = arch_unmap_area_topdown; } diff --git a/arch/score/include/asm/cache.h b/arch/score/include/asm/cache.h index ae3d59f..f65f075 100644 --- a/arch/score/include/asm/cache.h +++ b/arch/score/include/asm/cache.h @@ -1,7 +1,9 @@ #ifndef _ASM_SCORE_CACHE_H #define _ASM_SCORE_CACHE_H +#include + #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_SCORE_CACHE_H */ diff --git a/arch/score/include/asm/exec.h b/arch/score/include/asm/exec.h index f9f3cd5..58ff438 100644 --- a/arch/score/include/asm/exec.h +++ b/arch/score/include/asm/exec.h @@ -1,6 +1,6 @@ #ifndef _ASM_SCORE_EXEC_H #define _ASM_SCORE_EXEC_H -extern unsigned long arch_align_stack(unsigned long sp); +#define arch_align_stack(x) (x) #endif /* _ASM_SCORE_EXEC_H */ diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index f4c6d02..e9355c3 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c @@ -116,8 +116,3 @@ unsigned long get_wchan(struct task_struct *task) return task_pt_regs(task)->cp0_epc; } - -unsigned long arch_align_stack(unsigned long sp) -{ - return sp; -} diff --git a/arch/sh/include/asm/cache.h b/arch/sh/include/asm/cache.h index ef9e555..331bd29 100644 --- a/arch/sh/include/asm/cache.h +++ b/arch/sh/include/asm/cache.h @@ -9,10 +9,11 @@ #define __ASM_SH_CACHE_H #ifdef __KERNEL__ +#include #include #include -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) #define __read_mostly __attribute__((__section__(".data..read_mostly"))) diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 03f2b55..b0270327 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -143,7 +143,7 @@ shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata shx3_cpu_notifier = { +static struct notifier_block shx3_cpu_notifier = { .notifier_call = shx3_cpu_callback, }; diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c index 6777177..cb5e44f 100644 --- a/arch/sh/mm/mmap.c +++ b/arch/sh/mm/mmap.c @@ -36,6 +36,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; int do_colour_align; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); struct vm_unmapped_area_info info; if (flags & MAP_FIXED) { @@ -55,6 +56,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, if (filp || (flags & MAP_SHARED)) do_colour_align = 1; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { if (do_colour_align) addr = COLOUR_ALIGN(addr, pgoff); @@ -62,14 +67,13 @@ unsigned long 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; } info.flags = 0; info.length = len; - info.low_limit = TASK_UNMAPPED_BASE; + info.low_limit = mm->mmap_base; info.high_limit = TASK_SIZE; info.align_mask = do_colour_align ? (PAGE_MASK & shm_align_mask) : 0; info.align_offset = pgoff << PAGE_SHIFT; @@ -85,6 +89,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, struct mm_struct *mm = current->mm; unsigned long addr = addr0; int do_colour_align; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); struct vm_unmapped_area_info info; if (flags & MAP_FIXED) { @@ -104,6 +109,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (filp || (flags & MAP_SHARED)) do_colour_align = 1; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + /* requesting a specific address */ if (addr) { if (do_colour_align) @@ -112,8 +121,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 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; } @@ -135,6 +143,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += mm->delta_mmap; +#endif + info.high_limit = TASK_SIZE; addr = vm_unmapped_area(&info); } diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index be56a24..443328f 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -14,18 +14,40 @@ #define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) +static inline int atomic_read_unchecked(const atomic_unchecked_t *v) +{ + return v->counter; +} #define atomic64_read(v) (*(volatile long *)&(v)->counter) +static inline long atomic64_read_unchecked(const atomic64_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; +} #define atomic64_set(v, i) (((v)->counter) = i) +static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i) +{ + v->counter = i; +} extern void atomic_add(int, atomic_t *); +extern void atomic_add_unchecked(int, atomic_unchecked_t *); extern void atomic64_add(long, atomic64_t *); +extern void atomic64_add_unchecked(long, atomic64_unchecked_t *); extern void atomic_sub(int, atomic_t *); +extern void atomic_sub_unchecked(int, atomic_unchecked_t *); extern void atomic64_sub(long, atomic64_t *); +extern void atomic64_sub_unchecked(long, atomic64_unchecked_t *); extern int atomic_add_ret(int, atomic_t *); +extern int atomic_add_ret_unchecked(int, atomic_unchecked_t *); extern long atomic64_add_ret(long, atomic64_t *); +extern long atomic64_add_ret_unchecked(long, atomic64_unchecked_t *); extern int atomic_sub_ret(int, atomic_t *); extern long atomic64_sub_ret(long, atomic64_t *); @@ -33,13 +55,29 @@ extern long atomic64_sub_ret(long, atomic64_t *); #define atomic64_dec_return(v) atomic64_sub_ret(1, v) #define atomic_inc_return(v) atomic_add_ret(1, v) +static inline int atomic_inc_return_unchecked(atomic_unchecked_t *v) +{ + return atomic_add_ret_unchecked(1, v); +} #define atomic64_inc_return(v) atomic64_add_ret(1, v) +static inline long atomic64_inc_return_unchecked(atomic64_unchecked_t *v) +{ + return atomic64_add_ret_unchecked(1, v); +} #define atomic_sub_return(i, v) atomic_sub_ret(i, v) #define atomic64_sub_return(i, v) atomic64_sub_ret(i, v) #define atomic_add_return(i, v) atomic_add_ret(i, v) +static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) +{ + return atomic_add_ret_unchecked(i, v); +} #define atomic64_add_return(i, v) atomic64_add_ret(i, v) +static inline long atomic64_add_return_unchecked(long i, atomic64_unchecked_t *v) +{ + return atomic64_add_ret_unchecked(i, v); +} /* * atomic_inc_and_test - increment and test @@ -50,6 +88,10 @@ extern long atomic64_sub_ret(long, atomic64_t *); * 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_inc_return_unchecked(v) == 0; +} #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) #define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0) @@ -59,25 +101,60 @@ extern long atomic64_sub_ret(long, atomic64_t *); #define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0) #define atomic_inc(v) atomic_add(1, v) +static inline void atomic_inc_unchecked(atomic_unchecked_t *v) +{ + atomic_add_unchecked(1, v); +} #define atomic64_inc(v) atomic64_add(1, v) +static inline void atomic64_inc_unchecked(atomic64_unchecked_t *v) +{ + atomic64_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 atomic64_dec(v) atomic64_sub(1, v) +static inline void atomic64_dec_unchecked(atomic64_unchecked_t *v) +{ + atomic64_sub_unchecked(1, v); +} #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0) #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0) #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) +static inline int atomic_cmpxchg_unchecked(atomic_unchecked_t *v, int old, int new) +{ + return cmpxchg(&v->counter, old, new); +} #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) { - int c, old; + int c, old, new; c = atomic_read(v); for (;;) { - if (unlikely(c == (u))) + if (unlikely(c == u)) break; - old = atomic_cmpxchg((v), c, c + (a)); + + asm volatile("addcc %2, %0, %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "tvs %%icc, 6\n" +#endif + + : "=r" (new) + : "0" (c), "ir" (a) + : "cc"); + + old = atomic_cmpxchg(v, c, new); if (likely(old == c)) break; c = old; @@ -88,20 +165,35 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) #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_xchg_unchecked(atomic64_unchecked_t *v, long new) +{ + return xchg(&v->counter, new); +} static inline long atomic64_add_unless(atomic64_t *v, long a, long u) { - long c, old; + long c, old, new; c = atomic64_read(v); for (;;) { - if (unlikely(c == (u))) + if (unlikely(c == u)) break; - old = atomic64_cmpxchg((v), c, c + (a)); + + asm volatile("addcc %2, %0, %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "tvs %%xcc, 6\n" +#endif + + : "=r" (new) + : "0" (c), "ir" (a) + : "cc"); + + old = atomic64_cmpxchg(v, c, new); if (likely(old == c)) break; c = old; } - return c != (u); + return c != u; } #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h index 5bb6991..5c2132e 100644 --- a/arch/sparc/include/asm/cache.h +++ b/arch/sparc/include/asm/cache.h @@ -7,10 +7,12 @@ #ifndef _SPARC_CACHE_H #define _SPARC_CACHE_H +#include + #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long) #define L1_CACHE_SHIFT 5 -#define L1_CACHE_BYTES 32 +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) #ifdef CONFIG_SPARC32 #define SMP_CACHE_BYTES_SHIFT 5 diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h index a24e41f..47677ff 100644 --- a/arch/sparc/include/asm/elf_32.h +++ b/arch/sparc/include/asm/elf_32.h @@ -114,6 +114,13 @@ typedef struct { #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE 0x10000UL + +#define PAX_DELTA_MMAP_LEN 16 +#define PAX_DELTA_STACK_LEN 16 +#endif + /* This yields a mask that user programs can use to figure out what instruction set this cpu supports. This can NOT be done in userspace on Sparc. */ diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h index 370ca1e..d4f4a98 100644 --- a/arch/sparc/include/asm/elf_64.h +++ b/arch/sparc/include/asm/elf_64.h @@ -189,6 +189,13 @@ typedef struct { #define ELF_ET_DYN_BASE 0x0000010000000000UL #define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL) + +#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT) ? 14 : 28) +#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT) ? 15 : 29) +#endif + extern unsigned long sparc64_elf_hwcap; #define ELF_HWCAP sparc64_elf_hwcap diff --git a/arch/sparc/include/asm/pgalloc_32.h b/arch/sparc/include/asm/pgalloc_32.h index 9b1c36d..209298b 100644 --- a/arch/sparc/include/asm/pgalloc_32.h +++ b/arch/sparc/include/asm/pgalloc_32.h @@ -33,6 +33,7 @@ static inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) } #define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD) +#define pgd_populate_kernel(MM, PGD, PMD) pgd_populate((MM), (PGD), (PMD)) static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h index bcfe063..b333142 100644 --- a/arch/sparc/include/asm/pgalloc_64.h +++ b/arch/sparc/include/asm/pgalloc_64.h @@ -26,6 +26,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) } #define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) +#define pud_populate_kernel(MM, PUD, PMD) pud_populate((MM), (PUD), (PMD)) static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) { diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 6fc1348..390c50a 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -50,6 +50,9 @@ extern unsigned long calc_highpages(void); #define PAGE_SHARED SRMMU_PAGE_SHARED #define PAGE_COPY SRMMU_PAGE_COPY #define PAGE_READONLY SRMMU_PAGE_RDONLY +#define PAGE_SHARED_NOEXEC SRMMU_PAGE_SHARED_NOEXEC +#define PAGE_COPY_NOEXEC SRMMU_PAGE_COPY_NOEXEC +#define PAGE_READONLY_NOEXEC SRMMU_PAGE_RDONLY_NOEXEC #define PAGE_KERNEL SRMMU_PAGE_KERNEL /* Top-level page directory - dummy used by init-mm. @@ -62,18 +65,18 @@ extern unsigned long ptr_in_current_pgd; /* xwr */ #define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY +#define __P001 PAGE_READONLY_NOEXEC +#define __P010 PAGE_COPY_NOEXEC +#define __P011 PAGE_COPY_NOEXEC #define __P100 PAGE_READONLY #define __P101 PAGE_READONLY #define __P110 PAGE_COPY #define __P111 PAGE_COPY #define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED +#define __S001 PAGE_READONLY_NOEXEC +#define __S010 PAGE_SHARED_NOEXEC +#define __S011 PAGE_SHARED_NOEXEC #define __S100 PAGE_READONLY #define __S101 PAGE_READONLY #define __S110 PAGE_SHARED diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h index 79da178..c2eede8 100644 --- a/arch/sparc/include/asm/pgtsrmmu.h +++ b/arch/sparc/include/asm/pgtsrmmu.h @@ -115,6 +115,11 @@ SRMMU_EXEC | SRMMU_REF) #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ SRMMU_EXEC | SRMMU_REF) + +#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_WRITE | SRMMU_REF) +#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF) +#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF) + #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \ SRMMU_DIRTY | SRMMU_REF) diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h index 9689176..63c18ea 100644 --- a/arch/sparc/include/asm/spinlock_64.h +++ b/arch/sparc/include/asm/spinlock_64.h @@ -92,14 +92,19 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long fla /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */ -static void inline arch_read_lock(arch_rwlock_t *lock) +static inline void arch_read_lock(arch_rwlock_t *lock) { unsigned long tmp1, tmp2; __asm__ __volatile__ ( "1: ldsw [%2], %0\n" " brlz,pn %0, 2f\n" -"4: add %0, 1, %1\n" +"4: addcc %0, 1, %1\n" + +#ifdef CONFIG_PAX_REFCOUNT +" tvs %%icc, 6\n" +#endif + " cas [%2], %0, %1\n" " cmp %0, %1\n" " bne,pn %%icc, 1b\n" @@ -112,10 +117,10 @@ static void inline arch_read_lock(arch_rwlock_t *lock) " .previous" : "=&r" (tmp1), "=&r" (tmp2) : "r" (lock) - : "memory"); + : "memory", "cc"); } -static int inline arch_read_trylock(arch_rwlock_t *lock) +static inline int arch_read_trylock(arch_rwlock_t *lock) { int tmp1, tmp2; @@ -123,7 +128,12 @@ static int inline arch_read_trylock(arch_rwlock_t *lock) "1: ldsw [%2], %0\n" " brlz,a,pn %0, 2f\n" " mov 0, %0\n" -" add %0, 1, %1\n" +" addcc %0, 1, %1\n" + +#ifdef CONFIG_PAX_REFCOUNT +" tvs %%icc, 6\n" +#endif + " cas [%2], %0, %1\n" " cmp %0, %1\n" " bne,pn %%icc, 1b\n" @@ -136,13 +146,18 @@ static int inline arch_read_trylock(arch_rwlock_t *lock) return tmp1; } -static void inline arch_read_unlock(arch_rwlock_t *lock) +static inline void arch_read_unlock(arch_rwlock_t *lock) { unsigned long tmp1, tmp2; __asm__ __volatile__( "1: lduw [%2], %0\n" -" sub %0, 1, %1\n" +" subcc %0, 1, %1\n" + +#ifdef CONFIG_PAX_REFCOUNT +" tvs %%icc, 6\n" +#endif + " cas [%2], %0, %1\n" " cmp %0, %1\n" " bne,pn %%xcc, 1b\n" @@ -152,7 +167,7 @@ static void inline arch_read_unlock(arch_rwlock_t *lock) : "memory"); } -static void inline arch_write_lock(arch_rwlock_t *lock) +static inline void arch_write_lock(arch_rwlock_t *lock) { unsigned long mask, tmp1, tmp2; @@ -177,7 +192,7 @@ static void inline arch_write_lock(arch_rwlock_t *lock) : "memory"); } -static void inline arch_write_unlock(arch_rwlock_t *lock) +static inline void arch_write_unlock(arch_rwlock_t *lock) { __asm__ __volatile__( " stw %%g0, [%0]" @@ -186,7 +201,7 @@ static void inline arch_write_unlock(arch_rwlock_t *lock) : "memory"); } -static int inline arch_write_trylock(arch_rwlock_t *lock) +static inline int arch_write_trylock(arch_rwlock_t *lock) { unsigned long mask, tmp1, tmp2, result; diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index dd38075..e7cac83 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h @@ -49,6 +49,8 @@ struct thread_info { unsigned long w_saved; struct restart_block restart_block; + + unsigned long lowest_stack; }; /* diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index d5e5042..9bfee76 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -63,6 +63,8 @@ struct thread_info { struct pt_regs *kern_una_regs; unsigned int kern_una_insn; + unsigned long lowest_stack; + unsigned long fpregs[0] __attribute__ ((aligned(64))); }; @@ -192,10 +194,11 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */ /* flag bit 6 is available */ #define TIF_32BIT 7 /* 32-bit binary */ -/* flag bit 8 is available */ +#define TIF_GRSEC_SETXID 8 /* update credentials on syscall entry/exit */ #define TIF_SECCOMP 9 /* secure computing */ #define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */ #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ + /* NOTE: Thread flags >= 12 should be ones we have no interest * in using in assembly, else we can't use the mask as * an immediate value in instructions such as andcc. @@ -214,12 +217,18 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_SYSCALL_AUDIT (1< #else diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 53a28dd..50c38c3 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h @@ -250,27 +250,46 @@ extern unsigned long __copy_user(void __user *to, const void __user *from, unsig static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) { - if (n && __access_ok((unsigned long) to, n)) + if ((long)n < 0) + return n; + + if (n && __access_ok((unsigned long) to, n)) { + if (!__builtin_constant_p(n)) + check_object_size(from, n, true); return __copy_user(to, (__force void __user *) from, n); - else + } else return n; } static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) { + if ((long)n < 0) + return n; + + if (!__builtin_constant_p(n)) + check_object_size(from, n, true); + return __copy_user(to, (__force void __user *) from, n); } static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { - if (n && __access_ok((unsigned long) from, n)) + if ((long)n < 0) + return n; + + if (n && __access_ok((unsigned long) from, n)) { + if (!__builtin_constant_p(n)) + check_object_size(to, n, false); return __copy_user((__force void __user *) to, from, n); - else + } else return n; } static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { + if ((long)n < 0) + return n; + return __copy_user((__force void __user *) to, from, n); } diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index e562d3c..191f176 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -214,8 +215,15 @@ extern unsigned long copy_from_user_fixup(void *to, const void __user *from, static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long size) { - unsigned long ret = ___copy_from_user(to, from, size); + unsigned long ret; + if ((long)size < 0 || size > INT_MAX) + return size; + + if (!__builtin_constant_p(size)) + check_object_size(to, size, false); + + ret = ___copy_from_user(to, from, size); if (unlikely(ret)) ret = copy_from_user_fixup(to, from, size); @@ -231,8 +239,15 @@ extern unsigned long copy_to_user_fixup(void __user *to, const void *from, static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long size) { - unsigned long ret = ___copy_to_user(to, from, size); + unsigned long ret; + + if ((long)size < 0 || size > INT_MAX) + return size; + + if (!__builtin_constant_p(size)) + check_object_size(from, size, true); + ret = ___copy_to_user(to, from, size); if (unlikely(ret)) ret = copy_to_user_fixup(to, from, size); return ret; diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index d432fb2..6056af1 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -3,7 +3,7 @@ # asflags-y := -ansi -ccflags-y := -Werror +#ccflags-y := -Werror extra-y := head_$(BITS).o diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 5ef48da..11d460f 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -783,6 +783,16 @@ void ldom_set_var(const char *var, const char *value) char *base, *p; int msg_len, loops; + if (strlen(var) + strlen(value) + 2 > + sizeof(pkt) - sizeof(pkt.header)) { + printk(KERN_ERR PFX + "contents length: %zu, which more than max: %lu," + "so could not set (%s) variable to (%s).\n", + strlen(var) + strlen(value) + 2, + sizeof(pkt) - sizeof(pkt.header), var, value); + return; + } + memset(&pkt, 0, sizeof(pkt)); pkt.header.data.tag.type = DS_DATA; pkt.header.data.handle = cp->handle; diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index fdd819d..5af08c8 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -116,14 +116,14 @@ void show_regs(struct pt_regs *r) printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n", r->psr, r->pc, r->npc, r->y, print_tainted()); - printk("PC: <%pS>\n", (void *) r->pc); + printk("PC: <%pA>\n", (void *) r->pc); printk("%%G: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", r->u_regs[0], r->u_regs[1], r->u_regs[2], r->u_regs[3], r->u_regs[4], r->u_regs[5], r->u_regs[6], r->u_regs[7]); printk("%%O: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", r->u_regs[8], r->u_regs[9], r->u_regs[10], r->u_regs[11], r->u_regs[12], r->u_regs[13], r->u_regs[14], r->u_regs[15]); - printk("RPC: <%pS>\n", (void *) r->u_regs[15]); + printk("RPC: <%pA>\n", (void *) r->u_regs[15]); printk("%%L: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3], @@ -160,7 +160,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) rw = (struct reg_window32 *) fp; pc = rw->ins[7]; printk("[%08lx : ", pc); - printk("%pS ] ", (void *) pc); + printk("%pA ] ", (void *) pc); fp = rw->ins[6]; } while (++count < 16); printk("\n"); diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index baebab2..9cd13b1 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -158,7 +158,7 @@ static void show_regwindow(struct pt_regs *regs) printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n", rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]); if (regs->tstate & TSTATE_PRIV) - printk("I7: <%pS>\n", (void *) rwk->ins[7]); + printk("I7: <%pA>\n", (void *) rwk->ins[7]); } void show_regs(struct pt_regs *regs) @@ -167,7 +167,7 @@ void show_regs(struct pt_regs *regs) printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate, regs->tpc, regs->tnpc, regs->y, print_tainted()); - printk("TPC: <%pS>\n", (void *) regs->tpc); + printk("TPC: <%pA>\n", (void *) regs->tpc); printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n", regs->u_regs[0], regs->u_regs[1], regs->u_regs[2], regs->u_regs[3]); @@ -180,7 +180,7 @@ void show_regs(struct pt_regs *regs) printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n", regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], regs->u_regs[15]); - printk("RPC: <%pS>\n", (void *) regs->u_regs[15]); + printk("RPC: <%pA>\n", (void *) regs->u_regs[15]); show_regwindow(regs); show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]); } @@ -269,7 +269,7 @@ void arch_trigger_all_cpu_backtrace(void) ((tp && tp->task) ? tp->task->pid : -1)); if (gp->tstate & TSTATE_PRIV) { - printk(" TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n", + printk(" TPC[%pA] O7[%pA] I7[%pA] RPC[%pA]\n", (void *) gp->tpc, (void *) gp->o7, (void *) gp->i7, diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 79cc0d1..ec62734 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -144,7 +144,7 @@ static int __init prom_common_nextprop(phandle node, char *prev, char *buf) unsigned int prom_early_allocated __initdata; -static struct of_pdt_ops prom_sparc_ops __initdata = { +static struct of_pdt_ops prom_sparc_ops __initconst = { .nextprop = prom_common_nextprop, .getproplen = prom_getproplen, .getproperty = prom_getproperty, diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 7ff45e4..a58f271 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -1057,6 +1057,10 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } +#ifdef CONFIG_GRKERNSEC_SETXID +extern void gr_delayed_cred_worker(void); +#endif + asmlinkage int syscall_trace_enter(struct pt_regs *regs) { int ret = 0; @@ -1064,6 +1068,11 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) /* do the secure computing check first */ secure_computing_strict(regs->u_regs[UREG_G1]); +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + if (test_thread_flag(TIF_SYSCALL_TRACE)) ret = tracehook_report_syscall_entry(regs); @@ -1084,6 +1093,11 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) asmlinkage void syscall_trace_leave(struct pt_regs *regs) { +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + audit_syscall_exit(regs); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 77539ed..3ffffe7 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -868,8 +868,8 @@ extern unsigned long xcall_flush_dcache_page_cheetah; extern unsigned long xcall_flush_dcache_page_spitfire; #ifdef CONFIG_DEBUG_DCFLUSH -extern atomic_t dcpage_flushes; -extern atomic_t dcpage_flushes_xcall; +extern atomic_unchecked_t dcpage_flushes; +extern atomic_unchecked_t dcpage_flushes_xcall; #endif static inline void __local_flush_dcache_page(struct page *page) @@ -893,7 +893,7 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) return; #ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); + atomic_inc_unchecked(&dcpage_flushes); #endif this_cpu = get_cpu(); @@ -917,7 +917,7 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) xcall_deliver(data0, __pa(pg_addr), (u64) pg_addr, cpumask_of(cpu)); #ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes_xcall); + atomic_inc_unchecked(&dcpage_flushes_xcall); #endif } } @@ -936,7 +936,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) preempt_disable(); #ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); + atomic_inc_unchecked(&dcpage_flushes); #endif data0 = 0; pg_addr = page_address(page); @@ -953,7 +953,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) xcall_deliver(data0, __pa(pg_addr), (u64) pg_addr, cpu_online_mask); #ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes_xcall); + atomic_inc_unchecked(&dcpage_flushes_xcall); #endif } __local_flush_dcache_page(page); diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 3a8d184..49498a8 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -52,7 +52,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi if (len > TASK_SIZE - PAGE_SIZE) return -ENOMEM; if (!addr) - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; info.flags = 0; info.length = len; diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 2daaaa6..4fb84dc 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -90,13 +90,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi struct vm_area_struct * vma; unsigned long task_size = TASK_SIZE; int do_color_align; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); struct vm_unmapped_area_info info; if (flags & MAP_FIXED) { /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && + if ((filp || (flags & MAP_SHARED)) && ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; @@ -111,6 +112,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi if (filp || (flags & MAP_SHARED)) do_color_align = 1; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { if (do_color_align) addr = COLOR_ALIGN(addr, pgoff); @@ -118,22 +123,28 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi 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.flags = 0; info.length = len; - info.low_limit = TASK_UNMAPPED_BASE; + info.low_limit = mm->mmap_base; info.high_limit = min(task_size, VA_EXCLUDE_START); info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; info.align_offset = pgoff << PAGE_SHIFT; + info.threadstack_offset = offset; addr = vm_unmapped_area(&info); if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) { VM_BUG_ON(addr != -ENOMEM); info.low_limit = VA_EXCLUDE_END; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += mm->delta_mmap; +#endif + info.high_limit = task_size; addr = vm_unmapped_area(&info); } @@ -151,6 +162,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, unsigned long task_size = STACK_TOP32; unsigned long addr = addr0; int do_color_align; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); struct vm_unmapped_area_info info; /* This should only ever run for 32-bit processes. */ @@ -160,7 +172,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && + if ((filp || (flags & MAP_SHARED)) && ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; @@ -173,6 +185,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (filp || (flags & MAP_SHARED)) do_color_align = 1; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + /* requesting a specific address */ if (addr) { if (do_color_align) @@ -181,8 +197,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 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; } @@ -192,6 +207,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.high_limit = mm->mmap_base; info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; info.align_offset = pgoff << PAGE_SHIFT; + info.threadstack_offset = offset; addr = vm_unmapped_area(&info); /* @@ -204,6 +220,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += mm->delta_mmap; +#endif + info.high_limit = STACK_TOP32; addr = vm_unmapped_area(&info); } @@ -260,10 +282,14 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u EXPORT_SYMBOL(get_fb_unmapped_area); /* Essentially the same as PowerPC. */ -static unsigned long mmap_rnd(void) +static unsigned long mmap_rnd(struct mm_struct *mm) { unsigned long rnd = 0UL; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (current->flags & PF_RANDOMIZE) { unsigned long val = get_random_int(); if (test_thread_flag(TIF_32BIT)) @@ -276,7 +302,7 @@ static unsigned long mmap_rnd(void) void arch_pick_mmap_layout(struct mm_struct *mm) { - unsigned long random_factor = mmap_rnd(); + unsigned long random_factor = mmap_rnd(mm); unsigned long gap; /* @@ -289,6 +315,12 @@ void arch_pick_mmap_layout(struct mm_struct *mm) gap == RLIM_INFINITY || sysctl_legacy_va_layout) { 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; mm->unmap_area = arch_unmap_area; } else { @@ -301,6 +333,12 @@ void arch_pick_mmap_layout(struct mm_struct *mm) gap = (task_size / 6 * 5); mm->mmap_base = PAGE_ALIGN(task_size - gap - 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; mm->unmap_area = arch_unmap_area_topdown; } diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 22a1098..6255eb9 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -52,7 +52,7 @@ sys32_rt_sigreturn: #endif .align 32 1: ldx [%g6 + TI_FLAGS], %l5 - andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + andcc %l5, _TIF_WORK_SYSCALL, %g0 be,pt %icc, rtrap nop call syscall_trace_leave @@ -184,7 +184,7 @@ linux_sparc_syscall32: srl %i5, 0, %o5 ! IEU1 srl %i2, 0, %o2 ! IEU0 Group - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + andcc %l0, _TIF_WORK_SYSCALL, %g0 bne,pn %icc, linux_syscall_trace32 ! CTI mov %i0, %l5 ! IEU1 call %l7 ! CTI Group brk forced @@ -207,7 +207,7 @@ linux_sparc_syscall: mov %i3, %o3 ! IEU1 mov %i4, %o4 ! IEU0 Group - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + andcc %l0, _TIF_WORK_SYSCALL, %g0 bne,pn %icc, linux_syscall_trace ! CTI Group mov %i0, %l5 ! IEU0 2: call %l7 ! CTI Group brk forced @@ -223,7 +223,7 @@ ret_sys_call: cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + andcc %l0, _TIF_WORK_SYSCALL, %g0 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc 2: diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index 654e8aa..45f431b 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -266,7 +266,7 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata sysfs_cpu_nb = { +static struct notifier_block sysfs_cpu_nb = { .notifier_call = sysfs_cpu_notify, }; diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c index 6629829..036032d 100644 --- a/arch/sparc/kernel/traps_32.c +++ b/arch/sparc/kernel/traps_32.c @@ -44,6 +44,8 @@ static void instruction_dump(unsigned long *pc) #define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t") #define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t") +extern void gr_handle_kernel_exploit(void); + void die_if_kernel(char *str, struct pt_regs *regs) { static int die_counter; @@ -76,15 +78,17 @@ void die_if_kernel(char *str, struct pt_regs *regs) count++ < 30 && (((unsigned long) rw) >= PAGE_OFFSET) && !(((unsigned long) rw) & 0x7)) { - printk("Caller[%08lx]: %pS\n", rw->ins[7], + printk("Caller[%08lx]: %pA\n", rw->ins[7], (void *) rw->ins[7]); rw = (struct reg_window32 *)rw->ins[6]; } } printk("Instruction DUMP:"); instruction_dump ((unsigned long *) regs->pc); - if(regs->psr & PSR_PS) + if(regs->psr & PSR_PS) { + gr_handle_kernel_exploit(); do_exit(SIGKILL); + } do_exit(SIGSEGV); } diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index b3f833a..f485f80 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -76,7 +76,7 @@ static void dump_tl1_traplog(struct tl1_traplog *p) i + 1, p->trapstack[i].tstate, p->trapstack[i].tpc, p->trapstack[i].tnpc, p->trapstack[i].tt); - printk("TRAPLOG: TPC<%pS>\n", (void *) p->trapstack[i].tpc); + printk("TRAPLOG: TPC<%pA>\n", (void *) p->trapstack[i].tpc); } } @@ -96,6 +96,12 @@ void bad_trap(struct pt_regs *regs, long lvl) lvl -= 0x100; if (regs->tstate & TSTATE_PRIV) { + +#ifdef CONFIG_PAX_REFCOUNT + if (lvl == 6) + pax_report_refcount_overflow(regs); +#endif + sprintf(buffer, "Kernel bad sw trap %lx", lvl); die_if_kernel(buffer, regs); } @@ -114,11 +120,16 @@ void bad_trap(struct pt_regs *regs, long lvl) void bad_trap_tl1(struct pt_regs *regs, long lvl) { char buffer[32]; - + if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs, 0, lvl, SIGTRAP) == NOTIFY_STOP) return; +#ifdef CONFIG_PAX_REFCOUNT + if (lvl == 6) + pax_report_refcount_overflow(regs); +#endif + dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); sprintf (buffer, "Bad trap %lx at tl>0", lvl); @@ -1142,7 +1153,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate); printk("%s" "ERROR(%d): ", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id()); - printk("TPC<%pS>\n", (void *) regs->tpc); + printk("TPC<%pA>\n", (void *) regs->tpc); printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, @@ -1749,7 +1760,7 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); - printk(KERN_EMERG "TPC<%pS>\n", (void *) regs->tpc); + printk(KERN_EMERG "TPC<%pA>\n", (void *) regs->tpc); panic("Irrecoverable Cheetah+ parity error."); } @@ -1757,7 +1768,7 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); - printk(KERN_WARNING "TPC<%pS>\n", (void *) regs->tpc); + printk(KERN_WARNING "TPC<%pA>\n", (void *) regs->tpc); } struct sun4v_error_entry { @@ -1830,8 +1841,8 @@ struct sun4v_error_entry { /*0x38*/u64 reserved_5; }; -static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0); -static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0); +static atomic_unchecked_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0); +static atomic_unchecked_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0); static const char *sun4v_err_type_to_str(u8 type) { @@ -1923,7 +1934,7 @@ static void sun4v_report_real_raddr(const char *pfx, struct pt_regs *regs) } static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, - int cpu, const char *pfx, atomic_t *ocnt) + int cpu, const char *pfx, atomic_unchecked_t *ocnt) { u64 *raw_ptr = (u64 *) ent; u32 attrs; @@ -1981,8 +1992,8 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, show_regs(regs); - if ((cnt = atomic_read(ocnt)) != 0) { - atomic_set(ocnt, 0); + if ((cnt = atomic_read_unchecked(ocnt)) != 0) { + atomic_set_unchecked(ocnt, 0); wmb(); printk("%s: Queue overflowed %d times.\n", pfx, cnt); @@ -2036,7 +2047,7 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset) */ void sun4v_resum_overflow(struct pt_regs *regs) { - atomic_inc(&sun4v_resum_oflow_cnt); + atomic_inc_unchecked(&sun4v_resum_oflow_cnt); } /* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate. @@ -2089,7 +2100,7 @@ void sun4v_nonresum_overflow(struct pt_regs *regs) /* XXX Actually even this can make not that much sense. Perhaps * XXX we should just pull the plug and panic directly from here? */ - atomic_inc(&sun4v_nonresum_oflow_cnt); + atomic_inc_unchecked(&sun4v_nonresum_oflow_cnt); } unsigned long sun4v_err_itlb_vaddr; @@ -2104,9 +2115,9 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); - printk(KERN_EMERG "SUN4V-ITLB: TPC<%pS>\n", (void *) regs->tpc); + printk(KERN_EMERG "SUN4V-ITLB: TPC<%pA>\n", (void *) regs->tpc); printk(KERN_EMERG "SUN4V-ITLB: O7[%lx]\n", regs->u_regs[UREG_I7]); - printk(KERN_EMERG "SUN4V-ITLB: O7<%pS>\n", + printk(KERN_EMERG "SUN4V-ITLB: O7<%pA>\n", (void *) regs->u_regs[UREG_I7]); printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", @@ -2128,9 +2139,9 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); - printk(KERN_EMERG "SUN4V-DTLB: TPC<%pS>\n", (void *) regs->tpc); + printk(KERN_EMERG "SUN4V-DTLB: TPC<%pA>\n", (void *) regs->tpc); printk(KERN_EMERG "SUN4V-DTLB: O7[%lx]\n", regs->u_regs[UREG_I7]); - printk(KERN_EMERG "SUN4V-DTLB: O7<%pS>\n", + printk(KERN_EMERG "SUN4V-DTLB: O7<%pA>\n", (void *) regs->u_regs[UREG_I7]); printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", @@ -2336,13 +2347,13 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) fp = (unsigned long)sf->fp + STACK_BIAS; } - printk(" [%016lx] %pS\n", pc, (void *) pc); + printk(" [%016lx] %pA\n", pc, (void *) pc); #ifdef CONFIG_FUNCTION_GRAPH_TRACER if ((pc + 8UL) == (unsigned long) &return_to_handler) { int index = tsk->curr_ret_stack; if (tsk->ret_stack && index >= graph) { pc = tsk->ret_stack[index - graph].ret; - printk(" [%016lx] %pS\n", pc, (void *) pc); + printk(" [%016lx] %pA\n", pc, (void *) pc); graph++; } } @@ -2360,6 +2371,8 @@ static inline struct reg_window *kernel_stack_up(struct reg_window *rw) return (struct reg_window *) (fp + STACK_BIAS); } +extern void gr_handle_kernel_exploit(void); + void die_if_kernel(char *str, struct pt_regs *regs) { static int die_counter; @@ -2388,7 +2401,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) while (rw && count++ < 30 && kstack_valid(tp, (unsigned long) rw)) { - printk("Caller[%016lx]: %pS\n", rw->ins[7], + printk("Caller[%016lx]: %pA\n", rw->ins[7], (void *) rw->ins[7]); rw = kernel_stack_up(rw); @@ -2401,8 +2414,10 @@ void die_if_kernel(char *str, struct pt_regs *regs) } user_instruction_dump ((unsigned int __user *) regs->tpc); } - if (regs->tstate & TSTATE_PRIV) + if (regs->tstate & TSTATE_PRIV) { + gr_handle_kernel_exploit(); do_exit(SIGKILL); + } do_exit(SIGSEGV); } EXPORT_SYMBOL(die_if_kernel); diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index 8201c25e..072a2a7 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -286,7 +286,7 @@ static void log_unaligned(struct pt_regs *regs) static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5); if (__ratelimit(&ratelimit)) { - printk("Kernel unaligned access at TPC[%lx] %pS\n", + printk("Kernel unaligned access at TPC[%lx] %pA\n", regs->tpc, (void *) regs->tpc); } } diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index dbe119b..089c7c1 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -2,7 +2,7 @@ # asflags-y := -ansi -DST_DIV0=0x02 -ccflags-y := -Werror +#ccflags-y := -Werror lib-$(CONFIG_SPARC32) += ashrdi3.o lib-$(CONFIG_SPARC32) += memcpy.o memset.o diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S index 85c233d..68500e0 100644 --- a/arch/sparc/lib/atomic_64.S +++ b/arch/sparc/lib/atomic_64.S @@ -17,7 +17,12 @@ ENTRY(atomic_add) /* %o0 = increment, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: lduw [%o1], %g1 - add %g1, %o0, %g7 + addcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %icc, 6 +#endif + cas [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %icc, BACKOFF_LABEL(2f, 1b) @@ -27,10 +32,28 @@ ENTRY(atomic_add) /* %o0 = increment, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic_add) +ENTRY(atomic_add_unchecked) /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: lduw [%o1], %g1 + add %g1, %o0, %g7 + cas [%o1], %g1, %g7 + cmp %g1, %g7 + bne,pn %icc, 2f + nop + retl + nop +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic_add_unchecked) + ENTRY(atomic_sub) /* %o0 = decrement, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: lduw [%o1], %g1 - sub %g1, %o0, %g7 + subcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %icc, 6 +#endif + cas [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %icc, BACKOFF_LABEL(2f, 1b) @@ -40,10 +63,28 @@ ENTRY(atomic_sub) /* %o0 = decrement, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic_sub) +ENTRY(atomic_sub_unchecked) /* %o0 = decrement, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: lduw [%o1], %g1 + sub %g1, %o0, %g7 + cas [%o1], %g1, %g7 + cmp %g1, %g7 + bne,pn %icc, 2f + nop + retl + nop +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic_sub_unchecked) + ENTRY(atomic_add_ret) /* %o0 = increment, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: lduw [%o1], %g1 - add %g1, %o0, %g7 + addcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %icc, 6 +#endif + cas [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %icc, BACKOFF_LABEL(2f, 1b) @@ -53,10 +94,29 @@ ENTRY(atomic_add_ret) /* %o0 = increment, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic_add_ret) +ENTRY(atomic_add_ret_unchecked) /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: lduw [%o1], %g1 + addcc %g1, %o0, %g7 + cas [%o1], %g1, %g7 + cmp %g1, %g7 + bne,pn %icc, 2f + add %g7, %o0, %g7 + sra %g7, 0, %o0 + retl + nop +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic_add_ret_unchecked) + ENTRY(atomic_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: lduw [%o1], %g1 - sub %g1, %o0, %g7 + subcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %icc, 6 +#endif + cas [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %icc, BACKOFF_LABEL(2f, 1b) @@ -69,7 +129,12 @@ ENDPROC(atomic_sub_ret) ENTRY(atomic64_add) /* %o0 = increment, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: ldx [%o1], %g1 - add %g1, %o0, %g7 + addcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %xcc, 6 +#endif + casx [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) @@ -79,10 +144,28 @@ ENTRY(atomic64_add) /* %o0 = increment, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic64_add) +ENTRY(atomic64_add_unchecked) /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: ldx [%o1], %g1 + addcc %g1, %o0, %g7 + casx [%o1], %g1, %g7 + cmp %g1, %g7 + bne,pn %xcc, 2f + nop + retl + nop +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic64_add_unchecked) + ENTRY(atomic64_sub) /* %o0 = decrement, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: ldx [%o1], %g1 - sub %g1, %o0, %g7 + subcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %xcc, 6 +#endif + casx [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) @@ -92,10 +175,28 @@ ENTRY(atomic64_sub) /* %o0 = decrement, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic64_sub) +ENTRY(atomic64_sub_unchecked) /* %o0 = decrement, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: ldx [%o1], %g1 + subcc %g1, %o0, %g7 + casx [%o1], %g1, %g7 + cmp %g1, %g7 + bne,pn %xcc, 2f + nop + retl + nop +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic64_sub_unchecked) + ENTRY(atomic64_add_ret) /* %o0 = increment, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: ldx [%o1], %g1 - add %g1, %o0, %g7 + addcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %xcc, 6 +#endif + casx [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) @@ -105,10 +206,29 @@ ENTRY(atomic64_add_ret) /* %o0 = increment, %o1 = atomic_ptr */ 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic64_add_ret) +ENTRY(atomic64_add_ret_unchecked) /* %o0 = increment, %o1 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: ldx [%o1], %g1 + addcc %g1, %o0, %g7 + casx [%o1], %g1, %g7 + cmp %g1, %g7 + bne,pn %xcc, 2f + add %g7, %o0, %g7 + mov %g7, %o0 + retl + nop +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic64_add_ret_unchecked) + ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */ BACKOFF_SETUP(%o2) 1: ldx [%o1], %g1 - sub %g1, %o0, %g7 + subcc %g1, %o0, %g7 + +#ifdef CONFIG_PAX_REFCOUNT + tvs %xcc, 6 +#endif + casx [%o1], %g1, %g7 cmp %g1, %g7 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c index 0c4e35e..745d3e4 100644 --- a/arch/sparc/lib/ksyms.c +++ b/arch/sparc/lib/ksyms.c @@ -109,12 +109,18 @@ EXPORT_SYMBOL(__downgrade_write); /* Atomic counter implementation. */ EXPORT_SYMBOL(atomic_add); +EXPORT_SYMBOL(atomic_add_unchecked); EXPORT_SYMBOL(atomic_add_ret); +EXPORT_SYMBOL(atomic_add_ret_unchecked); EXPORT_SYMBOL(atomic_sub); +EXPORT_SYMBOL(atomic_sub_unchecked); EXPORT_SYMBOL(atomic_sub_ret); EXPORT_SYMBOL(atomic64_add); +EXPORT_SYMBOL(atomic64_add_unchecked); EXPORT_SYMBOL(atomic64_add_ret); +EXPORT_SYMBOL(atomic64_add_ret_unchecked); EXPORT_SYMBOL(atomic64_sub); +EXPORT_SYMBOL(atomic64_sub_unchecked); EXPORT_SYMBOL(atomic64_sub_ret); EXPORT_SYMBOL(atomic64_dec_if_positive); diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 30c3ecc..736f015 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -2,7 +2,7 @@ # asflags-y := -ansi -ccflags-y := -Werror +#ccflags-y := -Werror obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o obj-y += fault_$(BITS).o diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index e98bfda..ea8d221 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #include #include @@ -159,6 +162,277 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) return safe_compute_effective_address(regs, insn); } +#ifdef CONFIG_PAX_PAGEEXEC +#ifdef CONFIG_PAX_DLRESOLVE +static void pax_emuplt_close(struct vm_area_struct *vma) +{ + vma->vm_mm->call_dl_resolve = 0UL; +} + +static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + unsigned int *kaddr; + + vmf->page = alloc_page(GFP_HIGHUSER); + if (!vmf->page) + return VM_FAULT_OOM; + + kaddr = kmap(vmf->page); + memset(kaddr, 0, PAGE_SIZE); + kaddr[0] = 0x9DE3BFA8U; /* save */ + flush_dcache_page(vmf->page); + kunmap(vmf->page); + return VM_FAULT_MAJOR; +} + +static const struct vm_operations_struct pax_vm_ops = { + .close = pax_emuplt_close, + .fault = pax_emuplt_fault +}; + +static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) +{ + int ret; + + INIT_LIST_HEAD(&vma->anon_vma_chain); + vma->vm_mm = current->mm; + vma->vm_start = addr; + vma->vm_end = addr + PAGE_SIZE; + vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &pax_vm_ops; + + ret = insert_vm_struct(current->mm, vma); + if (ret) + return ret; + + ++current->mm->total_vm; + return 0; +} +#endif + +/* + * 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 sethi1, sethi2, jmpl; + + err = get_user(sethi1, (unsigned int *)regs->pc); + err |= get_user(sethi2, (unsigned int *)(regs->pc+4)); + err |= get_user(jmpl, (unsigned int *)(regs->pc+8)); + + if (err) + break; + + if ((sethi1 & 0xFFC00000U) == 0x03000000U && + (sethi2 & 0xFFC00000U) == 0x03000000U && + (jmpl & 0xFFFFE000U) == 0x81C06000U) + { + unsigned int addr; + + regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; + addr = regs->u_regs[UREG_G1]; + addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); + regs->pc = addr; + regs->npc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #2 */ + unsigned int ba; + + err = get_user(ba, (unsigned int *)regs->pc); + + if (err) + break; + + if ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30480000U) { + unsigned int addr; + + if ((ba & 0xFFC00000U) == 0x30800000U) + addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); + else + addr = regs->pc + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); + regs->pc = addr; + regs->npc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #3 */ + unsigned int sethi, bajmpl, nop; + + err = get_user(sethi, (unsigned int *)regs->pc); + err |= get_user(bajmpl, (unsigned int *)(regs->pc+4)); + err |= get_user(nop, (unsigned int *)(regs->pc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + ((bajmpl & 0xFFFFE000U) == 0x81C06000U || (bajmpl & 0xFFF80000U) == 0x30480000U) && + nop == 0x01000000U) + { + unsigned int addr; + + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; + if ((bajmpl & 0xFFFFE000U) == 0x81C06000U) + addr += (((bajmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); + else + addr = regs->pc + ((((bajmpl | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); + regs->pc = addr; + regs->npc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: unpatched PLT emulation step 1 */ + unsigned int sethi, ba, nop; + + err = get_user(sethi, (unsigned int *)regs->pc); + err |= get_user(ba, (unsigned int *)(regs->pc+4)); + err |= get_user(nop, (unsigned int *)(regs->pc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && + nop == 0x01000000U) + { + unsigned int addr, save, call; + + if ((ba & 0xFFC00000U) == 0x30800000U) + addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); + else + addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); + + err = get_user(save, (unsigned int *)addr); + err |= get_user(call, (unsigned int *)(addr+4)); + err |= get_user(nop, (unsigned int *)(addr+8)); + if (err) + break; + +#ifdef CONFIG_PAX_DLRESOLVE + if (save == 0x9DE3BFA8U && + (call & 0xC0000000U) == 0x40000000U && + nop == 0x01000000U) + { + struct vm_area_struct *vma; + unsigned long call_dl_resolve; + + down_read(¤t->mm->mmap_sem); + call_dl_resolve = current->mm->call_dl_resolve; + up_read(¤t->mm->mmap_sem); + if (likely(call_dl_resolve)) + goto emulate; + + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); + + down_write(¤t->mm->mmap_sem); + if (current->mm->call_dl_resolve) { + call_dl_resolve = current->mm->call_dl_resolve; + up_write(¤t->mm->mmap_sem); + if (vma) + kmem_cache_free(vm_area_cachep, vma); + goto emulate; + } + + call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); + if (!vma || (call_dl_resolve & ~PAGE_MASK)) { + up_write(¤t->mm->mmap_sem); + if (vma) + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + if (pax_insert_vma(vma, call_dl_resolve)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + current->mm->call_dl_resolve = call_dl_resolve; + up_write(¤t->mm->mmap_sem); + +emulate: + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; + regs->pc = call_dl_resolve; + regs->npc = addr+4; + return 3; + } +#endif + + /* PaX: glibc 2.4+ generates sethi/jmpl instead of save/call */ + if ((save & 0xFFC00000U) == 0x05000000U && + (call & 0xFFFFE000U) == 0x85C0A000U && + nop == 0x01000000U) + { + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G2] = addr + 4; + addr = (save & 0x003FFFFFU) << 10; + addr += (((call | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); + regs->pc = addr; + regs->npc = addr+4; + return 3; + } + } + } while (0); + + do { /* PaX: unpatched PLT emulation step 2 */ + unsigned int save, call, nop; + + err = get_user(save, (unsigned int *)(regs->pc-4)); + err |= get_user(call, (unsigned int *)regs->pc); + err |= get_user(nop, (unsigned int *)(regs->pc+4)); + if (err) + break; + + if (save == 0x9DE3BFA8U && + (call & 0xC0000000U) == 0x40000000U && + nop == 0x01000000U) + { + unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2); + + regs->u_regs[UREG_RETPC] = regs->pc; + regs->pc = dl_resolve; + regs->npc = dl_resolve+4; + 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 < 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 + static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs, int text_fault) { @@ -230,6 +504,24 @@ good_area: if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { + +#ifdef CONFIG_PAX_PAGEEXEC + if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) { + 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 *)regs->u_regs[UREG_FP]); + do_group_exit(SIGKILL); + } +#endif + /* Allow reads even for write-only mappings */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 5062ff3..e0b75f3 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #include #include @@ -74,7 +77,7 @@ static void __kprobes bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr) printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", regs->tpc); printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]); - printk("OOPS: RPC <%pS>\n", (void *) regs->u_regs[15]); + printk("OOPS: RPC <%pA>\n", (void *) regs->u_regs[15]); printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr); dump_stack(); unhandled_fault(regs->tpc, current, regs); @@ -270,6 +273,466 @@ static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, show_regs(regs); } +#ifdef CONFIG_PAX_PAGEEXEC +#ifdef CONFIG_PAX_DLRESOLVE +static void pax_emuplt_close(struct vm_area_struct *vma) +{ + vma->vm_mm->call_dl_resolve = 0UL; +} + +static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + unsigned int *kaddr; + + vmf->page = alloc_page(GFP_HIGHUSER); + if (!vmf->page) + return VM_FAULT_OOM; + + kaddr = kmap(vmf->page); + memset(kaddr, 0, PAGE_SIZE); + kaddr[0] = 0x9DE3BFA8U; /* save */ + flush_dcache_page(vmf->page); + kunmap(vmf->page); + return VM_FAULT_MAJOR; +} + +static const struct vm_operations_struct pax_vm_ops = { + .close = pax_emuplt_close, + .fault = pax_emuplt_fault +}; + +static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) +{ + int ret; + + INIT_LIST_HEAD(&vma->anon_vma_chain); + vma->vm_mm = current->mm; + vma->vm_start = addr; + vma->vm_end = addr + PAGE_SIZE; + vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &pax_vm_ops; + + ret = insert_vm_struct(current->mm, vma); + if (ret) + return ret; + + ++current->mm->total_vm; + return 0; +} +#endif + +/* + * PaX: decide what to do with offenders (regs->tpc = 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 sethi1, sethi2, jmpl; + + err = get_user(sethi1, (unsigned int *)regs->tpc); + err |= get_user(sethi2, (unsigned int *)(regs->tpc+4)); + err |= get_user(jmpl, (unsigned int *)(regs->tpc+8)); + + if (err) + break; + + if ((sethi1 & 0xFFC00000U) == 0x03000000U && + (sethi2 & 0xFFC00000U) == 0x03000000U && + (jmpl & 0xFFFFE000U) == 0x81C06000U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; + addr = regs->u_regs[UREG_G1]; + addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #2 */ + unsigned int ba; + + err = get_user(ba, (unsigned int *)regs->tpc); + + if (err) + break; + + if ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30480000U) { + unsigned long addr; + + if ((ba & 0xFFC00000U) == 0x30800000U) + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); + else + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #3 */ + unsigned int sethi, bajmpl, nop; + + err = get_user(sethi, (unsigned int *)regs->tpc); + err |= get_user(bajmpl, (unsigned int *)(regs->tpc+4)); + err |= get_user(nop, (unsigned int *)(regs->tpc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + ((bajmpl & 0xFFFFE000U) == 0x81C06000U || (bajmpl & 0xFFF80000U) == 0x30480000U) && + nop == 0x01000000U) + { + unsigned long addr; + + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; + if ((bajmpl & 0xFFFFE000U) == 0x81C06000U) + addr += (((bajmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); + else + addr = regs->tpc + ((((bajmpl | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #4 */ + unsigned int sethi, mov1, call, mov2; + + err = get_user(sethi, (unsigned int *)regs->tpc); + err |= get_user(mov1, (unsigned int *)(regs->tpc+4)); + err |= get_user(call, (unsigned int *)(regs->tpc+8)); + err |= get_user(mov2, (unsigned int *)(regs->tpc+12)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + mov1 == 0x8210000FU && + (call & 0xC0000000U) == 0x40000000U && + mov2 == 0x9E100001U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC]; + addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #5 */ + unsigned int sethi, sethi1, sethi2, or1, or2, sllx, jmpl, nop; + + err = get_user(sethi, (unsigned int *)regs->tpc); + err |= get_user(sethi1, (unsigned int *)(regs->tpc+4)); + err |= get_user(sethi2, (unsigned int *)(regs->tpc+8)); + err |= get_user(or1, (unsigned int *)(regs->tpc+12)); + err |= get_user(or2, (unsigned int *)(regs->tpc+16)); + err |= get_user(sllx, (unsigned int *)(regs->tpc+20)); + err |= get_user(jmpl, (unsigned int *)(regs->tpc+24)); + err |= get_user(nop, (unsigned int *)(regs->tpc+28)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + (sethi1 & 0xFFC00000U) == 0x03000000U && + (sethi2 & 0xFFC00000U) == 0x0B000000U && + (or1 & 0xFFFFE000U) == 0x82106000U && + (or2 & 0xFFFFE000U) == 0x8A116000U && + sllx == 0x83287020U && + jmpl == 0x81C04005U && + nop == 0x01000000U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU); + regs->u_regs[UREG_G1] <<= 32; + regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU); + addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #6 */ + unsigned int sethi, sethi1, sethi2, sllx, or, jmpl, nop; + + err = get_user(sethi, (unsigned int *)regs->tpc); + err |= get_user(sethi1, (unsigned int *)(regs->tpc+4)); + err |= get_user(sethi2, (unsigned int *)(regs->tpc+8)); + err |= get_user(sllx, (unsigned int *)(regs->tpc+12)); + err |= get_user(or, (unsigned int *)(regs->tpc+16)); + err |= get_user(jmpl, (unsigned int *)(regs->tpc+20)); + err |= get_user(nop, (unsigned int *)(regs->tpc+24)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + (sethi1 & 0xFFC00000U) == 0x03000000U && + (sethi2 & 0xFFC00000U) == 0x0B000000U && + sllx == 0x83287020U && + (or & 0xFFFFE000U) == 0x8A116000U && + jmpl == 0x81C04005U && + nop == 0x01000000U) + { + unsigned long addr; + + regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] <<= 32; + regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU); + addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } while (0); + + do { /* PaX: unpatched PLT emulation step 1 */ + unsigned int sethi, ba, nop; + + err = get_user(sethi, (unsigned int *)regs->tpc); + err |= get_user(ba, (unsigned int *)(regs->tpc+4)); + err |= get_user(nop, (unsigned int *)(regs->tpc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && + nop == 0x01000000U) + { + unsigned long addr; + unsigned int save, call; + unsigned int sethi1, sethi2, or1, or2, sllx, add, jmpl; + + if ((ba & 0xFFC00000U) == 0x30800000U) + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); + else + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + err = get_user(save, (unsigned int *)addr); + err |= get_user(call, (unsigned int *)(addr+4)); + err |= get_user(nop, (unsigned int *)(addr+8)); + if (err) + break; + +#ifdef CONFIG_PAX_DLRESOLVE + if (save == 0x9DE3BFA8U && + (call & 0xC0000000U) == 0x40000000U && + nop == 0x01000000U) + { + struct vm_area_struct *vma; + unsigned long call_dl_resolve; + + down_read(¤t->mm->mmap_sem); + call_dl_resolve = current->mm->call_dl_resolve; + up_read(¤t->mm->mmap_sem); + if (likely(call_dl_resolve)) + goto emulate; + + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); + + down_write(¤t->mm->mmap_sem); + if (current->mm->call_dl_resolve) { + call_dl_resolve = current->mm->call_dl_resolve; + up_write(¤t->mm->mmap_sem); + if (vma) + kmem_cache_free(vm_area_cachep, vma); + goto emulate; + } + + call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); + if (!vma || (call_dl_resolve & ~PAGE_MASK)) { + up_write(¤t->mm->mmap_sem); + if (vma) + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + if (pax_insert_vma(vma, call_dl_resolve)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + current->mm->call_dl_resolve = call_dl_resolve; + up_write(¤t->mm->mmap_sem); + +emulate: + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; + regs->tpc = call_dl_resolve; + regs->tnpc = addr+4; + return 3; + } +#endif + + /* PaX: glibc 2.4+ generates sethi/jmpl instead of save/call */ + if ((save & 0xFFC00000U) == 0x05000000U && + (call & 0xFFFFE000U) == 0x85C0A000U && + nop == 0x01000000U) + { + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G2] = addr + 4; + addr = (save & 0x003FFFFFU) << 10; + addr += (((call | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + regs->tpc = addr; + regs->tnpc = addr+4; + return 3; + } + + /* PaX: 64-bit PLT stub */ + err = get_user(sethi1, (unsigned int *)addr); + err |= get_user(sethi2, (unsigned int *)(addr+4)); + err |= get_user(or1, (unsigned int *)(addr+8)); + err |= get_user(or2, (unsigned int *)(addr+12)); + err |= get_user(sllx, (unsigned int *)(addr+16)); + err |= get_user(add, (unsigned int *)(addr+20)); + err |= get_user(jmpl, (unsigned int *)(addr+24)); + err |= get_user(nop, (unsigned int *)(addr+28)); + if (err) + break; + + if ((sethi1 & 0xFFC00000U) == 0x09000000U && + (sethi2 & 0xFFC00000U) == 0x0B000000U && + (or1 & 0xFFFFE000U) == 0x88112000U && + (or2 & 0xFFFFE000U) == 0x8A116000U && + sllx == 0x89293020U && + add == 0x8A010005U && + jmpl == 0x89C14000U && + nop == 0x01000000U) + { + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G4] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU); + regs->u_regs[UREG_G4] <<= 32; + regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU); + regs->u_regs[UREG_G5] += regs->u_regs[UREG_G4]; + regs->u_regs[UREG_G4] = addr + 24; + addr = regs->u_regs[UREG_G5]; + regs->tpc = addr; + regs->tnpc = addr+4; + return 3; + } + } + } while (0); + +#ifdef CONFIG_PAX_DLRESOLVE + do { /* PaX: unpatched PLT emulation step 2 */ + unsigned int save, call, nop; + + err = get_user(save, (unsigned int *)(regs->tpc-4)); + err |= get_user(call, (unsigned int *)regs->tpc); + err |= get_user(nop, (unsigned int *)(regs->tpc+4)); + if (err) + break; + + if (save == 0x9DE3BFA8U && + (call & 0xC0000000U) == 0x40000000U && + nop == 0x01000000U) + { + unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + dl_resolve &= 0xFFFFFFFFUL; + + regs->u_regs[UREG_RETPC] = regs->tpc; + regs->tpc = dl_resolve; + regs->tnpc = dl_resolve+4; + return 3; + } + } while (0); +#endif + + do { /* PaX: patched PLT emulation #7, must be AFTER the unpatched PLT emulation */ + unsigned int sethi, ba, nop; + + err = get_user(sethi, (unsigned int *)regs->tpc); + err |= get_user(ba, (unsigned int *)(regs->tpc+4)); + err |= get_user(nop, (unsigned int *)(regs->tpc+8)); + + if (err) + break; + + if ((sethi & 0xFFC00000U) == 0x03000000U && + (ba & 0xFFF00000U) == 0x30600000U && + nop == 0x01000000U) + { + unsigned long addr; + + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + + if (test_thread_flag(TIF_32BIT)) + addr &= 0xFFFFFFFFUL; + + regs->tpc = addr; + regs->tnpc = addr+4; + return 2; + } + } 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 < 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 + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; @@ -341,6 +804,29 @@ retry: if (!vma) goto bad_area; +#ifdef CONFIG_PAX_PAGEEXEC + /* PaX: detect ITLB misses on non-exec pages */ + if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address && + !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB)) + { + if (address != regs->tpc) + goto good_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->tpc, (void *)(regs->u_regs[UREG_FP] + STACK_BIAS)); + do_group_exit(SIGKILL); + } +#endif + /* Pure DTLB misses do not tell us whether the fault causing * load/store/atomic was a write or not, it only says that there * was no match. So in such a case we (carefully) read the diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index d2b5944..d878f3c 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c @@ -28,7 +28,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) + unsigned long flags, + unsigned long offset) { unsigned long task_size = TASK_SIZE; struct vm_unmapped_area_info info; @@ -38,15 +39,22 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, info.flags = 0; info.length = len; - info.low_limit = TASK_UNMAPPED_BASE; + info.low_limit = mm->mmap_base; info.high_limit = min(task_size, VA_EXCLUDE_START); info.align_mask = PAGE_MASK & ~HPAGE_MASK; info.align_offset = 0; + info.threadstack_offset = offset; addr = vm_unmapped_area(&info); if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) { VM_BUG_ON(addr != -ENOMEM); info.low_limit = VA_EXCLUDE_END; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += mm->delta_mmap; +#endif + info.high_limit = task_size; addr = vm_unmapped_area(&info); } @@ -58,7 +66,8 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, const unsigned long len, const unsigned long pgoff, - const unsigned long flags) + const unsigned long flags, + const unsigned long offset) { struct mm_struct *mm = current->mm; unsigned long addr = addr0; @@ -73,6 +82,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.high_limit = mm->mmap_base; info.align_mask = PAGE_MASK & ~HPAGE_MASK; info.align_offset = 0; + info.threadstack_offset = offset; addr = vm_unmapped_area(&info); /* @@ -85,6 +95,12 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += mm->delta_mmap; +#endif + info.high_limit = STACK_TOP32; addr = vm_unmapped_area(&info); } @@ -99,6 +115,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long task_size = TASK_SIZE; + unsigned long offset = gr_rand_threadstack_offset(mm, file, flags); if (test_thread_flag(TIF_32BIT)) task_size = STACK_TOP32; @@ -114,19 +131,22 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, return addr; } +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { addr = ALIGN(addr, HPAGE_SIZE); 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; } if (mm->get_unmapped_area == arch_get_unmapped_area) return hugetlb_get_unmapped_area_bottomup(file, addr, len, - pgoff, flags); + pgoff, flags, offset); else return hugetlb_get_unmapped_area_topdown(file, addr, len, - pgoff, flags); + pgoff, flags, offset); } pte_t *huge_pte_alloc(struct mm_struct *mm, diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 04fd55a..4ede686 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -188,9 +188,9 @@ unsigned long sparc64_kern_sec_context __read_mostly; int num_kernel_image_mappings; #ifdef CONFIG_DEBUG_DCFLUSH -atomic_t dcpage_flushes = ATOMIC_INIT(0); +atomic_unchecked_t dcpage_flushes = ATOMIC_INIT(0); #ifdef CONFIG_SMP -atomic_t dcpage_flushes_xcall = ATOMIC_INIT(0); +atomic_unchecked_t dcpage_flushes_xcall = ATOMIC_INIT(0); #endif #endif @@ -198,7 +198,7 @@ inline void flush_dcache_page_impl(struct page *page) { BUG_ON(tlb_type == hypervisor); #ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); + atomic_inc_unchecked(&dcpage_flushes); #endif #ifdef DCACHE_ALIASING_POSSIBLE @@ -466,10 +466,10 @@ void mmu_info(struct seq_file *m) #ifdef CONFIG_DEBUG_DCFLUSH seq_printf(m, "DCPageFlushes\t: %d\n", - atomic_read(&dcpage_flushes)); + atomic_read_unchecked(&dcpage_flushes)); #ifdef CONFIG_SMP seq_printf(m, "DCPageFlushesXC\t: %d\n", - atomic_read(&dcpage_flushes_xcall)); + atomic_read_unchecked(&dcpage_flushes_xcall)); #endif /* CONFIG_SMP */ #endif /* CONFIG_DEBUG_DCFLUSH */ } diff --git a/arch/tile/include/asm/atomic_64.h b/arch/tile/include/asm/atomic_64.h index f4500c6..889656c 100644 --- a/arch/tile/include/asm/atomic_64.h +++ b/arch/tile/include/asm/atomic_64.h @@ -143,6 +143,16 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +#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)) + /* Atomic dec and inc don't implement barrier, so provide them if needed. */ #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() diff --git a/arch/tile/include/asm/cache.h b/arch/tile/include/asm/cache.h index a9a5299..0fce79e 100644 --- a/arch/tile/include/asm/cache.h +++ b/arch/tile/include/asm/cache.h @@ -15,11 +15,12 @@ #ifndef _ASM_TILE_CACHE_H #define _ASM_TILE_CACHE_H +#include #include /* bytes per L1 data cache line */ #define L1_CACHE_SHIFT CHIP_L1D_LOG_LINE_SIZE() -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) /* bytes per L2 cache line */ #define L2_CACHE_SHIFT CHIP_L2_LOG_LINE_SIZE() diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h index 8a082bc..7a6bf87 100644 --- a/arch/tile/include/asm/uaccess.h +++ b/arch/tile/include/asm/uaccess.h @@ -408,9 +408,9 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { - int sz = __compiletime_object_size(to); + size_t sz = __compiletime_object_size(to); - if (likely(sz == -1 || sz >= n)) + if (likely(sz == (size_t)-1 || sz >= n)) n = _copy_from_user(to, from, n); else copy_from_user_overflow(); diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c index 650ccff..45fe2d6 100644 --- a/arch/tile/mm/hugetlbpage.c +++ b/arch/tile/mm/hugetlbpage.c @@ -239,6 +239,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, info.high_limit = TASK_SIZE; info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; + info.threadstack_offset = 0; return vm_unmapped_area(&info); } @@ -256,6 +257,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, info.high_limit = current->mm->mmap_base; info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; + info.threadstack_offset = 0; addr = vm_unmapped_area(&info); /* diff --git a/arch/um/Makefile b/arch/um/Makefile index 133f7de..1d6f2f1 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -62,6 +62,10 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include +ifdef CONSTIFY_PLUGIN +USER_CFLAGS += -fplugin-arg-constify_plugin-no-constify +endif + #This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) diff --git a/arch/um/defconfig b/arch/um/defconfig index 08107a7..ab22afe 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig @@ -51,7 +51,6 @@ CONFIG_X86_CMPXCHG=y CONFIG_X86_L1_CACHE_SHIFT=5 CONFIG_X86_XADD=y CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_WP_WORKS_OK=y CONFIG_X86_INVLPG=y CONFIG_X86_BSWAP=y CONFIG_X86_POPAD_OK=y diff --git a/arch/um/include/asm/cache.h b/arch/um/include/asm/cache.h index 19e1bdd..3665b77 100644 --- a/arch/um/include/asm/cache.h +++ b/arch/um/include/asm/cache.h @@ -1,6 +1,7 @@ #ifndef __UM_CACHE_H #define __UM_CACHE_H +#include #if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT) # define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) @@ -12,6 +13,6 @@ # define L1_CACHE_SHIFT 5 #endif -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) #endif diff --git a/arch/um/include/asm/kmap_types.h b/arch/um/include/asm/kmap_types.h index 2e0a6b1..a64d0f5 100644 --- a/arch/um/include/asm/kmap_types.h +++ b/arch/um/include/asm/kmap_types.h @@ -8,6 +8,6 @@ /* No more #include "asm/arch/kmap_types.h" ! */ -#define KM_TYPE_NR 14 +#define KM_TYPE_NR 15 #endif diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h index 5ff53d9..5850cdf 100644 --- a/arch/um/include/asm/page.h +++ b/arch/um/include/asm/page.h @@ -14,6 +14,9 @@ #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) +#define ktla_ktva(addr) (addr) +#define ktva_ktla(addr) (addr) + #ifndef __ASSEMBLY__ struct page; diff --git a/arch/um/include/asm/pgtable-3level.h b/arch/um/include/asm/pgtable-3level.h index 0032f92..cd151e0 100644 --- a/arch/um/include/asm/pgtable-3level.h +++ b/arch/um/include/asm/pgtable-3level.h @@ -58,6 +58,7 @@ #define pud_present(x) (pud_val(x) & _PAGE_PRESENT) #define pud_populate(mm, pud, pmd) \ set_pud(pud, __pud(_PAGE_TABLE + __pa(pmd))) +#define pud_populate_kernel(mm, pud, pmd) pud_populate((mm), (pud), (pmd)) #ifdef CONFIG_64BIT #define set_pud(pudptr, pudval) set_64bit((u64 *) (pudptr), pud_val(pudval)) diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index bbcef52..6a2a483 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -367,22 +367,6 @@ int singlestepping(void * t) return 2; } -/* - * Only x86 and x86_64 have an arch_align_stack(). - * All other arches have "#define arch_align_stack(x) (x)" - * in their asm/system.h - * As this is included in UML from asm-um/system-generic.h, - * we can use it to behave as the subarch does. - */ -#ifndef arch_align_stack -unsigned long arch_align_stack(unsigned long sp) -{ - if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) - sp -= get_random_int() % 8192; - return sp & ~0xf; -} -#endif - unsigned long get_wchan(struct task_struct *p) { unsigned long stack_page, sp, ip; diff --git a/arch/unicore32/include/asm/cache.h b/arch/unicore32/include/asm/cache.h index ad8f795..2c7eec6 100644 --- a/arch/unicore32/include/asm/cache.h +++ b/arch/unicore32/include/asm/cache.h @@ -12,8 +12,10 @@ #ifndef __UNICORE_CACHE_H__ #define __UNICORE_CACHE_H__ -#define L1_CACHE_SHIFT (5) -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#include + +#define L1_CACHE_SHIFT 5 +#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/x86/Kconfig b/arch/x86/Kconfig index fe120da..24177f7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -239,7 +239,7 @@ config X86_HT config X86_32_LAZY_GS def_bool y - depends on X86_32 && !CC_STACKPROTECTOR + depends on X86_32 && !CC_STACKPROTECTOR && !PAX_MEMORY_UDEREF config ARCH_HWEIGHT_CFLAGS string @@ -1073,6 +1073,7 @@ config MICROCODE_EARLY config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" + depends on !GRKERNSEC_KMEM ---help--- This device gives privileged processes access to the x86 Model-Specific Registers (MSRs). It is a character device with @@ -1096,7 +1097,7 @@ choice config NOHIGHMEM bool "off" - depends on !X86_NUMAQ + depends on !X86_NUMAQ && !(PAX_PAGEEXEC && PAX_ENABLE_PAE) ---help--- Linux can use up to 64 Gigabytes of physical memory on x86 systems. However, the address space of 32-bit x86 processors is only 4 @@ -1133,7 +1134,7 @@ config NOHIGHMEM config HIGHMEM4G bool "4GB" - depends on !X86_NUMAQ + depends on !X86_NUMAQ && !(PAX_PAGEEXEC && PAX_ENABLE_PAE) ---help--- Select this if you have a 32-bit processor and between 1 and 4 gigabytes of physical RAM. @@ -1186,7 +1187,7 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT default 0x80000000 if VMSPLIT_2G - default 0x78000000 if VMSPLIT_2G_OPT + default 0x70000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000 depends on X86_32 @@ -1584,6 +1585,7 @@ config SECCOMP config CC_STACKPROTECTOR bool "Enable -fstack-protector buffer overflow detection" + depends on X86_64 || !PAX_MEMORY_UDEREF ---help--- This option turns on the -fstack-protector GCC feature. This feature puts, at the beginning of functions, a canary value on @@ -1703,6 +1705,8 @@ config X86_NEED_RELOCS config PHYSICAL_ALIGN hex "Alignment value to which kernel should be aligned" if X86_32 default "0x1000000" + range 0x200000 0x1000000 if PAX_KERNEXEC && X86_PAE + range 0x400000 0x1000000 if PAX_KERNEXEC && !X86_PAE range 0x2000 0x1000000 ---help--- This value puts the alignment restrictions on physical address @@ -1778,9 +1782,10 @@ config DEBUG_HOTPLUG_CPU0 If unsure, say N. config COMPAT_VDSO - def_bool y + def_bool n prompt "Compat VDSO support" depends on X86_32 || IA32_EMULATION + depends on !PAX_PAGEEXEC && !PAX_SEGMEXEC && !PAX_KERNEXEC && !PAX_MEMORY_UDEREF ---help--- Map the 32-bit VDSO to the predictable old-style address too. diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index c026cca..14657ae 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -319,7 +319,7 @@ config X86_PPRO_FENCE config X86_F00F_BUG def_bool y - depends on M586MMX || M586TSC || M586 || M486 + depends on (M586MMX || M586TSC || M586 || M486) && !PAX_KERNEXEC config X86_INVD_BUG def_bool y @@ -327,7 +327,7 @@ config X86_INVD_BUG config X86_ALIGNMENT_16 def_bool y - depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 + depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MCORE2 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 config X86_INTEL_USERCOPY def_bool y @@ -373,7 +373,7 @@ config X86_CMPXCHG64 # generates cmov. config X86_CMOV def_bool y - depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX) + depends on (MK8 || MK7 || MCORE2 || MPSC || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX) config X86_MINIMUM_CPU_FAMILY int diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index c198b7e..63eea60 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -84,7 +84,7 @@ config X86_PTDUMP config DEBUG_RODATA bool "Write protect kernel read-only data structures" default y - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && BROKEN ---help--- Mark the kernel read-only data as write-protected in the pagetables, in order to catch accidental (and incorrect) writes to such const @@ -102,7 +102,7 @@ config DEBUG_RODATA_TEST config DEBUG_SET_MODULE_RONX bool "Set loadable kernel module data as NX and text as RO" - depends on MODULES + depends on MODULES && BROKEN ---help--- This option helps catch unintended modifications to loadable kernel module's text and read-only data. It also prevents execution diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 5c47726..8c4fa67 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -54,6 +54,7 @@ else UTS_MACHINE := x86_64 CHECKFLAGS += -D__x86_64__ -m64 + biarch := $(call cc-option,-m64) KBUILD_AFLAGS += -m64 KBUILD_CFLAGS += -m64 @@ -234,3 +235,12 @@ define archhelp echo ' FDARGS="..." arguments for the booted kernel' echo ' FDINITRD=file initrd for the booted kernel' endef + +define OLD_LD + +*** ${VERSION}.${PATCHLEVEL} PaX kernels no longer build correctly with old versions of binutils. +*** Please upgrade your binutils to 2.18 or newer +endef + +archprepare: + $(if $(LDFLAGS_BUILD_ID),,$(error $(OLD_LD))) diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 379814b..add62ce 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -65,6 +65,9 @@ KBUILD_CFLAGS := $(USERINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ $(call cc-option, -fno-stack-protector) \ $(call cc-option, -mpreferred-stack-boundary=2) KBUILD_CFLAGS += $(call cc-option, -m32) +ifdef CONSTIFY_PLUGIN +KBUILD_CFLAGS += -fplugin-arg-constify_plugin-no-constify +endif KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ GCOV_PROFILE := n diff --git a/arch/x86/boot/bitops.h b/arch/x86/boot/bitops.h index 878e4b9..20537ab 100644 --- a/arch/x86/boot/bitops.h +++ b/arch/x86/boot/bitops.h @@ -26,7 +26,7 @@ static inline int variable_test_bit(int nr, const void *addr) u8 v; const u32 *p = (const u32 *)addr; - asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); + asm volatile("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); return v; } @@ -37,7 +37,7 @@ static inline int variable_test_bit(int nr, const void *addr) static inline void set_bit(int nr, void *addr) { - asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); + asm volatile("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); } #endif /* BOOT_BITOPS_H */ diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 5b75319..331a4ca 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h @@ -85,7 +85,7 @@ static inline void io_delay(void) static inline u16 ds(void) { u16 seg; - asm("movw %%ds,%0" : "=rm" (seg)); + asm volatile("movw %%ds,%0" : "=rm" (seg)); return seg; } @@ -181,7 +181,7 @@ static inline void wrgs32(u32 v, addr_t addr) static inline int memcmp(const void *s1, const void *s2, size_t len) { u8 diff; - asm("repe; cmpsb; setnz %0" + asm volatile("repe; cmpsb; setnz %0" : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); return diff; } diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 5ef205c..342191d 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -14,6 +14,9 @@ cflags-$(CONFIG_X86_64) := -mcmodel=small KBUILD_CFLAGS += $(cflags-y) KBUILD_CFLAGS += $(call cc-option,-ffreestanding) KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector) +ifdef CONSTIFY_PLUGIN +KBUILD_CFLAGS += -fplugin-arg-constify_plugin-no-constify +endif KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ GCOV_PROFILE := n diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index d606463..b887794 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -150,7 +150,6 @@ again: *addr = max_addr; } -free_pool: efi_call_phys1(sys_table->boottime->free_pool, map); fail: @@ -214,7 +213,6 @@ static efi_status_t low_alloc(unsigned long size, unsigned long align, if (i == map_size / desc_size) status = EFI_NOT_FOUND; -free_pool: efi_call_phys1(sys_table->boottime->free_pool, map); fail: return status; diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S index a53440e..c3dbf1e 100644 --- a/arch/x86/boot/compressed/efi_stub_32.S +++ b/arch/x86/boot/compressed/efi_stub_32.S @@ -46,16 +46,13 @@ ENTRY(efi_call_phys) * parameter 2, ..., param n. To make things easy, we save the return * address of efi_call_phys in a global variable. */ - popl %ecx - movl %ecx, saved_return_addr(%edx) - /* get the function pointer into ECX*/ - popl %ecx - movl %ecx, efi_rt_function_ptr(%edx) + popl saved_return_addr(%edx) + popl efi_rt_function_ptr(%edx) /* * 3. Call the physical function. */ - call *%ecx + call *efi_rt_function_ptr(%edx) /* * 4. Balance the stack. And because EAX contain the return value, @@ -67,15 +64,12 @@ ENTRY(efi_call_phys) 1: popl %edx subl $1b, %edx - movl efi_rt_function_ptr(%edx), %ecx - pushl %ecx + pushl efi_rt_function_ptr(%edx) /* * 10. Push the saved return address onto the stack and return. */ - movl saved_return_addr(%edx), %ecx - pushl %ecx - ret + jmpl *saved_return_addr(%edx) ENDPROC(efi_call_phys) .previous diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 1e3184f..0d11e2e 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -118,7 +118,7 @@ preferred_addr: notl %eax andl %eax, %ebx #else - movl $LOAD_PHYSICAL_ADDR, %ebx + movl $____LOAD_PHYSICAL_ADDR, %ebx #endif /* Target address to relocate to for decompression */ @@ -204,7 +204,7 @@ relocated: * and where it was actually loaded. */ movl %ebp, %ebx - subl $LOAD_PHYSICAL_ADDR, %ebx + subl $____LOAD_PHYSICAL_ADDR, %ebx jz 2f /* Nothing to be done if loaded at compiled addr. */ /* * Process relocations. @@ -212,8 +212,7 @@ relocated: 1: subl $4, %edi movl (%edi), %ecx - testl %ecx, %ecx - jz 2f + jecxz 2f addl %ebx, -__PAGE_OFFSET(%ebx, %ecx) jmp 1b 2: diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 16f24e6..47491a3 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -97,7 +97,7 @@ ENTRY(startup_32) notl %eax andl %eax, %ebx #else - movl $LOAD_PHYSICAL_ADDR, %ebx + movl $____LOAD_PHYSICAL_ADDR, %ebx #endif /* Target address to relocate to for decompression */ @@ -272,7 +272,7 @@ preferred_addr: notq %rax andq %rax, %rbp #else - movq $LOAD_PHYSICAL_ADDR, %rbp + movq $____LOAD_PHYSICAL_ADDR, %rbp #endif /* Target address to relocate to for decompression */ @@ -363,8 +363,8 @@ gdt: .long gdt .word 0 .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x00af9a000000ffff /* __KERNEL_CS */ - .quad 0x00cf92000000ffff /* __KERNEL_DS */ + .quad 0x00af9b000000ffff /* __KERNEL_CS */ + .quad 0x00cf93000000ffff /* __KERNEL_DS */ .quad 0x0080890000000000 /* TS descriptor */ .quad 0x0000000000000000 /* TS continued */ gdt_end: diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 7cb56c6..d382d84 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -303,7 +303,7 @@ static void parse_elf(void *output) case PT_LOAD: #ifdef CONFIG_RELOCATABLE dest = output; - dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR); + dest += (phdr->p_paddr - ____LOAD_PHYSICAL_ADDR); #else dest = (void *)(phdr->p_paddr); #endif @@ -354,7 +354,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, error("Destination address too large"); #endif #ifndef CONFIG_RELOCATABLE - if ((unsigned long)output != LOAD_PHYSICAL_ADDR) + if ((unsigned long)output != ____LOAD_PHYSICAL_ADDR) error("Wrong destination address"); #endif diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 4d3ff03..e4972ff 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -74,7 +74,7 @@ static int has_fpu(void) u16 fcw = -1, fsw = -1; u32 cr0; - asm("movl %%cr0,%0" : "=r" (cr0)); + asm volatile("movl %%cr0,%0" : "=r" (cr0)); if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { cr0 &= ~(X86_CR0_EM|X86_CR0_TS); asm volatile("movl %0,%%cr0" : : "r" (cr0)); @@ -90,7 +90,7 @@ static int has_eflag(u32 mask) { u32 f0, f1; - asm("pushfl ; " + asm volatile("pushfl ; " "pushfl ; " "popl %0 ; " "movl %0,%1 ; " @@ -115,7 +115,7 @@ static void get_flags(void) set_bit(X86_FEATURE_FPU, cpu.flags); if (has_eflag(X86_EFLAGS_ID)) { - asm("cpuid" + asm volatile("cpuid" : "=a" (max_intel_level), "=b" (cpu_vendor[0]), "=d" (cpu_vendor[1]), @@ -124,7 +124,7 @@ static void get_flags(void) if (max_intel_level >= 0x00000001 && max_intel_level <= 0x0000ffff) { - asm("cpuid" + asm volatile("cpuid" : "=a" (tfms), "=c" (cpu.flags[4]), "=d" (cpu.flags[0]) @@ -136,7 +136,7 @@ static void get_flags(void) cpu.model += ((tfms >> 16) & 0xf) << 4; } - asm("cpuid" + asm volatile("cpuid" : "=a" (max_amd_level) : "a" (0x80000000) : "ebx", "ecx", "edx"); @@ -144,7 +144,7 @@ static void get_flags(void) if (max_amd_level >= 0x80000001 && max_amd_level <= 0x8000ffff) { u32 eax = 0x80000001; - asm("cpuid" + asm volatile("cpuid" : "+a" (eax), "=c" (cpu.flags[6]), "=d" (cpu.flags[1]) @@ -203,9 +203,9 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) u32 ecx = MSR_K7_HWCR; u32 eax, edx; - asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); + asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); eax &= ~(1 << 15); - asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); + asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); get_flags(); /* Make sure it really did something */ err = check_flags(); @@ -218,9 +218,9 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) u32 ecx = MSR_VIA_FCR; u32 eax, edx; - asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); + asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); eax |= (1<<1)|(1<<7); - asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); + asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); set_bit(X86_FEATURE_CX8, cpu.flags); err = check_flags(); @@ -231,12 +231,12 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) u32 eax, edx; u32 level = 1; - asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); - asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); - asm("cpuid" + asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); + asm volatile("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); + asm volatile("cpuid" : "+a" (level), "=d" (cpu.flags[0]) : : "ecx", "ebx"); - asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); + asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); err = check_flags(); } diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 9ec06a1..2c25e79 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -409,10 +409,14 @@ setup_data: .quad 0 # 64-bit physical pointer to # single linked list of # struct setup_data -pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr +pref_address: .quad ____LOAD_PHYSICAL_ADDR # preferred load addr #define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset) +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) +#define VO_INIT_SIZE (VO__end - VO__text - __PAGE_OFFSET - ____LOAD_PHYSICAL_ADDR) +#else #define VO_INIT_SIZE (VO__end - VO__text) +#endif #if ZO_INIT_SIZE > VO_INIT_SIZE #define INIT_SIZE ZO_INIT_SIZE #else diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c index db75d07..8e6d0af 100644 --- a/arch/x86/boot/memory.c +++ b/arch/x86/boot/memory.c @@ -19,7 +19,7 @@ static int detect_memory_e820(void) { - int count = 0; + unsigned int count = 0; struct biosregs ireg, oreg; struct e820entry *desc = boot_params.e820_map; static struct e820entry buf; /* static so it is zeroed */ diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 11e8c6e..fdbb1ed 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -200,6 +200,7 @@ static void vesa_store_pm_info(void) boot_params.screen_info.vesapm_seg = oreg.es; boot_params.screen_info.vesapm_off = oreg.di; + boot_params.screen_info.vesapm_size = oreg.cx; } /* diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c index 43eda28..5ab5fdb 100644 --- a/arch/x86/boot/video.c +++ b/arch/x86/boot/video.c @@ -96,7 +96,7 @@ static void store_mode_params(void) static unsigned int get_entry(void) { char entry_buf[4]; - int i, len = 0; + unsigned int i, len = 0; int key; unsigned int v; diff --git a/arch/x86/crypto/aes-x86_64-asm_64.S b/arch/x86/crypto/aes-x86_64-asm_64.S index 9105655..5e37f27 100644 --- a/arch/x86/crypto/aes-x86_64-asm_64.S +++ b/arch/x86/crypto/aes-x86_64-asm_64.S @@ -8,6 +8,8 @@ * including this sentence is retained in full. */ +#include + .extern crypto_ft_tab .extern crypto_it_tab .extern crypto_fl_tab @@ -70,6 +72,8 @@ je B192; \ leaq 32(r9),r9; +#define ret pax_force_retaddr 0, 1; ret + #define epilogue(FUNC,r1,r2,r3,r4,r5,r6,r7,r8,r9) \ movq r1,r2; \ movq r3,r4; \ diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index 477e9d7..3ab339f 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -31,6 +31,7 @@ #include #include +#include #ifdef __x86_64__ .data @@ -1441,6 +1442,7 @@ _return_T_done_decrypt: pop %r14 pop %r13 pop %r12 + pax_force_retaddr 0, 1 ret ENDPROC(aesni_gcm_dec) @@ -1705,6 +1707,7 @@ _return_T_done_encrypt: pop %r14 pop %r13 pop %r12 + pax_force_retaddr 0, 1 ret ENDPROC(aesni_gcm_enc) @@ -1722,6 +1725,7 @@ _key_expansion_256a: pxor %xmm1, %xmm0 movaps %xmm0, (TKEYP) add $0x10, TKEYP + pax_force_retaddr_bts ret ENDPROC(_key_expansion_128) ENDPROC(_key_expansion_256a) @@ -1748,6 +1752,7 @@ _key_expansion_192a: shufps $0b01001110, %xmm2, %xmm1 movaps %xmm1, 0x10(TKEYP) add $0x20, TKEYP + pax_force_retaddr_bts ret ENDPROC(_key_expansion_192a) @@ -1768,6 +1773,7 @@ _key_expansion_192b: movaps %xmm0, (TKEYP) add $0x10, TKEYP + pax_force_retaddr_bts ret ENDPROC(_key_expansion_192b) @@ -1781,6 +1787,7 @@ _key_expansion_256b: pxor %xmm1, %xmm2 movaps %xmm2, (TKEYP) add $0x10, TKEYP + pax_force_retaddr_bts ret ENDPROC(_key_expansion_256b) @@ -1894,6 +1901,7 @@ ENTRY(aesni_set_key) #ifndef __x86_64__ popl KEYP #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_set_key) @@ -1916,6 +1924,7 @@ ENTRY(aesni_enc) popl KLEN popl KEYP #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_enc) @@ -1974,6 +1983,7 @@ _aesni_enc1: AESENC KEY STATE movaps 0x70(TKEYP), KEY AESENCLAST KEY STATE + pax_force_retaddr_bts ret ENDPROC(_aesni_enc1) @@ -2083,6 +2093,7 @@ _aesni_enc4: AESENCLAST KEY STATE2 AESENCLAST KEY STATE3 AESENCLAST KEY STATE4 + pax_force_retaddr_bts ret ENDPROC(_aesni_enc4) @@ -2106,6 +2117,7 @@ ENTRY(aesni_dec) popl KLEN popl KEYP #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_dec) @@ -2164,6 +2176,7 @@ _aesni_dec1: AESDEC KEY STATE movaps 0x70(TKEYP), KEY AESDECLAST KEY STATE + pax_force_retaddr_bts ret ENDPROC(_aesni_dec1) @@ -2273,6 +2286,7 @@ _aesni_dec4: AESDECLAST KEY STATE2 AESDECLAST KEY STATE3 AESDECLAST KEY STATE4 + pax_force_retaddr_bts ret ENDPROC(_aesni_dec4) @@ -2331,6 +2345,7 @@ ENTRY(aesni_ecb_enc) popl KEYP popl LEN #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_ecb_enc) @@ -2390,6 +2405,7 @@ ENTRY(aesni_ecb_dec) popl KEYP popl LEN #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_ecb_dec) @@ -2432,6 +2448,7 @@ ENTRY(aesni_cbc_enc) popl LEN popl IVP #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_cbc_enc) @@ -2523,6 +2540,7 @@ ENTRY(aesni_cbc_dec) popl LEN popl IVP #endif + pax_force_retaddr 0, 1 ret ENDPROC(aesni_cbc_dec) @@ -2550,6 +2568,7 @@ _aesni_inc_init: mov $1, TCTR_LOW MOVQ_R64_XMM TCTR_LOW INC MOVQ_R64_XMM CTR TCTR_LOW + pax_force_retaddr_bts ret ENDPROC(_aesni_inc_init) @@ -2579,6 +2598,7 @@ _aesni_inc: .Linc_low: movaps CTR, IV PSHUFB_XMM BSWAP_MASK IV + pax_force_retaddr_bts ret ENDPROC(_aesni_inc) @@ -2640,6 +2660,7 @@ ENTRY(aesni_ctr_enc) .Lctr_enc_ret: movups IV, (IVP) .Lctr_enc_just_ret: + pax_force_retaddr 0, 1 ret ENDPROC(aesni_ctr_enc) @@ -2766,6 +2787,7 @@ ENTRY(aesni_xts_crypt8) pxor INC, STATE4 movdqu STATE4, 0x70(OUTP) + pax_force_retaddr 0, 1 ret ENDPROC(aesni_xts_crypt8) diff --git a/arch/x86/crypto/blowfish-avx2-asm_64.S b/arch/x86/crypto/blowfish-avx2-asm_64.S index 784452e..46982c7 100644 --- a/arch/x86/crypto/blowfish-avx2-asm_64.S +++ b/arch/x86/crypto/blowfish-avx2-asm_64.S @@ -221,6 +221,7 @@ __blowfish_enc_blk32: write_block(RXl, RXr); + pax_force_retaddr 0, 1 ret; ENDPROC(__blowfish_enc_blk32) @@ -250,6 +251,7 @@ __blowfish_dec_blk32: write_block(RXl, RXr); + pax_force_retaddr 0, 1 ret; ENDPROC(__blowfish_dec_blk32) @@ -284,6 +286,7 @@ ENTRY(blowfish_ecb_enc_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_ecb_enc_32way) @@ -318,6 +321,7 @@ ENTRY(blowfish_ecb_dec_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_ecb_dec_32way) @@ -365,6 +369,7 @@ ENTRY(blowfish_cbc_dec_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_cbc_dec_32way) @@ -445,5 +450,6 @@ ENTRY(blowfish_ctr_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_ctr_32way) diff --git a/arch/x86/crypto/blowfish-x86_64-asm_64.S b/arch/x86/crypto/blowfish-x86_64-asm_64.S index 246c670..4d1ed00 100644 --- a/arch/x86/crypto/blowfish-x86_64-asm_64.S +++ b/arch/x86/crypto/blowfish-x86_64-asm_64.S @@ -21,6 +21,7 @@ */ #include +#include .file "blowfish-x86_64-asm.S" .text @@ -149,9 +150,11 @@ ENTRY(__blowfish_enc_blk) jnz .L__enc_xor; write_block(); + pax_force_retaddr 0, 1 ret; .L__enc_xor: xor_block(); + pax_force_retaddr 0, 1 ret; ENDPROC(__blowfish_enc_blk) @@ -183,6 +186,7 @@ ENTRY(blowfish_dec_blk) movq %r11, %rbp; + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_dec_blk) @@ -334,6 +338,7 @@ ENTRY(__blowfish_enc_blk_4way) popq %rbx; popq %rbp; + pax_force_retaddr 0, 1 ret; .L__enc_xor4: @@ -341,6 +346,7 @@ ENTRY(__blowfish_enc_blk_4way) popq %rbx; popq %rbp; + pax_force_retaddr 0, 1 ret; ENDPROC(__blowfish_enc_blk_4way) @@ -375,5 +381,6 @@ ENTRY(blowfish_dec_blk_4way) popq %rbx; popq %rbp; + pax_force_retaddr 0, 1 ret; ENDPROC(blowfish_dec_blk_4way) diff --git a/arch/x86/crypto/camellia-aesni-avx-asm_64.S b/arch/x86/crypto/camellia-aesni-avx-asm_64.S index ce71f92..2dd5b1e 100644 --- a/arch/x86/crypto/camellia-aesni-avx-asm_64.S +++ b/arch/x86/crypto/camellia-aesni-avx-asm_64.S @@ -16,6 +16,7 @@ */ #include +#include #define CAMELLIA_TABLE_BYTE_LEN 272 @@ -191,6 +192,7 @@ roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd: roundsm16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, %rcx, (%r9)); + pax_force_retaddr_bts ret; ENDPROC(roundsm16_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd) @@ -199,6 +201,7 @@ roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab: roundsm16(%xmm4, %xmm5, %xmm6, %xmm7, %xmm0, %xmm1, %xmm2, %xmm3, %xmm12, %xmm13, %xmm14, %xmm15, %xmm8, %xmm9, %xmm10, %xmm11, %rax, (%r9)); + pax_force_retaddr_bts ret; ENDPROC(roundsm16_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) @@ -780,6 +783,7 @@ __camellia_enc_blk16: %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax)); + pax_force_retaddr_bts ret; .align 8 @@ -865,6 +869,7 @@ __camellia_dec_blk16: %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax)); + pax_force_retaddr_bts ret; .align 8 @@ -904,6 +909,7 @@ ENTRY(camellia_ecb_enc_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_ecb_enc_16way) @@ -932,6 +938,7 @@ ENTRY(camellia_ecb_dec_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_ecb_dec_16way) @@ -981,6 +988,7 @@ ENTRY(camellia_cbc_dec_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_cbc_dec_16way) @@ -1092,6 +1100,7 @@ ENTRY(camellia_ctr_16way) %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_ctr_16way) @@ -1234,6 +1243,7 @@ camellia_xts_crypt_16way: %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_xts_crypt_16way) diff --git a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S index 91a1878..bcf340a 100644 --- a/arch/x86/crypto/camellia-aesni-avx2-asm_64.S +++ b/arch/x86/crypto/camellia-aesni-avx2-asm_64.S @@ -11,6 +11,7 @@ */ #include +#include #define CAMELLIA_TABLE_BYTE_LEN 272 @@ -212,6 +213,7 @@ roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd: roundsm32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, %rcx, (%r9)); + pax_force_retaddr_bts ret; ENDPROC(roundsm32_x0_x1_x2_x3_x4_x5_x6_x7_y0_y1_y2_y3_y4_y5_y6_y7_cd) @@ -220,6 +222,7 @@ roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab: roundsm32(%ymm4, %ymm5, %ymm6, %ymm7, %ymm0, %ymm1, %ymm2, %ymm3, %ymm12, %ymm13, %ymm14, %ymm15, %ymm8, %ymm9, %ymm10, %ymm11, %rax, (%r9)); + pax_force_retaddr_bts ret; ENDPROC(roundsm32_x4_x5_x6_x7_x0_x1_x2_x3_y4_y5_y6_y7_y0_y1_y2_y3_ab) @@ -802,6 +805,7 @@ __camellia_enc_blk32: %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax)); + pax_force_retaddr_bts ret; .align 8 @@ -887,6 +891,7 @@ __camellia_dec_blk32: %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax)); + pax_force_retaddr_bts ret; .align 8 @@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_ecb_enc_32way) @@ -962,6 +968,7 @@ ENTRY(camellia_ecb_dec_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_ecb_dec_32way) @@ -1028,6 +1035,7 @@ ENTRY(camellia_cbc_dec_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_cbc_dec_32way) @@ -1166,6 +1174,7 @@ ENTRY(camellia_ctr_32way) vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_ctr_32way) @@ -1331,6 +1340,7 @@ camellia_xts_crypt_32way: vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_xts_crypt_32way) diff --git a/arch/x86/crypto/camellia-x86_64-asm_64.S b/arch/x86/crypto/camellia-x86_64-asm_64.S index 310319c..ce174a4 100644 --- a/arch/x86/crypto/camellia-x86_64-asm_64.S +++ b/arch/x86/crypto/camellia-x86_64-asm_64.S @@ -21,6 +21,7 @@ */ #include +#include .file "camellia-x86_64-asm_64.S" .text @@ -228,12 +229,14 @@ ENTRY(__camellia_enc_blk) enc_outunpack(mov, RT1); movq RRBP, %rbp; + pax_force_retaddr 0, 1 ret; .L__enc_xor: enc_outunpack(xor, RT1); movq RRBP, %rbp; + pax_force_retaddr 0, 1 ret; ENDPROC(__camellia_enc_blk) @@ -272,6 +275,7 @@ ENTRY(camellia_dec_blk) dec_outunpack(); movq RRBP, %rbp; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_dec_blk) @@ -463,6 +467,7 @@ ENTRY(__camellia_enc_blk_2way) movq RRBP, %rbp; popq %rbx; + pax_force_retaddr 0, 1 ret; .L__enc2_xor: @@ -470,6 +475,7 @@ ENTRY(__camellia_enc_blk_2way) movq RRBP, %rbp; popq %rbx; + pax_force_retaddr 0, 1 ret; ENDPROC(__camellia_enc_blk_2way) @@ -510,5 +516,6 @@ ENTRY(camellia_dec_blk_2way) movq RRBP, %rbp; movq RXOR, %rbx; + pax_force_retaddr 0, 1 ret; ENDPROC(camellia_dec_blk_2way) diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S index c35fd5d..c1ee236 100644 --- a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S @@ -24,6 +24,7 @@ */ #include +#include .file "cast5-avx-x86_64-asm_64.S" @@ -281,6 +282,7 @@ __cast5_enc_blk16: outunpack_blocks(RR3, RL3, RTMP, RX, RKM); outunpack_blocks(RR4, RL4, RTMP, RX, RKM); + pax_force_retaddr 0, 1 ret; ENDPROC(__cast5_enc_blk16) @@ -352,6 +354,7 @@ __cast5_dec_blk16: outunpack_blocks(RR3, RL3, RTMP, RX, RKM); outunpack_blocks(RR4, RL4, RTMP, RX, RKM); + pax_force_retaddr 0, 1 ret; .L__skip_dec: @@ -388,6 +391,7 @@ ENTRY(cast5_ecb_enc_16way) vmovdqu RR4, (6*4*4)(%r11); vmovdqu RL4, (7*4*4)(%r11); + pax_force_retaddr ret; ENDPROC(cast5_ecb_enc_16way) @@ -420,6 +424,7 @@ ENTRY(cast5_ecb_dec_16way) vmovdqu RR4, (6*4*4)(%r11); vmovdqu RL4, (7*4*4)(%r11); + pax_force_retaddr ret; ENDPROC(cast5_ecb_dec_16way) @@ -469,6 +474,7 @@ ENTRY(cast5_cbc_dec_16way) popq %r12; + pax_force_retaddr ret; ENDPROC(cast5_cbc_dec_16way) @@ -542,5 +548,6 @@ ENTRY(cast5_ctr_16way) popq %r12; + pax_force_retaddr ret; ENDPROC(cast5_ctr_16way) diff --git a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S index e3531f8..18ded3a 100644 --- a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S @@ -24,6 +24,7 @@ */ #include +#include #include "glue_helper-asm-avx.S" .file "cast6-avx-x86_64-asm_64.S" @@ -295,6 +296,7 @@ __cast6_enc_blk8: outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM); outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM); + pax_force_retaddr 0, 1 ret; ENDPROC(__cast6_enc_blk8) @@ -340,6 +342,7 @@ __cast6_dec_blk8: outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM); outunpack_blocks(RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM); + pax_force_retaddr 0, 1 ret; ENDPROC(__cast6_dec_blk8) @@ -358,6 +361,7 @@ ENTRY(cast6_ecb_enc_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(cast6_ecb_enc_8way) @@ -376,6 +380,7 @@ ENTRY(cast6_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(cast6_ecb_dec_8way) @@ -399,6 +404,7 @@ ENTRY(cast6_cbc_dec_8way) popq %r12; + pax_force_retaddr ret; ENDPROC(cast6_cbc_dec_8way) @@ -424,6 +430,7 @@ ENTRY(cast6_ctr_8way) popq %r12; + pax_force_retaddr ret; ENDPROC(cast6_ctr_8way) @@ -446,6 +453,7 @@ ENTRY(cast6_xts_enc_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(cast6_xts_enc_8way) @@ -468,5 +476,6 @@ ENTRY(cast6_xts_dec_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(cast6_xts_dec_8way) diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S index dbc4339..3d868c5 100644 --- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S +++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S @@ -45,6 +45,7 @@ #include #include +#include ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction @@ -312,6 +313,7 @@ do_return: popq %rsi popq %rdi popq %rbx + pax_force_retaddr 0, 1 ret ################################################################ diff --git a/arch/x86/crypto/ghash-clmulni-intel_asm.S b/arch/x86/crypto/ghash-clmulni-intel_asm.S index 586f41a..d02851e 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_asm.S +++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S @@ -18,6 +18,7 @@ #include #include +#include .data @@ -93,6 +94,7 @@ __clmul_gf128mul_ble: psrlq $1, T2 pxor T2, T1 pxor T1, DATA + pax_force_retaddr ret ENDPROC(__clmul_gf128mul_ble) @@ -105,6 +107,7 @@ ENTRY(clmul_ghash_mul) call __clmul_gf128mul_ble PSHUFB_XMM BSWAP DATA movups DATA, (%rdi) + pax_force_retaddr ret ENDPROC(clmul_ghash_mul) @@ -132,6 +135,7 @@ ENTRY(clmul_ghash_update) PSHUFB_XMM BSWAP DATA movups DATA, (%rdi) .Lupdate_just_ret: + pax_force_retaddr ret ENDPROC(clmul_ghash_update) @@ -157,5 +161,6 @@ ENTRY(clmul_ghash_setkey) pand .Lpoly, %xmm1 pxor %xmm1, %xmm0 movups %xmm0, (%rdi) + pax_force_retaddr ret ENDPROC(clmul_ghash_setkey) diff --git a/arch/x86/crypto/salsa20-x86_64-asm_64.S b/arch/x86/crypto/salsa20-x86_64-asm_64.S index 9279e0b..9270820 100644 --- a/arch/x86/crypto/salsa20-x86_64-asm_64.S +++ b/arch/x86/crypto/salsa20-x86_64-asm_64.S @@ -1,4 +1,5 @@ #include +#include # enter salsa20_encrypt_bytes ENTRY(salsa20_encrypt_bytes) @@ -789,6 +790,7 @@ ENTRY(salsa20_encrypt_bytes) add %r11,%rsp mov %rdi,%rax mov %rsi,%rdx + pax_force_retaddr 0, 1 ret # bytesatleast65: ._bytesatleast65: @@ -889,6 +891,7 @@ ENTRY(salsa20_keysetup) add %r11,%rsp mov %rdi,%rax mov %rsi,%rdx + pax_force_retaddr ret ENDPROC(salsa20_keysetup) @@ -914,5 +917,6 @@ ENTRY(salsa20_ivsetup) add %r11,%rsp mov %rdi,%rax mov %rsi,%rdx + pax_force_retaddr ret ENDPROC(salsa20_ivsetup) diff --git a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S index 2f202f4..d9164d6 100644 --- a/arch/x86/crypto/serpent-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/serpent-avx-x86_64-asm_64.S @@ -24,6 +24,7 @@ */ #include +#include #include "glue_helper-asm-avx.S" .file "serpent-avx-x86_64-asm_64.S" @@ -618,6 +619,7 @@ __serpent_enc_blk8_avx: write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2); write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2); + pax_force_retaddr ret; ENDPROC(__serpent_enc_blk8_avx) @@ -672,6 +674,7 @@ __serpent_dec_blk8_avx: write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2); write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2); + pax_force_retaddr ret; ENDPROC(__serpent_dec_blk8_avx) @@ -688,6 +691,7 @@ ENTRY(serpent_ecb_enc_8way_avx) store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(serpent_ecb_enc_8way_avx) @@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_8way_avx) store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + pax_force_retaddr ret; ENDPROC(serpent_ecb_dec_8way_avx) @@ -720,6 +725,7 @@ ENTRY(serpent_cbc_dec_8way_avx) store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + pax_force_retaddr ret; ENDPROC(serpent_cbc_dec_8way_avx) @@ -738,6 +744,7 @@ ENTRY(serpent_ctr_8way_avx) store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(serpent_ctr_8way_avx) @@ -758,6 +765,7 @@ ENTRY(serpent_xts_enc_8way_avx) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr ret; ENDPROC(serpent_xts_enc_8way_avx) @@ -778,5 +786,6 @@ ENTRY(serpent_xts_dec_8way_avx) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2); + pax_force_retaddr ret; ENDPROC(serpent_xts_dec_8way_avx) diff --git a/arch/x86/crypto/serpent-avx2-asm_64.S b/arch/x86/crypto/serpent-avx2-asm_64.S index b222085..abd483c 100644 --- a/arch/x86/crypto/serpent-avx2-asm_64.S +++ b/arch/x86/crypto/serpent-avx2-asm_64.S @@ -15,6 +15,7 @@ */ #include +#include #include "glue_helper-asm-avx2.S" .file "serpent-avx2-asm_64.S" @@ -610,6 +611,7 @@ __serpent_enc_blk16: write_blocks(RA1, RB1, RC1, RD1, RK0, RK1, RK2); write_blocks(RA2, RB2, RC2, RD2, RK0, RK1, RK2); + pax_force_retaddr ret; ENDPROC(__serpent_enc_blk16) @@ -664,6 +666,7 @@ __serpent_dec_blk16: write_blocks(RC1, RD1, RB1, RE1, RK0, RK1, RK2); write_blocks(RC2, RD2, RB2, RE2, RK0, RK1, RK2); + pax_force_retaddr ret; ENDPROC(__serpent_dec_blk16) @@ -684,6 +687,7 @@ ENTRY(serpent_ecb_enc_16way) vzeroupper; + pax_force_retaddr ret; ENDPROC(serpent_ecb_enc_16way) @@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way) vzeroupper; + pax_force_retaddr ret; ENDPROC(serpent_ecb_dec_16way) @@ -725,6 +730,7 @@ ENTRY(serpent_cbc_dec_16way) vzeroupper; + pax_force_retaddr ret; ENDPROC(serpent_cbc_dec_16way) @@ -748,6 +754,7 @@ ENTRY(serpent_ctr_16way) vzeroupper; + pax_force_retaddr ret; ENDPROC(serpent_ctr_16way) @@ -772,6 +779,7 @@ ENTRY(serpent_xts_enc_16way) vzeroupper; + pax_force_retaddr ret; ENDPROC(serpent_xts_enc_16way) @@ -796,5 +804,6 @@ ENTRY(serpent_xts_dec_16way) vzeroupper; + pax_force_retaddr ret; ENDPROC(serpent_xts_dec_16way) diff --git a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S index acc066c..1559cc4 100644 --- a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S +++ b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S @@ -25,6 +25,7 @@ */ #include +#include .file "serpent-sse2-x86_64-asm_64.S" .text @@ -690,12 +691,14 @@ ENTRY(__serpent_enc_blk_8way) write_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); write_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + pax_force_retaddr ret; .L__enc_xor8: xor_blocks(%rsi, RA1, RB1, RC1, RD1, RK0, RK1, RK2); xor_blocks(%rax, RA2, RB2, RC2, RD2, RK0, RK1, RK2); + pax_force_retaddr ret; ENDPROC(__serpent_enc_blk_8way) @@ -750,5 +753,6 @@ ENTRY(serpent_dec_blk_8way) write_blocks(%rsi, RC1, RD1, RB1, RE1, RK0, RK1, RK2); write_blocks(%rax, RC2, RD2, RB2, RE2, RK0, RK1, RK2); + pax_force_retaddr ret; ENDPROC(serpent_dec_blk_8way) diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S index a410950..3356d42 100644 --- a/arch/x86/crypto/sha1_ssse3_asm.S +++ b/arch/x86/crypto/sha1_ssse3_asm.S @@ -29,6 +29,7 @@ */ #include +#include #define CTX %rdi // arg1 #define BUF %rsi // arg2 @@ -104,6 +105,7 @@ pop %r12 pop %rbp pop %rbx + pax_force_retaddr 0, 1 ret ENDPROC(\name) diff --git a/arch/x86/crypto/sha256-avx-asm.S b/arch/x86/crypto/sha256-avx-asm.S index 642f156..4ab07b9 100644 --- a/arch/x86/crypto/sha256-avx-asm.S +++ b/arch/x86/crypto/sha256-avx-asm.S @@ -49,6 +49,7 @@ #ifdef CONFIG_AS_AVX #include +#include ## assume buffers not aligned #define VMOVDQ vmovdqu @@ -460,6 +461,7 @@ done_hash: popq %r13 popq %rbp popq %rbx + pax_force_retaddr 0, 1 ret ENDPROC(sha256_transform_avx) diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S index 9e86944..2e7f95a 100644 --- a/arch/x86/crypto/sha256-avx2-asm.S +++ b/arch/x86/crypto/sha256-avx2-asm.S @@ -50,6 +50,7 @@ #ifdef CONFIG_AS_AVX2 #include +#include ## assume buffers not aligned #define VMOVDQ vmovdqu @@ -720,6 +721,7 @@ done_hash: popq %r12 popq %rbp popq %rbx + pax_force_retaddr 0, 1 ret ENDPROC(sha256_transform_rorx) diff --git a/arch/x86/crypto/sha256-ssse3-asm.S b/arch/x86/crypto/sha256-ssse3-asm.S index f833b74..c36ed14 100644 --- a/arch/x86/crypto/sha256-ssse3-asm.S +++ b/arch/x86/crypto/sha256-ssse3-asm.S @@ -47,6 +47,7 @@ ######################################################################## #include +#include ## assume buffers not aligned #define MOVDQ movdqu @@ -471,6 +472,7 @@ done_hash: popq %rbp popq %rbx + pax_force_retaddr 0, 1 ret ENDPROC(sha256_transform_ssse3) diff --git a/arch/x86/crypto/sha512-avx-asm.S b/arch/x86/crypto/sha512-avx-asm.S index 974dde9..4533d34 100644 --- a/arch/x86/crypto/sha512-avx-asm.S +++ b/arch/x86/crypto/sha512-avx-asm.S @@ -49,6 +49,7 @@ #ifdef CONFIG_AS_AVX #include +#include .text @@ -364,6 +365,7 @@ updateblock: mov frame_RSPSAVE(%rsp), %rsp nowork: + pax_force_retaddr 0, 1 ret ENDPROC(sha512_transform_avx) diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S index 568b961..061ef1d 100644 --- a/arch/x86/crypto/sha512-avx2-asm.S +++ b/arch/x86/crypto/sha512-avx2-asm.S @@ -51,6 +51,7 @@ #ifdef CONFIG_AS_AVX2 #include +#include .text @@ -678,6 +679,7 @@ done_hash: # Restore Stack Pointer mov frame_RSPSAVE(%rsp), %rsp + pax_force_retaddr 0, 1 ret ENDPROC(sha512_transform_rorx) diff --git a/arch/x86/crypto/sha512-ssse3-asm.S b/arch/x86/crypto/sha512-ssse3-asm.S index fb56855..e23914f 100644 --- a/arch/x86/crypto/sha512-ssse3-asm.S +++ b/arch/x86/crypto/sha512-ssse3-asm.S @@ -48,6 +48,7 @@ ######################################################################## #include +#include .text @@ -363,6 +364,7 @@ updateblock: mov frame_RSPSAVE(%rsp), %rsp nowork: + pax_force_retaddr 0, 1 ret ENDPROC(sha512_transform_ssse3) diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S index 0505813..63b1d00 100644 --- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S +++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S @@ -24,6 +24,7 @@ */ #include +#include #include "glue_helper-asm-avx.S" .file "twofish-avx-x86_64-asm_64.S" @@ -284,6 +285,7 @@ __twofish_enc_blk8: outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2); outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2); + pax_force_retaddr 0, 1 ret; ENDPROC(__twofish_enc_blk8) @@ -324,6 +326,7 @@ __twofish_dec_blk8: outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2); outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2); + pax_force_retaddr 0, 1 ret; ENDPROC(__twofish_dec_blk8) @@ -342,6 +345,7 @@ ENTRY(twofish_ecb_enc_8way) store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_ecb_enc_8way) @@ -360,6 +364,7 @@ ENTRY(twofish_ecb_dec_8way) store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_ecb_dec_8way) @@ -383,6 +388,7 @@ ENTRY(twofish_cbc_dec_8way) popq %r12; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_cbc_dec_8way) @@ -408,6 +414,7 @@ ENTRY(twofish_ctr_8way) popq %r12; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_ctr_8way) @@ -430,6 +437,7 @@ ENTRY(twofish_xts_enc_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2); + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_xts_enc_8way) @@ -452,5 +460,6 @@ ENTRY(twofish_xts_dec_8way) /* dst <= regs xor IVs(in dst) */ store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2); + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_xts_dec_8way) diff --git a/arch/x86/crypto/twofish-avx2-asm_64.S b/arch/x86/crypto/twofish-avx2-asm_64.S index e1a83b9..33006b9 100644 --- a/arch/x86/crypto/twofish-avx2-asm_64.S +++ b/arch/x86/crypto/twofish-avx2-asm_64.S @@ -11,6 +11,7 @@ */ #include +#include #include "glue_helper-asm-avx2.S" .file "twofish-avx2-asm_64.S" @@ -422,6 +423,7 @@ __twofish_enc_blk16: outunpack_enc16(RA, RB, RC, RD); write_blocks16(RA, RB, RC, RD); + pax_force_retaddr_bts ret; ENDPROC(__twofish_enc_blk16) @@ -454,6 +456,7 @@ __twofish_dec_blk16: outunpack_dec16(RA, RB, RC, RD); write_blocks16(RA, RB, RC, RD); + pax_force_retaddr_bts ret; ENDPROC(__twofish_dec_blk16) @@ -476,6 +479,7 @@ ENTRY(twofish_ecb_enc_16way) popq %r12; vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_ecb_enc_16way) @@ -498,6 +502,7 @@ ENTRY(twofish_ecb_dec_16way) popq %r12; vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_ecb_dec_16way) @@ -521,6 +526,7 @@ ENTRY(twofish_cbc_dec_16way) popq %r12; vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_cbc_dec_16way) @@ -546,6 +552,7 @@ ENTRY(twofish_ctr_16way) popq %r12; vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_ctr_16way) @@ -574,6 +581,7 @@ twofish_xts_crypt_16way: popq %r12; vzeroupper; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_xts_crypt_16way) diff --git a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S index 1c3b7ce..b365c5e 100644 --- a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S +++ b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S @@ -21,6 +21,7 @@ */ #include +#include .file "twofish-x86_64-asm-3way.S" .text @@ -258,6 +259,7 @@ ENTRY(__twofish_enc_blk_3way) popq %r13; popq %r14; popq %r15; + pax_force_retaddr 0, 1 ret; .L__enc_xor3: @@ -269,6 +271,7 @@ ENTRY(__twofish_enc_blk_3way) popq %r13; popq %r14; popq %r15; + pax_force_retaddr 0, 1 ret; ENDPROC(__twofish_enc_blk_3way) @@ -308,5 +311,6 @@ ENTRY(twofish_dec_blk_3way) popq %r13; popq %r14; popq %r15; + pax_force_retaddr 0, 1 ret; ENDPROC(twofish_dec_blk_3way) diff --git a/arch/x86/crypto/twofish-x86_64-asm_64.S b/arch/x86/crypto/twofish-x86_64-asm_64.S index a039d21..29e7615 100644 --- a/arch/x86/crypto/twofish-x86_64-asm_64.S +++ b/arch/x86/crypto/twofish-x86_64-asm_64.S @@ -22,6 +22,7 @@ #include #include +#include #define a_offset 0 #define b_offset 4 @@ -265,6 +266,7 @@ ENTRY(twofish_enc_blk) popq R1 movq $1,%rax + pax_force_retaddr 0, 1 ret ENDPROC(twofish_enc_blk) @@ -317,5 +319,6 @@ ENTRY(twofish_dec_blk) popq R1 movq $1,%rax + pax_force_retaddr 0, 1 ret ENDPROC(twofish_dec_blk) diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 52ff81c..98af645 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -159,6 +159,8 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long dump_start, dump_size; struct user32 dump; + memset(&dump, 0, sizeof(dump)); + fs = get_fs(); set_fs(KERNEL_DS); has_dumped = 1; diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 10adb41..95ea4c2 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -340,7 +340,7 @@ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, sp -= frame_size; /* Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ - sp = ((sp + 4) & -16ul) - 4; + sp = ((sp - 12) & -16ul) - 4; return (void __user *) sp; } @@ -398,7 +398,7 @@ int ia32_setup_frame(int sig, struct ksignal *ksig, * These are actually not used anymore, but left because some * gdb versions depend on them as a marker. */ - put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); + put_user_ex(*((const u64 *)&code), (u64 __user *)frame->retcode); } put_user_catch(err); if (err) @@ -440,7 +440,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, 0xb8, __NR_ia32_rt_sigreturn, 0x80cd, - 0, + 0 }; frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate); @@ -463,16 +463,18 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, if (ksig->ka.sa.sa_flags & SA_RESTORER) restorer = ksig->ka.sa.sa_restorer; + else if (current->mm->context.vdso) + /* Return stub is in 32bit vsyscall page */ + restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); else - restorer = VDSO32_SYMBOL(current->mm->context.vdso, - rt_sigreturn); + restorer = &frame->retcode; put_user_ex(ptr_to_compat(restorer), &frame->pretcode); /* * Not actually used anymore, but left because some gdb * versions need it. */ - put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); + put_user_ex(*((const u64 *)&code), (u64 __user *)frame->retcode); } put_user_catch(err); err |= copy_siginfo_to_user32(&frame->info, &ksig->info); diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 474dc1b..9297c58 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -15,8 +15,10 @@ #include #include #include +#include #include #include +#include /* Avoid __ASSEMBLER__'ifying just for this. */ #include @@ -96,6 +98,32 @@ ENTRY(native_irq_enable_sysexit) ENDPROC(native_irq_enable_sysexit) #endif + .macro pax_enter_kernel_user + pax_set_fptr_mask +#ifdef CONFIG_PAX_MEMORY_UDEREF + call pax_enter_kernel_user +#endif + .endm + + .macro pax_exit_kernel_user +#ifdef CONFIG_PAX_MEMORY_UDEREF + call pax_exit_kernel_user +#endif +#ifdef CONFIG_PAX_RANDKSTACK + pushq %rax + pushq %r11 + call pax_randomize_kstack + popq %r11 + popq %rax +#endif + .endm + + .macro pax_erase_kstack +#ifdef CONFIG_PAX_MEMORY_STACKLEAK + call pax_erase_kstack +#endif + .endm + /* * 32bit SYSENTER instruction entry. * @@ -122,12 +150,6 @@ ENTRY(ia32_sysenter_target) CFI_REGISTER rsp,rbp SWAPGS_UNSAFE_STACK movq PER_CPU_VAR(kernel_stack), %rsp - addq $(KERNEL_STACK_OFFSET),%rsp - /* - * No need to follow this irqs on/off section: the syscall - * disabled irqs, here we enable it straight after entry: - */ - ENABLE_INTERRUPTS(CLBR_NONE) movl %ebp,%ebp /* zero extension */ pushq_cfi $__USER32_DS /*CFI_REL_OFFSET ss,0*/ @@ -135,24 +157,49 @@ ENTRY(ia32_sysenter_target) CFI_REL_OFFSET rsp,0 pushfq_cfi /*CFI_REL_OFFSET rflags,0*/ - movl TI_sysenter_return+THREAD_INFO(%rsp,3*8-KERNEL_STACK_OFFSET),%r10d - CFI_REGISTER rip,r10 + orl $X86_EFLAGS_IF,(%rsp) + GET_THREAD_INFO(%r11) + movl TI_sysenter_return(%r11), %r11d + CFI_REGISTER rip,r11 pushq_cfi $__USER32_CS /*CFI_REL_OFFSET cs,0*/ movl %eax, %eax - pushq_cfi %r10 + pushq_cfi %r11 CFI_REL_OFFSET rip,0 pushq_cfi %rax cld SAVE_ARGS 0,1,0 + pax_enter_kernel_user + +#ifdef CONFIG_PAX_RANDKSTACK + pax_erase_kstack +#endif + + /* + * No need to follow this irqs on/off section: the syscall + * disabled irqs, here we enable it straight after entry: + */ + ENABLE_INTERRUPTS(CLBR_NONE) /* no need to do an access_ok check here because rbp has been 32bit zero extended */ + +#ifdef CONFIG_PAX_MEMORY_UDEREF + addq pax_user_shadow_base,%rbp + ASM_PAX_OPEN_USERLAND +#endif + ASM_STAC 1: movl (%rbp),%ebp _ASM_EXTABLE(1b,ia32_badarg) ASM_CLAC - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + +#ifdef CONFIG_PAX_MEMORY_UDEREF + ASM_PAX_CLOSE_USERLAND +#endif + + GET_THREAD_INFO(%r11) + orl $TS_COMPAT,TI_status(%r11) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r11) CFI_REMEMBER_STATE jnz sysenter_tracesys cmpq $(IA32_NR_syscalls-1),%rax @@ -162,12 +209,15 @@ sysenter_do_call: sysenter_dispatch: call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) + GET_THREAD_INFO(%r11) DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_ALLWORK_MASK,TI_flags(%r11) jnz sysexit_audit sysexit_from_sys_call: - andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + pax_exit_kernel_user + pax_erase_kstack + andl $~TS_COMPAT,TI_status(%r11) /* clear IF, that popfq doesn't enable interrupts early */ andl $~0x200,EFLAGS-R11(%rsp) movl RIP-R11(%rsp),%edx /* User %eip */ @@ -193,6 +243,9 @@ sysexit_from_sys_call: movl %eax,%esi /* 2nd arg: syscall number */ movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */ call __audit_syscall_entry + + pax_erase_kstack + movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */ cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys @@ -204,7 +257,7 @@ sysexit_from_sys_call: .endm .macro auditsys_exit exit - testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r11) jnz ia32_ret_from_sys_call TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) @@ -215,11 +268,12 @@ sysexit_from_sys_call: 1: setbe %al /* 1 if error, 0 if not */ movzbl %al,%edi /* zero-extend that into %edi */ call __audit_syscall_exit + GET_THREAD_INFO(%r11) movq RAX-ARGOFFSET(%rsp),%rax /* reload syscall return value */ movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl %edi,TI_flags(%r11) jz \exit CLEAR_RREGS -ARGOFFSET jmp int_with_check @@ -237,7 +291,7 @@ sysexit_audit: sysenter_tracesys: #ifdef CONFIG_AUDITSYSCALL - testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r11) jz sysenter_auditsys #endif SAVE_REST @@ -249,6 +303,9 @@ sysenter_tracesys: RESTORE_REST cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ + + pax_erase_kstack + jmp sysenter_do_call CFI_ENDPROC ENDPROC(ia32_sysenter_target) @@ -276,19 +333,25 @@ ENDPROC(ia32_sysenter_target) ENTRY(ia32_cstar_target) CFI_STARTPROC32 simple CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET + CFI_DEF_CFA rsp,0 CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ SWAPGS_UNSAFE_STACK movl %esp,%r8d CFI_REGISTER rsp,r8 movq PER_CPU_VAR(kernel_stack),%rsp + SAVE_ARGS 8*6,0,0 + pax_enter_kernel_user + +#ifdef CONFIG_PAX_RANDKSTACK + pax_erase_kstack +#endif + /* * No need to follow this irqs on/off section: the syscall * disabled irqs and here we enable it straight after entry: */ ENABLE_INTERRUPTS(CLBR_NONE) - SAVE_ARGS 8,0,0 movl %eax,%eax /* zero extension */ movq %rax,ORIG_RAX-ARGOFFSET(%rsp) movq %rcx,RIP-ARGOFFSET(%rsp) @@ -304,12 +367,25 @@ ENTRY(ia32_cstar_target) /* no need to do an access_ok check here because r8 has been 32bit zero extended */ /* hardware stack frame is complete now */ + +#ifdef CONFIG_PAX_MEMORY_UDEREF + ASM_PAX_OPEN_USERLAND + movq pax_user_shadow_base,%r8 + addq RSP-ARGOFFSET(%rsp),%r8 +#endif + ASM_STAC 1: movl (%r8),%r9d _ASM_EXTABLE(1b,ia32_badarg) ASM_CLAC - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + +#ifdef CONFIG_PAX_MEMORY_UDEREF + ASM_PAX_CLOSE_USERLAND +#endif + + GET_THREAD_INFO(%r11) + orl $TS_COMPAT,TI_status(%r11) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r11) CFI_REMEMBER_STATE jnz cstar_tracesys cmpq $IA32_NR_syscalls-1,%rax @@ -319,12 +395,15 @@ cstar_do_call: cstar_dispatch: call *ia32_sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) + GET_THREAD_INFO(%r11) DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_ALLWORK_MASK,TI_flags(%r11) jnz sysretl_audit sysretl_from_sys_call: - andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + pax_exit_kernel_user + pax_erase_kstack + andl $~TS_COMPAT,TI_status(%r11) RESTORE_ARGS 0,-ARG_SKIP,0,0,0 movl RIP-ARGOFFSET(%rsp),%ecx CFI_REGISTER rip,rcx @@ -352,7 +431,7 @@ sysretl_audit: cstar_tracesys: #ifdef CONFIG_AUDITSYSCALL - testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r11) jz cstar_auditsys #endif xchgl %r9d,%ebp @@ -366,11 +445,19 @@ cstar_tracesys: xchgl %ebp,%r9d cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ + + pax_erase_kstack + jmp cstar_do_call END(ia32_cstar_target) ia32_badarg: ASM_CLAC + +#ifdef CONFIG_PAX_MEMORY_UDEREF + ASM_PAX_CLOSE_USERLAND +#endif + movq $-EFAULT,%rax jmp ia32_sysret CFI_ENDPROC @@ -407,19 +494,26 @@ ENTRY(ia32_syscall) CFI_REL_OFFSET rip,RIP-RIP PARAVIRT_ADJUST_EXCEPTION_FRAME SWAPGS - /* - * No need to follow this irqs on/off section: the syscall - * disabled irqs and here we enable it straight after entry: - */ - ENABLE_INTERRUPTS(CLBR_NONE) movl %eax,%eax pushq_cfi %rax cld /* note the registers are not zero extended to the sf. this could be a problem. */ SAVE_ARGS 0,1,0 - orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + pax_enter_kernel_user + +#ifdef CONFIG_PAX_RANDKSTACK + pax_erase_kstack +#endif + + /* + * No need to follow this irqs on/off section: the syscall + * disabled irqs and here we enable it straight after entry: + */ + ENABLE_INTERRUPTS(CLBR_NONE) + GET_THREAD_INFO(%r11) + orl $TS_COMPAT,TI_status(%r11) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r11) jnz ia32_tracesys cmpq $(IA32_NR_syscalls-1),%rax ja ia32_badsys @@ -442,6 +536,9 @@ ia32_tracesys: RESTORE_REST cmpq $(IA32_NR_syscalls-1),%rax ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ + + pax_erase_kstack + jmp ia32_do_call END(ia32_syscall) diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 8e0ceec..af13504 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -69,8 +69,8 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long offset_low, */ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) { - typeof(ubuf->st_uid) uid = 0; - typeof(ubuf->st_gid) gid = 0; + typeof(((struct stat64 *)0)->st_uid) uid = 0; + typeof(((struct stat64 *)0)->st_gid) gid = 0; SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid)); SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid)); if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h index 372231c..a5aa1a1 100644 --- a/arch/x86/include/asm/alternative-asm.h +++ b/arch/x86/include/asm/alternative-asm.h @@ -18,6 +18,45 @@ .endm #endif +#ifdef KERNEXEC_PLUGIN + .macro pax_force_retaddr_bts rip=0 + btsq $63,\rip(%rsp) + .endm +#ifdef CONFIG_PAX_KERNEXEC_PLUGIN_METHOD_BTS + .macro pax_force_retaddr rip=0, reload=0 + btsq $63,\rip(%rsp) + .endm + .macro pax_force_fptr ptr + btsq $63,\ptr + .endm + .macro pax_set_fptr_mask + .endm +#endif +#ifdef CONFIG_PAX_KERNEXEC_PLUGIN_METHOD_OR + .macro pax_force_retaddr rip=0, reload=0 + .if \reload + pax_set_fptr_mask + .endif + orq %r10,\rip(%rsp) + .endm + .macro pax_force_fptr ptr + orq %r10,\ptr + .endm + .macro pax_set_fptr_mask + movabs $0x8000000000000000,%r10 + .endm +#endif +#else + .macro pax_force_retaddr rip=0, reload=0 + .endm + .macro pax_force_fptr ptr + .endm + .macro pax_force_retaddr_bts rip=0 + .endm + .macro pax_set_fptr_mask + .endm +#endif + .macro altinstruction_entry orig alt feature orig_len alt_len .long \orig - . .long \alt - . diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 58ed6d9..f1cbe58 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -105,7 +105,7 @@ static inline int alternatives_text_reserved(void *start, void *end) ".pushsection .discard,\"aw\",@progbits\n" \ DISCARD_ENTRY(1) \ ".popsection\n" \ - ".pushsection .altinstr_replacement, \"ax\"\n" \ + ".pushsection .altinstr_replacement, \"a\"\n" \ ALTINSTR_REPLACEMENT(newinstr, feature, 1) \ ".popsection" @@ -119,7 +119,7 @@ static inline int alternatives_text_reserved(void *start, void *end) DISCARD_ENTRY(1) \ DISCARD_ENTRY(2) \ ".popsection\n" \ - ".pushsection .altinstr_replacement, \"ax\"\n" \ + ".pushsection .altinstr_replacement, \"a\"\n" \ ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \ ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \ ".popsection" diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 3388034..050f0b9 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -44,7 +44,7 @@ static inline void generic_apic_probe(void) #ifdef CONFIG_X86_LOCAL_APIC -extern unsigned int apic_verbosity; +extern int apic_verbosity; extern int local_apic_timer_c2_ok; extern int disable_apic; diff --git a/arch/x86/include/asm/apm.h b/arch/x86/include/asm/apm.h index 20370c6..a2eb9b0 100644 --- a/arch/x86/include/asm/apm.h +++ b/arch/x86/include/asm/apm.h @@ -34,7 +34,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in, __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" - "lcall *%%cs:apm_bios_entry\n\t" + "lcall *%%ss:apm_bios_entry\n\t" "setc %%al\n\t" "popl %%ebp\n\t" "popl %%edi\n\t" @@ -58,7 +58,7 @@ static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in, __asm__ __volatile__(APM_DO_ZERO_SEGS "pushl %%edi\n\t" "pushl %%ebp\n\t" - "lcall *%%cs:apm_bios_entry\n\t" + "lcall *%%ss:apm_bios_entry\n\t" "setc %%bl\n\t" "popl %%ebp\n\t" "popl %%edi\n\t" diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 722aa3b..3a0bb27 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -22,7 +22,18 @@ */ static inline int atomic_read(const atomic_t *v) { - return (*(volatile int *)&(v)->counter); + return (*(volatile const int *)&(v)->counter); +} + +/** + * atomic_read_unchecked - read atomic variable + * @v: pointer of type atomic_unchecked_t + * + * Atomically reads the value of @v. + */ +static inline int atomic_read_unchecked(const atomic_unchecked_t *v) +{ + return (*(volatile const int *)&(v)->counter); } /** @@ -38,6 +49,18 @@ static inline void atomic_set(atomic_t *v, int i) } /** + * atomic_set_unchecked - set atomic variable + * @v: pointer of type atomic_unchecked_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i) +{ + v->counter = i; +} + +/** * atomic_add - add integer to atomic variable * @i: integer value to add * @v: pointer of type atomic_t @@ -46,7 +69,29 @@ static inline void atomic_set(atomic_t *v, int i) */ static inline void atomic_add(int i, atomic_t *v) { - asm volatile(LOCK_PREFIX "addl %1,%0" + asm volatile(LOCK_PREFIX "addl %1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "subl %1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (v->counter) + : "ir" (i)); +} + +/** + * atomic_add_unchecked - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_unchecked_t + * + * Atomically adds @i to @v. + */ +static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "addl %1,%0\n" : "+m" (v->counter) : "ir" (i)); } @@ -60,7 +105,29 @@ static inline void atomic_add(int i, atomic_t *v) */ static inline void atomic_sub(int i, atomic_t *v) { - asm volatile(LOCK_PREFIX "subl %1,%0" + asm volatile(LOCK_PREFIX "subl %1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "addl %1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (v->counter) + : "ir" (i)); +} + +/** + * atomic_sub_unchecked - subtract integer from atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_unchecked_t + * + * Atomically subtracts @i from @v. + */ +static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "subl %1,%0\n" : "+m" (v->counter) : "ir" (i)); } @@ -78,7 +145,16 @@ static inline int atomic_sub_and_test(int i, atomic_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "subl %2,%0; sete %1" + asm volatile(LOCK_PREFIX "subl %2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "addl %2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "+m" (v->counter), "=qm" (c) : "ir" (i) : "memory"); return c; @@ -92,7 +168,27 @@ static inline int atomic_sub_and_test(int i, atomic_t *v) */ static inline void atomic_inc(atomic_t *v) { - asm volatile(LOCK_PREFIX "incl %0" + asm volatile(LOCK_PREFIX "incl %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "decl %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (v->counter)); +} + +/** + * atomic_inc_unchecked - increment atomic variable + * @v: pointer of type atomic_unchecked_t + * + * Atomically increments @v by 1. + */ +static inline void atomic_inc_unchecked(atomic_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "incl %0\n" : "+m" (v->counter)); } @@ -104,7 +200,27 @@ static inline void atomic_inc(atomic_t *v) */ static inline void atomic_dec(atomic_t *v) { - asm volatile(LOCK_PREFIX "decl %0" + asm volatile(LOCK_PREFIX "decl %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "incl %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (v->counter)); +} + +/** + * atomic_dec_unchecked - decrement atomic variable + * @v: pointer of type atomic_unchecked_t + * + * Atomically decrements @v by 1. + */ +static inline void atomic_dec_unchecked(atomic_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "decl %0\n" : "+m" (v->counter)); } @@ -120,7 +236,16 @@ static inline int atomic_dec_and_test(atomic_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "decl %0; sete %1" + asm volatile(LOCK_PREFIX "decl %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "incl %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "+m" (v->counter), "=qm" (c) : : "memory"); return c != 0; @@ -138,7 +263,35 @@ static inline int atomic_inc_and_test(atomic_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "incl %0; sete %1" + asm volatile(LOCK_PREFIX "incl %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "decl %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" + : "+m" (v->counter), "=qm" (c) + : : "memory"); + return c != 0; +} + +/** + * atomic_inc_and_test_unchecked - increment and test + * @v: pointer of type atomic_unchecked_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +static inline int atomic_inc_and_test_unchecked(atomic_unchecked_t *v) +{ + unsigned char c; + + asm volatile(LOCK_PREFIX "incl %0\n" + "sete %1\n" : "+m" (v->counter), "=qm" (c) : : "memory"); return c != 0; @@ -157,7 +310,16 @@ static inline int atomic_add_negative(int i, atomic_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "addl %2,%0; sets %1" + asm volatile(LOCK_PREFIX "addl %2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "subl %2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sets %1\n" : "+m" (v->counter), "=qm" (c) : "ir" (i) : "memory"); return c; @@ -172,6 +334,18 @@ static inline int atomic_add_negative(int i, atomic_t *v) */ static inline int atomic_add_return(int i, atomic_t *v) { + return i + xadd_check_overflow(&v->counter, i); +} + +/** + * atomic_add_return_unchecked - add integer and return + * @i: integer value to add + * @v: pointer of type atomic_unchecked_t + * + * Atomically adds @i to @v and returns @i + @v + */ +static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) +{ return i + xadd(&v->counter, i); } @@ -188,6 +362,10 @@ static inline int atomic_sub_return(int i, atomic_t *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); +} #define atomic_dec_return(v) (atomic_sub_return(1, v)) static inline int atomic_cmpxchg(atomic_t *v, int old, int new) @@ -195,11 +373,21 @@ 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 already a given value * @v: pointer of type atomic_t @@ -211,12 +399,25 @@ static inline int atomic_xchg(atomic_t *v, int new) */ static inline int __atomic_add_unless(atomic_t *v, int a, int u) { - int c, old; + int c, old, new; c = atomic_read(v); for (;;) { - if (unlikely(c == (u))) + if (unlikely(c == u)) break; - old = atomic_cmpxchg((v), c, c + (a)); + + asm volatile("addl %2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "subl %2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=r" (new) + : "0" (c), "ir" (a)); + + old = atomic_cmpxchg(v, c, new); if (likely(old == c)) break; c = old; @@ -225,6 +426,49 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) } /** + * atomic_inc_not_zero_hint - increment if not null + * @v: pointer of type atomic_t + * @hint: probable value of the atomic before the increment + * + * This version of atomic_inc_not_zero() gives a hint of probable + * value of the atomic. This helps processor to not read the memory + * before doing the atomic read/modify/write cycle, lowering + * number of bus transactions on some arches. + * + * Returns: 0 if increment was not done, 1 otherwise. + */ +#define atomic_inc_not_zero_hint atomic_inc_not_zero_hint +static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint) +{ + int val, c = hint, new; + + /* sanity test, should be removed by compiler if hint is a constant */ + if (!hint) + return __atomic_add_unless(v, 1, 0); + + do { + asm volatile("incl %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "decl %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=r" (new) + : "0" (c)); + + val = atomic_cmpxchg(v, c, new); + if (val == c) + return 1; + c = val; + } while (c); + + return 0; +} + +/** * atomic_inc_short - increment of a short integer * @v: pointer to type int * @@ -253,14 +497,37 @@ static inline void atomic_or_long(unsigned long *v1, unsigned long v2) #endif /* These are x86-specific, used by some header files */ -#define atomic_clear_mask(mask, addr) \ - asm volatile(LOCK_PREFIX "andl %0,%1" \ - : : "r" (~(mask)), "m" (*(addr)) : "memory") - -#define atomic_set_mask(mask, addr) \ - asm volatile(LOCK_PREFIX "orl %0,%1" \ - : : "r" ((unsigned)(mask)), "m" (*(addr)) \ - : "memory") +static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) +{ + asm volatile(LOCK_PREFIX "andl %1,%0" + : "+m" (v->counter) + : "r" (~(mask)) + : "memory"); +} + +static inline void atomic_clear_mask_unchecked(unsigned int mask, atomic_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "andl %1,%0" + : "+m" (v->counter) + : "r" (~(mask)) + : "memory"); +} + +static inline void atomic_set_mask(unsigned int mask, atomic_t *v) +{ + asm volatile(LOCK_PREFIX "orl %1,%0" + : "+m" (v->counter) + : "r" (mask) + : "memory"); +} + +static inline void atomic_set_mask_unchecked(unsigned int mask, atomic_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "orl %1,%0" + : "+m" (v->counter) + : "r" (mask) + : "memory"); +} /* Atomic operations are already serializing on x86 */ #define smp_mb__before_atomic_dec() barrier() diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index b154de7..aadebd8 100644 --- a/arch/x86/include/asm/atomic64_32.h +++ b/arch/x86/include/asm/atomic64_32.h @@ -12,6 +12,14 @@ typedef struct { u64 __aligned(8) counter; } atomic64_t; +#ifdef CONFIG_PAX_REFCOUNT +typedef struct { + u64 __aligned(8) counter; +} atomic64_unchecked_t; +#else +typedef atomic64_t atomic64_unchecked_t; +#endif + #define ATOMIC64_INIT(val) { (val) } #define __ATOMIC64_DECL(sym) void atomic64_##sym(atomic64_t *, ...) @@ -37,21 +45,31 @@ typedef struct { ATOMIC64_DECL_ONE(sym##_386) ATOMIC64_DECL_ONE(add_386); +ATOMIC64_DECL_ONE(add_unchecked_386); ATOMIC64_DECL_ONE(sub_386); +ATOMIC64_DECL_ONE(sub_unchecked_386); ATOMIC64_DECL_ONE(inc_386); +ATOMIC64_DECL_ONE(inc_unchecked_386); ATOMIC64_DECL_ONE(dec_386); +ATOMIC64_DECL_ONE(dec_unchecked_386); #endif #define alternative_atomic64(f, out, in...) \ __alternative_atomic64(f, f, ASM_OUTPUT2(out), ## in) ATOMIC64_DECL(read); +ATOMIC64_DECL(read_unchecked); ATOMIC64_DECL(set); +ATOMIC64_DECL(set_unchecked); ATOMIC64_DECL(xchg); ATOMIC64_DECL(add_return); +ATOMIC64_DECL(add_return_unchecked); ATOMIC64_DECL(sub_return); +ATOMIC64_DECL(sub_return_unchecked); ATOMIC64_DECL(inc_return); +ATOMIC64_DECL(inc_return_unchecked); ATOMIC64_DECL(dec_return); +ATOMIC64_DECL(dec_return_unchecked); ATOMIC64_DECL(dec_if_positive); ATOMIC64_DECL(inc_not_zero); ATOMIC64_DECL(add_unless); @@ -77,6 +95,21 @@ static inline long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n } /** + * atomic64_cmpxchg_unchecked - cmpxchg atomic64 variable + * @p: pointer to type atomic64_unchecked_t + * @o: expected value + * @n: new value + * + * Atomically sets @v to @n if it was equal to @o and returns + * the old value. + */ + +static inline long long atomic64_cmpxchg_unchecked(atomic64_unchecked_t *v, long long o, long long n) +{ + return cmpxchg64(&v->counter, o, n); +} + +/** * atomic64_xchg - xchg atomic64 variable * @v: pointer to type atomic64_t * @n: value to assign @@ -112,6 +145,22 @@ static inline void atomic64_set(atomic64_t *v, long long i) } /** + * atomic64_set_unchecked - set atomic64 variable + * @v: pointer to type atomic64_unchecked_t + * @n: value to assign + * + * Atomically sets the value of @v to @n. + */ +static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long long i) +{ + unsigned high = (unsigned)(i >> 32); + unsigned low = (unsigned)i; + alternative_atomic64(set, /* no output */, + "S" (v), "b" (low), "c" (high) + : "eax", "edx", "memory"); +} + +/** * atomic64_read - read atomic64 variable * @v: pointer to type atomic64_t * @@ -125,6 +174,19 @@ static inline long long atomic64_read(const atomic64_t *v) } /** + * atomic64_read_unchecked - read atomic64 variable + * @v: pointer to type atomic64_unchecked_t + * + * Atomically reads the value of @v and returns it. + */ +static inline long long atomic64_read_unchecked(atomic64_unchecked_t *v) +{ + long long r; + alternative_atomic64(read, "=&A" (r), "c" (v) : "memory"); + return r; + } + +/** * atomic64_add_return - add and return * @i: integer value to add * @v: pointer to type atomic64_t @@ -139,6 +201,21 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v) return i; } +/** + * atomic64_add_return_unchecked - add and return + * @i: integer value to add + * @v: pointer to type atomic64_unchecked_t + * + * Atomically adds @i to @v and returns @i + *@v + */ +static inline long long atomic64_add_return_unchecked(long long i, atomic64_unchecked_t *v) +{ + alternative_atomic64(add_return_unchecked, + ASM_OUTPUT2("+A" (i), "+c" (v)), + ASM_NO_INPUT_CLOBBER("memory")); + return i; +} + /* * Other variants with different arithmetic operators: */ @@ -158,6 +235,14 @@ static inline long long atomic64_inc_return(atomic64_t *v) return a; } +static inline long long atomic64_inc_return_unchecked(atomic64_unchecked_t *v) +{ + long long a; + alternative_atomic64(inc_return_unchecked, "=&A" (a), + "S" (v) : "memory", "ecx"); + return a; +} + static inline long long atomic64_dec_return(atomic64_t *v) { long long a; @@ -182,6 +267,21 @@ static inline long long atomic64_add(long long i, atomic64_t *v) } /** + * atomic64_add_unchecked - add integer to atomic64 variable + * @i: integer value to add + * @v: pointer to type atomic64_unchecked_t + * + * Atomically adds @i to @v. + */ +static inline long long atomic64_add_unchecked(long long i, atomic64_unchecked_t *v) +{ + __alternative_atomic64(add_unchecked, add_return_unchecked, + ASM_OUTPUT2("+A" (i), "+c" (v)), + ASM_NO_INPUT_CLOBBER("memory")); + return i; +} + +/** * atomic64_sub - subtract the atomic64 variable * @i: integer value to subtract * @v: pointer to type atomic64_t diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 0e1cbfc..5623683 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h @@ -18,7 +18,19 @@ */ static inline long atomic64_read(const atomic64_t *v) { - return (*(volatile long *)&(v)->counter); + return (*(volatile const long *)&(v)->counter); +} + +/** + * atomic64_read_unchecked - read atomic64 variable + * @v: pointer of type atomic64_unchecked_t + * + * Atomically reads the value of @v. + * Doesn't imply a read memory barrier. + */ +static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v) +{ + return (*(volatile const long *)&(v)->counter); } /** @@ -34,6 +46,18 @@ static inline void atomic64_set(atomic64_t *v, long i) } /** + * atomic64_set_unchecked - set atomic64 variable + * @v: pointer to type atomic64_unchecked_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i) +{ + v->counter = i; +} + +/** * atomic64_add - add integer to atomic64 variable * @i: integer value to add * @v: pointer to type atomic64_t @@ -42,6 +66,28 @@ static inline void atomic64_set(atomic64_t *v, long i) */ static inline void atomic64_add(long i, atomic64_t *v) { + asm volatile(LOCK_PREFIX "addq %1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "subq %1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=m" (v->counter) + : "er" (i), "m" (v->counter)); +} + +/** + * atomic64_add_unchecked - add integer to atomic64 variable + * @i: integer value to add + * @v: pointer to type atomic64_unchecked_t + * + * Atomically adds @i to @v. + */ +static inline void atomic64_add_unchecked(long i, atomic64_unchecked_t *v) +{ asm volatile(LOCK_PREFIX "addq %1,%0" : "=m" (v->counter) : "er" (i), "m" (v->counter)); @@ -56,7 +102,29 @@ static inline void atomic64_add(long i, atomic64_t *v) */ static inline void atomic64_sub(long i, atomic64_t *v) { - asm volatile(LOCK_PREFIX "subq %1,%0" + asm volatile(LOCK_PREFIX "subq %1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "addq %1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=m" (v->counter) + : "er" (i), "m" (v->counter)); +} + +/** + * atomic64_sub_unchecked - subtract the atomic64 variable + * @i: integer value to subtract + * @v: pointer to type atomic64_unchecked_t + * + * Atomically subtracts @i from @v. + */ +static inline void atomic64_sub_unchecked(long i, atomic64_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "subq %1,%0\n" : "=m" (v->counter) : "er" (i), "m" (v->counter)); } @@ -74,7 +142,16 @@ static inline int atomic64_sub_and_test(long i, atomic64_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "subq %2,%0; sete %1" + asm volatile(LOCK_PREFIX "subq %2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "addq %2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "=m" (v->counter), "=qm" (c) : "er" (i), "m" (v->counter) : "memory"); return c; @@ -88,6 +165,27 @@ static inline int atomic64_sub_and_test(long i, atomic64_t *v) */ static inline void atomic64_inc(atomic64_t *v) { + asm volatile(LOCK_PREFIX "incq %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "decq %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=m" (v->counter) + : "m" (v->counter)); +} + +/** + * atomic64_inc_unchecked - increment atomic64 variable + * @v: pointer to type atomic64_unchecked_t + * + * Atomically increments @v by 1. + */ +static inline void atomic64_inc_unchecked(atomic64_unchecked_t *v) +{ asm volatile(LOCK_PREFIX "incq %0" : "=m" (v->counter) : "m" (v->counter)); @@ -101,7 +199,28 @@ static inline void atomic64_inc(atomic64_t *v) */ static inline void atomic64_dec(atomic64_t *v) { - asm volatile(LOCK_PREFIX "decq %0" + asm volatile(LOCK_PREFIX "decq %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "incq %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=m" (v->counter) + : "m" (v->counter)); +} + +/** + * atomic64_dec_unchecked - decrement atomic64 variable + * @v: pointer to type atomic64_t + * + * Atomically decrements @v by 1. + */ +static inline void atomic64_dec_unchecked(atomic64_unchecked_t *v) +{ + asm volatile(LOCK_PREFIX "decq %0\n" : "=m" (v->counter) : "m" (v->counter)); } @@ -118,7 +237,16 @@ static inline int atomic64_dec_and_test(atomic64_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "decq %0; sete %1" + asm volatile(LOCK_PREFIX "decq %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "incq %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "=m" (v->counter), "=qm" (c) : "m" (v->counter) : "memory"); return c != 0; @@ -136,7 +264,16 @@ static inline int atomic64_inc_and_test(atomic64_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "incq %0; sete %1" + asm volatile(LOCK_PREFIX "incq %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "decq %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "=m" (v->counter), "=qm" (c) : "m" (v->counter) : "memory"); return c != 0; @@ -155,7 +292,16 @@ static inline int atomic64_add_negative(long i, atomic64_t *v) { unsigned char c; - asm volatile(LOCK_PREFIX "addq %2,%0; sets %1" + asm volatile(LOCK_PREFIX "addq %2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX "subq %2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sets %1\n" : "=m" (v->counter), "=qm" (c) : "er" (i), "m" (v->counter) : "memory"); return c; @@ -170,6 +316,18 @@ static inline int atomic64_add_negative(long i, atomic64_t *v) */ static inline long atomic64_add_return(long i, atomic64_t *v) { + return i + xadd_check_overflow(&v->counter, i); +} + +/** + * atomic64_add_return_unchecked - add and return + * @i: integer value to add + * @v: pointer to type atomic64_unchecked_t + * + * Atomically adds @i to @v and returns @i + @v + */ +static inline long atomic64_add_return_unchecked(long i, atomic64_unchecked_t *v) +{ return i + xadd(&v->counter, i); } @@ -179,6 +337,10 @@ static inline long atomic64_sub_return(long i, atomic64_t *v) } #define atomic64_inc_return(v) (atomic64_add_return(1, (v))) +static inline long atomic64_inc_return_unchecked(atomic64_unchecked_t *v) +{ + return atomic64_add_return_unchecked(1, v); +} #define atomic64_dec_return(v) (atomic64_sub_return(1, (v))) static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) @@ -186,6 +348,11 @@ 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); @@ -202,17 +369,30 @@ static inline long atomic64_xchg(atomic64_t *v, long new) */ static inline int atomic64_add_unless(atomic64_t *v, long a, long u) { - long c, old; + long c, old, new; c = atomic64_read(v); for (;;) { - if (unlikely(c == (u))) + if (unlikely(c == u)) break; - old = atomic64_cmpxchg((v), c, c + (a)); + + asm volatile("add %2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "sub %2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "=r" (new) + : "0" (c), "ir" (a)); + + old = atomic64_cmpxchg(v, c, new); if (likely(old == c)) break; c = old; } - return c != (u); + return c != u; } #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 6dfd019..28e188d 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -40,7 +40,7 @@ * a mask operation on a byte. */ #define IS_IMMEDIATE(nr) (__builtin_constant_p(nr)) -#define CONST_MASK_ADDR(nr, addr) BITOP_ADDR((void *)(addr) + ((nr)>>3)) +#define CONST_MASK_ADDR(nr, addr) BITOP_ADDR((volatile void *)(addr) + ((nr)>>3)) #define CONST_MASK(nr) (1 << ((nr) & 7)) /** @@ -486,7 +486,7 @@ static inline int fls(int x) * at position 64. */ #ifdef CONFIG_X86_64 -static __always_inline int fls64(__u64 x) +static __always_inline long fls64(__u64 x) { int bitpos = -1; /* diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index 4fa687a..60f2d39 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h @@ -6,10 +6,15 @@ #include /* Physical address where kernel should be loaded. */ -#define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ +#define ____LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ + (CONFIG_PHYSICAL_ALIGN - 1)) \ & ~(CONFIG_PHYSICAL_ALIGN - 1)) +#ifndef __ASSEMBLY__ +extern unsigned char __LOAD_PHYSICAL_ADDR[]; +#define LOAD_PHYSICAL_ADDR ((unsigned long)__LOAD_PHYSICAL_ADDR) +#endif + /* Minimum kernel alignment, as a power of two */ #ifdef CONFIG_X86_64 #define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h index 48f99f1..d78ebf9 100644 --- a/arch/x86/include/asm/cache.h +++ b/arch/x86/include/asm/cache.h @@ -5,12 +5,13 @@ /* L1 cache line size */ #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define L1_CACHE_BYTES (_AC(1,UL) << L1_CACHE_SHIFT) #define __read_mostly __attribute__((__section__(".data..read_mostly"))) +#define __read_only __attribute__((__section__(".data..read_only"))) #define INTERNODE_CACHE_SHIFT CONFIG_X86_INTERNODE_CACHE_SHIFT -#define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT) +#define INTERNODE_CACHE_BYTES (_AC(1,UL) << INTERNODE_CACHE_SHIFT) #ifdef CONFIG_X86_VSMP #ifdef CONFIG_SMP diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index 9863ee3..4a1f8e1 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h @@ -27,7 +27,7 @@ static inline unsigned long get_page_memtype(struct page *pg) unsigned long pg_flags = pg->flags & _PGMT_MASK; if (pg_flags == _PGMT_DEFAULT) - return -1; + return ~0UL; else if (pg_flags == _PGMT_WC) return _PAGE_CACHE_WC; else if (pg_flags == _PGMT_UC_MINUS) diff --git a/arch/x86/include/asm/checksum_32.h b/arch/x86/include/asm/checksum_32.h index f50de69..2b0a458 100644 --- a/arch/x86/include/asm/checksum_32.h +++ b/arch/x86/include/asm/checksum_32.h @@ -31,6 +31,14 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr); +asmlinkage __wsum csum_partial_copy_generic_to_user(const void *src, void *dst, + int len, __wsum sum, + int *src_err_ptr, int *dst_err_ptr); + +asmlinkage __wsum csum_partial_copy_generic_from_user(const void *src, void *dst, + int len, __wsum sum, + int *src_err_ptr, int *dst_err_ptr); + /* * Note: when you get a NULL pointer exception here this means someone * passed in an incorrect kernel address to one of these functions. @@ -53,7 +61,7 @@ static inline __wsum csum_partial_copy_from_user(const void __user *src, might_sleep(); stac(); - ret = csum_partial_copy_generic((__force void *)src, dst, + ret = csum_partial_copy_generic_from_user((__force void *)src, dst, len, sum, err_ptr, NULL); clac(); @@ -187,7 +195,7 @@ static inline __wsum csum_and_copy_to_user(const void *src, might_sleep(); if (access_ok(VERIFY_WRITE, dst, len)) { stac(); - ret = csum_partial_copy_generic(src, (__force void *)dst, + ret = csum_partial_copy_generic_to_user(src, (__force void *)dst, len, sum, NULL, err_ptr); clac(); return ret; diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index d47786a..ce1b05d 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -14,8 +14,12 @@ extern void __cmpxchg_wrong_size(void) __compiletime_error("Bad argument size for cmpxchg"); extern void __xadd_wrong_size(void) __compiletime_error("Bad argument size for xadd"); +extern void __xadd_check_overflow_wrong_size(void) + __compiletime_error("Bad argument size for xadd_check_overflow"); extern void __add_wrong_size(void) __compiletime_error("Bad argument size for add"); +extern void __add_check_overflow_wrong_size(void) + __compiletime_error("Bad argument size for add_check_overflow"); /* * Constants for operation sizes. On 32-bit, the 64-bit size it set to @@ -67,6 +71,34 @@ extern void __add_wrong_size(void) __ret; \ }) +#define __xchg_op_check_overflow(ptr, arg, op, lock) \ + ({ \ + __typeof__ (*(ptr)) __ret = (arg); \ + switch (sizeof(*(ptr))) { \ + case __X86_CASE_L: \ + asm volatile (lock #op "l %0, %1\n" \ + "jno 0f\n" \ + "mov %0,%1\n" \ + "int $4\n0:\n" \ + _ASM_EXTABLE(0b, 0b) \ + : "+r" (__ret), "+m" (*(ptr)) \ + : : "memory", "cc"); \ + break; \ + case __X86_CASE_Q: \ + asm volatile (lock #op "q %q0, %1\n" \ + "jno 0f\n" \ + "mov %0,%1\n" \ + "int $4\n0:\n" \ + _ASM_EXTABLE(0b, 0b) \ + : "+r" (__ret), "+m" (*(ptr)) \ + : : "memory", "cc"); \ + break; \ + default: \ + __ ## op ## _check_overflow_wrong_size(); \ + } \ + __ret; \ + }) + /* * Note: no "lock" prefix even on SMP: xchg always implies lock anyway. * Since this is generally used to protect other memory information, we @@ -167,6 +199,9 @@ extern void __add_wrong_size(void) #define xadd_sync(ptr, inc) __xadd((ptr), (inc), "lock; ") #define xadd_local(ptr, inc) __xadd((ptr), (inc), "") +#define __xadd_check_overflow(ptr, inc, lock) __xchg_op_check_overflow((ptr), (inc), xadd, lock) +#define xadd_check_overflow(ptr, inc) __xadd_check_overflow((ptr), (inc), LOCK_PREFIX) + #define __add(ptr, inc, lock) \ ({ \ __typeof__ (*(ptr)) __ret = (inc); \ diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 59c6c40..5e0b22c 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -41,7 +41,7 @@ typedef s64 __attribute__((aligned(4))) compat_s64; typedef u32 compat_uint_t; typedef u32 compat_ulong_t; typedef u64 __attribute__((aligned(4))) compat_u64; -typedef u32 compat_uptr_t; +typedef u32 __user compat_uptr_t; struct compat_timespec { compat_time_t tv_sec; diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index e99ac27..10d834e 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -203,7 +203,7 @@ #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ - +#define X86_FEATURE_STRONGUDEREF (8*32+31) /* PaX PCID based strong UDEREF */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ #define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ @@ -211,7 +211,7 @@ #define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */ #define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision */ #define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */ -#define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Protection */ +#define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Prevention */ #define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */ #define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */ #define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */ @@ -353,6 +353,7 @@ extern const char * const x86_power_flags[32]; #undef cpu_has_centaur_mcr #define cpu_has_centaur_mcr 0 +#define cpu_has_pcid boot_cpu_has(X86_FEATURE_PCID) #endif /* CONFIG_X86_64 */ #if __GNUC__ >= 4 @@ -394,7 +395,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) ".section .discard,\"aw\",@progbits\n" " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" + ".section .altinstr_replacement,\"a\"\n" "3: movb $1,%0\n" "4:\n" ".previous\n" diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index 8bf1c06..b6ae785 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in desc->type = (info->read_exec_only ^ 1) << 1; desc->type |= info->contents << 2; + desc->type |= info->seg_not_present ^ 1; desc->s = 1; desc->dpl = 0x3; @@ -35,19 +37,14 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in } extern struct desc_ptr idt_descr; -extern gate_desc idt_table[]; extern struct desc_ptr nmi_idt_descr; -extern gate_desc nmi_idt_table[]; - -struct gdt_page { - struct desc_struct gdt[GDT_ENTRIES]; -} __attribute__((aligned(PAGE_SIZE))); - -DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page); +extern gate_desc idt_table[256]; +extern gate_desc nmi_idt_table[256]; +extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)]; static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) { - return per_cpu(gdt_page, cpu).gdt; + return cpu_gdt_table[cpu]; } #ifdef CONFIG_X86_64 @@ -72,8 +69,14 @@ static inline void pack_gate(gate_desc *gate, unsigned char type, unsigned long base, unsigned dpl, unsigned flags, unsigned short seg) { - gate->a = (seg << 16) | (base & 0xffff); - gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8); + gate->gate.offset_low = base; + gate->gate.seg = seg; + gate->gate.reserved = 0; + gate->gate.type = type; + gate->gate.s = 0; + gate->gate.dpl = dpl; + gate->gate.p = 1; + gate->gate.offset_high = base >> 16; } #endif @@ -118,12 +121,16 @@ static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries) static inline void native_write_idt_entry(gate_desc *idt, int entry, const gate_desc *gate) { + pax_open_kernel(); memcpy(&idt[entry], gate, sizeof(*gate)); + pax_close_kernel(); } static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry, const void *desc) { + pax_open_kernel(); memcpy(&ldt[entry], desc, 8); + pax_close_kernel(); } static inline void @@ -137,7 +144,9 @@ native_write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc, int default: size = sizeof(*gdt); break; } + pax_open_kernel(); memcpy(&gdt[entry], desc, size); + pax_close_kernel(); } static inline void pack_descriptor(struct desc_struct *desc, unsigned long base, @@ -210,7 +219,9 @@ static inline void native_set_ldt(const void *addr, unsigned int entries) static inline void native_load_tr_desc(void) { + pax_open_kernel(); asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); + pax_close_kernel(); } static inline void native_load_gdt(const struct desc_ptr *dtr) @@ -247,8 +258,10 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) struct desc_struct *gdt = get_cpu_gdt_table(cpu); unsigned int i; + pax_open_kernel(); for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; + pax_close_kernel(); } #define _LDT_empty(info) \ @@ -287,7 +300,7 @@ static inline void load_LDT(mm_context_t *pc) preempt_enable(); } -static inline unsigned long get_desc_base(const struct desc_struct *desc) +static inline unsigned long __intentional_overflow(-1) get_desc_base(const struct desc_struct *desc) { return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24)); } @@ -311,7 +324,7 @@ static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) } #ifdef CONFIG_X86_64 -static inline void set_nmi_gate(int gate, void *addr) +static inline void set_nmi_gate(int gate, const void *addr) { gate_desc s; @@ -320,7 +333,7 @@ static inline void set_nmi_gate(int gate, void *addr) } #endif -static inline void _set_gate(int gate, unsigned type, void *addr, +static inline void _set_gate(int gate, unsigned type, const void *addr, unsigned dpl, unsigned ist, unsigned seg) { gate_desc s; @@ -339,7 +352,7 @@ static inline void _set_gate(int gate, unsigned type, void *addr, * Pentium F0 0F bugfix can have resulted in the mapped * IDT being write-protected. */ -static inline void set_intr_gate(unsigned int n, void *addr) +static inline void set_intr_gate(unsigned int n, const void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS); @@ -369,19 +382,19 @@ static inline void alloc_intr_gate(unsigned int n, void *addr) /* * This routine sets up an interrupt gate at directory privilege level 3. */ -static inline void set_system_intr_gate(unsigned int n, void *addr) +static inline void set_system_intr_gate(unsigned int n, const void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); } -static inline void set_system_trap_gate(unsigned int n, void *addr) +static inline void set_system_trap_gate(unsigned int n, const void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS); } -static inline void set_trap_gate(unsigned int n, void *addr) +static inline void set_trap_gate(unsigned int n, const void *addr) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS); @@ -390,19 +403,31 @@ static inline void set_trap_gate(unsigned int n, void *addr) static inline void set_task_gate(unsigned int n, unsigned int gdt_entry) { BUG_ON((unsigned)n > 0xFF); - _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3)); + _set_gate(n, GATE_TASK, (const void *)0, 0, 0, (gdt_entry<<3)); } -static inline void set_intr_gate_ist(int n, void *addr, unsigned ist) +static inline void set_intr_gate_ist(int n, const void *addr, unsigned ist) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS); } -static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist) +static inline void set_system_intr_gate_ist(int n, const void *addr, unsigned ist) { BUG_ON((unsigned)n > 0xFF); _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); } +#ifdef CONFIG_X86_32 +static inline void set_user_cs(unsigned long base, unsigned long limit, int cpu) +{ + struct desc_struct d; + + if (likely(limit)) + limit = (limit - 1UL) >> PAGE_SHIFT; + pack_descriptor(&d, base, limit, 0xFB, 0xC); + write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_CS, &d, DESCTYPE_S); +} +#endif + #endif /* _ASM_X86_DESC_H */ diff --git a/arch/x86/include/asm/desc_defs.h b/arch/x86/include/asm/desc_defs.h index 278441f..b95a174 100644 --- a/arch/x86/include/asm/desc_defs.h +++ b/arch/x86/include/asm/desc_defs.h @@ -31,6 +31,12 @@ struct desc_struct { unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1; unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8; }; + struct { + u16 offset_low; + u16 seg; + unsigned reserved: 8, type: 4, s: 1, dpl: 2, p: 1; + unsigned offset_high: 16; + } gate; }; } __attribute__((packed)); diff --git a/arch/x86/include/asm/div64.h b/arch/x86/include/asm/div64.h index ced283a..ffe04cc 100644 --- a/arch/x86/include/asm/div64.h +++ b/arch/x86/include/asm/div64.h @@ -39,7 +39,7 @@ __mod; \ }) -static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) +static inline u64 __intentional_overflow(-1) div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) { union { u64 v64; diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 9c999c1..3860cb8 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -243,7 +243,25 @@ extern int force_personality32; 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. */ +#ifdef CONFIG_PAX_SEGMEXEC +#define ELF_ET_DYN_BASE ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2) +#else #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) +#endif + +#ifdef CONFIG_PAX_ASLR +#ifdef CONFIG_X86_32 +#define PAX_ELF_ET_DYN_BASE 0x10000000UL + +#define PAX_DELTA_MMAP_LEN (current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16) +#define PAX_DELTA_STACK_LEN (current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16) +#else +#define PAX_ELF_ET_DYN_BASE 0x400000UL + +#define PAX_DELTA_MMAP_LEN ((test_thread_flag(TIF_ADDR32)) ? 16 : TASK_SIZE_MAX_SHIFT - PAGE_SHIFT - 3) +#define PAX_DELTA_STACK_LEN ((test_thread_flag(TIF_ADDR32)) ? 16 : TASK_SIZE_MAX_SHIFT - PAGE_SHIFT - 3) +#endif +#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, @@ -296,16 +314,12 @@ do { \ #define ARCH_DLINFO \ do { \ - if (vdso_enabled) \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, \ - (unsigned long)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso); \ } while (0) #define ARCH_DLINFO_X32 \ do { \ - if (vdso_enabled) \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, \ - (unsigned long)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso); \ } while (0) #define AT_SYSINFO 32 @@ -320,7 +334,7 @@ else \ #endif /* !CONFIG_X86_32 */ -#define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso) +#define VDSO_CURRENT_BASE (current->mm->context.vdso) #define VDSO_ENTRY \ ((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall)) @@ -336,9 +350,6 @@ extern int x32_setup_additional_pages(struct linux_binprm *bprm, extern int syscall32_setup_pages(struct linux_binprm *, int exstack); #define compat_arch_setup_additional_pages syscall32_setup_pages -extern unsigned long arch_randomize_brk(struct mm_struct *mm); -#define arch_randomize_brk arch_randomize_brk - /* * True on X86_32 or when emulating IA32 on X86_64 */ diff --git a/arch/x86/include/asm/emergency-restart.h b/arch/x86/include/asm/emergency-restart.h index 75ce3f4..882e801 100644 --- a/arch/x86/include/asm/emergency-restart.h +++ b/arch/x86/include/asm/emergency-restart.h @@ -13,6 +13,6 @@ enum reboot_type { extern enum reboot_type reboot_type; -extern void machine_emergency_restart(void); +extern void machine_emergency_restart(void) __noreturn; #endif /* _ASM_X86_EMERGENCY_RESTART_H */ diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index e25cc33..7d3ec01 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h @@ -126,8 +126,11 @@ static inline void sanitize_i387_state(struct task_struct *tsk) #define user_insn(insn, output, input...) \ ({ \ int err; \ + pax_open_userland(); \ asm volatile(ASM_STAC "\n" \ - "1:" #insn "\n\t" \ + "1:" \ + __copyuser_seg \ + #insn "\n\t" \ "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "3: movl $-1,%[err]\n" \ @@ -136,6 +139,7 @@ static inline void sanitize_i387_state(struct task_struct *tsk) _ASM_EXTABLE(1b, 3b) \ : [err] "=r" (err), output \ : "0"(0), input); \ + pax_close_userland(); \ err; \ }) @@ -300,7 +304,7 @@ static inline int restore_fpu_checking(struct task_struct *tsk) "emms\n\t" /* clear stack tags */ "fildl %P[addr]", /* set F?P to defined value */ X86_FEATURE_FXSAVE_LEAK, - [addr] "m" (tsk->thread.fpu.has_fpu)); + [addr] "m" (init_tss[raw_smp_processor_id()].x86_tss.sp0)); return fpu_restore_checking(&tsk->thread.fpu); } diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h index be27ba1..04a8801 100644 --- a/arch/x86/include/asm/futex.h +++ b/arch/x86/include/asm/futex.h @@ -12,6 +12,7 @@ #include #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \ + typecheck(u32 __user *, uaddr); \ asm volatile("\t" ASM_STAC "\n" \ "1:\t" insn "\n" \ "2:\t" ASM_CLAC "\n" \ @@ -20,15 +21,16 @@ "\tjmp\t2b\n" \ "\t.previous\n" \ _ASM_EXTABLE(1b, 3b) \ - : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \ + : "=r" (oldval), "=r" (ret), "+m" (*(u32 __user *)____m(uaddr)) \ : "i" (-EFAULT), "0" (oparg), "1" (0)) #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \ + typecheck(u32 __user *, uaddr); \ asm volatile("\t" ASM_STAC "\n" \ "1:\tmovl %2, %0\n" \ "\tmovl\t%0, %3\n" \ "\t" insn "\n" \ - "2:\t" LOCK_PREFIX "cmpxchgl %3, %2\n" \ + "2:\t" LOCK_PREFIX __copyuser_seg"cmpxchgl %3, %2\n" \ "\tjnz\t1b\n" \ "3:\t" ASM_CLAC "\n" \ "\t.section .fixup,\"ax\"\n" \ @@ -38,7 +40,7 @@ _ASM_EXTABLE(1b, 4b) \ _ASM_EXTABLE(2b, 4b) \ : "=&a" (oldval), "=&r" (ret), \ - "+m" (*uaddr), "=&r" (tem) \ + "+m" (*(u32 __user *)____m(uaddr)), "=&r" (tem) \ : "r" (oparg), "i" (-EFAULT), "1" (0)) static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) @@ -57,12 +59,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) pagefault_disable(); + pax_open_userland(); switch (op) { case FUTEX_OP_SET: - __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); + __futex_atomic_op1(__copyuser_seg"xchgl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_ADD: - __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval, + __futex_atomic_op1(LOCK_PREFIX __copyuser_seg"xaddl %0, %2", ret, oldval, uaddr, oparg); break; case FUTEX_OP_OR: @@ -77,6 +80,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) default: ret = -ENOSYS; } + pax_close_userland(); pagefault_enable(); @@ -115,18 +119,20 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; + pax_open_userland(); asm volatile("\t" ASM_STAC "\n" - "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n" + "1:\t" LOCK_PREFIX __copyuser_seg"cmpxchgl %4, %2\n" "2:\t" ASM_CLAC "\n" "\t.section .fixup, \"ax\"\n" "3:\tmov %3, %0\n" "\tjmp 2b\n" "\t.previous\n" _ASM_EXTABLE(1b, 3b) - : "+r" (ret), "=a" (oldval), "+m" (*uaddr) + : "+r" (ret), "=a" (oldval), "+m" (*(u32 __user *)____m(uaddr)) : "i" (-EFAULT), "r" (newval), "1" (oldval) : "memory" ); + pax_close_userland(); *uval = oldval; return ret; diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 1da97ef..9c2ebff 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -148,8 +148,8 @@ extern void setup_ioapic_dest(void); extern void enable_IO_APIC(void); /* Statistics */ -extern atomic_t irq_err_count; -extern atomic_t irq_mis_count; +extern atomic_unchecked_t irq_err_count; +extern atomic_unchecked_t irq_mis_count; /* EISA */ extern void eisa_set_level_irq(unsigned int irq); diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h index a203659..9889f1c 100644 --- a/arch/x86/include/asm/i8259.h +++ b/arch/x86/include/asm/i8259.h @@ -62,7 +62,7 @@ struct legacy_pic { void (*init)(int auto_eoi); int (*irq_pending)(unsigned int irq); void (*make_irq)(unsigned int irq); -}; +} __do_const; extern struct legacy_pic *legacy_pic; extern struct legacy_pic null_legacy_pic; diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index d8e8eef..1765f78 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -51,12 +51,12 @@ static inline void name(type val, volatile void __iomem *addr) \ "m" (*(volatile type __force *)addr) barrier); } build_mmio_read(readb, "b", unsigned char, "=q", :"memory") -build_mmio_read(readw, "w", unsigned short, "=r", :"memory") -build_mmio_read(readl, "l", unsigned int, "=r", :"memory") +build_mmio_read(__intentional_overflow(-1) readw, "w", unsigned short, "=r", :"memory") +build_mmio_read(__intentional_overflow(-1) readl, "l", unsigned int, "=r", :"memory") build_mmio_read(__readb, "b", unsigned char, "=q", ) -build_mmio_read(__readw, "w", unsigned short, "=r", ) -build_mmio_read(__readl, "l", unsigned int, "=r", ) +build_mmio_read(__intentional_overflow(-1) __readw, "w", unsigned short, "=r", ) +build_mmio_read(__intentional_overflow(-1) __readl, "l", unsigned int, "=r", ) build_mmio_write(writeb, "b", unsigned char, "q", :"memory") build_mmio_write(writew, "w", unsigned short, "r", :"memory") @@ -184,7 +184,7 @@ static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) return ioremap_nocache(offset, size); } -extern void iounmap(volatile void __iomem *addr); +extern void iounmap(const volatile void __iomem *addr); extern void set_iounmap_nonlazy(void); @@ -194,6 +194,17 @@ extern void set_iounmap_nonlazy(void); #include +#define ARCH_HAS_VALID_PHYS_ADDR_RANGE +static inline int valid_phys_addr_range(unsigned long addr, size_t count) +{ + return ((addr + count + PAGE_SIZE - 1) >> PAGE_SHIFT) < (1ULL << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0; +} + +static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t count) +{ + return (pfn + (count >> PAGE_SHIFT)) < (1ULL << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0; +} + /* * Convert a virtual cached pointer to an uncached pointer */ diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index bba3cf8..06bc8da 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -141,6 +141,11 @@ static inline notrace unsigned long arch_local_irq_save(void) sti; \ sysexit +#define GET_CR0_INTO_RDI mov %cr0, %rdi +#define SET_RDI_INTO_CR0 mov %rdi, %cr0 +#define GET_CR3_INTO_RDI mov %cr3, %rdi +#define SET_RDI_INTO_CR3 mov %rdi, %cr3 + #else #define INTERRUPT_RETURN iret #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h index 5a6d287..f815789 100644 --- a/arch/x86/include/asm/kprobes.h +++ b/arch/x86/include/asm/kprobes.h @@ -38,13 +38,8 @@ typedef u8 kprobe_opcode_t; #define RELATIVEJUMP_SIZE 5 #define RELATIVECALL_OPCODE 0xe8 #define RELATIVE_ADDR_SIZE 4 -#define MAX_STACK_SIZE 64 -#define MIN_STACK_SIZE(ADDR) \ - (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \ - THREAD_SIZE - (unsigned long)(ADDR))) \ - ? (MAX_STACK_SIZE) \ - : (((unsigned long)current_thread_info()) + \ - THREAD_SIZE - (unsigned long)(ADDR))) +#define MAX_STACK_SIZE 64UL +#define MIN_STACK_SIZE(ADDR) min(MAX_STACK_SIZE, current->thread.sp0 - (unsigned long)(ADDR)) #define flush_insn_slot(p) do { } while (0) diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h index 2d89e39..baee879 100644 --- a/arch/x86/include/asm/local.h +++ b/arch/x86/include/asm/local.h @@ -10,33 +10,97 @@ 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)) static inline void local_inc(local_t *l) { - asm volatile(_ASM_INC "%0" + asm volatile(_ASM_INC "%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_DEC "%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (l->a.counter)); +} + +static inline void local_inc_unchecked(local_unchecked_t *l) +{ + asm volatile(_ASM_INC "%0\n" : "+m" (l->a.counter)); } static inline void local_dec(local_t *l) { - asm volatile(_ASM_DEC "%0" + asm volatile(_ASM_DEC "%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_INC "%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (l->a.counter)); +} + +static inline void local_dec_unchecked(local_unchecked_t *l) +{ + asm volatile(_ASM_DEC "%0\n" : "+m" (l->a.counter)); } static inline void local_add(long i, local_t *l) { - asm volatile(_ASM_ADD "%1,%0" + asm volatile(_ASM_ADD "%1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_SUB "%1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (l->a.counter) + : "ir" (i)); +} + +static inline void local_add_unchecked(long i, local_unchecked_t *l) +{ + asm volatile(_ASM_ADD "%1,%0\n" : "+m" (l->a.counter) : "ir" (i)); } static inline void local_sub(long i, local_t *l) { - asm volatile(_ASM_SUB "%1,%0" + asm volatile(_ASM_SUB "%1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_ADD "%1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+m" (l->a.counter) + : "ir" (i)); +} + +static inline void local_sub_unchecked(long i, local_unchecked_t *l) +{ + asm volatile(_ASM_SUB "%1,%0\n" : "+m" (l->a.counter) : "ir" (i)); } @@ -54,7 +118,16 @@ static inline int local_sub_and_test(long i, local_t *l) { unsigned char c; - asm volatile(_ASM_SUB "%2,%0; sete %1" + asm volatile(_ASM_SUB "%2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_ADD "%2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "+m" (l->a.counter), "=qm" (c) : "ir" (i) : "memory"); return c; @@ -72,7 +145,16 @@ static inline int local_dec_and_test(local_t *l) { unsigned char c; - asm volatile(_ASM_DEC "%0; sete %1" + asm volatile(_ASM_DEC "%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_INC "%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "+m" (l->a.counter), "=qm" (c) : : "memory"); return c != 0; @@ -90,7 +172,16 @@ static inline int local_inc_and_test(local_t *l) { unsigned char c; - asm volatile(_ASM_INC "%0; sete %1" + asm volatile(_ASM_INC "%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_DEC "%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sete %1\n" : "+m" (l->a.counter), "=qm" (c) : : "memory"); return c != 0; @@ -109,7 +200,16 @@ static inline int local_add_negative(long i, local_t *l) { unsigned char c; - asm volatile(_ASM_ADD "%2,%0; sets %1" + asm volatile(_ASM_ADD "%2,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_SUB "%2,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + "sets %1\n" : "+m" (l->a.counter), "=qm" (c) : "ir" (i) : "memory"); return c; @@ -125,6 +225,30 @@ static inline int local_add_negative(long i, local_t *l) static inline long local_add_return(long i, local_t *l) { long __i = i; + asm volatile(_ASM_XADD "%0, %1\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + _ASM_MOV "%0,%1\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + + : "+r" (i), "+m" (l->a.counter) + : : "memory"); + return i + __i; +} + +/** + * local_add_return_unchecked - add and return + * @i: integer value to add + * @l: pointer to type local_unchecked_t + * + * Atomically adds @i to @l and returns @i + @l + */ +static inline long local_add_return_unchecked(long i, local_unchecked_t *l) +{ + long __i = i; asm volatile(_ASM_XADD "%0, %1;" : "+r" (i), "+m" (l->a.counter) : : "memory"); @@ -141,6 +265,8 @@ static inline long local_sub_return(long i, local_t *l) #define local_cmpxchg(l, o, n) \ (cmpxchg_local(&((l)->a.counter), (o), (n))) +#define local_cmpxchg_unchecked(l, o, n) \ + (cmpxchg_local(&((l)->a.counter), (o), (n))) /* Always has a lock prefix */ #define local_xchg(l, n) (xchg(&((l)->a.counter), (n))) diff --git a/arch/x86/include/asm/mman.h b/arch/x86/include/asm/mman.h new file mode 100644 index 0000000..2bfd3ba --- /dev/null +++ b/arch/x86/include/asm/mman.h @@ -0,0 +1,15 @@ +#ifndef _X86_MMAN_H +#define _X86_MMAN_H + +#include + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#ifdef CONFIG_X86_32 +#define arch_mmap_check i386_mmap_check +int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags); +#endif +#endif +#endif + +#endif /* X86_MMAN_H */ diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 5f55e69..e20bfb1 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -9,7 +9,7 @@ * we put the segment information here. */ typedef struct { - void *ldt; + struct desc_struct *ldt; int size; #ifdef CONFIG_X86_64 @@ -18,7 +18,19 @@ typedef struct { #endif struct mutex lock; - void *vdso; + unsigned long vdso; + +#ifdef CONFIG_X86_32 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + unsigned long user_cs_base; + unsigned long user_cs_limit; + +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) + cpumask_t cpu_user_cs_mask; +#endif + +#endif +#endif } mm_context_t; #ifdef CONFIG_SMP diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index be12c53..7430027 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -24,6 +24,20 @@ void destroy_context(struct mm_struct *mm); static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (!(static_cpu_has(X86_FEATURE_PCID))) { + unsigned int i; + pgd_t *pgd; + + pax_open_kernel(); + pgd = get_cpu_pgd(smp_processor_id(), kernel); + for (i = USER_PGD_PTRS; i < 2 * USER_PGD_PTRS; ++i) + set_pgd_batched(pgd+i, native_make_pgd(0)); + pax_close_kernel(); + } +#endif + #ifdef CONFIG_SMP if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY); @@ -34,16 +48,55 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { unsigned cpu = smp_processor_id(); +#if defined(CONFIG_X86_32) && defined(CONFIG_SMP) && (defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)) + int tlbstate = TLBSTATE_OK; +#endif if (likely(prev != next)) { #ifdef CONFIG_SMP +#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)) + tlbstate = this_cpu_read(cpu_tlbstate.state); +#endif this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); this_cpu_write(cpu_tlbstate.active_mm, next); #endif cpumask_set_cpu(cpu, mm_cpumask(next)); /* Re-load page tables */ +#ifdef CONFIG_PAX_PER_CPU_PGD + pax_open_kernel(); + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (static_cpu_has(X86_FEATURE_PCID)) + __clone_user_pgds(get_cpu_pgd(cpu, user), next->pgd); + else +#endif + + __clone_user_pgds(get_cpu_pgd(cpu, kernel), next->pgd); + __shadow_user_pgds(get_cpu_pgd(cpu, kernel) + USER_PGD_PTRS, next->pgd); + pax_close_kernel(); + BUG_ON((__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL) != (read_cr3() & __PHYSICAL_MASK) && (__pa(get_cpu_pgd(cpu, user)) | PCID_USER) != (read_cr3() & __PHYSICAL_MASK)); + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (static_cpu_has(X86_FEATURE_PCID)) { + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; + descriptor[0] = PCID_USER; + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_CONTEXT) : "memory"); + } else { + write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER); + if (static_cpu_has(X86_FEATURE_STRONGUDEREF)) + write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); + else + write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL); + } + } else +#endif + + load_cr3(get_cpu_pgd(cpu, kernel)); +#else load_cr3(next->pgd); +#endif /* Stop flush ipis for the previous mm */ cpumask_clear_cpu(cpu, mm_cpumask(prev)); @@ -51,9 +104,63 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* Load the LDT, if the LDT is different: */ if (unlikely(prev->context.ldt != next->context.ldt)) load_LDT_nolock(&next->context); + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) + if (!(__supported_pte_mask & _PAGE_NX)) { + smp_mb__before_clear_bit(); + cpu_clear(cpu, prev->context.cpu_user_cs_mask); + smp_mb__after_clear_bit(); + cpu_set(cpu, next->context.cpu_user_cs_mask); + } +#endif + +#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)) + if (unlikely(prev->context.user_cs_base != next->context.user_cs_base || + prev->context.user_cs_limit != next->context.user_cs_limit)) + set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu); +#ifdef CONFIG_SMP + else if (unlikely(tlbstate != TLBSTATE_OK)) + set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu); +#endif +#endif + } + else { + +#ifdef CONFIG_PAX_PER_CPU_PGD + pax_open_kernel(); + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (static_cpu_has(X86_FEATURE_PCID)) + __clone_user_pgds(get_cpu_pgd(cpu, user), next->pgd); + else +#endif + + __clone_user_pgds(get_cpu_pgd(cpu, kernel), next->pgd); + __shadow_user_pgds(get_cpu_pgd(cpu, kernel) + USER_PGD_PTRS, next->pgd); + pax_close_kernel(); + BUG_ON((__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL) != (read_cr3() & __PHYSICAL_MASK) && (__pa(get_cpu_pgd(cpu, user)) | PCID_USER) != (read_cr3() & __PHYSICAL_MASK)); + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (static_cpu_has(X86_FEATURE_PCID)) { + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; + descriptor[0] = PCID_USER; + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_CONTEXT) : "memory"); + } else { + write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER); + if (static_cpu_has(X86_FEATURE_STRONGUDEREF)) + write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); + else + write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL); + } + } else +#endif + + load_cr3(get_cpu_pgd(cpu, kernel)); +#endif + #ifdef CONFIG_SMP - else { this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next); @@ -70,11 +177,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, * tlb flush IPI delivery. We must reload CR3 * to make sure to use no freed page tables. */ + +#ifndef CONFIG_PAX_PER_CPU_PGD load_cr3(next->pgd); +#endif + load_LDT_nolock(&next->context); + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) + if (!(__supported_pte_mask & _PAGE_NX)) + cpu_set(cpu, next->context.cpu_user_cs_mask); +#endif + +#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)) +#ifdef CONFIG_PAX_PAGEEXEC + if (!((next->pax_flags & MF_PAX_PAGEEXEC) && (__supported_pte_mask & _PAGE_NX))) +#endif + set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu); +#endif + } - } #endif + } } #define activate_mm(prev, next) \ diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h index e3b7819..b257c64 100644 --- a/arch/x86/include/asm/module.h +++ b/arch/x86/include/asm/module.h @@ -5,6 +5,7 @@ #ifdef CONFIG_X86_64 /* X86_64 does not define MODULE_PROC_FAMILY */ +#define MODULE_PROC_FAMILY "" #elif defined CONFIG_M486 #define MODULE_PROC_FAMILY "486 " #elif defined CONFIG_M586 @@ -57,8 +58,20 @@ #error unknown processor family #endif -#ifdef CONFIG_X86_32 -# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY +#ifdef CONFIG_PAX_KERNEXEC_PLUGIN_METHOD_BTS +#define MODULE_PAX_KERNEXEC "KERNEXEC_BTS " +#elif defined(CONFIG_PAX_KERNEXEC_PLUGIN_METHOD_OR) +#define MODULE_PAX_KERNEXEC "KERNEXEC_OR " +#else +#define MODULE_PAX_KERNEXEC "" #endif +#ifdef CONFIG_PAX_MEMORY_UDEREF +#define MODULE_PAX_UDEREF "UDEREF " +#else +#define MODULE_PAX_UDEREF "" +#endif + +#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_PAX_KERNEXEC MODULE_PAX_UDEREF + #endif /* _ASM_X86_MODULE_H */ diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h index 86f9301..b365cda 100644 --- a/arch/x86/include/asm/nmi.h +++ b/arch/x86/include/asm/nmi.h @@ -40,11 +40,11 @@ struct nmiaction { nmi_handler_t handler; unsigned long flags; const char *name; -}; +} __do_const; #define register_nmi_handler(t, fn, fg, n, init...) \ ({ \ - static struct nmiaction init fn##_na = { \ + static const struct nmiaction init fn##_na = { \ .handler = (fn), \ .name = (n), \ .flags = (fg), \ @@ -52,7 +52,7 @@ struct nmiaction { __register_nmi_handler((t), &fn##_na); \ }) -int __register_nmi_handler(unsigned int, struct nmiaction *); +int __register_nmi_handler(unsigned int, const struct nmiaction *); void unregister_nmi_handler(unsigned int, const char *); diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index c878924..21f4889 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -52,6 +52,7 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr, __phys_addr_symbol(__phys_reloc_hide((unsigned long)(x))) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) +#define __early_va(x) ((void *)((unsigned long)(x)+__START_KERNEL_map - phys_base)) #define __boot_va(x) __va(x) #define __boot_pa(x) __pa(x) diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index 0f1ddee..e2fc3d1 100644 --- a/arch/x86/include/asm/page_64.h +++ b/arch/x86/include/asm/page_64.h @@ -7,9 +7,9 @@ /* duplicated to the one in bootmem.h */ extern unsigned long max_pfn; -extern unsigned long phys_base; +extern const unsigned long phys_base; -static inline unsigned long __phys_addr_nodebug(unsigned long x) +static inline unsigned long __intentional_overflow(-1) __phys_addr_nodebug(unsigned long x) { unsigned long y = x - __START_KERNEL_map; diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index cfdc9ee..3f7b5d6 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -560,7 +560,7 @@ static inline pmd_t __pmd(pmdval_t val) return (pmd_t) { ret }; } -static inline pmdval_t pmd_val(pmd_t pmd) +static inline __intentional_overflow(-1) pmdval_t pmd_val(pmd_t pmd) { pmdval_t ret; @@ -626,6 +626,18 @@ static inline void set_pgd(pgd_t *pgdp, pgd_t pgd) val); } +static inline void set_pgd_batched(pgd_t *pgdp, pgd_t pgd) +{ + pgdval_t val = native_pgd_val(pgd); + + if (sizeof(pgdval_t) > sizeof(long)) + PVOP_VCALL3(pv_mmu_ops.set_pgd_batched, pgdp, + val, (u64)val >> 32); + else + PVOP_VCALL2(pv_mmu_ops.set_pgd_batched, pgdp, + val); +} + static inline void pgd_clear(pgd_t *pgdp) { set_pgd(pgdp, __pgd(0)); @@ -710,6 +722,21 @@ static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, pv_mmu_ops.set_fixmap(idx, phys, flags); } +#ifdef CONFIG_PAX_KERNEXEC +static inline unsigned long pax_open_kernel(void) +{ + return PVOP_CALL0(unsigned long, pv_mmu_ops.pax_open_kernel); +} + +static inline unsigned long pax_close_kernel(void) +{ + return PVOP_CALL0(unsigned long, pv_mmu_ops.pax_close_kernel); +} +#else +static inline unsigned long pax_open_kernel(void) { return 0; } +static inline unsigned long pax_close_kernel(void) { return 0; } +#endif + #if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS) static inline int arch_spin_is_locked(struct arch_spinlock *lock) @@ -926,7 +953,7 @@ extern void default_banner(void); #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) -#define PARA_INDIRECT(addr) *%cs:addr +#define PARA_INDIRECT(addr) *%ss:addr #endif #define INTERRUPT_RETURN \ @@ -1001,6 +1028,21 @@ extern void default_banner(void); PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit), \ CLBR_NONE, \ jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit)) + +#define GET_CR0_INTO_RDI \ + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \ + mov %rax,%rdi + +#define SET_RDI_INTO_CR0 \ + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0) + +#define GET_CR3_INTO_RDI \ + call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr3); \ + mov %rax,%rdi + +#define SET_RDI_INTO_CR3 \ + call PARA_INDIRECT(pv_mmu_ops+PV_MMU_write_cr3) + #endif /* CONFIG_X86_32 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 0db1fca..52310cc 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -84,7 +84,7 @@ struct pv_init_ops { */ unsigned (*patch)(u8 type, u16 clobber, void *insnbuf, unsigned long addr, unsigned len); -}; +} __no_const; struct pv_lazy_ops { @@ -98,7 +98,7 @@ struct pv_time_ops { unsigned long long (*sched_clock)(void); unsigned long long (*steal_clock)(int cpu); unsigned long (*get_tsc_khz)(void); -}; +} __no_const; struct pv_cpu_ops { /* hooks for various privileged instructions */ @@ -192,7 +192,7 @@ struct pv_cpu_ops { void (*start_context_switch)(struct task_struct *prev); void (*end_context_switch)(struct task_struct *next); -}; +} __no_const; struct pv_irq_ops { /* @@ -223,7 +223,7 @@ struct pv_apic_ops { unsigned long start_eip, unsigned long start_esp); #endif -}; +} __no_const; struct pv_mmu_ops { unsigned long (*read_cr2)(void); @@ -313,6 +313,7 @@ struct pv_mmu_ops { struct paravirt_callee_save make_pud; void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); + void (*set_pgd_batched)(pgd_t *pudp, pgd_t pgdval); #endif /* PAGETABLE_LEVELS == 4 */ #endif /* PAGETABLE_LEVELS >= 3 */ @@ -324,6 +325,12 @@ struct pv_mmu_ops { an mfn. We can tell which is which from the index. */ void (*set_fixmap)(unsigned /* enum fixed_addresses */ idx, phys_addr_t phys, pgprot_t flags); + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long (*pax_open_kernel)(void); + unsigned long (*pax_close_kernel)(void); +#endif + }; struct arch_spinlock; @@ -334,7 +341,7 @@ struct pv_lock_ops { void (*spin_lock_flags)(struct arch_spinlock *lock, unsigned long flags); int (*spin_trylock)(struct arch_spinlock *lock); void (*spin_unlock)(struct arch_spinlock *lock); -}; +} __no_const; /* This contains all the paravirt structures: we get a convenient * number for each function using the offset which we use to indicate diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h index b4389a4..7024269 100644 --- a/arch/x86/include/asm/pgalloc.h +++ b/arch/x86/include/asm/pgalloc.h @@ -63,6 +63,13 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) { paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT); + set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE)); +} + +static inline void pmd_populate_user(struct mm_struct *mm, + pmd_t *pmd, pte_t *pte) +{ + paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT); set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE)); } @@ -99,12 +106,22 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, #ifdef CONFIG_X86_PAE extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd); +static inline void pud_populate_kernel(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) +{ + pud_populate(mm, pudp, pmd); +} #else /* !CONFIG_X86_PAE */ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) { paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT); set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd))); } + +static inline void pud_populate_kernel(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) +{ + paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT); + set_pud(pud, __pud(_KERNPG_TABLE | __pa(pmd))); +} #endif /* CONFIG_X86_PAE */ #if PAGETABLE_LEVELS > 3 @@ -114,6 +131,12 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))); } +static inline void pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) +{ + paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT); + set_pgd(pgd, __pgd(_KERNPG_TABLE | __pa(pud))); +} + static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h index f2b489c..4f7e2e5 100644 --- a/arch/x86/include/asm/pgtable-2level.h +++ b/arch/x86/include/asm/pgtable-2level.h @@ -18,7 +18,9 @@ static inline void native_set_pte(pte_t *ptep , pte_t pte) static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) { + pax_open_kernel(); *pmdp = pmd; + pax_close_kernel(); } static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 4cc9f2b..5fd9226 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -92,12 +92,16 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) { + pax_open_kernel(); set_64bit((unsigned long long *)(pmdp), native_pmd_val(pmd)); + pax_close_kernel(); } static inline void native_set_pud(pud_t *pudp, pud_t pud) { + pax_open_kernel(); set_64bit((unsigned long long *)(pudp), native_pud_val(pud)); + pax_close_kernel(); } /* diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 1e67223..92a9585 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -44,6 +44,7 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); #ifndef __PAGETABLE_PUD_FOLDED #define set_pgd(pgdp, pgd) native_set_pgd(pgdp, pgd) +#define set_pgd_batched(pgdp, pgd) native_set_pgd_batched(pgdp, pgd) #define pgd_clear(pgd) native_pgd_clear(pgd) #endif @@ -81,12 +82,51 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); #define arch_end_context_switch(prev) do {} while(0) +#define pax_open_kernel() native_pax_open_kernel() +#define pax_close_kernel() native_pax_close_kernel() #endif /* CONFIG_PARAVIRT */ +#define __HAVE_ARCH_PAX_OPEN_KERNEL +#define __HAVE_ARCH_PAX_CLOSE_KERNEL + +#ifdef CONFIG_PAX_KERNEXEC +static inline unsigned long native_pax_open_kernel(void) +{ + unsigned long cr0; + + preempt_disable(); + barrier(); + cr0 = read_cr0() ^ X86_CR0_WP; + BUG_ON(cr0 & X86_CR0_WP); + write_cr0(cr0); + return cr0 ^ X86_CR0_WP; +} + +static inline unsigned long native_pax_close_kernel(void) +{ + unsigned long cr0; + + cr0 = read_cr0() ^ X86_CR0_WP; + BUG_ON(!(cr0 & X86_CR0_WP)); + write_cr0(cr0); + barrier(); + preempt_enable_no_resched(); + return cr0 ^ X86_CR0_WP; +} +#else +static inline unsigned long native_pax_open_kernel(void) { return 0; } +static inline unsigned long native_pax_close_kernel(void) { return 0; } +#endif + /* * The following only work if pte_present() is true. * Undefined behaviour if not.. */ +static inline int pte_user(pte_t pte) +{ + return pte_val(pte) & _PAGE_USER; +} + static inline int pte_dirty(pte_t pte) { return pte_flags(pte) & _PAGE_DIRTY; @@ -147,6 +187,11 @@ static inline unsigned long pud_pfn(pud_t pud) return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT; } +static inline unsigned long pgd_pfn(pgd_t pgd) +{ + return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT; +} + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) static inline int pmd_large(pmd_t pte) @@ -200,9 +245,29 @@ static inline pte_t pte_wrprotect(pte_t pte) return pte_clear_flags(pte, _PAGE_RW); } +static inline pte_t pte_mkread(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_USER); +} + static inline pte_t pte_mkexec(pte_t pte) { - return pte_clear_flags(pte, _PAGE_NX); +#ifdef CONFIG_X86_PAE + if (__supported_pte_mask & _PAGE_NX) + return pte_clear_flags(pte, _PAGE_NX); + else +#endif + return pte_set_flags(pte, _PAGE_USER); +} + +static inline pte_t pte_exprotect(pte_t pte) +{ +#ifdef CONFIG_X86_PAE + if (__supported_pte_mask & _PAGE_NX) + return pte_set_flags(pte, _PAGE_NX); + else +#endif + return pte_clear_flags(pte, _PAGE_USER); } static inline pte_t pte_mkdirty(pte_t pte) @@ -394,6 +459,16 @@ pte_t *populate_extra_pte(unsigned long vaddr); #endif #ifndef __ASSEMBLY__ + +#ifdef CONFIG_PAX_PER_CPU_PGD +extern pgd_t cpu_pgd[NR_CPUS][2][PTRS_PER_PGD]; +enum cpu_pgd_type {kernel = 0, user = 1}; +static inline pgd_t *get_cpu_pgd(unsigned int cpu, enum cpu_pgd_type type) +{ + return cpu_pgd[cpu][type]; +} +#endif + #include #include @@ -529,7 +604,7 @@ static inline unsigned long pud_page_vaddr(pud_t pud) * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ -#define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT) +#define pud_page(pud) pfn_to_page((pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT) /* Find an entry in the second-level page table.. */ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) @@ -569,7 +644,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd) * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ -#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT) +#define pgd_page(pgd) pfn_to_page((pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT) /* to find an entry in a page-table-directory. */ static inline unsigned long pud_index(unsigned long address) @@ -584,7 +659,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) static inline int pgd_bad(pgd_t pgd) { - return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE; + return (pgd_flags(pgd) & ~(_PAGE_USER | _PAGE_NX)) != _KERNPG_TABLE; } static inline int pgd_none(pgd_t pgd) @@ -607,7 +682,12 @@ static inline int pgd_none(pgd_t pgd) * pgd_offset() returns a (pgd_t *) * pgd_index() is used get the offset into the pgd page's array of pgd_t's; */ -#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address))) +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) + +#ifdef CONFIG_PAX_PER_CPU_PGD +#define pgd_offset_cpu(cpu, type, address) (get_cpu_pgd(cpu, type) + pgd_index(address)) +#endif + /* * a shortcut which implies the use of the kernel's pgd, instead * of a process's @@ -618,6 +698,23 @@ static inline int pgd_none(pgd_t pgd) #define KERNEL_PGD_BOUNDARY pgd_index(PAGE_OFFSET) #define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY) +#ifdef CONFIG_X86_32 +#define USER_PGD_PTRS KERNEL_PGD_BOUNDARY +#else +#define TASK_SIZE_MAX_SHIFT CONFIG_TASK_SIZE_MAX_SHIFT +#define USER_PGD_PTRS (_AC(1,UL) << (TASK_SIZE_MAX_SHIFT - PGDIR_SHIFT)) + +#ifdef CONFIG_PAX_MEMORY_UDEREF +#ifdef __ASSEMBLY__ +#define pax_user_shadow_base pax_user_shadow_base(%rip) +#else +extern unsigned long pax_user_shadow_base; +extern pgdval_t clone_pgd_mask; +#endif +#endif + +#endif + #ifndef __ASSEMBLY__ extern int direct_gbpages; @@ -784,11 +881,24 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, * dst and src can be on the same page, but the range must not overlap, * and must not cross a page boundary. */ -static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) +static inline void clone_pgd_range(pgd_t *dst, const pgd_t *src, int count) { - memcpy(dst, src, count * sizeof(pgd_t)); + pax_open_kernel(); + while (count--) + *dst++ = *src++; + pax_close_kernel(); } +#ifdef CONFIG_PAX_PER_CPU_PGD +extern void __clone_user_pgds(pgd_t *dst, const pgd_t *src); +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +extern void __shadow_user_pgds(pgd_t *dst, const pgd_t *src); +#else +static inline void __shadow_user_pgds(pgd_t *dst, const pgd_t *src) {} +#endif + #define PTE_SHIFT ilog2(PTRS_PER_PTE) static inline int page_level_shift(enum pg_level level) { diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 9ee3221..b979c6b 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h @@ -25,9 +25,6 @@ struct mm_struct; struct vm_area_struct; -extern pgd_t swapper_pg_dir[1024]; -extern pgd_t initial_page_table[1024]; - static inline void pgtable_cache_init(void) { } static inline void check_pgt_cache(void) { } void paging_init(void); @@ -48,6 +45,12 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); # include #endif +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern pgd_t initial_page_table[PTRS_PER_PGD]; +#ifdef CONFIG_X86_PAE +extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD]; +#endif + #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ ((pte_t *)kmap_atomic(pmd_page(*(dir))) + \ @@ -62,12 +65,17 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); /* Clear a kernel PTE and flush it from the TLB */ #define kpte_clear_flush(ptep, vaddr) \ do { \ + pax_open_kernel(); \ pte_clear(&init_mm, (vaddr), (ptep)); \ + pax_close_kernel(); \ __flush_tlb_one((vaddr)); \ } while (0) #endif /* !__ASSEMBLY__ */ +#define HAVE_ARCH_UNMAPPED_AREA +#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN + /* * kern_addr_valid() is (1) for FLATMEM and (0) for * SPARSEMEM and DISCONTIGMEM diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h index ed5903b..c7fe163 100644 --- a/arch/x86/include/asm/pgtable_32_types.h +++ b/arch/x86/include/asm/pgtable_32_types.h @@ -8,7 +8,7 @@ */ #ifdef CONFIG_X86_PAE # include -# define PMD_SIZE (1UL << PMD_SHIFT) +# define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) # define PMD_MASK (~(PMD_SIZE - 1)) #else # include @@ -46,6 +46,19 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */ # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) #endif +#ifdef CONFIG_PAX_KERNEXEC +#ifndef __ASSEMBLY__ +extern unsigned char MODULES_EXEC_VADDR[]; +extern unsigned char MODULES_EXEC_END[]; +#endif +#include +#define ktla_ktva(addr) (addr + LOAD_PHYSICAL_ADDR + PAGE_OFFSET) +#define ktva_ktla(addr) (addr - LOAD_PHYSICAL_ADDR - PAGE_OFFSET) +#else +#define ktla_ktva(addr) (addr) +#define ktva_ktla(addr) (addr) +#endif + #define MODULES_VADDR VMALLOC_START #define MODULES_END VMALLOC_END #define MODULES_LEN (MODULES_VADDR - MODULES_END) diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index e22c1db..23a625a 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h @@ -16,10 +16,14 @@ extern pud_t level3_kernel_pgt[512]; extern pud_t level3_ident_pgt[512]; +extern pud_t level3_vmalloc_start_pgt[512]; +extern pud_t level3_vmalloc_end_pgt[512]; +extern pud_t level3_vmemmap_pgt[512]; +extern pud_t level2_vmemmap_pgt[512]; extern pmd_t level2_kernel_pgt[512]; extern pmd_t level2_fixmap_pgt[512]; -extern pmd_t level2_ident_pgt[512]; -extern pgd_t init_level4_pgt[]; +extern pmd_t level2_ident_pgt[512*2]; +extern pgd_t init_level4_pgt[512]; #define swapper_pg_dir init_level4_pgt @@ -61,7 +65,9 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) { + pax_open_kernel(); *pmdp = pmd; + pax_close_kernel(); } static inline void native_pmd_clear(pmd_t *pmd) @@ -97,7 +103,9 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) static inline void native_set_pud(pud_t *pudp, pud_t pud) { + pax_open_kernel(); *pudp = pud; + pax_close_kernel(); } static inline void native_pud_clear(pud_t *pud) @@ -107,6 +115,13 @@ static inline void native_pud_clear(pud_t *pud) static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd) { + pax_open_kernel(); + *pgdp = pgd; + pax_close_kernel(); +} + +static inline void native_set_pgd_batched(pgd_t *pgdp, pgd_t pgd) +{ *pgdp = pgd; } diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h index 2d88344..4679fc3 100644 --- a/arch/x86/include/asm/pgtable_64_types.h +++ b/arch/x86/include/asm/pgtable_64_types.h @@ -61,6 +61,11 @@ typedef struct { pteval_t pte; } pte_t; #define MODULES_VADDR _AC(0xffffffffa0000000, UL) #define MODULES_END _AC(0xffffffffff000000, UL) #define MODULES_LEN (MODULES_END - MODULES_VADDR) +#define MODULES_EXEC_VADDR MODULES_VADDR +#define MODULES_EXEC_END MODULES_END + +#define ktla_ktva(addr) (addr) +#define ktva_ktla(addr) (addr) #define EARLY_DYNAMIC_PAGE_TABLES 64 diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index e642300..0ef8f31 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -16,13 +16,12 @@ #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */ #define _PAGE_BIT_PAT 7 /* on 4KB pages */ #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */ -#define _PAGE_BIT_UNUSED1 9 /* available for programmer */ +#define _PAGE_BIT_SPECIAL 9 /* special mappings, no associated struct page */ #define _PAGE_BIT_IOMAP 10 /* flag used to indicate IO mapping */ #define _PAGE_BIT_HIDDEN 11 /* hidden by kmemcheck */ #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ -#define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1 -#define _PAGE_BIT_CPA_TEST _PAGE_BIT_UNUSED1 -#define _PAGE_BIT_SPLITTING _PAGE_BIT_UNUSED1 /* only valid on a PSE pmd */ +#define _PAGE_BIT_CPA_TEST _PAGE_BIT_SPECIAL +#define _PAGE_BIT_SPLITTING _PAGE_BIT_SPECIAL /* only valid on a PSE pmd */ #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */ /* If _PAGE_BIT_PRESENT is clear, we use these: */ @@ -40,7 +39,6 @@ #define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY) #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) -#define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1) #define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP) #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) @@ -57,8 +55,10 @@ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) -#else +#elif defined(CONFIG_KMEMCHECK) #define _PAGE_NX (_AT(pteval_t, 0)) +#else +#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN) #endif #define _PAGE_FILE (_AT(pteval_t, 1) << _PAGE_BIT_FILE) @@ -116,6 +116,9 @@ #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ _PAGE_ACCESSED) +#define PAGE_READONLY_NOEXEC PAGE_READONLY +#define PAGE_SHARED_NOEXEC PAGE_SHARED + #define __PAGE_KERNEL_EXEC \ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL) #define __PAGE_KERNEL (__PAGE_KERNEL_EXEC | _PAGE_NX) @@ -126,7 +129,7 @@ #define __PAGE_KERNEL_WC (__PAGE_KERNEL | _PAGE_CACHE_WC) #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) -#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) +#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RO | _PAGE_USER) #define __PAGE_KERNEL_VVAR (__PAGE_KERNEL_RO | _PAGE_USER) #define __PAGE_KERNEL_VVAR_NOCACHE (__PAGE_KERNEL_VVAR | _PAGE_PCD | _PAGE_PWT) #define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE) @@ -188,8 +191,8 @@ * bits are combined, this will alow user to access the high address mapped * VDSO in the presence of CONFIG_COMPAT_VDSO */ -#define PTE_IDENT_ATTR 0x003 /* PRESENT+RW */ -#define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ +#define PTE_IDENT_ATTR 0x063 /* PRESENT+RW+DIRTY+ACCESSED */ +#define PDE_IDENT_ATTR 0x063 /* PRESENT+RW+DIRTY+ACCESSED */ #define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */ #endif @@ -227,7 +230,17 @@ static inline pgdval_t pgd_flags(pgd_t pgd) { return native_pgd_val(pgd) & PTE_FLAGS_MASK; } +#endif +#if PAGETABLE_LEVELS == 3 +#include +#endif + +#if PAGETABLE_LEVELS == 2 +#include +#endif + +#ifndef __ASSEMBLY__ #if PAGETABLE_LEVELS > 3 typedef struct { pudval_t pud; } pud_t; @@ -241,8 +254,6 @@ static inline pudval_t native_pud_val(pud_t pud) return pud.pud; } #else -#include - static inline pudval_t native_pud_val(pud_t pud) { return native_pgd_val(pud.pgd); @@ -262,8 +273,6 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) return pmd.pmd; } #else -#include - static inline pmdval_t native_pmd_val(pmd_t pmd) { return native_pgd_val(pmd.pud.pgd); @@ -303,7 +312,6 @@ typedef struct page *pgtable_t; extern pteval_t __supported_pte_mask; extern void set_nx(void); -extern int nx_enabled; #define pgprot_writecombine pgprot_writecombine extern pgprot_t pgprot_writecombine(pgprot_t prot); diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 22224b3..b3a2f90 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -198,9 +198,21 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, : "memory"); } +/* invpcid (%rdx),%rax */ +#define __ASM_INVPCID ".byte 0x66,0x0f,0x38,0x82,0x02" + +#define INVPCID_SINGLE_ADDRESS 0UL +#define INVPCID_SINGLE_CONTEXT 1UL +#define INVPCID_ALL_GLOBAL 2UL +#define INVPCID_ALL_MONGLOBAL 3UL + +#define PCID_KERNEL 0UL +#define PCID_USER 1UL +#define PCID_NOFLUSH (1UL << 63) + static inline void load_cr3(pgd_t *pgdir) { - write_cr3(__pa(pgdir)); + write_cr3(__pa(pgdir) | PCID_KERNEL); } #ifdef CONFIG_X86_32 @@ -282,7 +294,7 @@ struct tss_struct { } ____cacheline_aligned; -DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss); +extern struct tss_struct init_tss[NR_CPUS]; /* * Save the original ist values for checking stack pointers during debugging @@ -452,6 +464,7 @@ struct thread_struct { unsigned short ds; unsigned short fsindex; unsigned short gsindex; + unsigned short ss; #endif #ifdef CONFIG_X86_32 unsigned long ip; @@ -552,29 +565,8 @@ static inline void load_sp0(struct tss_struct *tss, extern unsigned long mmu_cr4_features; extern u32 *trampoline_cr4_features; -static inline void set_in_cr4(unsigned long mask) -{ - unsigned long cr4; - - mmu_cr4_features |= mask; - if (trampoline_cr4_features) - *trampoline_cr4_features = mmu_cr4_features; - cr4 = read_cr4(); - cr4 |= mask; - write_cr4(cr4); -} - -static inline void clear_in_cr4(unsigned long mask) -{ - unsigned long cr4; - - mmu_cr4_features &= ~mask; - if (trampoline_cr4_features) - *trampoline_cr4_features = mmu_cr4_features; - cr4 = read_cr4(); - cr4 &= ~mask; - write_cr4(cr4); -} +extern void set_in_cr4(unsigned long mask); +extern void clear_in_cr4(unsigned long mask); typedef struct { unsigned long seg; @@ -823,11 +815,18 @@ static inline void spin_lock_prefetch(const void *x) */ #define TASK_SIZE PAGE_OFFSET #define TASK_SIZE_MAX TASK_SIZE + +#ifdef CONFIG_PAX_SEGMEXEC +#define SEGMEXEC_TASK_SIZE (TASK_SIZE / 2) +#define STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE:TASK_SIZE) +#else #define STACK_TOP TASK_SIZE -#define STACK_TOP_MAX STACK_TOP +#endif + +#define STACK_TOP_MAX TASK_SIZE #define INIT_THREAD { \ - .sp0 = sizeof(init_stack) + (long)&init_stack, \ + .sp0 = sizeof(init_stack) + (long)&init_stack - 8, \ .vm86_info = NULL, \ .sysenter_cs = __KERNEL_CS, \ .io_bitmap_ptr = NULL, \ @@ -841,7 +840,7 @@ static inline void spin_lock_prefetch(const void *x) */ #define INIT_TSS { \ .x86_tss = { \ - .sp0 = sizeof(init_stack) + (long)&init_stack, \ + .sp0 = sizeof(init_stack) + (long)&init_stack - 8, \ .ss0 = __KERNEL_DS, \ .ss1 = __KERNEL_CS, \ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \ @@ -852,11 +851,7 @@ static inline void spin_lock_prefetch(const void *x) extern unsigned long thread_saved_pc(struct task_struct *tsk); #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long)) -#define KSTK_TOP(info) \ -({ \ - unsigned long *__ptr = (unsigned long *)(info); \ - (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ -}) +#define KSTK_TOP(info) ((container_of(info, struct task_struct, tinfo))->thread.sp0) /* * The below -8 is to reserve 8 bytes on top of the ring0 stack. @@ -871,7 +866,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); #define task_pt_regs(task) \ ({ \ struct pt_regs *__regs__; \ - __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \ + __regs__ = (struct pt_regs *)((task)->thread.sp0); \ __regs__ - 1; \ }) @@ -881,13 +876,13 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); /* * User space process size. 47bits minus one guard page. */ -#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE) +#define TASK_SIZE_MAX ((1UL << TASK_SIZE_MAX_SHIFT) - PAGE_SIZE) /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ #define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \ - 0xc0000000 : 0xFFFFe000) + 0xc0000000 : 0xFFFFf000) #define TASK_SIZE (test_thread_flag(TIF_ADDR32) ? \ IA32_PAGE_OFFSET : TASK_SIZE_MAX) @@ -898,11 +893,11 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); #define STACK_TOP_MAX TASK_SIZE_MAX #define INIT_THREAD { \ - .sp0 = (unsigned long)&init_stack + sizeof(init_stack) \ + .sp0 = (unsigned long)&init_stack + sizeof(init_stack) - 16 \ } #define INIT_TSS { \ - .x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \ + .x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) - 16 \ } /* @@ -930,6 +925,10 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, */ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) +#ifdef CONFIG_PAX_SEGMEXEC +#define SEGMEXEC_TASK_UNMAPPED_BASE (PAGE_ALIGN(SEGMEXEC_TASK_SIZE / 3)) +#endif + #define KSTK_EIP(task) (task_pt_regs(task)->ip) /* Get/set a process' ability to use the timestamp counter instruction */ @@ -942,7 +941,8 @@ extern int set_tsc_mode(unsigned int val); extern u16 amd_get_nb_id(int cpu); struct aperfmperf { - u64 aperf, mperf; + u64 aperf __intentional_overflow(0); + u64 mperf __intentional_overflow(0); }; static inline void get_aperfmperf(struct aperfmperf *am) @@ -970,7 +970,7 @@ unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, return ratio; } -extern unsigned long arch_align_stack(unsigned long sp); +#define arch_align_stack(x) ((x) & ~0xfUL) extern void free_init_pages(char *what, unsigned long begin, unsigned long end); void default_idle(void); @@ -980,6 +980,6 @@ bool xen_set_default_idle(void); #define xen_set_default_idle 0 #endif -void stop_this_cpu(void *dummy); +void stop_this_cpu(void *dummy) __noreturn; #endif /* _ASM_X86_PROCESSOR_H */ diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 942a086..6c26446 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -85,28 +85,29 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) } /* - * user_mode_vm(regs) determines whether a register set came from user mode. + * user_mode(regs) determines whether a register set came from user mode. * This is true if V8086 mode was enabled OR if the register set was from * protected mode with RPL-3 CS value. This tricky test checks that with * one comparison. Many places in the kernel can bypass this full check - * if they have already ruled out V8086 mode, so user_mode(regs) can be used. + * if they have already ruled out V8086 mode, so user_mode_novm(regs) can + * be used. */ -static inline int user_mode(struct pt_regs *regs) +static inline int user_mode_novm(struct pt_regs *regs) { #ifdef CONFIG_X86_32 return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL; #else - return !!(regs->cs & 3); + return !!(regs->cs & SEGMENT_RPL_MASK); #endif } -static inline int user_mode_vm(struct pt_regs *regs) +static inline int user_mode(struct pt_regs *regs) { #ifdef CONFIG_X86_32 return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL; #else - return user_mode(regs); + return user_mode_novm(regs); #endif } @@ -122,15 +123,16 @@ static inline int v8086_mode(struct pt_regs *regs) #ifdef CONFIG_X86_64 static inline bool user_64bit_mode(struct pt_regs *regs) { + unsigned long cs = regs->cs & 0xffff; #ifndef CONFIG_PARAVIRT /* * On non-paravirt systems, this is the only long mode CPL 3 * selector. We do not allow long mode selectors in the LDT. */ - return regs->cs == __USER_CS; + return cs == __USER_CS; #else /* Headers are too twisted for this to go in paravirt.h. */ - return regs->cs == __USER_CS || regs->cs == pv_info.extra_user_64bit_cs; + return cs == __USER_CS || cs == pv_info.extra_user_64bit_cs; #endif } @@ -181,9 +183,11 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, * Traps from the kernel do not save sp and ss. * Use the helper function to retrieve sp. */ - if (offset == offsetof(struct pt_regs, sp) && - regs->cs == __KERNEL_CS) - return kernel_stack_pointer(regs); + if (offset == offsetof(struct pt_regs, sp)) { + unsigned long cs = regs->cs & 0xffff; + if (cs == __KERNEL_CS || cs == __KERNEXEC_KERNEL_CS) + return kernel_stack_pointer(regs); + } #endif return *(unsigned long *)((unsigned long)regs + offset); } diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index 9c6b890..5305f53 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h @@ -22,16 +22,14 @@ struct real_mode_header { #endif /* APM/BIOS reboot */ u32 machine_real_restart_asm; -#ifdef CONFIG_X86_64 u32 machine_real_restart_seg; -#endif }; /* This must match data at trampoline_32/64.S */ struct trampoline_header { #ifdef CONFIG_X86_32 u32 start; - u16 gdt_pad; + u16 boot_cs; u16 gdt_limit; u32 gdt_base; #else diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index a82c4f1..ac45053 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h @@ -6,13 +6,13 @@ struct pt_regs; struct machine_ops { - void (*restart)(char *cmd); - void (*halt)(void); - void (*power_off)(void); + void (* __noreturn restart)(char *cmd); + void (* __noreturn halt)(void); + void (* __noreturn power_off)(void); void (*shutdown)(void); void (*crash_shutdown)(struct pt_regs *); - void (*emergency_restart)(void); -}; + void (* __noreturn emergency_restart)(void); +} __no_const; extern struct machine_ops machine_ops; diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index cad82c9..2e5c5c1 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -64,6 +64,14 @@ static inline void __down_read(struct rw_semaphore *sem) { asm volatile("# beginning down_read\n\t" LOCK_PREFIX _ASM_INC "(%1)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX _ASM_DEC "(%1)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + /* adds 0x00000001 */ " jns 1f\n" " call call_rwsem_down_read_failed\n" @@ -85,6 +93,14 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) "1:\n\t" " mov %1,%2\n\t" " add %3,%2\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "sub %3,%2\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + " jle 2f\n\t" LOCK_PREFIX " cmpxchg %2,%0\n\t" " jnz 1b\n\t" @@ -104,6 +120,14 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) long tmp; asm volatile("# beginning down_write\n\t" LOCK_PREFIX " xadd %1,(%2)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "mov %1,(%2)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + /* adds 0xffff0001, returns the old value */ " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" /* was the active mask 0 before? */ @@ -155,6 +179,14 @@ static inline void __up_read(struct rw_semaphore *sem) long tmp; asm volatile("# beginning __up_read\n\t" LOCK_PREFIX " xadd %1,(%2)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "mov %1,(%2)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + /* subtracts 1, returns the old value */ " jns 1f\n\t" " call call_rwsem_wake\n" /* expects old value in %edx */ @@ -173,6 +205,14 @@ static inline void __up_write(struct rw_semaphore *sem) long tmp; asm volatile("# beginning __up_write\n\t" LOCK_PREFIX " xadd %1,(%2)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + "mov %1,(%2)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + /* subtracts 0xffff0001, returns the old value */ " jns 1f\n\t" " call call_rwsem_wake\n" /* expects old value in %edx */ @@ -190,6 +230,14 @@ static inline void __downgrade_write(struct rw_semaphore *sem) { asm volatile("# beginning __downgrade_write\n\t" LOCK_PREFIX _ASM_ADD "%2,(%1)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX _ASM_SUB "%2,(%1)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + /* * transitions 0xZZZZ0001 -> 0xYYYY0001 (i386) * 0xZZZZZZZZ00000001 -> 0xYYYYYYYY00000001 (x86_64) @@ -208,7 +256,15 @@ static inline void __downgrade_write(struct rw_semaphore *sem) */ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) { - asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0" + asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX _ASM_SUB "%1,%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + : "+m" (sem->count) : "er" (delta)); } @@ -218,7 +274,7 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) */ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) { - return delta + xadd(&sem->count, delta); + return delta + xadd_check_overflow(&sem->count, delta); } #endif /* __KERNEL__ */ diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index c48a950..bc40804 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h @@ -64,10 +64,15 @@ * 26 - ESPFIX small SS * 27 - per-cpu [ offset to per-cpu data area ] * 28 - stack_canary-20 [ for stack protector ] - * 29 - unused - * 30 - unused + * 29 - PCI BIOS CS + * 30 - PCI BIOS DS * 31 - TSS for double fault handler */ +#define GDT_ENTRY_KERNEXEC_EFI_CS (1) +#define GDT_ENTRY_KERNEXEC_EFI_DS (2) +#define __KERNEXEC_EFI_CS (GDT_ENTRY_KERNEXEC_EFI_CS*8) +#define __KERNEXEC_EFI_DS (GDT_ENTRY_KERNEXEC_EFI_DS*8) + #define GDT_ENTRY_TLS_MIN 6 #define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) @@ -79,6 +84,8 @@ #define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE+0) +#define GDT_ENTRY_KERNEXEC_KERNEL_CS (4) + #define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE+1) #define GDT_ENTRY_TSS (GDT_ENTRY_KERNEL_BASE+4) @@ -104,6 +111,12 @@ #define __KERNEL_STACK_CANARY 0 #endif +#define GDT_ENTRY_PCIBIOS_CS (GDT_ENTRY_KERNEL_BASE+17) +#define __PCIBIOS_CS (GDT_ENTRY_PCIBIOS_CS * 8) + +#define GDT_ENTRY_PCIBIOS_DS (GDT_ENTRY_KERNEL_BASE+18) +#define __PCIBIOS_DS (GDT_ENTRY_PCIBIOS_DS * 8) + #define GDT_ENTRY_DOUBLEFAULT_TSS 31 /* @@ -141,7 +154,7 @@ */ /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */ -#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8) +#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xFFFCU) == PNP_CS32 || ((x) & 0xFFFCU) == PNP_CS16) #else @@ -165,6 +178,8 @@ #define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8+3) #define __USER32_DS __USER_DS +#define GDT_ENTRY_KERNEXEC_KERNEL_CS 7 + #define GDT_ENTRY_TSS 8 /* needs two entries */ #define GDT_ENTRY_LDT 10 /* needs two entries */ #define GDT_ENTRY_TLS_MIN 12 @@ -173,6 +188,8 @@ #define GDT_ENTRY_PER_CPU 15 /* Abused to load per CPU data from limit */ #define __PER_CPU_SEG (GDT_ENTRY_PER_CPU * 8 + 3) +#define GDT_ENTRY_UDEREF_KERNEL_DS 16 + /* TLS indexes for 64bit - hardcoded in arch_prctl */ #define FS_TLS 0 #define GS_TLS 1 @@ -180,12 +197,14 @@ #define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3) #define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) -#define GDT_ENTRIES 16 +#define GDT_ENTRIES 17 #endif #define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8) +#define __KERNEXEC_KERNEL_CS (GDT_ENTRY_KERNEXEC_KERNEL_CS*8) #define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8) +#define __UDEREF_KERNEL_DS (GDT_ENTRY_UDEREF_KERNEL_DS*8) #define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3) #define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3) #ifndef CONFIG_PARAVIRT @@ -265,7 +284,7 @@ static inline unsigned long get_limit(unsigned long segment) { unsigned long __limit; asm("lsll %1,%0" : "=r" (__limit) : "r" (segment)); - return __limit + 1; + return __limit; } #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h index 8d3120f..352b440 100644 --- a/arch/x86/include/asm/smap.h +++ b/arch/x86/include/asm/smap.h @@ -25,11 +25,40 @@ #include +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define ASM_PAX_OPEN_USERLAND \ + 661: jmp 663f; \ + .pushsection .altinstr_replacement, "a" ; \ + 662: pushq %rax; nop; \ + .popsection ; \ + .pushsection .altinstructions, "a" ; \ + altinstruction_entry 661b, 662b, X86_FEATURE_STRONGUDEREF, 2, 2;\ + .popsection ; \ + call __pax_open_userland; \ + popq %rax; \ + 663: + +#define ASM_PAX_CLOSE_USERLAND \ + 661: jmp 663f; \ + .pushsection .altinstr_replacement, "a" ; \ + 662: pushq %rax; nop; \ + .popsection; \ + .pushsection .altinstructions, "a" ; \ + altinstruction_entry 661b, 662b, X86_FEATURE_STRONGUDEREF, 2, 2;\ + .popsection; \ + call __pax_close_userland; \ + popq %rax; \ + 663: +#else +#define ASM_PAX_OPEN_USERLAND +#define ASM_PAX_CLOSE_USERLAND +#endif + #ifdef CONFIG_X86_SMAP #define ASM_CLAC \ 661: ASM_NOP3 ; \ - .pushsection .altinstr_replacement, "ax" ; \ + .pushsection .altinstr_replacement, "a" ; \ 662: __ASM_CLAC ; \ .popsection ; \ .pushsection .altinstructions, "a" ; \ @@ -38,7 +67,7 @@ #define ASM_STAC \ 661: ASM_NOP3 ; \ - .pushsection .altinstr_replacement, "ax" ; \ + .pushsection .altinstr_replacement, "a" ; \ 662: __ASM_STAC ; \ .popsection ; \ .pushsection .altinstructions, "a" ; \ @@ -56,6 +85,37 @@ #include +#define __HAVE_ARCH_PAX_OPEN_USERLAND +#define __HAVE_ARCH_PAX_CLOSE_USERLAND + +extern void __pax_open_userland(void); +static __always_inline unsigned long pax_open_userland(void) +{ + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + asm volatile(ALTERNATIVE(ASM_NOP5, "call %P[open]", X86_FEATURE_STRONGUDEREF) + : + : [open] "i" (__pax_open_userland) + : "memory", "rax"); +#endif + + return 0; +} + +extern void __pax_close_userland(void); +static __always_inline unsigned long pax_close_userland(void) +{ + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + asm volatile(ALTERNATIVE(ASM_NOP5, "call %P[close]", X86_FEATURE_STRONGUDEREF) + : + : [close] "i" (__pax_close_userland) + : "memory", "rax"); +#endif + + return 0; +} + #ifdef CONFIG_X86_SMAP static __always_inline void clac(void) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index b073aae..39f9bdd 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -36,7 +36,7 @@ DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); /* cpus sharing the last level cache: */ DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id); -DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number); +DECLARE_PER_CPU_READ_MOSTLY(unsigned int, cpu_number); static inline struct cpumask *cpu_sibling_mask(int cpu) { @@ -79,7 +79,7 @@ struct smp_ops { void (*send_call_func_ipi)(const struct cpumask *mask); void (*send_call_func_single_ipi)(int cpu); -}; +} __no_const; /* Globals due to paravirt */ extern void set_cpu_sibling_map(int cpu); @@ -191,14 +191,8 @@ extern unsigned disabled_cpus __cpuinitdata; extern int safe_smp_processor_id(void); #elif defined(CONFIG_X86_64_SMP) -#define raw_smp_processor_id() (this_cpu_read(cpu_number)) - -#define stack_smp_processor_id() \ -({ \ - struct thread_info *ti; \ - __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK)); \ - ti->cpu; \ -}) +#define raw_smp_processor_id() (this_cpu_read(cpu_number)) +#define stack_smp_processor_id() raw_smp_processor_id() #define safe_smp_processor_id() smp_processor_id() #endif diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index 33692ea..350a534 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -172,6 +172,14 @@ static inline int arch_write_can_lock(arch_rwlock_t *lock) static inline void arch_read_lock(arch_rwlock_t *rw) { asm volatile(LOCK_PREFIX READ_LOCK_SIZE(dec) " (%0)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX READ_LOCK_SIZE(inc) " (%0)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + "jns 1f\n" "call __read_lock_failed\n\t" "1:\n" @@ -181,6 +189,14 @@ static inline void arch_read_lock(arch_rwlock_t *rw) static inline void arch_write_lock(arch_rwlock_t *rw) { asm volatile(LOCK_PREFIX WRITE_LOCK_SUB(%1) "(%0)\n\t" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX WRITE_LOCK_ADD(%1) "(%0)\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + "jz 1f\n" "call __write_lock_failed\n\t" "1:\n" @@ -210,13 +226,29 @@ static inline int arch_write_trylock(arch_rwlock_t *lock) static inline void arch_read_unlock(arch_rwlock_t *rw) { - asm volatile(LOCK_PREFIX READ_LOCK_SIZE(inc) " %0" + asm volatile(LOCK_PREFIX READ_LOCK_SIZE(inc) " %0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX READ_LOCK_SIZE(dec) " %0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + :"+m" (rw->lock) : : "memory"); } static inline void arch_write_unlock(arch_rwlock_t *rw) { - asm volatile(LOCK_PREFIX WRITE_LOCK_ADD(%1) "%0" + asm volatile(LOCK_PREFIX WRITE_LOCK_ADD(%1) "%0\n" + +#ifdef CONFIG_PAX_REFCOUNT + "jno 0f\n" + LOCK_PREFIX WRITE_LOCK_SUB(%1) "%0\n" + "int $4\n0:\n" + _ASM_EXTABLE(0b, 0b) +#endif + : "+m" (rw->write) : "i" (RW_LOCK_BIAS) : "memory"); } diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index 6a99859..03cb807 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h @@ -47,7 +47,7 @@ * head_32 for boot CPU and setup_per_cpu_areas() for others. */ #define GDT_STACK_CANARY_INIT \ - [GDT_ENTRY_STACK_CANARY] = GDT_ENTRY_INIT(0x4090, 0, 0x18), + [GDT_ENTRY_STACK_CANARY] = GDT_ENTRY_INIT(0x4090, 0, 0x17), /* * Initialize the stackprotector canary value. @@ -112,7 +112,7 @@ static inline void setup_stack_canary_segment(int cpu) static inline void load_stack_canary_segment(void) { -#ifdef CONFIG_X86_32 +#if defined(CONFIG_X86_32) && !defined(CONFIG_PAX_MEMORY_UDEREF) asm volatile ("mov %0, %%gs" : : "r" (0)); #endif } diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index 70bbe39..4ae2bd4 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h @@ -11,28 +11,20 @@ extern int kstack_depth_to_print; -struct thread_info; +struct task_struct; struct stacktrace_ops; -typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo, - unsigned long *stack, - unsigned long bp, - const struct stacktrace_ops *ops, - void *data, - unsigned long *end, - int *graph); - -extern unsigned long -print_context_stack(struct thread_info *tinfo, - unsigned long *stack, unsigned long bp, - const struct stacktrace_ops *ops, void *data, - unsigned long *end, int *graph); - -extern unsigned long -print_context_stack_bp(struct thread_info *tinfo, - unsigned long *stack, unsigned long bp, - const struct stacktrace_ops *ops, void *data, - unsigned long *end, int *graph); +typedef unsigned long walk_stack_t(struct task_struct *task, + void *stack_start, + unsigned long *stack, + unsigned long bp, + const struct stacktrace_ops *ops, + void *data, + unsigned long *end, + int *graph); + +extern walk_stack_t print_context_stack; +extern walk_stack_t print_context_stack_bp; /* Generic stack tracer with callbacks */ @@ -40,7 +32,7 @@ struct stacktrace_ops { void (*address)(void *data, unsigned long address, int reliable); /* On negative return stop dumping */ int (*stack)(void *data, char *name); - walk_stack_t walk_stack; + walk_stack_t *walk_stack; }; void dump_trace(struct task_struct *tsk, struct pt_regs *regs, diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h index 4ec45b3..a4f0a8a 100644 --- a/arch/x86/include/asm/switch_to.h +++ b/arch/x86/include/asm/switch_to.h @@ -108,7 +108,7 @@ do { \ "call __switch_to\n\t" \ "movq "__percpu_arg([current_task])",%%rsi\n\t" \ __switch_canary \ - "movq %P[thread_info](%%rsi),%%r8\n\t" \ + "movq "__percpu_arg([thread_info])",%%r8\n\t" \ "movq %%rax,%%rdi\n\t" \ "testl %[_tif_fork],%P[ti_flags](%%r8)\n\t" \ "jnz ret_from_fork\n\t" \ @@ -119,7 +119,7 @@ do { \ [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ [_tif_fork] "i" (_TIF_FORK), \ - [thread_info] "i" (offsetof(struct task_struct, stack)), \ + [thread_info] "m" (current_tinfo), \ [current_task] "m" (current_task) \ __switch_canary_iparam \ : "memory", "cc" __EXTRA_CLOBBER) diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index a1df6e8..e002940 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -10,6 +10,7 @@ #include #include #include +#include /* * low level task data that entry.S needs immediate access to @@ -23,7 +24,6 @@ struct exec_domain; #include struct thread_info { - struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ __u32 flags; /* low level flags */ __u32 status; /* thread synchronous flags */ @@ -33,19 +33,13 @@ struct thread_info { mm_segment_t addr_limit; struct restart_block restart_block; void __user *sysenter_return; -#ifdef CONFIG_X86_32 - unsigned long previous_esp; /* ESP of the previous stack in - case of nested (IRQ) stacks - */ - __u8 supervisor_stack[0]; -#endif + unsigned long lowest_stack; unsigned int sig_on_uaccess_error:1; unsigned int uaccess_err:1; /* uaccess failed */ }; -#define INIT_THREAD_INFO(tsk) \ +#define INIT_THREAD_INFO \ { \ - .task = &tsk, \ .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ @@ -56,7 +50,7 @@ struct thread_info { }, \ } -#define init_thread_info (init_thread_union.thread_info) +#define init_thread_info (init_thread_union.stack) #define init_stack (init_thread_union.stack) #else /* !__ASSEMBLY__ */ @@ -97,6 +91,7 @@ struct thread_info { #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ #define TIF_ADDR32 29 /* 32-bit address space on 64 bits */ #define TIF_X32 30 /* 32-bit native x86-64 binary */ +#define TIF_GRSEC_SETXID 31 /* update credentials on syscall entry/exit */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) @@ -121,17 +116,18 @@ struct thread_info { #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) #define _TIF_ADDR32 (1 << TIF_ADDR32) #define _TIF_X32 (1 << TIF_X32) +#define _TIF_GRSEC_SETXID (1 << TIF_GRSEC_SETXID) /* work to do in syscall_trace_enter() */ #define _TIF_WORK_SYSCALL_ENTRY \ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_AUDIT | \ _TIF_SECCOMP | _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT | \ - _TIF_NOHZ) + _TIF_NOHZ | _TIF_GRSEC_SETXID) /* work to do in syscall_trace_leave() */ #define _TIF_WORK_SYSCALL_EXIT \ (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP | \ - _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ) + _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ | _TIF_GRSEC_SETXID) /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK \ @@ -142,7 +138,7 @@ struct thread_info { /* work to do on any return to user space */ #define _TIF_ALLWORK_MASK \ ((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_TRACEPOINT | \ - _TIF_NOHZ) + _TIF_NOHZ | _TIF_GRSEC_SETXID) /* Only used for 64 bit */ #define _TIF_DO_NOTIFY_MASK \ @@ -158,6 +154,23 @@ struct thread_info { #define PREEMPT_ACTIVE 0x10000000 +#ifdef __ASSEMBLY__ +/* how to get the thread information struct from ASM */ +#define GET_THREAD_INFO(reg) \ + mov PER_CPU_VAR(current_tinfo), reg + +/* use this one if reg already contains %esp */ +#define GET_THREAD_INFO_WITH_ESP(reg) GET_THREAD_INFO(reg) +#else +/* how to get the thread information struct from C */ +DECLARE_PER_CPU(struct thread_info *, current_tinfo); + +static __always_inline struct thread_info *current_thread_info(void) +{ + return this_cpu_read_stable(current_tinfo); +} +#endif + #ifdef CONFIG_X86_32 #define STACK_WARN (THREAD_SIZE/8) @@ -168,35 +181,13 @@ struct thread_info { */ #ifndef __ASSEMBLY__ - /* how to get the current stack pointer from C */ register unsigned long current_stack_pointer asm("esp") __used; -/* how to get the thread information struct from C */ -static inline struct thread_info *current_thread_info(void) -{ - return (struct thread_info *) - (current_stack_pointer & ~(THREAD_SIZE - 1)); -} - -#else /* !__ASSEMBLY__ */ - -/* how to get the thread information struct from ASM */ -#define GET_THREAD_INFO(reg) \ - movl $-THREAD_SIZE, reg; \ - andl %esp, reg - -/* use this one if reg already contains %esp */ -#define GET_THREAD_INFO_WITH_ESP(reg) \ - andl $-THREAD_SIZE, reg - #endif #else /* X86_32 */ -#include -#define KERNEL_STACK_OFFSET (5*8) - /* * macros/functions for gaining access to the thread information structure * preempt_count needs to be 1 initially, until the scheduler is functional. @@ -204,27 +195,8 @@ static inline struct thread_info *current_thread_info(void) #ifndef __ASSEMBLY__ DECLARE_PER_CPU(unsigned long, kernel_stack); -static inline struct thread_info *current_thread_info(void) -{ - struct thread_info *ti; - ti = (void *)(this_cpu_read_stable(kernel_stack) + - KERNEL_STACK_OFFSET - THREAD_SIZE); - return ti; -} - -#else /* !__ASSEMBLY__ */ - -/* how to get the thread information struct from ASM */ -#define GET_THREAD_INFO(reg) \ - movq PER_CPU_VAR(kernel_stack),reg ; \ - subq $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg - -/* - * Same if PER_CPU_VAR(kernel_stack) is, perhaps with some offset, already in - * a certain register (to be used in assembler memory operands). - */ -#define THREAD_INFO(reg, off) KERNEL_STACK_OFFSET+(off)-THREAD_SIZE(reg) - +/* how to get the current stack pointer from C */ +register unsigned long current_stack_pointer asm("rsp") __used; #endif #endif /* !X86_32 */ @@ -283,5 +255,12 @@ static inline bool is_ia32_task(void) extern void arch_task_cache_init(void); extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); extern void arch_release_task_struct(struct task_struct *tsk); + +#define __HAVE_THREAD_FUNCTIONS +#define task_thread_info(task) (&(task)->tinfo) +#define task_stack_page(task) ((task)->stack) +#define setup_thread_stack(p, org) do {} while (0) +#define end_of_stack(p) ((unsigned long *)task_stack_page(p) + 1) + #endif #endif /* _ASM_X86_THREAD_INFO_H */ diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 50a7fc0..45844c0 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -17,18 +17,44 @@ static inline void __native_flush_tlb(void) { + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; + + descriptor[0] = PCID_KERNEL; + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_MONGLOBAL) : "memory"); + return; + } + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (static_cpu_has(X86_FEATURE_PCID)) { + unsigned int cpu = raw_get_cpu(); + + native_write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER); + native_write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL); + raw_put_cpu_no_resched(); + return; + } +#endif + native_write_cr3(native_read_cr3()); } static inline void __native_flush_tlb_global_irq_disabled(void) { - unsigned long cr4; - - cr4 = native_read_cr4(); - /* clear PGE */ - native_write_cr4(cr4 & ~X86_CR4_PGE); - /* write old PGE again and flush TLBs */ - native_write_cr4(cr4); + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; + + descriptor[0] = PCID_KERNEL; + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_GLOBAL) : "memory"); + } else { + unsigned long cr4; + + cr4 = native_read_cr4(); + /* clear PGE */ + native_write_cr4(cr4 & ~X86_CR4_PGE); + /* write old PGE again and flush TLBs */ + native_write_cr4(cr4); + } } static inline void __native_flush_tlb_global(void) @@ -49,6 +75,42 @@ static inline void __native_flush_tlb_global(void) static inline void __native_flush_tlb_single(unsigned long addr) { + + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; + + descriptor[0] = PCID_KERNEL; + descriptor[1] = addr; + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (!static_cpu_has(X86_FEATURE_STRONGUDEREF) || addr >= TASK_SIZE_MAX) { + if (addr < TASK_SIZE_MAX) + descriptor[1] += pax_user_shadow_base; + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_ADDRESS) : "memory"); + } + + descriptor[0] = PCID_USER; + descriptor[1] = addr; +#endif + + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_SINGLE_ADDRESS) : "memory"); + return; + } + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (static_cpu_has(X86_FEATURE_PCID)) { + unsigned int cpu = raw_get_cpu(); + + native_write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER | PCID_NOFLUSH); + asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); + native_write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); + raw_put_cpu_no_resched(); + + if (!static_cpu_has(X86_FEATURE_STRONGUDEREF) && addr < TASK_SIZE_MAX) + addr += pax_user_shadow_base; + } +#endif + asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); } diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 5ee2687..74590b9 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,12 @@ #define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF) +void __set_fs(mm_segment_t x); +void set_fs(mm_segment_t x); +#else #define set_fs(x) (current_thread_info()->addr_limit = (x)) +#endif #define segment_eq(a, b) ((a).seg == (b).seg) @@ -77,8 +83,33 @@ * checks that the pointer is in the user space range - after calling * this function, memory access functions may still return -EFAULT. */ -#define access_ok(type, addr, size) \ - (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) +#define __access_ok(type, addr, size) (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) +#define access_ok(type, addr, size) \ +({ \ + long __size = size; \ + unsigned long __addr = (unsigned long)addr; \ + unsigned long __addr_ao = __addr & PAGE_MASK; \ + unsigned long __end_ao = __addr + __size - 1; \ + bool __ret_ao = __range_not_ok(__addr, __size, user_addr_max()) == 0;\ + if (__ret_ao && unlikely((__end_ao ^ __addr_ao) & PAGE_MASK)) { \ + while(__addr_ao <= __end_ao) { \ + char __c_ao; \ + __addr_ao += PAGE_SIZE; \ + if (__size > PAGE_SIZE) \ + cond_resched(); \ + if (__get_user(__c_ao, (char __user *)__addr)) \ + break; \ + if (type != VERIFY_WRITE) { \ + __addr = __addr_ao; \ + continue; \ + } \ + if (__put_user(__c_ao, (char __user *)__addr)) \ + break; \ + __addr = __addr_ao; \ + } \ + } \ + __ret_ao; \ +}) /* * The exception table consists of pairs of addresses relative to the @@ -165,10 +196,12 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) register __inttype(*(ptr)) __val_gu asm("%edx"); \ __chk_user_ptr(ptr); \ might_fault(); \ + pax_open_userland(); \ asm volatile("call __get_user_%P3" \ : "=a" (__ret_gu), "=r" (__val_gu) \ : "0" (ptr), "i" (sizeof(*(ptr)))); \ (x) = (__typeof__(*(ptr))) __val_gu; \ + pax_close_userland(); \ __ret_gu; \ }) @@ -176,13 +209,21 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) asm volatile("call __put_user_" #size : "=a" (__ret_pu) \ : "0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx") - +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define __copyuser_seg "gs;" +#define __COPYUSER_SET_ES "pushl %%gs; popl %%es\n" +#define __COPYUSER_RESTORE_ES "pushl %%ss; popl %%es\n" +#else +#define __copyuser_seg +#define __COPYUSER_SET_ES +#define __COPYUSER_RESTORE_ES +#endif #ifdef CONFIG_X86_32 #define __put_user_asm_u64(x, addr, err, errret) \ asm volatile(ASM_STAC "\n" \ - "1: movl %%eax,0(%2)\n" \ - "2: movl %%edx,4(%2)\n" \ + "1: "__copyuser_seg"movl %%eax,0(%2)\n" \ + "2: "__copyuser_seg"movl %%edx,4(%2)\n" \ "3: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "4: movl %3,%0\n" \ @@ -195,8 +236,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) #define __put_user_asm_ex_u64(x, addr) \ asm volatile(ASM_STAC "\n" \ - "1: movl %%eax,0(%1)\n" \ - "2: movl %%edx,4(%1)\n" \ + "1: "__copyuser_seg"movl %%eax,0(%1)\n" \ + "2: "__copyuser_seg"movl %%edx,4(%1)\n" \ "3: " ASM_CLAC "\n" \ _ASM_EXTABLE_EX(1b, 2b) \ _ASM_EXTABLE_EX(2b, 3b) \ @@ -246,7 +287,8 @@ extern void __put_user_8(void); __typeof__(*(ptr)) __pu_val; \ __chk_user_ptr(ptr); \ might_fault(); \ - __pu_val = x; \ + __pu_val = (x); \ + pax_open_userland(); \ switch (sizeof(*(ptr))) { \ case 1: \ __put_user_x(1, __pu_val, ptr, __ret_pu); \ @@ -264,6 +306,7 @@ extern void __put_user_8(void); __put_user_x(X, __pu_val, ptr, __ret_pu); \ break; \ } \ + pax_close_userland(); \ __ret_pu; \ }) @@ -344,8 +387,10 @@ do { \ } while (0) #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \ +do { \ + pax_open_userland(); \ asm volatile(ASM_STAC "\n" \ - "1: mov"itype" %2,%"rtype"1\n" \ + "1: "__copyuser_seg"mov"itype" %2,%"rtype"1\n"\ "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "3: mov %3,%0\n" \ @@ -353,8 +398,10 @@ do { \ " jmp 2b\n" \ ".previous\n" \ _ASM_EXTABLE(1b, 3b) \ - : "=r" (err), ltype(x) \ - : "m" (__m(addr)), "i" (errret), "0" (err)) + : "=r" (err), ltype (x) \ + : "m" (__m(addr)), "i" (errret), "0" (err)); \ + pax_close_userland(); \ +} while (0) #define __get_user_size_ex(x, ptr, size) \ do { \ @@ -378,7 +425,7 @@ do { \ } while (0) #define __get_user_asm_ex(x, addr, itype, rtype, ltype) \ - asm volatile("1: mov"itype" %1,%"rtype"0\n" \ + asm volatile("1: "__copyuser_seg"mov"itype" %1,%"rtype"0\n"\ "2:\n" \ _ASM_EXTABLE_EX(1b, 2b) \ : ltype(x) : "m" (__m(addr))) @@ -395,13 +442,24 @@ do { \ int __gu_err; \ unsigned long __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \ - (x) = (__force __typeof__(*(ptr)))__gu_val; \ + (x) = (__typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) /* FIXME: this hack is definitely wrong -AK */ struct __large_struct { unsigned long buf[100]; }; -#define __m(x) (*(struct __large_struct __user *)(x)) +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define ____m(x) \ +({ \ + unsigned long ____x = (unsigned long)(x); \ + if (____x < pax_user_shadow_base) \ + ____x += pax_user_shadow_base; \ + (typeof(x))____x; \ +}) +#else +#define ____m(x) (x) +#endif +#define __m(x) (*(struct __large_struct __user *)____m(x)) /* * Tell gcc we read from memory instead of writing: this is because @@ -409,8 +467,10 @@ struct __large_struct { unsigned long buf[100]; }; * aliasing issues. */ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ +do { \ + pax_open_userland(); \ asm volatile(ASM_STAC "\n" \ - "1: mov"itype" %"rtype"1,%2\n" \ + "1: "__copyuser_seg"mov"itype" %"rtype"1,%2\n"\ "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ "3: mov %3,%0\n" \ @@ -418,10 +478,12 @@ struct __large_struct { unsigned long buf[100]; }; ".previous\n" \ _ASM_EXTABLE(1b, 3b) \ : "=r"(err) \ - : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) + : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err));\ + pax_close_userland(); \ +} while (0) #define __put_user_asm_ex(x, addr, itype, rtype, ltype) \ - asm volatile("1: mov"itype" %"rtype"0,%1\n" \ + asm volatile("1: "__copyuser_seg"mov"itype" %"rtype"0,%1\n"\ "2:\n" \ _ASM_EXTABLE_EX(1b, 2b) \ : : ltype(x), "m" (__m(addr))) @@ -431,11 +493,13 @@ struct __large_struct { unsigned long buf[100]; }; */ #define uaccess_try do { \ current_thread_info()->uaccess_err = 0; \ + pax_open_userland(); \ stac(); \ barrier(); #define uaccess_catch(err) \ clac(); \ + pax_close_userland(); \ (err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \ } while (0) @@ -460,8 +524,12 @@ struct __large_struct { unsigned long buf[100]; }; * On error, the variable @x is set to zero. */ +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define __get_user(x, ptr) get_user((x), (ptr)) +#else #define __get_user(x, ptr) \ __get_user_nocheck((x), (ptr), sizeof(*(ptr))) +#endif /** * __put_user: - Write a simple value into user space, with less checking. @@ -483,8 +551,12 @@ struct __large_struct { unsigned long buf[100]; }; * Returns zero on success, or -EFAULT on error. */ +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define __put_user(x, ptr) put_user((x), (ptr)) +#else #define __put_user(x, ptr) \ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#endif #define __get_user_unaligned __get_user #define __put_user_unaligned __put_user @@ -502,7 +574,7 @@ struct __large_struct { unsigned long buf[100]; }; #define get_user_ex(x, ptr) do { \ unsigned long __gue_val; \ __get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr)))); \ - (x) = (__force __typeof__(*(ptr)))__gue_val; \ + (x) = (__typeof__(*(ptr)))__gue_val; \ } while (0) #define put_user_try uaccess_try @@ -519,8 +591,8 @@ strncpy_from_user(char *dst, const char __user *src, long count); extern __must_check long strlen_user(const char __user *str); extern __must_check long strnlen_user(const char __user *str, long n); -unsigned long __must_check clear_user(void __user *mem, unsigned long len); -unsigned long __must_check __clear_user(void __user *mem, unsigned long len); +unsigned long __must_check clear_user(void __user *mem, unsigned long len) __size_overflow(2); +unsigned long __must_check __clear_user(void __user *mem, unsigned long len) __size_overflow(2); /* * movsl can be slow when source and dest are not both 8-byte aligned diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index 7f760a9..04b1c65 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h @@ -11,15 +11,15 @@ #include unsigned long __must_check __copy_to_user_ll - (void __user *to, const void *from, unsigned long n); + (void __user *to, const void *from, unsigned long n) __size_overflow(3); unsigned long __must_check __copy_from_user_ll - (void *to, const void __user *from, unsigned long n); + (void *to, const void __user *from, unsigned long n) __size_overflow(3); unsigned long __must_check __copy_from_user_ll_nozero - (void *to, const void __user *from, unsigned long n); + (void *to, const void __user *from, unsigned long n) __size_overflow(3); unsigned long __must_check __copy_from_user_ll_nocache - (void *to, const void __user *from, unsigned long n); + (void *to, const void __user *from, unsigned long n) __size_overflow(3); unsigned long __must_check __copy_from_user_ll_nocache_nozero - (void *to, const void __user *from, unsigned long n); + (void *to, const void __user *from, unsigned long n) __size_overflow(3); /** * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking. @@ -43,6 +43,11 @@ unsigned long __must_check __copy_from_user_ll_nocache_nozero static __always_inline unsigned long __must_check __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { + if ((long)n < 0) + return n; + + check_object_size(from, n, true); + if (__builtin_constant_p(n)) { unsigned long ret; @@ -82,12 +87,16 @@ static __always_inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n) { might_fault(); + return __copy_to_user_inatomic(to, from, n); } static __always_inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { + if ((long)n < 0) + return n; + /* Avoid zeroing the tail if the copy fails.. * If 'n' is constant and 1, 2, or 4, we do still zero on a failure, * but as the zeroing behaviour is only significant when n is not @@ -137,6 +146,12 @@ static __always_inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_fault(); + + if ((long)n < 0) + return n; + + check_object_size(to, n, false); + if (__builtin_constant_p(n)) { unsigned long ret; @@ -159,6 +174,10 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to, const void __user *from, unsigned long n) { might_fault(); + + if ((long)n < 0) + return n; + if (__builtin_constant_p(n)) { unsigned long ret; @@ -181,15 +200,19 @@ static __always_inline unsigned long __copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n) { - return __copy_from_user_ll_nocache_nozero(to, from, n); -} + if ((long)n < 0) + return n; -unsigned long __must_check copy_to_user(void __user *to, - const void *from, unsigned long n); -unsigned long __must_check _copy_from_user(void *to, - const void __user *from, - unsigned long n); + return __copy_from_user_ll_nocache_nozero(to, from, n); +} +extern void copy_to_user_overflow(void) +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS + __compiletime_error("copy_to_user() buffer size is not provably correct") +#else + __compiletime_warning("copy_to_user() buffer size is not provably correct") +#endif +; extern void copy_from_user_overflow(void) #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS @@ -199,17 +222,60 @@ extern void copy_from_user_overflow(void) #endif ; -static inline unsigned long __must_check copy_from_user(void *to, - const void __user *from, - unsigned long n) +/** + * copy_to_user: - Copy a block of data into user space. + * @to: Destination address, in user space. + * @from: Source address, in kernel space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from kernel space to user space. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +static inline unsigned long __must_check +copy_to_user(void __user *to, const void *from, unsigned long n) { - int sz = __compiletime_object_size(to); + size_t sz = __compiletime_object_size(from); - if (likely(sz == -1 || sz >= n)) - n = _copy_from_user(to, from, n); - else - copy_from_user_overflow(); + if (unlikely(sz != (size_t)-1 && sz < n)) + copy_to_user_overflow(); + else if (access_ok(VERIFY_WRITE, to, n)) + n = __copy_to_user(to, from, n); + return n; +} +/** + * copy_from_user: - Copy a block of data from user space. + * @to: Destination address, in kernel space. + * @from: Source address, in user space. + * @n: Number of bytes to copy. + * + * Context: User context only. This function may sleep. + * + * Copy data from user space to kernel space. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * If some data could not be copied, this function will pad the copied + * data to the requested size using zero bytes. + */ +static inline unsigned long __must_check +copy_from_user(void *to, const void __user *from, unsigned long n) +{ + size_t sz = __compiletime_object_size(to); + + check_object_size(to, n, false); + + if (unlikely(sz != (size_t)-1 && sz < n)) + copy_from_user_overflow(); + else if (access_ok(VERIFY_READ, from, n)) + n = __copy_from_user(to, from, n); + else if ((long)n > 0) + memset(to, 0, n); return n; } diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index 142810c..1dbe82f 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -10,6 +10,9 @@ #include #include #include +#include + +#define set_fs(x) (current_thread_info()->addr_limit = (x)) /* * Copy To/From Userspace @@ -17,13 +20,13 @@ /* Handles exceptions in both to and from, but doesn't do access_ok */ __must_check unsigned long -copy_user_enhanced_fast_string(void *to, const void *from, unsigned len); +copy_user_enhanced_fast_string(void *to, const void *from, unsigned len) __size_overflow(3); __must_check unsigned long -copy_user_generic_string(void *to, const void *from, unsigned len); +copy_user_generic_string(void *to, const void *from, unsigned len) __size_overflow(3); __must_check unsigned long -copy_user_generic_unrolled(void *to, const void *from, unsigned len); +copy_user_generic_unrolled(void *to, const void *from, unsigned len) __size_overflow(3); -static __always_inline __must_check unsigned long +static __always_inline __must_check __size_overflow(3) unsigned long copy_user_generic(void *to, const void *from, unsigned len) { unsigned ret; @@ -41,142 +44,204 @@ copy_user_generic(void *to, const void *from, unsigned len) ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from), "=d" (len)), "1" (to), "2" (from), "3" (len) - : "memory", "rcx", "r8", "r9", "r10", "r11"); + : "memory", "rcx", "r8", "r9", "r11"); return ret; } +static __always_inline __must_check unsigned long +__copy_to_user(void __user *to, const void *from, unsigned long len); +static __always_inline __must_check unsigned long +__copy_from_user(void *to, const void __user *from, unsigned long len); __must_check unsigned long -_copy_to_user(void __user *to, const void *from, unsigned len); -__must_check unsigned long -_copy_from_user(void *to, const void __user *from, unsigned len); -__must_check unsigned long -copy_in_user(void __user *to, const void __user *from, unsigned len); +copy_in_user(void __user *to, const void __user *from, unsigned long len); + +extern void copy_to_user_overflow(void) +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS + __compiletime_error("copy_to_user() buffer size is not provably correct") +#else + __compiletime_warning("copy_to_user() buffer size is not provably correct") +#endif +; + +extern void copy_from_user_overflow(void) +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS + __compiletime_error("copy_from_user() buffer size is not provably correct") +#else + __compiletime_warning("copy_from_user() buffer size is not provably correct") +#endif +; static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { - int sz = __compiletime_object_size(to); - might_fault(); - if (likely(sz == -1 || sz >= n)) - n = _copy_from_user(to, from, n); -#ifdef CONFIG_DEBUG_VM - else - WARN(1, "Buffer overflow detected!\n"); -#endif + + check_object_size(to, n, false); + + if (access_ok(VERIFY_READ, from, n)) + n = __copy_from_user(to, from, n); + else if (n < INT_MAX) + memset(to, 0, n); return n; } static __always_inline __must_check -int copy_to_user(void __user *dst, const void *src, unsigned size) +int copy_to_user(void __user *dst, const void *src, unsigned long size) { might_fault(); - return _copy_to_user(dst, src, size); + if (access_ok(VERIFY_WRITE, dst, size)) + size = __copy_to_user(dst, src, size); + return size; } static __always_inline __must_check -int __copy_from_user(void *dst, const void __user *src, unsigned size) +unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long size) { - int ret = 0; + size_t sz = __compiletime_object_size(dst); + unsigned ret = 0; might_fault(); + + if (size > INT_MAX) + return size; + + check_object_size(dst, size, false); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_READ, src, size)) + return size; +#endif + + if (unlikely(sz != (size_t)-1 && sz < size)) { + copy_from_user_overflow(); + return size; + } + if (!__builtin_constant_p(size)) - return copy_user_generic(dst, (__force void *)src, size); + return copy_user_generic(dst, (__force_kernel const void *)____m(src), size); switch (size) { - case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src, + case 1:__get_user_asm(*(u8 *)dst, (const u8 __user *)src, ret, "b", "b", "=q", 1); return ret; - case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src, + case 2:__get_user_asm(*(u16 *)dst, (const u16 __user *)src, ret, "w", "w", "=r", 2); return ret; - case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src, + case 4:__get_user_asm(*(u32 *)dst, (const u32 __user *)src, ret, "l", "k", "=r", 4); return ret; - case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src, + case 8:__get_user_asm(*(u64 *)dst, (const u64 __user *)src, ret, "q", "", "=r", 8); return ret; case 10: - __get_user_asm(*(u64 *)dst, (u64 __user *)src, + __get_user_asm(*(u64 *)dst, (const u64 __user *)src, ret, "q", "", "=r", 10); if (unlikely(ret)) return ret; __get_user_asm(*(u16 *)(8 + (char *)dst), - (u16 __user *)(8 + (char __user *)src), + (const u16 __user *)(8 + (const char __user *)src), ret, "w", "w", "=r", 2); return ret; case 16: - __get_user_asm(*(u64 *)dst, (u64 __user *)src, + __get_user_asm(*(u64 *)dst, (const u64 __user *)src, ret, "q", "", "=r", 16); if (unlikely(ret)) return ret; __get_user_asm(*(u64 *)(8 + (char *)dst), - (u64 __user *)(8 + (char __user *)src), + (const u64 __user *)(8 + (const char __user *)src), ret, "q", "", "=r", 8); return ret; default: - return copy_user_generic(dst, (__force void *)src, size); + return copy_user_generic(dst, (__force_kernel const void *)____m(src), size); } } static __always_inline __must_check -int __copy_to_user(void __user *dst, const void *src, unsigned size) +unsigned long __copy_to_user(void __user *dst, const void *src, unsigned long size) { - int ret = 0; + size_t sz = __compiletime_object_size(src); + unsigned ret = 0; might_fault(); + + if (size > INT_MAX) + return size; + + check_object_size(src, size, true); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_WRITE, dst, size)) + return size; +#endif + + if (unlikely(sz != (size_t)-1 && sz < size)) { + copy_to_user_overflow(); + return size; + } + if (!__builtin_constant_p(size)) - return copy_user_generic((__force void *)dst, src, size); + return copy_user_generic((__force_kernel void *)____m(dst), src, size); switch (size) { - case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst, + case 1:__put_user_asm(*(const u8 *)src, (u8 __user *)dst, ret, "b", "b", "iq", 1); return ret; - case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst, + case 2:__put_user_asm(*(const u16 *)src, (u16 __user *)dst, ret, "w", "w", "ir", 2); return ret; - case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst, + case 4:__put_user_asm(*(const u32 *)src, (u32 __user *)dst, ret, "l", "k", "ir", 4); return ret; - case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst, + case 8:__put_user_asm(*(const u64 *)src, (u64 __user *)dst, ret, "q", "", "er", 8); return ret; case 10: - __put_user_asm(*(u64 *)src, (u64 __user *)dst, + __put_user_asm(*(const u64 *)src, (u64 __user *)dst, ret, "q", "", "er", 10); if (unlikely(ret)) return ret; asm("":::"memory"); - __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst, + __put_user_asm(4[(const u16 *)src], 4 + (u16 __user *)dst, ret, "w", "w", "ir", 2); return ret; case 16: - __put_user_asm(*(u64 *)src, (u64 __user *)dst, + __put_user_asm(*(const u64 *)src, (u64 __user *)dst, ret, "q", "", "er", 16); if (unlikely(ret)) return ret; asm("":::"memory"); - __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst, + __put_user_asm(1[(const u64 *)src], 1 + (u64 __user *)dst, ret, "q", "", "er", 8); return ret; default: - return copy_user_generic((__force void *)dst, src, size); + return copy_user_generic((__force_kernel void *)____m(dst), src, size); } } static __always_inline __must_check -int __copy_in_user(void __user *dst, const void __user *src, unsigned size) +unsigned long __copy_in_user(void __user *dst, const void __user *src, unsigned long size) { - int ret = 0; + unsigned ret = 0; might_fault(); + + if (size > INT_MAX) + return size; + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_READ, src, size)) + return size; + if (!__access_ok(VERIFY_WRITE, dst, size)) + return size; +#endif + if (!__builtin_constant_p(size)) - return copy_user_generic((__force void *)dst, - (__force void *)src, size); + return copy_user_generic((__force_kernel void *)____m(dst), + (__force_kernel const void *)____m(src), size); switch (size) { case 1: { u8 tmp; - __get_user_asm(tmp, (u8 __user *)src, + __get_user_asm(tmp, (const u8 __user *)src, ret, "b", "b", "=q", 1); if (likely(!ret)) __put_user_asm(tmp, (u8 __user *)dst, @@ -185,7 +250,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) } case 2: { u16 tmp; - __get_user_asm(tmp, (u16 __user *)src, + __get_user_asm(tmp, (const u16 __user *)src, ret, "w", "w", "=r", 2); if (likely(!ret)) __put_user_asm(tmp, (u16 __user *)dst, @@ -195,7 +260,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) case 4: { u32 tmp; - __get_user_asm(tmp, (u32 __user *)src, + __get_user_asm(tmp, (const u32 __user *)src, ret, "l", "k", "=r", 4); if (likely(!ret)) __put_user_asm(tmp, (u32 __user *)dst, @@ -204,7 +269,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) } case 8: { u64 tmp; - __get_user_asm(tmp, (u64 __user *)src, + __get_user_asm(tmp, (const u64 __user *)src, ret, "q", "", "=r", 8); if (likely(!ret)) __put_user_asm(tmp, (u64 __user *)dst, @@ -212,41 +277,72 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size) return ret; } default: - return copy_user_generic((__force void *)dst, - (__force void *)src, size); + return copy_user_generic((__force_kernel void *)____m(dst), + (__force_kernel const void *)____m(src), size); } } -static __must_check __always_inline int -__copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) +static __must_check __always_inline unsigned long +__copy_from_user_inatomic(void *dst, const void __user *src, unsigned long size) { - return copy_user_generic(dst, (__force const void *)src, size); + if (size > INT_MAX) + return size; + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_READ, src, size)) + return size; +#endif + + return copy_user_generic(dst, (__force_kernel const void *)____m(src), size); } -static __must_check __always_inline int -__copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) +static __must_check __always_inline unsigned long +__copy_to_user_inatomic(void __user *dst, const void *src, unsigned long size) { - return copy_user_generic((__force void *)dst, src, size); + if (size > INT_MAX) + return size; + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_WRITE, dst, size)) + return size; +#endif + + return copy_user_generic((__force_kernel void *)____m(dst), src, size); } -extern long __copy_user_nocache(void *dst, const void __user *src, - unsigned size, int zerorest); +extern unsigned long __copy_user_nocache(void *dst, const void __user *src, + unsigned long size, int zerorest) __size_overflow(3); -static inline int -__copy_from_user_nocache(void *dst, const void __user *src, unsigned size) +static inline unsigned long __copy_from_user_nocache(void *dst, const void __user *src, unsigned long size) { might_sleep(); + + if (size > INT_MAX) + return size; + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_READ, src, size)) + return size; +#endif + return __copy_user_nocache(dst, src, size, 1); } -static inline int -__copy_from_user_inatomic_nocache(void *dst, const void __user *src, - unsigned size) +static inline unsigned long __copy_from_user_inatomic_nocache(void *dst, const void __user *src, + unsigned long size) { + if (size > INT_MAX) + return size; + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!__access_ok(VERIFY_READ, src, size)) + return size; +#endif + return __copy_user_nocache(dst, src, size, 0); } -unsigned long -copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest); +extern unsigned long +copy_user_handle_tail(char __user *to, char __user *from, unsigned long len, unsigned zerorest) __size_overflow(3); #endif /* _ASM_X86_UACCESS_64_H */ diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h index 5b238981..77fdd78 100644 --- a/arch/x86/include/asm/word-at-a-time.h +++ b/arch/x86/include/asm/word-at-a-time.h @@ -11,7 +11,7 @@ * and shift, for example. */ struct word_at_a_time { - const unsigned long one_bits, high_bits; + unsigned long one_bits, high_bits; }; #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index d8d9922..bf6cecb 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -129,7 +129,7 @@ struct x86_init_ops { struct x86_init_timers timers; struct x86_init_iommu iommu; struct x86_init_pci pci; -}; +} __no_const; /** * struct x86_cpuinit_ops - platform specific cpu hotplug setups @@ -140,7 +140,7 @@ struct x86_cpuinit_ops { void (*setup_percpu_clockev)(void); void (*early_percpu_clock_init)(void); void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node); -}; +} __no_const; /** * struct x86_platform_ops - platform specific runtime functions @@ -166,7 +166,7 @@ struct x86_platform_ops { void (*save_sched_clock_state)(void); void (*restore_sched_clock_state)(void); void (*apic_post_init)(void); -}; +} __no_const; struct pci_dev; struct msi_msg; @@ -180,7 +180,7 @@ struct x86_msi_ops { void (*teardown_msi_irqs)(struct pci_dev *dev); void (*restore_msi_irqs)(struct pci_dev *dev, int irq); int (*setup_hpet_msi)(unsigned int irq, unsigned int id); -}; +} __no_const; struct IO_APIC_route_entry; struct io_apic_irq_attr; @@ -201,7 +201,7 @@ struct x86_io_apic_ops { unsigned int destination, int vector, struct io_apic_irq_attr *attr); void (*eoi_ioapic_pin)(int apic, int pin, int vector); -}; +} __no_const; extern struct x86_init_ops x86_init; extern struct x86_cpuinit_ops x86_cpuinit; diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h index 0415cda..3b22adc 100644 --- a/arch/x86/include/asm/xsave.h +++ b/arch/x86/include/asm/xsave.h @@ -70,8 +70,11 @@ static inline int xsave_user(struct xsave_struct __user *buf) if (unlikely(err)) return -EFAULT; + pax_open_userland(); __asm__ __volatile__(ASM_STAC "\n" - "1: .byte " REX_PREFIX "0x0f,0xae,0x27\n" + "1:" + __copyuser_seg + ".byte " REX_PREFIX "0x0f,0xae,0x27\n" "2: " ASM_CLAC "\n" ".section .fixup,\"ax\"\n" "3: movl $-1,%[err]\n" @@ -81,18 +84,22 @@ static inline int xsave_user(struct xsave_struct __user *buf) : [err] "=r" (err) : "D" (buf), "a" (-1), "d" (-1), "0" (0) : "memory"); + pax_close_userland(); return err; } static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) { int err; - struct xsave_struct *xstate = ((__force struct xsave_struct *)buf); + struct xsave_struct *xstate = ((__force_kernel struct xsave_struct *)buf); u32 lmask = mask; u32 hmask = mask >> 32; + pax_open_userland(); __asm__ __volatile__(ASM_STAC "\n" - "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n" + "1:" + __copyuser_seg + ".byte " REX_PREFIX "0x0f,0xae,0x2f\n" "2: " ASM_CLAC "\n" ".section .fixup,\"ax\"\n" "3: movl $-1,%[err]\n" @@ -102,6 +109,7 @@ static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask) : [err] "=r" (err) : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0) : "memory"); /* memory required? */ + pax_close_userland(); return err; } diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h index bbae024..e1528f9 100644 --- a/arch/x86/include/uapi/asm/e820.h +++ b/arch/x86/include/uapi/asm/e820.h @@ -63,7 +63,7 @@ struct e820map { #define ISA_START_ADDRESS 0xa0000 #define ISA_END_ADDRESS 0x100000 -#define BIOS_BEGIN 0x000a0000 +#define BIOS_BEGIN 0x000c0000 #define BIOS_END 0x00100000 #define BIOS_ROM_BASE 0xffe00000 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 7bd3bd3..5dac791 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -22,7 +22,7 @@ obj-y += time.o ioport.o ldt.o dumpstack.o nmi.o obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o obj-$(CONFIG_IRQ_WORK) += irq_work.o obj-y += probe_roms.o -obj-$(CONFIG_X86_32) += i386_ksyms_32.o +obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o obj-y += syscall_$(BITS).o obj-$(CONFIG_X86_64) += vsyscall_64.o diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 230c8ea..f915130 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1361,7 +1361,7 @@ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) * If your system is blacklisted here, but you find that acpi=force * works for you, please contact linux-acpi@vger.kernel.org */ -static struct dmi_system_id __initdata acpi_dmi_table[] = { +static const struct dmi_system_id __initconst acpi_dmi_table[] = { /* * Boxes that need ACPI disabled */ @@ -1436,7 +1436,7 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { }; /* second table for DMI checks that should run after early-quirks */ -static struct dmi_system_id __initdata acpi_dmi_table_late[] = { +static const struct dmi_system_id __initconst acpi_dmi_table_late[] = { /* * HP laptops which use a DSDT reporting as HP/SB400/10000, * which includes some code which overrides all temperature diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index ec94e11..7fbbec0 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -88,8 +88,12 @@ int acpi_suspend_lowlevel(void) #else /* CONFIG_64BIT */ #ifdef CONFIG_SMP stack_start = (unsigned long)temp_stack + sizeof(temp_stack); + + pax_open_kernel(); early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); + pax_close_kernel(); + initial_gs = per_cpu_offset(smp_processor_id()); #endif initial_code = (unsigned long)wakeup_long64; diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index d1daa66..59fecba 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -29,13 +29,11 @@ wakeup_pmode_return: # and restore the stack ... but you need gdt for this to work movl saved_context_esp, %esp - movl %cs:saved_magic, %eax - cmpl $0x12345678, %eax + cmpl $0x12345678, saved_magic jne bogus_magic # jump to place where we left off - movl saved_eip, %eax - jmp *%eax + jmp *(saved_eip) bogus_magic: jmp bogus_magic diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c15cf9a..0e63558 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -268,6 +268,13 @@ void __init_or_module apply_alternatives(struct alt_instr *start, */ for (a = start; a < end; a++) { instr = (u8 *)&a->instr_offset + a->instr_offset; + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + instr += ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; + if (instr < (u8 *)_text || (u8 *)_einittext <= instr) + instr -= ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; +#endif + replacement = (u8 *)&a->repl_offset + a->repl_offset; BUG_ON(a->replacementlen > a->instrlen); BUG_ON(a->instrlen > sizeof(insnbuf)); @@ -299,10 +306,16 @@ static void alternatives_smp_lock(const s32 *start, const s32 *end, for (poff = start; poff < end; poff++) { u8 *ptr = (u8 *)poff + *poff; +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + ptr += ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; + if (ptr < (u8 *)_text || (u8 *)_einittext <= ptr) + ptr -= ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; +#endif + if (!*poff || ptr < text || ptr >= text_end) continue; /* turn DS segment override prefix into lock prefix */ - if (*ptr == 0x3e) + if (*ktla_ktva(ptr) == 0x3e) text_poke(ptr, ((unsigned char []){0xf0}), 1); } mutex_unlock(&text_mutex); @@ -317,10 +330,16 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end, for (poff = start; poff < end; poff++) { u8 *ptr = (u8 *)poff + *poff; +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + ptr += ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; + if (ptr < (u8 *)_text || (u8 *)_einittext <= ptr) + ptr -= ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; +#endif + if (!*poff || ptr < text || ptr >= text_end) continue; /* turn lock prefix into DS segment override prefix */ - if (*ptr == 0xf0) + if (*ktla_ktva(ptr) == 0xf0) text_poke(ptr, ((unsigned char []){0x3E}), 1); } mutex_unlock(&text_mutex); @@ -468,7 +487,7 @@ void __init_or_module apply_paravirt(struct paravirt_patch_site *start, BUG_ON(p->len > MAX_PATCH_LEN); /* prep the buffer with the original instructions */ - memcpy(insnbuf, p->instr, p->len); + memcpy(insnbuf, ktla_ktva(p->instr), p->len); used = pv_init_ops.patch(p->instrtype, p->clobbers, insnbuf, (unsigned long)p->instr, p->len); @@ -515,7 +534,7 @@ void __init alternative_instructions(void) if (!uniproc_patched || num_possible_cpus() == 1) free_init_pages("SMP alternatives", (unsigned long)__smp_locks, - (unsigned long)__smp_locks_end); + PAGE_ALIGN((unsigned long)__smp_locks_end)); #endif apply_paravirt(__parainstructions, __parainstructions_end); @@ -535,13 +554,17 @@ void __init alternative_instructions(void) * instructions. And on the local CPU you need to be protected again NMI or MCE * handlers seeing an inconsistent instruction while you patch. */ -void *__init_or_module text_poke_early(void *addr, const void *opcode, +void *__kprobes text_poke_early(void *addr, const void *opcode, size_t len) { unsigned long flags; local_irq_save(flags); - memcpy(addr, opcode, len); + + pax_open_kernel(); + memcpy(ktla_ktva(addr), opcode, len); sync_core(); + pax_close_kernel(); + local_irq_restore(flags); /* Could also do a CLFLUSH here to speed up CPU recovery; but that causes hangs on some VIA CPUs. */ @@ -563,36 +586,22 @@ void *__init_or_module text_poke_early(void *addr, const void *opcode, */ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) { - unsigned long flags; - char *vaddr; + unsigned char *vaddr = ktla_ktva(addr); struct page *pages[2]; - int i; + size_t i; if (!core_kernel_text((unsigned long)addr)) { - pages[0] = vmalloc_to_page(addr); - pages[1] = vmalloc_to_page(addr + PAGE_SIZE); + pages[0] = vmalloc_to_page(vaddr); + pages[1] = vmalloc_to_page(vaddr + PAGE_SIZE); } else { - pages[0] = virt_to_page(addr); + pages[0] = virt_to_page(vaddr); WARN_ON(!PageReserved(pages[0])); - pages[1] = virt_to_page(addr + PAGE_SIZE); + pages[1] = virt_to_page(vaddr + PAGE_SIZE); } BUG_ON(!pages[0]); - local_irq_save(flags); - set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0])); - if (pages[1]) - set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1])); - vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0); - memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); - clear_fixmap(FIX_TEXT_POKE0); - if (pages[1]) - clear_fixmap(FIX_TEXT_POKE1); - local_flush_tlb(); - sync_core(); - /* Could also do a CLFLUSH here to speed up CPU recovery; but - that causes hangs on some VIA CPUs. */ + text_poke_early(addr, opcode, len); for (i = 0; i < len; i++) - BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]); - local_irq_restore(flags); + BUG_ON((vaddr)[i] != ((const unsigned char *)opcode)[i]); return addr; } diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 904611b..004dde6 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -189,7 +189,7 @@ int first_system_vector = 0xfe; /* * Debug level, exported for io_apic.c */ -unsigned int apic_verbosity; +int apic_verbosity; int pic_mode; @@ -1955,7 +1955,7 @@ void smp_error_interrupt(struct pt_regs *regs) apic_write(APIC_ESR, 0); v1 = apic_read(APIC_ESR); ack_APIC_irq(); - atomic_inc(&irq_err_count); + atomic_inc_unchecked(&irq_err_count); apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)", smp_processor_id(), v0 , v1); diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 00c77cf..2dc6a2d 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -157,7 +157,7 @@ static int flat_probe(void) return 1; } -static struct apic apic_flat = { +static struct apic apic_flat __read_only = { .name = "flat", .probe = flat_probe, .acpi_madt_oem_check = flat_acpi_madt_oem_check, @@ -271,7 +271,7 @@ static int physflat_probe(void) return 0; } -static struct apic apic_physflat = { +static struct apic apic_physflat __read_only = { .name = "physical flat", .probe = physflat_probe, diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index e145f28..2752888 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -119,7 +119,7 @@ static void noop_apic_write(u32 reg, u32 v) WARN_ON_ONCE(cpu_has_apic && !disable_apic); } -struct apic apic_noop = { +struct apic apic_noop __read_only = { .name = "noop", .probe = noop_probe, .acpi_madt_oem_check = NULL, diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index d50e364..543bee3 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -152,7 +152,7 @@ static int probe_bigsmp(void) return dmi_bigsmp; } -static struct apic apic_bigsmp = { +static struct apic apic_bigsmp __read_only = { .name = "bigsmp", .probe = probe_bigsmp, diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 0874799..a7a7892 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -608,8 +608,7 @@ static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem, return ret && es7000_apic_is_cluster(); } -/* We've been warned by a false positive warning.Use __refdata to keep calm. */ -static struct apic __refdata apic_es7000_cluster = { +static struct apic apic_es7000_cluster __read_only = { .name = "es7000", .probe = probe_es7000, @@ -675,7 +674,7 @@ static struct apic __refdata apic_es7000_cluster = { .x86_32_early_logical_apicid = es7000_early_logical_apicid, }; -static struct apic __refdata apic_es7000 = { +static struct apic apic_es7000 __read_only = { .name = "es7000", .probe = probe_es7000, diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 9ed796c..e930fe4 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1060,7 +1060,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, } EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); -void lock_vector_lock(void) +void lock_vector_lock(void) __acquires(vector_lock) { /* Used to the online set of cpus does not change * during assign_irq_vector. @@ -1068,7 +1068,7 @@ void lock_vector_lock(void) raw_spin_lock(&vector_lock); } -void unlock_vector_lock(void) +void unlock_vector_lock(void) __releases(vector_lock) { raw_spin_unlock(&vector_lock); } @@ -2362,7 +2362,7 @@ static void ack_apic_edge(struct irq_data *data) ack_APIC_irq(); } -atomic_t irq_mis_count; +atomic_unchecked_t irq_mis_count; #ifdef CONFIG_GENERIC_PENDING_IRQ static bool io_apic_level_ack_pending(struct irq_cfg *cfg) @@ -2503,7 +2503,7 @@ static void ack_apic_level(struct irq_data *data) * at the cpu. */ if (!(v & (1 << (i & 0x1f)))) { - atomic_inc(&irq_mis_count); + atomic_inc_unchecked(&irq_mis_count); eoi_ioapic_irq(irq, cfg); } diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index d661ee9..791fd33 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -455,8 +455,7 @@ static void numaq_setup_portio_remap(void) (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD); } -/* Use __refdata to keep false positive warning calm. */ -static struct apic __refdata apic_numaq = { +static struct apic apic_numaq __read_only = { .name = "NUMAQ", .probe = probe_numaq, diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index eb35ef9..f184a21 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -72,7 +72,7 @@ static int probe_default(void) return 1; } -static struct apic apic_default = { +static struct apic apic_default __read_only = { .name = "default", .probe = probe_default, diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 77c95c0..434f8a4 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -486,7 +486,7 @@ void setup_summit(void) } #endif -static struct apic apic_summit = { +static struct apic apic_summit __read_only = { .name = "summit", .probe = probe_summit, diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index c88baa4..757aee1 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -183,7 +183,7 @@ update_clusterinfo(struct notifier_block *nfb, unsigned long action, void *hcpu) return notifier_from_errno(err); } -static struct notifier_block __refdata x2apic_cpu_notifier = { +static struct notifier_block x2apic_cpu_notifier = { .notifier_call = update_clusterinfo, }; @@ -235,7 +235,7 @@ static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask, cpumask_and(retmask, mask, per_cpu(cpus_in_cluster, cpu)); } -static struct apic apic_x2apic_cluster = { +static struct apic apic_x2apic_cluster __read_only = { .name = "cluster x2apic", .probe = x2apic_cluster_probe, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 562a76d..a003c0f 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -89,7 +89,7 @@ static int x2apic_phys_probe(void) return apic == &apic_x2apic_phys; } -static struct apic apic_x2apic_phys = { +static struct apic apic_x2apic_phys __read_only = { .name = "physical x2apic", .probe = x2apic_phys_probe, diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 794f6eb..67e1db2 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -342,7 +342,7 @@ static int uv_probe(void) return apic == &apic_x2apic_uv_x; } -static struct apic __refdata apic_x2apic_uv_x = { +static struct apic apic_x2apic_uv_x __read_only = { .name = "UV large system", .probe = uv_probe, diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 53a4e27..038760a 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -433,7 +433,7 @@ static DEFINE_MUTEX(apm_mutex); * This is for buggy BIOS's that refer to (real mode) segment 0x40 * even though they are called in protected mode. */ -static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, +static const struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4093, (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1); static const char driver_version[] = "1.16ac"; /* no spaces */ @@ -611,7 +611,10 @@ static long __apm_bios_call(void *_call) BUG_ON(cpu != 0); gdt = get_cpu_gdt_table(cpu); save_desc_40 = gdt[0x40 / 8]; + + pax_open_kernel(); gdt[0x40 / 8] = bad_bios_desc; + pax_close_kernel(); apm_irq_save(flags); APM_DO_SAVE_SEGS; @@ -620,7 +623,11 @@ static long __apm_bios_call(void *_call) &call->esi); APM_DO_RESTORE_SEGS; apm_irq_restore(flags); + + pax_open_kernel(); gdt[0x40 / 8] = save_desc_40; + pax_close_kernel(); + put_cpu(); return call->eax & 0xff; @@ -687,7 +694,10 @@ static long __apm_bios_call_simple(void *_call) BUG_ON(cpu != 0); gdt = get_cpu_gdt_table(cpu); save_desc_40 = gdt[0x40 / 8]; + + pax_open_kernel(); gdt[0x40 / 8] = bad_bios_desc; + pax_close_kernel(); apm_irq_save(flags); APM_DO_SAVE_SEGS; @@ -695,7 +705,11 @@ static long __apm_bios_call_simple(void *_call) &call->eax); APM_DO_RESTORE_SEGS; apm_irq_restore(flags); + + pax_open_kernel(); gdt[0x40 / 8] = save_desc_40; + pax_close_kernel(); + put_cpu(); return error; } @@ -2362,12 +2376,15 @@ static int __init apm_init(void) * code to that CPU. */ gdt = get_cpu_gdt_table(0); + + pax_open_kernel(); set_desc_base(&gdt[APM_CS >> 3], (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4)); set_desc_base(&gdt[APM_CS_16 >> 3], (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4)); set_desc_base(&gdt[APM_DS >> 3], (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4)); + pax_close_kernel(); proc_create("apm", 0, NULL, &apm_file_ops); diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index 2861082..6d4718e 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c @@ -33,6 +33,8 @@ void common(void) { OFFSET(TI_status, thread_info, status); OFFSET(TI_addr_limit, thread_info, addr_limit); OFFSET(TI_preempt_count, thread_info, preempt_count); + OFFSET(TI_lowest_stack, thread_info, lowest_stack); + DEFINE(TI_task_thread_sp0, offsetof(struct task_struct, thread.sp0) - offsetof(struct task_struct, tinfo)); BLANK(); OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); @@ -53,8 +55,26 @@ void common(void) { OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit); OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0); OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2); + +#ifdef CONFIG_PAX_KERNEXEC + OFFSET(PV_CPU_write_cr0, pv_cpu_ops, write_cr0); +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + OFFSET(PV_MMU_read_cr3, pv_mmu_ops, read_cr3); + OFFSET(PV_MMU_write_cr3, pv_mmu_ops, write_cr3); +#ifdef CONFIG_X86_64 + OFFSET(PV_MMU_set_pgd_batched, pv_mmu_ops, set_pgd_batched); +#endif #endif +#endif + + BLANK(); + DEFINE(PAGE_SIZE_asm, PAGE_SIZE); + DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT); + DEFINE(THREAD_SIZE_asm, THREAD_SIZE); + #ifdef CONFIG_XEN BLANK(); OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask); diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index e7c798b..2b2019b 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -77,6 +77,7 @@ int main(void) BLANK(); #undef ENTRY + DEFINE(TSS_size, sizeof(struct tss_struct)); OFFSET(TSS_ist, tss_struct, x86_tss.ist); BLANK(); diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index b0684e4..22ccfd7 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -8,10 +8,6 @@ CFLAGS_REMOVE_common.o = -pg CFLAGS_REMOVE_perf_event.o = -pg endif -# Make sure load_percpu_segment has no stackprotector -nostackp := $(call cc-option, -fno-stack-protector) -CFLAGS_common.o := $(nostackp) - obj-y := intel_cacheinfo.o scattered.o topology.o obj-y += proc.o capflags.o powerflags.o common.o obj-y += rdrand.o diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 5013a48..0782c53 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -744,7 +744,7 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* AMD errata T13 (order #21922) */ - if ((c->x86 == 6)) { + if (c->x86 == 6) { /* Duron Rev A0 */ if (c->x86_model == 3 && c->x86_mask == 0) size = 64; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 22018f7..df77e23 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -88,60 +88,6 @@ static const struct cpu_dev __cpuinitconst default_cpu = { static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu; -DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { -#ifdef CONFIG_X86_64 - /* - * We need valid kernel segments for data and code in long mode too - * IRET will check the segment types kkeil 2000/10/28 - * Also sysret mandates a special GDT layout - * - * TLS descriptors are currently at a different place compared to i386. - * Hopefully nobody expects them at a fixed place (Wine?) - */ - [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff), - [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff), - [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff), - [GDT_ENTRY_DEFAULT_USER32_CS] = GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff), - [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff), - [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff), -#else - [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xc09a, 0, 0xfffff), - [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), - [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff), - [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff), - /* - * Segments used for calling PnP BIOS have byte granularity. - * They code segments and data segments have fixed 64k limits, - * the transfer segment sizes are set at run time. - */ - /* 32-bit code */ - [GDT_ENTRY_PNPBIOS_CS32] = GDT_ENTRY_INIT(0x409a, 0, 0xffff), - /* 16-bit code */ - [GDT_ENTRY_PNPBIOS_CS16] = GDT_ENTRY_INIT(0x009a, 0, 0xffff), - /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_DS] = GDT_ENTRY_INIT(0x0092, 0, 0xffff), - /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS1] = GDT_ENTRY_INIT(0x0092, 0, 0), - /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS2] = GDT_ENTRY_INIT(0x0092, 0, 0), - /* - * The APM segments have byte granularity and their bases - * are set at run time. All have 64k limits. - */ - /* 32-bit code */ - [GDT_ENTRY_APMBIOS_BASE] = GDT_ENTRY_INIT(0x409a, 0, 0xffff), - /* 16-bit code */ - [GDT_ENTRY_APMBIOS_BASE+1] = GDT_ENTRY_INIT(0x009a, 0, 0xffff), - /* data */ - [GDT_ENTRY_APMBIOS_BASE+2] = GDT_ENTRY_INIT(0x4092, 0, 0xffff), - - [GDT_ENTRY_ESPFIX_SS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), - [GDT_ENTRY_PERCPU] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), - GDT_STACK_CANARY_INIT -#endif -} }; -EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); - static int __init x86_xsave_setup(char *s) { setup_clear_cpu_cap(X86_FEATURE_XSAVE); @@ -288,6 +234,57 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c) set_in_cr4(X86_CR4_SMAP); } +#ifdef CONFIG_X86_64 +static __init int setup_disable_pcid(char *arg) +{ + setup_clear_cpu_cap(X86_FEATURE_PCID); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (clone_pgd_mask != ~(pgdval_t)0UL) + pax_user_shadow_base = 1UL << TASK_SIZE_MAX_SHIFT; +#endif + + return 1; +} +__setup("nopcid", setup_disable_pcid); + +static void setup_pcid(struct cpuinfo_x86 *c) +{ + if (!cpu_has(c, X86_FEATURE_PCID)) { + +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (clone_pgd_mask != ~(pgdval_t)0UL) { + pax_open_kernel(); + pax_user_shadow_base = 1UL << TASK_SIZE_MAX_SHIFT; + pax_close_kernel(); + printk("PAX: slow and weak UDEREF enabled\n"); + } else + printk("PAX: UDEREF disabled\n"); +#endif + + return; + } + + printk("PAX: PCID detected\n"); + set_in_cr4(X86_CR4_PCIDE); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + pax_open_kernel(); + clone_pgd_mask = ~(pgdval_t)0UL; + pax_close_kernel(); + if (pax_user_shadow_base) + printk("PAX: weak UDEREF enabled\n"); + else { + set_cpu_cap(c, X86_FEATURE_STRONGUDEREF); + printk("PAX: strong UDEREF enabled\n"); + } +#endif + + if (cpu_has(c, X86_FEATURE_INVPCID)) + printk("PAX: INVPCID detected\n"); +} +#endif + /* * Some CPU features depend on higher CPUID levels, which may not always * be available due to CPUID level capping or broken virtualization @@ -386,7 +383,7 @@ void switch_to_new_gdt(int cpu) { struct desc_ptr gdt_descr; - gdt_descr.address = (long)get_cpu_gdt_table(cpu); + gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); /* Reload the per-cpu base */ @@ -874,6 +871,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) setup_smep(c); setup_smap(c); +#ifdef CONFIG_X86_64 + setup_pcid(c); +#endif + /* * The vendor-specific functions might have changed features. * Now we do "generic changes." @@ -882,6 +883,10 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Filter out anything that depends on CPUID levels we don't have */ filter_cpuid_features(c, true); +#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF)) + setup_clear_cpu_cap(X86_FEATURE_SEP); +#endif + /* If the model name is still unset, do table lookup. */ if (!c->x86_model_id[0]) { const char *p; @@ -1069,10 +1074,12 @@ static __init int setup_disablecpuid(char *arg) } __setup("clearcpuid=", setup_disablecpuid); +DEFINE_PER_CPU(struct thread_info *, current_tinfo) = &init_task.tinfo; +EXPORT_PER_CPU_SYMBOL(current_tinfo); + #ifdef CONFIG_X86_64 struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table }; -struct desc_ptr nmi_idt_descr = { NR_VECTORS * 16 - 1, - (unsigned long) nmi_idt_table }; +struct desc_ptr nmi_idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) nmi_idt_table }; DEFINE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union) __aligned(PAGE_SIZE); @@ -1086,7 +1093,7 @@ DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned = EXPORT_PER_CPU_SYMBOL(current_task); DEFINE_PER_CPU(unsigned long, kernel_stack) = - (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE; + (unsigned long)&init_thread_union - 16 + THREAD_SIZE; EXPORT_PER_CPU_SYMBOL(kernel_stack); DEFINE_PER_CPU(char *, irq_stack_ptr) = @@ -1231,7 +1238,7 @@ void __cpuinit cpu_init(void) load_ucode_ap(); cpu = stack_smp_processor_id(); - t = &per_cpu(init_tss, cpu); + t = init_tss + cpu; oist = &per_cpu(orig_ist, cpu); #ifdef CONFIG_NUMA @@ -1257,7 +1264,7 @@ void __cpuinit cpu_init(void) switch_to_new_gdt(cpu); loadsegment(fs, 0); - load_idt((const struct desc_ptr *)&idt_descr); + load_idt(&idt_descr); memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8); syscall_init(); @@ -1266,7 +1273,6 @@ void __cpuinit cpu_init(void) wrmsrl(MSR_KERNEL_GS_BASE, 0); barrier(); - x86_configure_nx(); enable_x2apic(); /* @@ -1318,7 +1324,7 @@ void __cpuinit cpu_init(void) { int cpu = smp_processor_id(); struct task_struct *curr = current; - struct tss_struct *t = &per_cpu(init_tss, cpu); + struct tss_struct *t = init_tss + cpu; struct thread_struct *thread = &curr->thread; show_ucode_info_early(); diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 7c6f7d5..8cac382 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -1017,6 +1017,22 @@ static struct attribute *default_attrs[] = { }; #ifdef CONFIG_AMD_NB +static struct attribute *default_attrs_amd_nb[] = { + &type.attr, + &level.attr, + &coherency_line_size.attr, + &physical_line_partition.attr, + &ways_of_associativity.attr, + &number_of_sets.attr, + &size.attr, + &shared_cpu_map.attr, + &shared_cpu_list.attr, + NULL, + NULL, + NULL, + NULL +}; + static struct attribute ** __cpuinit amd_l3_attrs(void) { static struct attribute **attrs; @@ -1027,18 +1043,7 @@ static struct attribute ** __cpuinit amd_l3_attrs(void) n = ARRAY_SIZE(default_attrs); - if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) - n += 2; - - if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING)) - n += 1; - - attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL); - if (attrs == NULL) - return attrs = default_attrs; - - for (n = 0; default_attrs[n]; n++) - attrs[n] = default_attrs[n]; + attrs = default_attrs_amd_nb; if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) { attrs[n++] = &cache_disable_0.attr; @@ -1089,6 +1094,13 @@ static struct kobj_type ktype_cache = { .default_attrs = default_attrs, }; +#ifdef CONFIG_AMD_NB +static struct kobj_type ktype_cache_amd_nb = { + .sysfs_ops = &sysfs_ops, + .default_attrs = default_attrs_amd_nb, +}; +#endif + static struct kobj_type ktype_percpu_entry = { .sysfs_ops = &sysfs_ops, }; @@ -1154,20 +1166,26 @@ static int __cpuinit cache_add_dev(struct device *dev) return retval; } +#ifdef CONFIG_AMD_NB + amd_l3_attrs(); +#endif + for (i = 0; i < num_cache_leaves; i++) { + struct kobj_type *ktype; + this_object = INDEX_KOBJECT_PTR(cpu, i); this_object->cpu = cpu; this_object->index = i; this_leaf = CPUID4_INFO_IDX(cpu, i); - ktype_cache.default_attrs = default_attrs; + ktype = &ktype_cache; #ifdef CONFIG_AMD_NB if (this_leaf->base.nb) - ktype_cache.default_attrs = amd_l3_attrs(); + ktype = &ktype_cache_amd_nb; #endif retval = kobject_init_and_add(&(this_object->kobj), - &ktype_cache, + ktype, per_cpu(ici_cache_kobject, cpu), "index%1lu", i); if (unlikely(retval)) { @@ -1222,7 +1240,7 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier = { +static struct notifier_block cacheinfo_cpu_notifier = { .notifier_call = cacheinfo_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 9239504..b2471ce 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "mce-internal.h" @@ -246,7 +247,7 @@ static void print_mce(struct mce *m) !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "", m->cs, m->ip); - if (m->cs == __KERNEL_CS) + if (m->cs == __KERNEL_CS || m->cs == __KERNEXEC_KERNEL_CS) print_symbol("{%s}", m->ip); pr_cont("\n"); } @@ -279,10 +280,10 @@ static void print_mce(struct mce *m) #define PANIC_TIMEOUT 5 /* 5 seconds */ -static atomic_t mce_paniced; +static atomic_unchecked_t mce_paniced; static int fake_panic; -static atomic_t mce_fake_paniced; +static atomic_unchecked_t mce_fake_paniced; /* Panic in progress. Enable interrupts and wait for final IPI */ static void wait_for_panic(void) @@ -306,7 +307,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp) /* * Make sure only one CPU runs in machine check panic */ - if (atomic_inc_return(&mce_paniced) > 1) + if (atomic_inc_return_unchecked(&mce_paniced) > 1) wait_for_panic(); barrier(); @@ -314,7 +315,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp) console_verbose(); } else { /* Don't log too much for fake panic */ - if (atomic_inc_return(&mce_fake_paniced) > 1) + if (atomic_inc_return_unchecked(&mce_fake_paniced) > 1) return; } /* First print corrected ones that are still unlogged */ @@ -353,7 +354,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp) if (!fake_panic) { if (panic_timeout == 0) panic_timeout = mca_cfg.panic_timeout; - panic(msg); + panic("%s", msg); } else pr_emerg(HW_ERR "Fake kernel panic: %s\n", msg); } @@ -683,7 +684,7 @@ static int mce_timed_out(u64 *t) * might have been modified by someone else. */ rmb(); - if (atomic_read(&mce_paniced)) + if (atomic_read_unchecked(&mce_paniced)) wait_for_panic(); if (!mca_cfg.monarch_timeout) goto out; @@ -1654,7 +1655,7 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code) } /* Call the installed machine check handler for this CPU setup. */ -void (*machine_check_vector)(struct pt_regs *, long error_code) = +void (*machine_check_vector)(struct pt_regs *, long error_code) __read_only = unexpected_machine_check; /* @@ -1677,7 +1678,9 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c) return; } + pax_open_kernel(); machine_check_vector = do_machine_check; + pax_close_kernel(); __mcheck_cpu_init_generic(); __mcheck_cpu_init_vendor(c); @@ -1691,7 +1694,7 @@ void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c) */ static DEFINE_SPINLOCK(mce_chrdev_state_lock); -static int mce_chrdev_open_count; /* #times opened */ +static local_t mce_chrdev_open_count; /* #times opened */ static int mce_chrdev_open_exclu; /* already open exclusive? */ static int mce_chrdev_open(struct inode *inode, struct file *file) @@ -1699,7 +1702,7 @@ static int mce_chrdev_open(struct inode *inode, struct file *file) spin_lock(&mce_chrdev_state_lock); if (mce_chrdev_open_exclu || - (mce_chrdev_open_count && (file->f_flags & O_EXCL))) { + (local_read(&mce_chrdev_open_count) && (file->f_flags & O_EXCL))) { spin_unlock(&mce_chrdev_state_lock); return -EBUSY; @@ -1707,7 +1710,7 @@ static int mce_chrdev_open(struct inode *inode, struct file *file) if (file->f_flags & O_EXCL) mce_chrdev_open_exclu = 1; - mce_chrdev_open_count++; + local_inc(&mce_chrdev_open_count); spin_unlock(&mce_chrdev_state_lock); @@ -1718,7 +1721,7 @@ static int mce_chrdev_release(struct inode *inode, struct file *file) { spin_lock(&mce_chrdev_state_lock); - mce_chrdev_open_count--; + local_dec(&mce_chrdev_open_count); mce_chrdev_open_exclu = 0; spin_unlock(&mce_chrdev_state_lock); @@ -2364,7 +2367,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block mce_cpu_notifier __cpuinitdata = { +static struct notifier_block mce_cpu_notifier = { .notifier_call = mce_cpu_callback, }; @@ -2374,7 +2377,7 @@ static __init void mce_init_banks(void) for (i = 0; i < mca_cfg.banks; i++) { struct mce_bank *b = &mce_banks[i]; - struct device_attribute *a = &b->attr; + device_attribute_no_const *a = &b->attr; sysfs_attr_init(&a->attr); a->attr.name = b->attrname; @@ -2442,7 +2445,7 @@ struct dentry *mce_get_debugfs_dir(void) static void mce_reset(void) { cpu_missing = 0; - atomic_set(&mce_fake_paniced, 0); + atomic_set_unchecked(&mce_fake_paniced, 0); atomic_set(&mce_executing, 0); atomic_set(&mce_callin, 0); atomic_set(&global_nwo, 0); diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index 1c044b1..37a2a43 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c @@ -11,6 +11,7 @@ #include #include #include +#include /* By default disabled */ int mce_p5_enabled __read_mostly; @@ -49,7 +50,9 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c) if (!cpu_has(c, X86_FEATURE_MCE)) return; + pax_open_kernel(); machine_check_vector = pentium_machine_check; + pax_close_kernel(); /* Make sure the vector pointer is visible before we enable MCEs: */ wmb(); diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 47a1870..8c019a7 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -288,7 +288,7 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block thermal_throttle_cpu_notifier __cpuinitdata = +static struct notifier_block thermal_throttle_cpu_notifier = { .notifier_call = thermal_throttle_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index e9a701a..35317d6 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c @@ -10,6 +10,7 @@ #include #include #include +#include /* Machine check handler for WinChip C6: */ static void winchip_machine_check(struct pt_regs *regs, long error_code) @@ -23,7 +24,9 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c) { u32 lo, hi; + pax_open_kernel(); machine_check_vector = winchip_machine_check; + pax_close_kernel(); /* Make sure the vector pointer is visible before we enable MCEs: */ wmb(); diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index ca22b73..9987afe 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -62,7 +62,7 @@ static DEFINE_MUTEX(mtrr_mutex); u64 size_or_mask, size_and_mask; static bool mtrr_aps_delayed_init; -static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM]; +static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __read_only; const struct mtrr_ops *mtrr_if; diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index df5e41f..816c719 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h @@ -25,7 +25,7 @@ struct mtrr_ops { int (*validate_add_page)(unsigned long base, unsigned long size, unsigned int type); int (*have_wrcomb)(void); -}; +} __do_const; extern int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1025f3c..824f677 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1311,7 +1311,7 @@ static void __init pmu_check_apic(void) pr_info("no hardware sampling interrupt available.\n"); } -static struct attribute_group x86_pmu_format_group = { +static attribute_group_no_const x86_pmu_format_group = { .name = "format", .attrs = NULL, }; @@ -1410,7 +1410,7 @@ static struct attribute *events_attr[] = { NULL, }; -static struct attribute_group x86_pmu_events_group = { +static attribute_group_no_const x86_pmu_events_group = { .name = "events", .attrs = events_attr, }; @@ -1920,7 +1920,7 @@ static unsigned long get_segment_base(unsigned int segment) if (idx > GDT_ENTRIES) return 0; - desc = __this_cpu_ptr(&gdt_page.gdt[0]); + desc = get_cpu_gdt_table(smp_processor_id()); } return get_desc_base(desc + idx); @@ -2010,7 +2010,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) break; perf_callchain_store(entry, frame.return_address); - fp = frame.next_frame; + fp = (const void __force_user *)frame.next_frame; } } diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index a9e2207..d70c83a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -2022,10 +2022,10 @@ __init int intel_pmu_init(void) * v2 and above have a perf capabilities MSR */ if (version > 1) { - u64 capabilities; + u64 capabilities = x86_pmu.intel_cap.capabilities; - rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); - x86_pmu.intel_cap.capabilities = capabilities; + if (rdmsrl_safe(MSR_IA32_PERF_CAPABILITIES, &x86_pmu.intel_cap.capabilities)) + x86_pmu.intel_cap.capabilities = capabilities; } intel_ds_init(); diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 8aac56b..588fb13 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -3093,7 +3093,7 @@ static void __init uncore_types_exit(struct intel_uncore_type **types) static int __init uncore_type_init(struct intel_uncore_type *type) { struct intel_uncore_pmu *pmus; - struct attribute_group *attr_group; + attribute_group_no_const *attr_group; struct attribute **attrs; int i, j; @@ -3518,7 +3518,7 @@ static int return NOTIFY_OK; } -static struct notifier_block uncore_cpu_nb __cpuinitdata = { +static struct notifier_block uncore_cpu_nb = { .notifier_call = uncore_cpu_notifier, /* * to migrate uncore events, our notifier should be executed diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index f952891..4722ad4 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -488,7 +488,7 @@ struct intel_uncore_box { struct uncore_event_desc { struct kobj_attribute attr; const char *config; -}; +} __do_const; #define INTEL_UNCORE_EVENT_DESC(_name, _config) \ { \ diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 1e4dbcf..b9a34c2 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -171,7 +171,7 @@ static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block __refdata cpuid_class_cpu_notifier = +static struct notifier_block cpuid_class_cpu_notifier = { .notifier_call = cpuid_class_cpu_callback, }; diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 74467fe..18793d5 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -58,10 +58,8 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs) { #ifdef CONFIG_X86_32 struct pt_regs fixed_regs; -#endif -#ifdef CONFIG_X86_32 - if (!user_mode_vm(regs)) { + if (!user_mode(regs)) { crash_fixup_ss_esp(&fixed_regs, regs); regs = &fixed_regs; } diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index afa64ad..dce67dd 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c @@ -36,7 +36,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, return -ENOMEM; if (userbuf) { - if (copy_to_user(buf, vaddr + offset, csize)) { + if (copy_to_user((char __force_user *)buf, vaddr + offset, csize)) { iounmap(vaddr); return -EFAULT; } diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index 155a13f..1672b9b 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c @@ -11,7 +11,7 @@ #define DOUBLEFAULT_STACKSIZE (1024) static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; -#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) +#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2) #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM) @@ -21,7 +21,7 @@ static void doublefault_fn(void) unsigned long gdt, tss; native_store_gdt(&gdt_desc); - gdt = gdt_desc.address; + gdt = (unsigned long)gdt_desc.address; printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); @@ -58,10 +58,10 @@ struct tss_struct doublefault_tss __cacheline_aligned = { /* 0x2 bit is always set */ .flags = X86_EFLAGS_SF | 0x2, .sp = STACK_START, - .es = __USER_DS, + .es = __KERNEL_DS, .cs = __KERNEL_CS, .ss = __KERNEL_DS, - .ds = __USER_DS, + .ds = __KERNEL_DS, .fs = __KERNEL_PERCPU, .__cr3 = __pa_nodebug(swapper_pg_dir), diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index deb6421..76bbc12 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -2,6 +2,9 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs */ +#ifdef CONFIG_GRKERNSEC_HIDESYM +#define __INCLUDED_BY_HIDESYM 1 +#endif #include #include #include @@ -35,16 +38,14 @@ void printk_address(unsigned long address, int reliable) static void print_ftrace_graph_addr(unsigned long addr, void *data, const struct stacktrace_ops *ops, - struct thread_info *tinfo, int *graph) + struct task_struct *task, int *graph) { - struct task_struct *task; unsigned long ret_addr; int index; if (addr != (unsigned long)return_to_handler) return; - task = tinfo->task; index = task->curr_ret_stack; if (!task->ret_stack || index < *graph) @@ -61,7 +62,7 @@ print_ftrace_graph_addr(unsigned long addr, void *data, static inline void print_ftrace_graph_addr(unsigned long addr, void *data, const struct stacktrace_ops *ops, - struct thread_info *tinfo, int *graph) + struct task_struct *task, int *graph) { } #endif @@ -72,10 +73,8 @@ print_ftrace_graph_addr(unsigned long addr, void *data, * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack */ -static inline int valid_stack_ptr(struct thread_info *tinfo, - void *p, unsigned int size, void *end) +static inline int valid_stack_ptr(void *t, void *p, unsigned int size, void *end) { - void *t = tinfo; if (end) { if (p < end && p >= (end-THREAD_SIZE)) return 1; @@ -86,14 +85,14 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, } unsigned long -print_context_stack(struct thread_info *tinfo, +print_context_stack(struct task_struct *task, void *stack_start, unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data, unsigned long *end, int *graph) { struct stack_frame *frame = (struct stack_frame *)bp; - while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) { + while (valid_stack_ptr(stack_start, stack, sizeof(*stack), end)) { unsigned long addr; addr = *stack; @@ -105,7 +104,7 @@ print_context_stack(struct thread_info *tinfo, } else { ops->address(data, addr, 0); } - print_ftrace_graph_addr(addr, data, ops, tinfo, graph); + print_ftrace_graph_addr(addr, data, ops, task, graph); } stack++; } @@ -114,7 +113,7 @@ print_context_stack(struct thread_info *tinfo, EXPORT_SYMBOL_GPL(print_context_stack); unsigned long -print_context_stack_bp(struct thread_info *tinfo, +print_context_stack_bp(struct task_struct *task, void *stack_start, unsigned long *stack, unsigned long bp, const struct stacktrace_ops *ops, void *data, unsigned long *end, int *graph) @@ -122,7 +121,7 @@ print_context_stack_bp(struct thread_info *tinfo, struct stack_frame *frame = (struct stack_frame *)bp; unsigned long *ret_addr = &frame->return_address; - while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) { + while (valid_stack_ptr(stack_start, ret_addr, sizeof(*ret_addr), end)) { unsigned long addr = *ret_addr; if (!__kernel_text_address(addr)) @@ -131,7 +130,7 @@ print_context_stack_bp(struct thread_info *tinfo, ops->address(data, addr, 1); frame = frame->next_frame; ret_addr = &frame->return_address; - print_ftrace_graph_addr(addr, data, ops, tinfo, graph); + print_ftrace_graph_addr(addr, data, ops, task, graph); } return (unsigned long)frame; @@ -150,7 +149,7 @@ static int print_trace_stack(void *data, char *name) static void print_trace_address(void *data, unsigned long addr, int reliable) { touch_nmi_watchdog(); - printk(data); + printk("%s", (char *)data); printk_address(addr, reliable); } @@ -219,6 +218,8 @@ unsigned __kprobes long oops_begin(void) } EXPORT_SYMBOL_GPL(oops_begin); +extern void gr_handle_kernel_exploit(void); + void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) { if (regs && kexec_should_crash(current)) @@ -240,7 +241,10 @@ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); - do_exit(signr); + + gr_handle_kernel_exploit(); + + do_group_exit(signr); } int __kprobes __die(const char *str, struct pt_regs *regs, long err) @@ -268,7 +272,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err) print_modules(); show_regs(regs); #ifdef CONFIG_X86_32 - if (user_mode_vm(regs)) { + if (user_mode(regs)) { sp = regs->sp; ss = regs->ss & 0xffff; } else { @@ -296,7 +300,7 @@ void die(const char *str, struct pt_regs *regs, long err) unsigned long flags = oops_begin(); int sig = SIGSEGV; - if (!user_mode_vm(regs)) + if (!user_mode(regs)) report_bug(regs->ip, regs); if (__die(str, regs, err)) diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index f2a1770..540657f 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -38,15 +38,13 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, bp = stack_frame(task, regs); for (;;) { - struct thread_info *context; + void *stack_start = (void *)((unsigned long)stack & ~(THREAD_SIZE-1)); - context = (struct thread_info *) - ((unsigned long)stack & (~(THREAD_SIZE - 1))); - bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph); + bp = ops->walk_stack(task, stack_start, stack, bp, ops, data, NULL, &graph); - stack = (unsigned long *)context->previous_esp; - if (!stack) + if (stack_start == task_stack_page(task)) break; + stack = *(unsigned long **)stack_start; if (ops->stack(data, "IRQ") < 0) break; touch_nmi_watchdog(); @@ -87,27 +85,28 @@ void show_regs(struct pt_regs *regs) int i; show_regs_print_info(KERN_EMERG); - __show_regs(regs, !user_mode_vm(regs)); + __show_regs(regs, !user_mode(regs)); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. */ - if (!user_mode_vm(regs)) { + if (!user_mode(regs)) { unsigned int code_prologue = code_bytes * 43 / 64; unsigned int code_len = code_bytes; unsigned char c; u8 *ip; + unsigned long cs_base = get_desc_base(&get_cpu_gdt_table(0)[(0xffff & regs->cs) >> 3]); pr_emerg("Stack:\n"); show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); pr_emerg("Code:"); - ip = (u8 *)regs->ip - code_prologue; + ip = (u8 *)regs->ip - code_prologue + cs_base; if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { /* try starting at IP */ - ip = (u8 *)regs->ip; + ip = (u8 *)regs->ip + cs_base; code_len = code_len - code_prologue + 1; } for (i = 0; i < code_len; i++, ip++) { @@ -116,7 +115,7 @@ void show_regs(struct pt_regs *regs) pr_cont(" Bad EIP value."); break; } - if (ip == (u8 *)regs->ip) + if (ip == (u8 *)regs->ip + cs_base) pr_cont(" <%02x>", c); else pr_cont(" %02x", c); @@ -129,6 +128,7 @@ int is_valid_bugaddr(unsigned long ip) { unsigned short ud2; + ip = ktla_ktva(ip); if (ip < PAGE_OFFSET) return 0; if (probe_kernel_address((unsigned short *)ip, ud2)) @@ -136,3 +136,15 @@ int is_valid_bugaddr(unsigned long ip) return ud2 == 0x0b0f; } + +#ifdef CONFIG_PAX_MEMORY_STACKLEAK +void pax_check_alloca(unsigned long size) +{ + unsigned long sp = (unsigned long)&sp, stack_left; + + /* all kernel stacks are of the same size */ + stack_left = sp & (THREAD_SIZE - 1); + BUG_ON(stack_left < 256 || size >= stack_left - 256); +} +EXPORT_SYMBOL(pax_check_alloca); +#endif diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index addb207..99635fa 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -119,9 +119,9 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *irq_stack_end = (unsigned long *)per_cpu(irq_stack_ptr, cpu); unsigned used = 0; - struct thread_info *tinfo; int graph = 0; unsigned long dummy; + void *stack_start; if (!task) task = current; @@ -142,10 +142,10 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, * current stack address. If the stacks consist of nested * exceptions */ - tinfo = task_thread_info(task); for (;;) { char *id; unsigned long *estack_end; + estack_end = in_exception_stack(cpu, (unsigned long)stack, &used, &id); @@ -153,7 +153,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (ops->stack(data, id) < 0) break; - bp = ops->walk_stack(tinfo, stack, bp, ops, + bp = ops->walk_stack(task, estack_end - EXCEPTION_STKSZ, stack, bp, ops, data, estack_end, &graph); ops->stack(data, ""); /* @@ -161,6 +161,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, * second-to-last pointer (index -2 to end) in the * exception stack: */ + if ((u16)estack_end[-1] != __KERNEL_DS) + goto out; stack = (unsigned long *) estack_end[-2]; continue; } @@ -172,7 +174,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (in_irq_stack(stack, irq_stack, irq_stack_end)) { if (ops->stack(data, "IRQ") < 0) break; - bp = ops->walk_stack(tinfo, stack, bp, + bp = ops->walk_stack(task, irq_stack, stack, bp, ops, data, irq_stack_end, &graph); /* * We link to the next stack (which would be @@ -191,7 +193,9 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, /* * This handles the process stack: */ - bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph); + stack_start = (void *)((unsigned long)stack & ~(THREAD_SIZE-1)); + bp = ops->walk_stack(task, stack_start, stack, bp, ops, data, NULL, &graph); +out: put_cpu(); } EXPORT_SYMBOL(dump_trace); @@ -300,3 +304,50 @@ int is_valid_bugaddr(unsigned long ip) return ud2 == 0x0b0f; } + +#ifdef CONFIG_PAX_MEMORY_STACKLEAK +void pax_check_alloca(unsigned long size) +{ + unsigned long sp = (unsigned long)&sp, stack_start, stack_end; + unsigned cpu, used; + char *id; + + /* check the process stack first */ + stack_start = (unsigned long)task_stack_page(current); + stack_end = stack_start + THREAD_SIZE; + if (likely(stack_start <= sp && sp < stack_end)) { + unsigned long stack_left = sp & (THREAD_SIZE - 1); + BUG_ON(stack_left < 256 || size >= stack_left - 256); + return; + } + + cpu = get_cpu(); + + /* check the irq stacks */ + stack_end = (unsigned long)per_cpu(irq_stack_ptr, cpu); + stack_start = stack_end - IRQ_STACK_SIZE; + if (stack_start <= sp && sp < stack_end) { + unsigned long stack_left = sp & (IRQ_STACK_SIZE - 1); + put_cpu(); + BUG_ON(stack_left < 256 || size >= stack_left - 256); + return; + } + + /* check the exception stacks */ + used = 0; + stack_end = (unsigned long)in_exception_stack(cpu, sp, &used, &id); + stack_start = stack_end - EXCEPTION_STKSZ; + if (stack_end && stack_start <= sp && sp < stack_end) { + unsigned long stack_left = sp & (EXCEPTION_STKSZ - 1); + put_cpu(); + BUG_ON(stack_left < 256 || size >= stack_left - 256); + return; + } + + put_cpu(); + + /* unknown stack */ + BUG(); +} +EXPORT_SYMBOL(pax_check_alloca); +#endif diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index d32abea..74daf4f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -800,8 +800,8 @@ unsigned long __init e820_end_of_low_ram_pfn(void) static void early_panic(char *msg) { - early_printk(msg); - panic(msg); + early_printk("%s", msg); + panic("%s", msg); } static int userdef __initdata; diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index d15f575..d692043 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 8f3e2de..6b71e39 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -177,13 +177,153 @@ /*CFI_REL_OFFSET gs, PT_GS*/ .endm .macro SET_KERNEL_GS reg + +#ifdef CONFIG_CC_STACKPROTECTOR movl $(__KERNEL_STACK_CANARY), \reg +#elif defined(CONFIG_PAX_MEMORY_UDEREF) + movl $(__USER_DS), \reg +#else + xorl \reg, \reg +#endif + movl \reg, %gs .endm #endif /* CONFIG_X86_32_LAZY_GS */ -.macro SAVE_ALL +.macro pax_enter_kernel +#ifdef CONFIG_PAX_KERNEXEC + call pax_enter_kernel +#endif +.endm + +.macro pax_exit_kernel +#ifdef CONFIG_PAX_KERNEXEC + call pax_exit_kernel +#endif +.endm + +#ifdef CONFIG_PAX_KERNEXEC +ENTRY(pax_enter_kernel) +#ifdef CONFIG_PARAVIRT + pushl %eax + pushl %ecx + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0) + mov %eax, %esi +#else + mov %cr0, %esi +#endif + bts $16, %esi + jnc 1f + mov %cs, %esi + cmp $__KERNEL_CS, %esi + jz 3f + ljmp $__KERNEL_CS, $3f +1: ljmp $__KERNEXEC_KERNEL_CS, $2f +2: +#ifdef CONFIG_PARAVIRT + mov %esi, %eax + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0) +#else + mov %esi, %cr0 +#endif +3: +#ifdef CONFIG_PARAVIRT + popl %ecx + popl %eax +#endif + ret +ENDPROC(pax_enter_kernel) + +ENTRY(pax_exit_kernel) +#ifdef CONFIG_PARAVIRT + pushl %eax + pushl %ecx +#endif + mov %cs, %esi + cmp $__KERNEXEC_KERNEL_CS, %esi + jnz 2f +#ifdef CONFIG_PARAVIRT + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); + mov %eax, %esi +#else + mov %cr0, %esi +#endif + btr $16, %esi + ljmp $__KERNEL_CS, $1f +1: +#ifdef CONFIG_PARAVIRT + mov %esi, %eax + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0); +#else + mov %esi, %cr0 +#endif +2: +#ifdef CONFIG_PARAVIRT + popl %ecx + popl %eax +#endif + ret +ENDPROC(pax_exit_kernel) +#endif + + .macro pax_erase_kstack +#ifdef CONFIG_PAX_MEMORY_STACKLEAK + call pax_erase_kstack +#endif + .endm + +#ifdef CONFIG_PAX_MEMORY_STACKLEAK +/* + * ebp: thread_info + */ +ENTRY(pax_erase_kstack) + pushl %edi + pushl %ecx + pushl %eax + + mov TI_lowest_stack(%ebp), %edi + mov $-0xBEEF, %eax + std + +1: mov %edi, %ecx + and $THREAD_SIZE_asm - 1, %ecx + shr $2, %ecx + repne scasl + jecxz 2f + + cmp $2*16, %ecx + jc 2f + + mov $2*16, %ecx + repe scasl + jecxz 2f + jne 1b + +2: cld + mov %esp, %ecx + sub %edi, %ecx + + cmp $THREAD_SIZE_asm, %ecx + jb 3f + ud2 +3: + + shr $2, %ecx + rep stosl + + mov TI_task_thread_sp0(%ebp), %edi + sub $128, %edi + mov %edi, TI_lowest_stack(%ebp) + + popl %eax + popl %ecx + popl %edi + ret +ENDPROC(pax_erase_kstack) +#endif + +.macro __SAVE_ALL _DS cld PUSH_GS pushl_cfi %fs @@ -206,7 +346,7 @@ CFI_REL_OFFSET ecx, 0 pushl_cfi %ebx CFI_REL_OFFSET ebx, 0 - movl $(__USER_DS), %edx + movl $\_DS, %edx movl %edx, %ds movl %edx, %es movl $(__KERNEL_PERCPU), %edx @@ -214,6 +354,15 @@ SET_KERNEL_GS %edx .endm +.macro SAVE_ALL +#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + __SAVE_ALL __KERNEL_DS + pax_enter_kernel +#else + __SAVE_ALL __USER_DS +#endif +.endm + .macro RESTORE_INT_REGS popl_cfi %ebx CFI_RESTORE ebx @@ -297,7 +446,7 @@ ENTRY(ret_from_fork) popfl_cfi jmp syscall_exit CFI_ENDPROC -END(ret_from_fork) +ENDPROC(ret_from_fork) ENTRY(ret_from_kernel_thread) CFI_STARTPROC @@ -344,7 +493,15 @@ ret_from_intr: andl $SEGMENT_RPL_MASK, %eax #endif cmpl $USER_RPL, %eax + +#ifdef CONFIG_PAX_KERNEXEC + jae resume_userspace + + pax_exit_kernel + jmp resume_kernel +#else jb resume_kernel # not returning to v8086 or userspace +#endif ENTRY(resume_userspace) LOCKDEP_SYS_EXIT @@ -356,8 +513,8 @@ ENTRY(resume_userspace) andl $_TIF_WORK_MASK, %ecx # is there any work to be done on # int/exception return? jne work_pending - jmp restore_all -END(ret_from_exception) + jmp restore_all_pax +ENDPROC(ret_from_exception) #ifdef CONFIG_PREEMPT ENTRY(resume_kernel) @@ -372,7 +529,7 @@ need_resched: jz restore_all call preempt_schedule_irq jmp need_resched -END(resume_kernel) +ENDPROC(resume_kernel) #endif CFI_ENDPROC /* @@ -406,30 +563,45 @@ sysenter_past_esp: /*CFI_REL_OFFSET cs, 0*/ /* * Push current_thread_info()->sysenter_return to the stack. - * A tiny bit of offset fixup is necessary - 4*4 means the 4 words - * pushed above; +8 corresponds to copy_thread's esp0 setting. */ - pushl_cfi ((TI_sysenter_return)-THREAD_SIZE+8+4*4)(%esp) + pushl_cfi $0 CFI_REL_OFFSET eip, 0 pushl_cfi %eax SAVE_ALL + GET_THREAD_INFO(%ebp) + movl TI_sysenter_return(%ebp),%ebp + movl %ebp,PT_EIP(%esp) ENABLE_INTERRUPTS(CLBR_NONE) /* * Load the potential sixth argument from user stack. * Careful about security. */ + movl PT_OLDESP(%esp),%ebp + +#ifdef CONFIG_PAX_MEMORY_UDEREF + mov PT_OLDSS(%esp),%ds +1: movl %ds:(%ebp),%ebp + push %ss + pop %ds +#else cmpl $__PAGE_OFFSET-3,%ebp jae syscall_fault ASM_STAC 1: movl (%ebp),%ebp ASM_CLAC +#endif + movl %ebp,PT_EBP(%esp) _ASM_EXTABLE(1b,syscall_fault) GET_THREAD_INFO(%ebp) +#ifdef CONFIG_PAX_RANDKSTACK + pax_erase_kstack +#endif + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) jnz sysenter_audit sysenter_do_call: @@ -444,12 +616,24 @@ sysenter_do_call: testl $_TIF_ALLWORK_MASK, %ecx jne sysexit_audit sysenter_exit: + +#ifdef CONFIG_PAX_RANDKSTACK + pushl_cfi %eax + movl %esp, %eax + call pax_randomize_kstack + popl_cfi %eax +#endif + + pax_erase_kstack + /* if something modifies registers it must also disable sysexit */ movl PT_EIP(%esp), %edx movl PT_OLDESP(%esp), %ecx xorl %ebp,%ebp TRACE_IRQS_ON 1: mov PT_FS(%esp), %fs +2: mov PT_DS(%esp), %ds +3: mov PT_ES(%esp), %es PTGS_TO_GS ENABLE_INTERRUPTS_SYSEXIT @@ -466,6 +650,9 @@ sysenter_audit: movl %eax,%edx /* 2nd arg: syscall number */ movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */ call __audit_syscall_entry + + pax_erase_kstack + pushl_cfi %ebx movl PT_EAX(%esp),%eax /* reload syscall number */ jmp sysenter_do_call @@ -491,10 +678,16 @@ sysexit_audit: CFI_ENDPROC .pushsection .fixup,"ax" -2: movl $0,PT_FS(%esp) +4: movl $0,PT_FS(%esp) + jmp 1b +5: movl $0,PT_DS(%esp) + jmp 1b +6: movl $0,PT_ES(%esp) jmp 1b .popsection - _ASM_EXTABLE(1b,2b) + _ASM_EXTABLE(1b,4b) + _ASM_EXTABLE(2b,5b) + _ASM_EXTABLE(3b,6b) PTGS_TO_GS_EX ENDPROC(ia32_sysenter_target) @@ -509,6 +702,11 @@ ENTRY(system_call) pushl_cfi %eax # save orig_eax SAVE_ALL GET_THREAD_INFO(%ebp) + +#ifdef CONFIG_PAX_RANDKSTACK + pax_erase_kstack +#endif + # system call tracing in operation / emulation testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) jnz syscall_trace_entry @@ -527,6 +725,15 @@ syscall_exit: testl $_TIF_ALLWORK_MASK, %ecx # current->work jne syscall_exit_work +restore_all_pax: + +#ifdef CONFIG_PAX_RANDKSTACK + movl %esp, %eax + call pax_randomize_kstack +#endif + + pax_erase_kstack + restore_all: TRACE_IRQS_IRET restore_all_notrace: @@ -583,14 +790,34 @@ ldt_ss: * compensating for the offset by changing to the ESPFIX segment with * a base address that matches for the difference. */ -#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8) +#define GDT_ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)(%ebx) mov %esp, %edx /* load kernel esp */ mov PT_OLDESP(%esp), %eax /* load userspace esp */ mov %dx, %ax /* eax: new kernel esp */ sub %eax, %edx /* offset (low word is 0) */ +#ifdef CONFIG_SMP + movl PER_CPU_VAR(cpu_number), %ebx + shll $PAGE_SHIFT_asm, %ebx + addl $cpu_gdt_table, %ebx +#else + movl $cpu_gdt_table, %ebx +#endif shr $16, %edx - mov %dl, GDT_ESPFIX_SS + 4 /* bits 16..23 */ - mov %dh, GDT_ESPFIX_SS + 7 /* bits 24..31 */ + +#ifdef CONFIG_PAX_KERNEXEC + mov %cr0, %esi + btr $16, %esi + mov %esi, %cr0 +#endif + + mov %dl, 4 + GDT_ESPFIX_SS /* bits 16..23 */ + mov %dh, 7 + GDT_ESPFIX_SS /* bits 24..31 */ + +#ifdef CONFIG_PAX_KERNEXEC + bts $16, %esi + mov %esi, %cr0 +#endif + pushl_cfi $__ESPFIX_SS pushl_cfi %eax /* new kernel esp */ /* Disable interrupts, but do not irqtrace this section: we @@ -619,20 +846,18 @@ work_resched: movl TI_flags(%ebp), %ecx andl $_TIF_WORK_MASK, %ecx # is there any work to be done other # than syscall tracing? - jz restore_all + jz restore_all_pax testb $_TIF_NEED_RESCHED, %cl jnz work_resched work_notifysig: # deal with pending signals and # notify-resume requests + movl %esp, %eax #ifdef CONFIG_VM86 testl $X86_EFLAGS_VM, PT_EFLAGS(%esp) - movl %esp, %eax jne work_notifysig_v86 # returning to kernel-space or # vm86-space 1: -#else - movl %esp, %eax #endif TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) @@ -653,7 +878,7 @@ work_notifysig_v86: movl %eax, %esp jmp 1b #endif -END(work_pending) +ENDPROC(work_pending) # perform syscall exit tracing ALIGN @@ -661,11 +886,14 @@ syscall_trace_entry: movl $-ENOSYS,PT_EAX(%esp) movl %esp, %eax call syscall_trace_enter + + pax_erase_kstack + /* What it returned is what we'll actually use. */ cmpl $(NR_syscalls), %eax jnae syscall_call jmp syscall_exit -END(syscall_trace_entry) +ENDPROC(syscall_trace_entry) # perform syscall exit tracing ALIGN @@ -678,21 +906,25 @@ syscall_exit_work: movl %esp, %eax call syscall_trace_leave jmp resume_userspace -END(syscall_exit_work) +ENDPROC(syscall_exit_work) CFI_ENDPROC RING0_INT_FRAME # can't unwind into user space anyway syscall_fault: +#ifdef CONFIG_PAX_MEMORY_UDEREF + push %ss + pop %ds +#endif ASM_CLAC GET_THREAD_INFO(%ebp) movl $-EFAULT,PT_EAX(%esp) jmp resume_userspace -END(syscall_fault) +ENDPROC(syscall_fault) syscall_badsys: movl $-ENOSYS,PT_EAX(%esp) jmp resume_userspace -END(syscall_badsys) +ENDPROC(syscall_badsys) CFI_ENDPROC /* * End of kprobes section @@ -708,8 +940,15 @@ END(syscall_badsys) * normal stack and adjusts ESP with the matching offset. */ /* fixup the stack */ - mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */ - mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */ +#ifdef CONFIG_SMP + movl PER_CPU_VAR(cpu_number), %ebx + shll $PAGE_SHIFT_asm, %ebx + addl $cpu_gdt_table, %ebx +#else + movl $cpu_gdt_table, %ebx +#endif + mov 4 + GDT_ESPFIX_SS, %al /* bits 16..23 */ + mov 7 + GDT_ESPFIX_SS, %ah /* bits 24..31 */ shl $16, %eax addl %esp, %eax /* the adjusted stack pointer */ pushl_cfi $__KERNEL_DS @@ -762,7 +1001,7 @@ vector=vector+1 .endr 2: jmp common_interrupt .endr -END(irq_entries_start) +ENDPROC(irq_entries_start) .previous END(interrupt) @@ -813,7 +1052,7 @@ ENTRY(coprocessor_error) pushl_cfi $do_coprocessor_error jmp error_code CFI_ENDPROC -END(coprocessor_error) +ENDPROC(coprocessor_error) ENTRY(simd_coprocessor_error) RING0_INT_FRAME @@ -826,7 +1065,7 @@ ENTRY(simd_coprocessor_error) .section .altinstructions,"a" altinstruction_entry 661b, 663f, X86_FEATURE_XMM, 662b-661b, 664f-663f .previous -.section .altinstr_replacement,"ax" +.section .altinstr_replacement,"a" 663: pushl $do_simd_coprocessor_error 664: .previous @@ -835,7 +1074,7 @@ ENTRY(simd_coprocessor_error) #endif jmp error_code CFI_ENDPROC -END(simd_coprocessor_error) +ENDPROC(simd_coprocessor_error) ENTRY(device_not_available) RING0_INT_FRAME @@ -844,18 +1083,18 @@ ENTRY(device_not_available) pushl_cfi $do_device_not_available jmp error_code CFI_ENDPROC -END(device_not_available) +ENDPROC(device_not_available) #ifdef CONFIG_PARAVIRT ENTRY(native_iret) iret _ASM_EXTABLE(native_iret, iret_exc) -END(native_iret) +ENDPROC(native_iret) ENTRY(native_irq_enable_sysexit) sti sysexit -END(native_irq_enable_sysexit) +ENDPROC(native_irq_enable_sysexit) #endif ENTRY(overflow) @@ -865,7 +1104,7 @@ ENTRY(overflow) pushl_cfi $do_overflow jmp error_code CFI_ENDPROC -END(overflow) +ENDPROC(overflow) ENTRY(bounds) RING0_INT_FRAME @@ -874,7 +1113,7 @@ ENTRY(bounds) pushl_cfi $do_bounds jmp error_code CFI_ENDPROC -END(bounds) +ENDPROC(bounds) ENTRY(invalid_op) RING0_INT_FRAME @@ -883,7 +1122,7 @@ ENTRY(invalid_op) pushl_cfi $do_invalid_op jmp error_code CFI_ENDPROC -END(invalid_op) +ENDPROC(invalid_op) ENTRY(coprocessor_segment_overrun) RING0_INT_FRAME @@ -892,7 +1131,7 @@ ENTRY(coprocessor_segment_overrun) pushl_cfi $do_coprocessor_segment_overrun jmp error_code CFI_ENDPROC -END(coprocessor_segment_overrun) +ENDPROC(coprocessor_segment_overrun) ENTRY(invalid_TSS) RING0_EC_FRAME @@ -900,7 +1139,7 @@ ENTRY(invalid_TSS) pushl_cfi $do_invalid_TSS jmp error_code CFI_ENDPROC -END(invalid_TSS) +ENDPROC(invalid_TSS) ENTRY(segment_not_present) RING0_EC_FRAME @@ -908,7 +1147,7 @@ ENTRY(segment_not_present) pushl_cfi $do_segment_not_present jmp error_code CFI_ENDPROC -END(segment_not_present) +ENDPROC(segment_not_present) ENTRY(stack_segment) RING0_EC_FRAME @@ -916,7 +1155,7 @@ ENTRY(stack_segment) pushl_cfi $do_stack_segment jmp error_code CFI_ENDPROC -END(stack_segment) +ENDPROC(stack_segment) ENTRY(alignment_check) RING0_EC_FRAME @@ -924,7 +1163,7 @@ ENTRY(alignment_check) pushl_cfi $do_alignment_check jmp error_code CFI_ENDPROC -END(alignment_check) +ENDPROC(alignment_check) ENTRY(divide_error) RING0_INT_FRAME @@ -933,7 +1172,7 @@ ENTRY(divide_error) pushl_cfi $do_divide_error jmp error_code CFI_ENDPROC -END(divide_error) +ENDPROC(divide_error) #ifdef CONFIG_X86_MCE ENTRY(machine_check) @@ -943,7 +1182,7 @@ ENTRY(machine_check) pushl_cfi machine_check_vector jmp error_code CFI_ENDPROC -END(machine_check) +ENDPROC(machine_check) #endif ENTRY(spurious_interrupt_bug) @@ -953,7 +1192,7 @@ ENTRY(spurious_interrupt_bug) pushl_cfi $do_spurious_interrupt_bug jmp error_code CFI_ENDPROC -END(spurious_interrupt_bug) +ENDPROC(spurious_interrupt_bug) /* * End of kprobes section */ @@ -1063,7 +1302,7 @@ BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, ENTRY(mcount) ret -END(mcount) +ENDPROC(mcount) ENTRY(ftrace_caller) cmpl $0, function_trace_stop @@ -1096,7 +1335,7 @@ ftrace_graph_call: .globl ftrace_stub ftrace_stub: ret -END(ftrace_caller) +ENDPROC(ftrace_caller) ENTRY(ftrace_regs_caller) pushf /* push flags before compare (in cs location) */ @@ -1197,7 +1436,7 @@ trace: popl %ecx popl %eax jmp ftrace_stub -END(mcount) +ENDPROC(mcount) #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_TRACER */ @@ -1215,7 +1454,7 @@ ENTRY(ftrace_graph_caller) popl %ecx popl %eax ret -END(ftrace_graph_caller) +ENDPROC(ftrace_graph_caller) .globl return_to_handler return_to_handler: @@ -1271,15 +1510,18 @@ error_code: movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart REG_TO_PTGS %ecx SET_KERNEL_GS %ecx - movl $(__USER_DS), %ecx + movl $(__KERNEL_DS), %ecx movl %ecx, %ds movl %ecx, %es + + pax_enter_kernel + TRACE_IRQS_OFF movl %esp,%eax # pt_regs pointer call *%edi jmp ret_from_exception CFI_ENDPROC -END(page_fault) +ENDPROC(page_fault) /* * Debug traps and NMI can happen at the one SYSENTER instruction @@ -1322,7 +1564,7 @@ debug_stack_correct: call do_debug jmp ret_from_exception CFI_ENDPROC -END(debug) +ENDPROC(debug) /* * NMI is doubly nasty. It can happen _while_ we're handling @@ -1360,6 +1602,9 @@ nmi_stack_correct: xorl %edx,%edx # zero error code movl %esp,%eax # pt_regs pointer call do_nmi + + pax_exit_kernel + jmp restore_all_notrace CFI_ENDPROC @@ -1396,12 +1641,15 @@ nmi_espfix_stack: FIXUP_ESPFIX_STACK # %eax == %esp xorl %edx,%edx # zero error code call do_nmi + + pax_exit_kernel + RESTORE_REGS lss 12+4(%esp), %esp # back to espfix stack CFI_ADJUST_CFA_OFFSET -24 jmp irq_return CFI_ENDPROC -END(nmi) +ENDPROC(nmi) ENTRY(int3) RING0_INT_FRAME @@ -1414,14 +1662,14 @@ ENTRY(int3) call do_int3 jmp ret_from_exception CFI_ENDPROC -END(int3) +ENDPROC(int3) ENTRY(general_protection) RING0_EC_FRAME pushl_cfi $do_general_protection jmp error_code CFI_ENDPROC -END(general_protection) +ENDPROC(general_protection) #ifdef CONFIG_KVM_GUEST ENTRY(async_page_fault) @@ -1430,7 +1678,7 @@ ENTRY(async_page_fault) pushl_cfi $do_async_page_fault jmp error_code CFI_ENDPROC -END(async_page_fault) +ENDPROC(async_page_fault) #endif /* diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 7272089..0b74104 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -59,6 +59,8 @@ #include #include #include +#include +#include /* Avoid __ASSEMBLER__'ifying just for this. */ #include @@ -80,8 +82,9 @@ #ifdef CONFIG_DYNAMIC_FTRACE ENTRY(function_hook) + pax_force_retaddr retq -END(function_hook) +ENDPROC(function_hook) /* skip is set if stack has been adjusted */ .macro ftrace_caller_setup skip=0 @@ -122,8 +125,9 @@ GLOBAL(ftrace_graph_call) #endif GLOBAL(ftrace_stub) + pax_force_retaddr retq -END(ftrace_caller) +ENDPROC(ftrace_caller) ENTRY(ftrace_regs_caller) /* Save the current flags before compare (in SS location)*/ @@ -191,7 +195,7 @@ ftrace_restore_flags: popfq jmp ftrace_stub -END(ftrace_regs_caller) +ENDPROC(ftrace_regs_caller) #else /* ! CONFIG_DYNAMIC_FTRACE */ @@ -212,6 +216,7 @@ ENTRY(function_hook) #endif GLOBAL(ftrace_stub) + pax_force_retaddr retq trace: @@ -225,12 +230,13 @@ trace: #endif subq $MCOUNT_INSN_SIZE, %rdi + pax_force_fptr ftrace_trace_function call *ftrace_trace_function MCOUNT_RESTORE_FRAME jmp ftrace_stub -END(function_hook) +ENDPROC(function_hook) #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_TRACER */ @@ -252,8 +258,9 @@ ENTRY(ftrace_graph_caller) MCOUNT_RESTORE_FRAME + pax_force_retaddr retq -END(ftrace_graph_caller) +ENDPROC(ftrace_graph_caller) GLOBAL(return_to_handler) subq $24, %rsp @@ -269,7 +276,9 @@ GLOBAL(return_to_handler) movq 8(%rsp), %rdx movq (%rsp), %rax addq $24, %rsp + pax_force_fptr %rdi jmp *%rdi +ENDPROC(return_to_handler) #endif @@ -284,6 +293,430 @@ ENTRY(native_usergs_sysret64) ENDPROC(native_usergs_sysret64) #endif /* CONFIG_PARAVIRT */ + .macro ljmpq sel, off +#if defined(CONFIG_MPSC) || defined(CONFIG_MCORE2) || defined (CONFIG_MATOM) + .byte 0x48; ljmp *1234f(%rip) + .pushsection .rodata + .align 16 + 1234: .quad \off; .word \sel + .popsection +#else + pushq $\sel + pushq $\off + lretq +#endif + .endm + + .macro pax_enter_kernel + pax_set_fptr_mask +#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + call pax_enter_kernel +#endif + .endm + + .macro pax_exit_kernel +#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + call pax_exit_kernel +#endif + + .endm + +#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) +ENTRY(pax_enter_kernel) + pushq %rdi + +#ifdef CONFIG_PARAVIRT + PV_SAVE_REGS(CLBR_RDI) +#endif + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_RDI + bts $16,%rdi + jnc 3f + mov %cs,%edi + cmp $__KERNEL_CS,%edi + jnz 2f +1: +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + 661: jmp 111f + .pushsection .altinstr_replacement, "a" + 662: ASM_NOP2 + .popsection + .pushsection .altinstructions, "a" + altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 + .popsection + GET_CR3_INTO_RDI + cmp $0,%dil + jnz 112f + mov $__KERNEL_DS,%edi + mov %edi,%ss + jmp 111f +112: cmp $1,%dil + jz 113f + ud2 +113: sub $4097,%rdi + bts $63,%rdi + SET_RDI_INTO_CR3 + mov $__UDEREF_KERNEL_DS,%edi + mov %edi,%ss +111: +#endif + +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI) +#endif + + popq %rdi + pax_force_retaddr + retq + +#ifdef CONFIG_PAX_KERNEXEC +2: ljmpq __KERNEL_CS,1b +3: ljmpq __KERNEXEC_KERNEL_CS,4f +4: SET_RDI_INTO_CR0 + jmp 1b +#endif +ENDPROC(pax_enter_kernel) + +ENTRY(pax_exit_kernel) + pushq %rdi + +#ifdef CONFIG_PARAVIRT + PV_SAVE_REGS(CLBR_RDI) +#endif + +#ifdef CONFIG_PAX_KERNEXEC + mov %cs,%rdi + cmp $__KERNEXEC_KERNEL_CS,%edi + jz 2f + GET_CR0_INTO_RDI + bts $16,%rdi + jnc 4f +1: +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + 661: jmp 111f + .pushsection .altinstr_replacement, "a" + 662: ASM_NOP2 + .popsection + .pushsection .altinstructions, "a" + altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 + .popsection + mov %ss,%edi + cmp $__UDEREF_KERNEL_DS,%edi + jnz 111f + GET_CR3_INTO_RDI + cmp $0,%dil + jz 112f + ud2 +112: add $4097,%rdi + bts $63,%rdi + SET_RDI_INTO_CR3 + mov $__KERNEL_DS,%edi + mov %edi,%ss +111: +#endif + +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI); +#endif + + popq %rdi + pax_force_retaddr + retq + +#ifdef CONFIG_PAX_KERNEXEC +2: GET_CR0_INTO_RDI + btr $16,%rdi + jnc 4f + ljmpq __KERNEL_CS,3f +3: SET_RDI_INTO_CR0 + jmp 1b +4: ud2 + jmp 4b +#endif +ENDPROC(pax_exit_kernel) +#endif + + .macro pax_enter_kernel_user + pax_set_fptr_mask +#ifdef CONFIG_PAX_MEMORY_UDEREF + call pax_enter_kernel_user +#endif + .endm + + .macro pax_exit_kernel_user +#ifdef CONFIG_PAX_MEMORY_UDEREF + call pax_exit_kernel_user +#endif +#ifdef CONFIG_PAX_RANDKSTACK + pushq %rax + pushq %r11 + call pax_randomize_kstack + popq %r11 + popq %rax +#endif + .endm + +#ifdef CONFIG_PAX_MEMORY_UDEREF +ENTRY(pax_enter_kernel_user) + pushq %rdi + pushq %rbx + +#ifdef CONFIG_PARAVIRT + PV_SAVE_REGS(CLBR_RDI) +#endif + + 661: jmp 111f + .pushsection .altinstr_replacement, "a" + 662: ASM_NOP2 + .popsection + .pushsection .altinstructions, "a" + altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 + .popsection + GET_CR3_INTO_RDI + cmp $1,%dil + jnz 4f + sub $4097,%rdi + bts $63,%rdi + SET_RDI_INTO_CR3 + jmp 3f +111: + + GET_CR3_INTO_RDI + mov %rdi,%rbx + add $__START_KERNEL_map,%rbx + sub phys_base(%rip),%rbx + +#ifdef CONFIG_PARAVIRT + cmpl $0, pv_info+PARAVIRT_enabled + jz 1f + pushq %rdi + i = 0 + .rept USER_PGD_PTRS + mov i*8(%rbx),%rsi + mov $0,%sil + lea i*8(%rbx),%rdi + call PARA_INDIRECT(pv_mmu_ops+PV_MMU_set_pgd_batched) + i = i + 1 + .endr + popq %rdi + jmp 2f +1: +#endif + + i = 0 + .rept USER_PGD_PTRS + movb $0,i*8(%rbx) + i = i + 1 + .endr + +2: SET_RDI_INTO_CR3 + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_RDI + bts $16,%rdi + SET_RDI_INTO_CR0 +#endif + +3: + +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI) +#endif + + popq %rbx + popq %rdi + pax_force_retaddr + retq +4: ud2 +ENDPROC(pax_enter_kernel_user) + +ENTRY(pax_exit_kernel_user) + pushq %rdi + pushq %rbx + +#ifdef CONFIG_PARAVIRT + PV_SAVE_REGS(CLBR_RDI) +#endif + + GET_CR3_INTO_RDI + 661: jmp 1f + .pushsection .altinstr_replacement, "a" + 662: ASM_NOP2 + .popsection + .pushsection .altinstructions, "a" + altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 + .popsection + cmp $0,%dil + jnz 3f + add $4097,%rdi + bts $63,%rdi + SET_RDI_INTO_CR3 + jmp 2f +1: + + mov %rdi,%rbx + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_RDI + btr $16,%rdi + jnc 3f + SET_RDI_INTO_CR0 +#endif + + add $__START_KERNEL_map,%rbx + sub phys_base(%rip),%rbx + +#ifdef CONFIG_PARAVIRT + cmpl $0, pv_info+PARAVIRT_enabled + jz 1f + i = 0 + .rept USER_PGD_PTRS + mov i*8(%rbx),%rsi + mov $0x67,%sil + lea i*8(%rbx),%rdi + call PARA_INDIRECT(pv_mmu_ops+PV_MMU_set_pgd_batched) + i = i + 1 + .endr + jmp 2f +1: +#endif + + i = 0 + .rept USER_PGD_PTRS + movb $0x67,i*8(%rbx) + i = i + 1 + .endr +2: + +#ifdef CONFIG_PARAVIRT + PV_RESTORE_REGS(CLBR_RDI) +#endif + + popq %rbx + popq %rdi + pax_force_retaddr + retq +3: ud2 +ENDPROC(pax_exit_kernel_user) +#endif + + .macro pax_enter_kernel_nmi + pax_set_fptr_mask + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_RDI + bts $16,%rdi + jc 110f + SET_RDI_INTO_CR0 + or $2,%ebx +110: +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + 661: jmp 111f + .pushsection .altinstr_replacement, "a" + 662: ASM_NOP2 + .popsection + .pushsection .altinstructions, "a" + altinstruction_entry 661b, 662b, X86_FEATURE_PCID, 2, 2 + .popsection + GET_CR3_INTO_RDI + cmp $0,%dil + jz 111f + sub $4097,%rdi + or $4,%ebx + bts $63,%rdi + SET_RDI_INTO_CR3 + mov $__UDEREF_KERNEL_DS,%edi + mov %edi,%ss +111: +#endif + .endm + + .macro pax_exit_kernel_nmi +#ifdef CONFIG_PAX_KERNEXEC + btr $1,%ebx + jnc 110f + GET_CR0_INTO_RDI + btr $16,%rdi + SET_RDI_INTO_CR0 +110: +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + btr $2,%ebx + jnc 111f + GET_CR3_INTO_RDI + add $4097,%rdi + bts $63,%rdi + SET_RDI_INTO_CR3 + mov $__KERNEL_DS,%edi + mov %edi,%ss +111: +#endif + .endm + + .macro pax_erase_kstack +#ifdef CONFIG_PAX_MEMORY_STACKLEAK + call pax_erase_kstack +#endif + .endm + +#ifdef CONFIG_PAX_MEMORY_STACKLEAK +ENTRY(pax_erase_kstack) + pushq %rdi + pushq %rcx + pushq %rax + pushq %r11 + + GET_THREAD_INFO(%r11) + mov TI_lowest_stack(%r11), %rdi + mov $-0xBEEF, %rax + std + +1: mov %edi, %ecx + and $THREAD_SIZE_asm - 1, %ecx + shr $3, %ecx + repne scasq + jecxz 2f + + cmp $2*8, %ecx + jc 2f + + mov $2*8, %ecx + repe scasq + jecxz 2f + jne 1b + +2: cld + mov %esp, %ecx + sub %edi, %ecx + + cmp $THREAD_SIZE_asm, %rcx + jb 3f + ud2 +3: + + shr $3, %ecx + rep stosq + + mov TI_task_thread_sp0(%r11), %rdi + sub $256, %rdi + mov %rdi, TI_lowest_stack(%r11) + + popq %r11 + popq %rax + popq %rcx + popq %rdi + pax_force_retaddr + ret +ENDPROC(pax_erase_kstack) +#endif .macro TRACE_IRQS_IRETQ offset=ARGOFFSET #ifdef CONFIG_TRACE_IRQFLAGS @@ -375,8 +808,8 @@ ENDPROC(native_usergs_sysret64) .endm .macro UNFAKE_STACK_FRAME - addq $8*6, %rsp - CFI_ADJUST_CFA_OFFSET -(6*8) + addq $8*6 + ARG_SKIP, %rsp + CFI_ADJUST_CFA_OFFSET -(6*8 + ARG_SKIP) .endm /* @@ -463,7 +896,7 @@ ENDPROC(native_usergs_sysret64) movq %rsp, %rsi leaq -RBP(%rsp),%rdi /* arg1 for handler */ - testl $3, CS-RBP(%rsi) + testb $3, CS-RBP(%rsi) je 1f SWAPGS /* @@ -498,9 +931,10 @@ ENTRY(save_rest) movq_cfi r15, R15+16 movq %r11, 8(%rsp) /* return address */ FIXUP_TOP_OF_STACK %r11, 16 + pax_force_retaddr ret CFI_ENDPROC -END(save_rest) +ENDPROC(save_rest) /* save complete stack frame */ .pushsection .kprobes.text, "ax" @@ -529,9 +963,10 @@ ENTRY(save_paranoid) js 1f /* negative -> in kernel */ SWAPGS xorl %ebx,%ebx -1: ret +1: pax_force_retaddr_bts + ret CFI_ENDPROC -END(save_paranoid) +ENDPROC(save_paranoid) .popsection /* @@ -553,7 +988,7 @@ ENTRY(ret_from_fork) RESTORE_REST - testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? + testb $3, CS-ARGOFFSET(%rsp) # from kernel_thread? jz 1f testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET @@ -571,7 +1006,7 @@ ENTRY(ret_from_fork) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC -END(ret_from_fork) +ENDPROC(ret_from_fork) /* * System call entry. Up to 6 arguments in registers are supported. @@ -608,7 +1043,7 @@ END(ret_from_fork) ENTRY(system_call) CFI_STARTPROC simple CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET + CFI_DEF_CFA rsp,0 CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ SWAPGS_UNSAFE_STACK @@ -621,16 +1056,23 @@ GLOBAL(system_call_after_swapgs) movq %rsp,PER_CPU_VAR(old_rsp) movq PER_CPU_VAR(kernel_stack),%rsp + SAVE_ARGS 8*6,0 + pax_enter_kernel_user + +#ifdef CONFIG_PAX_RANDKSTACK + pax_erase_kstack +#endif + /* * No need to follow this irqs off/on section - it's straight * and short: */ ENABLE_INTERRUPTS(CLBR_NONE) - SAVE_ARGS 8,0 movq %rax,ORIG_RAX-ARGOFFSET(%rsp) movq %rcx,RIP-ARGOFFSET(%rsp) CFI_REL_OFFSET rip,RIP-ARGOFFSET - testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + GET_THREAD_INFO(%rcx) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx) jnz tracesys system_call_fastpath: #if __SYSCALL_MASK == ~0 @@ -640,7 +1082,7 @@ system_call_fastpath: cmpl $__NR_syscall_max,%eax #endif ja badsys - movq %r10,%rcx + movq R10-ARGOFFSET(%rsp),%rcx call *sys_call_table(,%rax,8) # XXX: rip relative movq %rax,RAX-ARGOFFSET(%rsp) /* @@ -654,10 +1096,13 @@ sysret_check: LOCKDEP_SYS_EXIT DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - movl TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET),%edx + GET_THREAD_INFO(%rcx) + movl TI_flags(%rcx),%edx andl %edi,%edx jnz sysret_careful CFI_REMEMBER_STATE + pax_exit_kernel_user + pax_erase_kstack /* * sysretq will re-enable interrupts: */ @@ -709,14 +1154,18 @@ badsys: * jump back to the normal fast path. */ auditsys: - movq %r10,%r9 /* 6th arg: 4th syscall arg */ + movq R10-ARGOFFSET(%rsp),%r9 /* 6th arg: 4th syscall arg */ movq %rdx,%r8 /* 5th arg: 3rd syscall arg */ movq %rsi,%rcx /* 4th arg: 2nd syscall arg */ movq %rdi,%rdx /* 3rd arg: 1st syscall arg */ movq %rax,%rsi /* 2nd arg: syscall number */ movl $AUDIT_ARCH_X86_64,%edi /* 1st arg: audit arch */ call __audit_syscall_entry + + pax_erase_kstack + LOAD_ARGS 0 /* reload call-clobbered registers */ + pax_set_fptr_mask jmp system_call_fastpath /* @@ -737,7 +1186,7 @@ sysret_audit: /* Do syscall tracing */ tracesys: #ifdef CONFIG_AUDITSYSCALL - testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx) jz auditsys #endif SAVE_REST @@ -745,12 +1194,16 @@ tracesys: FIXUP_TOP_OF_STACK %rdi movq %rsp,%rdi call syscall_trace_enter + + pax_erase_kstack + /* * Reload arg registers from stack in case ptrace changed them. * We don't reload %rax because syscall_trace_enter() returned * the value it wants us to use in the table lookup. */ LOAD_ARGS ARGOFFSET, 1 + pax_set_fptr_mask RESTORE_REST #if __SYSCALL_MASK == ~0 cmpq $__NR_syscall_max,%rax @@ -759,7 +1212,7 @@ tracesys: cmpl $__NR_syscall_max,%eax #endif ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */ - movq %r10,%rcx /* fixup for C */ + movq R10-ARGOFFSET(%rsp),%rcx /* fixup for C */ call *sys_call_table(,%rax,8) movq %rax,RAX-ARGOFFSET(%rsp) /* Use IRET because user could have changed frame */ @@ -780,7 +1233,9 @@ GLOBAL(int_with_check) andl %edi,%edx jnz int_careful andl $~TS_COMPAT,TI_status(%rcx) - jmp retint_swapgs + pax_exit_kernel_user + pax_erase_kstack + jmp retint_swapgs_pax /* Either reschedule or signal or syscall exit tracking needed. */ /* First do a reschedule test. */ @@ -826,7 +1281,7 @@ int_restore_rest: TRACE_IRQS_OFF jmp int_with_check CFI_ENDPROC -END(system_call) +ENDPROC(system_call) .macro FORK_LIKE func ENTRY(stub_\func) @@ -839,9 +1294,10 @@ ENTRY(stub_\func) DEFAULT_FRAME 0 8 /* offset 8: return address */ call sys_\func RESTORE_TOP_OF_STACK %r11, 8 + pax_force_retaddr ret $REST_SKIP /* pop extended registers */ CFI_ENDPROC -END(stub_\func) +ENDPROC(stub_\func) .endm .macro FIXED_FRAME label,func @@ -851,9 +1307,10 @@ ENTRY(\label) FIXUP_TOP_OF_STACK %r11, 8-ARGOFFSET call \func RESTORE_TOP_OF_STACK %r11, 8-ARGOFFSET + pax_force_retaddr ret CFI_ENDPROC -END(\label) +ENDPROC(\label) .endm FORK_LIKE clone @@ -870,9 +1327,10 @@ ENTRY(ptregscall_common) movq_cfi_restore R12+8, r12 movq_cfi_restore RBP+8, rbp movq_cfi_restore RBX+8, rbx + pax_force_retaddr ret $REST_SKIP /* pop extended registers */ CFI_ENDPROC -END(ptregscall_common) +ENDPROC(ptregscall_common) ENTRY(stub_execve) CFI_STARTPROC @@ -885,7 +1343,7 @@ ENTRY(stub_execve) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC -END(stub_execve) +ENDPROC(stub_execve) /* * sigreturn is special because it needs to restore all registers on return. @@ -902,7 +1360,7 @@ ENTRY(stub_rt_sigreturn) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC -END(stub_rt_sigreturn) +ENDPROC(stub_rt_sigreturn) #ifdef CONFIG_X86_X32_ABI ENTRY(stub_x32_rt_sigreturn) @@ -916,7 +1374,7 @@ ENTRY(stub_x32_rt_sigreturn) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC -END(stub_x32_rt_sigreturn) +ENDPROC(stub_x32_rt_sigreturn) ENTRY(stub_x32_execve) CFI_STARTPROC @@ -930,7 +1388,7 @@ ENTRY(stub_x32_execve) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC -END(stub_x32_execve) +ENDPROC(stub_x32_execve) #endif @@ -967,7 +1425,7 @@ vector=vector+1 2: jmp common_interrupt .endr CFI_ENDPROC -END(irq_entries_start) +ENDPROC(irq_entries_start) .previous END(interrupt) @@ -987,6 +1445,16 @@ END(interrupt) subq $ORIG_RAX-RBP, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP SAVE_ARGS_IRQ +#ifdef CONFIG_PAX_MEMORY_UDEREF + testb $3, CS(%rdi) + jnz 1f + pax_enter_kernel + jmp 2f +1: pax_enter_kernel_user +2: +#else + pax_enter_kernel +#endif call \func .endm @@ -1019,7 +1487,7 @@ ret_from_intr: exit_intr: GET_THREAD_INFO(%rcx) - testl $3,CS-ARGOFFSET(%rsp) + testb $3,CS-ARGOFFSET(%rsp) je retint_kernel /* Interrupt came from user space */ @@ -1041,12 +1509,16 @@ retint_swapgs: /* return to user-space */ * The iretq could re-enable interrupts: */ DISABLE_INTERRUPTS(CLBR_ANY) + pax_exit_kernel_user +retint_swapgs_pax: TRACE_IRQS_IRETQ SWAPGS jmp restore_args retint_restore_args: /* return to kernel space */ DISABLE_INTERRUPTS(CLBR_ANY) + pax_exit_kernel + pax_force_retaddr (RIP-ARGOFFSET) /* * The iretq could re-enable interrupts: */ @@ -1129,7 +1601,7 @@ ENTRY(retint_kernel) #endif CFI_ENDPROC -END(common_interrupt) +ENDPROC(common_interrupt) /* * End of kprobes section */ @@ -1147,7 +1619,7 @@ ENTRY(\sym) interrupt \do_sym jmp ret_from_intr CFI_ENDPROC -END(\sym) +ENDPROC(\sym) .endm #ifdef CONFIG_SMP @@ -1208,12 +1680,22 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call error_entry DEFAULT_FRAME 0 +#ifdef CONFIG_PAX_MEMORY_UDEREF + testb $3, CS(%rsp) + jnz 1f + pax_enter_kernel + jmp 2f +1: pax_enter_kernel_user +2: +#else + pax_enter_kernel +#endif movq %rsp,%rdi /* pt_regs pointer */ xorl %esi,%esi /* no error code */ call \do_sym jmp error_exit /* %ebx: no swapgs flag */ CFI_ENDPROC -END(\sym) +ENDPROC(\sym) .endm .macro paranoidzeroentry sym do_sym @@ -1226,15 +1708,25 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call save_paranoid TRACE_IRQS_OFF +#ifdef CONFIG_PAX_MEMORY_UDEREF + testb $3, CS(%rsp) + jnz 1f + pax_enter_kernel + jmp 2f +1: pax_enter_kernel_user +2: +#else + pax_enter_kernel +#endif movq %rsp,%rdi /* pt_regs pointer */ xorl %esi,%esi /* no error code */ call \do_sym jmp paranoid_exit /* %ebx: no swapgs flag */ CFI_ENDPROC -END(\sym) +ENDPROC(\sym) .endm -#define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8) +#define INIT_TSS_IST(x) (TSS_ist + ((x) - 1) * 8)(%r12) .macro paranoidzeroentry_ist sym do_sym ist ENTRY(\sym) INTR_FRAME @@ -1245,14 +1737,30 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call save_paranoid TRACE_IRQS_OFF_DEBUG +#ifdef CONFIG_PAX_MEMORY_UDEREF + testb $3, CS(%rsp) + jnz 1f + pax_enter_kernel + jmp 2f +1: pax_enter_kernel_user +2: +#else + pax_enter_kernel +#endif movq %rsp,%rdi /* pt_regs pointer */ xorl %esi,%esi /* no error code */ +#ifdef CONFIG_SMP + imul $TSS_size, PER_CPU_VAR(cpu_number), %r12d + lea init_tss(%r12), %r12 +#else + lea init_tss(%rip), %r12 +#endif subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist) call \do_sym addq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist) jmp paranoid_exit /* %ebx: no swapgs flag */ CFI_ENDPROC -END(\sym) +ENDPROC(\sym) .endm .macro errorentry sym do_sym @@ -1264,13 +1772,23 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call error_entry DEFAULT_FRAME 0 +#ifdef CONFIG_PAX_MEMORY_UDEREF + testb $3, CS(%rsp) + jnz 1f + pax_enter_kernel + jmp 2f +1: pax_enter_kernel_user +2: +#else + pax_enter_kernel +#endif movq %rsp,%rdi /* pt_regs pointer */ movq ORIG_RAX(%rsp),%rsi /* get error code */ movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */ call \do_sym jmp error_exit /* %ebx: no swapgs flag */ CFI_ENDPROC -END(\sym) +ENDPROC(\sym) .endm /* error code is on the stack already */ @@ -1284,13 +1802,23 @@ ENTRY(\sym) call save_paranoid DEFAULT_FRAME 0 TRACE_IRQS_OFF +#ifdef CONFIG_PAX_MEMORY_UDEREF + testb $3, CS(%rsp) + jnz 1f + pax_enter_kernel + jmp 2f +1: pax_enter_kernel_user +2: +#else + pax_enter_kernel +#endif movq %rsp,%rdi /* pt_regs pointer */ movq ORIG_RAX(%rsp),%rsi /* get error code */ movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */ call \do_sym jmp paranoid_exit /* %ebx: no swapgs flag */ CFI_ENDPROC -END(\sym) +ENDPROC(\sym) .endm zeroentry divide_error do_divide_error @@ -1320,9 +1848,10 @@ gs_change: 2: mfence /* workaround */ SWAPGS popfq_cfi + pax_force_retaddr ret CFI_ENDPROC -END(native_load_gs_index) +ENDPROC(native_load_gs_index) _ASM_EXTABLE(gs_change,bad_gs) .section .fixup,"ax" @@ -1350,9 +1879,10 @@ ENTRY(call_softirq) CFI_DEF_CFA_REGISTER rsp CFI_ADJUST_CFA_OFFSET -8 decl PER_CPU_VAR(irq_count) + pax_force_retaddr ret CFI_ENDPROC -END(call_softirq) +ENDPROC(call_softirq) #ifdef CONFIG_XEN zeroentry xen_hypervisor_callback xen_do_hypervisor_callback @@ -1390,7 +1920,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) decl PER_CPU_VAR(irq_count) jmp error_exit CFI_ENDPROC -END(xen_do_hypervisor_callback) +ENDPROC(xen_do_hypervisor_callback) /* * Hypervisor uses this for application faults while it executes. @@ -1449,7 +1979,7 @@ ENTRY(xen_failsafe_callback) SAVE_ALL jmp error_exit CFI_ENDPROC -END(xen_failsafe_callback) +ENDPROC(xen_failsafe_callback) apicinterrupt HYPERVISOR_CALLBACK_VECTOR \ xen_hvm_callback_vector xen_evtchn_do_upcall @@ -1501,18 +2031,33 @@ ENTRY(paranoid_exit) DEFAULT_FRAME DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF_DEBUG - testl %ebx,%ebx /* swapgs needed? */ + testl $1,%ebx /* swapgs needed? */ jnz paranoid_restore - testl $3,CS(%rsp) + testb $3,CS(%rsp) jnz paranoid_userspace +#ifdef CONFIG_PAX_MEMORY_UDEREF + pax_exit_kernel + TRACE_IRQS_IRETQ 0 + SWAPGS_UNSAFE_STACK + RESTORE_ALL 8 + pax_force_retaddr_bts + jmp irq_return +#endif paranoid_swapgs: +#ifdef CONFIG_PAX_MEMORY_UDEREF + pax_exit_kernel_user +#else + pax_exit_kernel +#endif TRACE_IRQS_IRETQ 0 SWAPGS_UNSAFE_STACK RESTORE_ALL 8 jmp irq_return paranoid_restore: + pax_exit_kernel TRACE_IRQS_IRETQ_DEBUG 0 RESTORE_ALL 8 + pax_force_retaddr_bts jmp irq_return paranoid_userspace: GET_THREAD_INFO(%rcx) @@ -1541,7 +2086,7 @@ paranoid_schedule: TRACE_IRQS_OFF jmp paranoid_userspace CFI_ENDPROC -END(paranoid_exit) +ENDPROC(paranoid_exit) /* * Exception entry point. This expects an error code/orig_rax on the stack. @@ -1568,12 +2113,13 @@ ENTRY(error_entry) movq_cfi r14, R14+8 movq_cfi r15, R15+8 xorl %ebx,%ebx - testl $3,CS+8(%rsp) + testb $3,CS+8(%rsp) je error_kernelspace error_swapgs: SWAPGS error_sti: TRACE_IRQS_OFF + pax_force_retaddr_bts ret /* @@ -1600,7 +2146,7 @@ bstep_iret: movq %rcx,RIP+8(%rsp) jmp error_swapgs CFI_ENDPROC -END(error_entry) +ENDPROC(error_entry) /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */ @@ -1611,7 +2157,7 @@ ENTRY(error_exit) DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF GET_THREAD_INFO(%rcx) - testl %eax,%eax + testl $1,%eax jne retint_kernel LOCKDEP_SYS_EXIT_IRQ movl TI_flags(%rcx),%edx @@ -1620,7 +2166,7 @@ ENTRY(error_exit) jnz retint_careful jmp retint_swapgs CFI_ENDPROC -END(error_exit) +ENDPROC(error_exit) /* * Test if a given stack is an NMI stack or not. @@ -1678,9 +2224,11 @@ ENTRY(nmi) * If %cs was not the kernel segment, then the NMI triggered in user * space, which means it is definitely not nested. */ + cmpl $__KERNEXEC_KERNEL_CS, 16(%rsp) + je 1f cmpl $__KERNEL_CS, 16(%rsp) jne first_nmi - +1: /* * Check the special variable on the stack to see if NMIs are * executing. @@ -1714,8 +2262,7 @@ nested_nmi: 1: /* Set up the interrupted NMIs stack to jump to repeat_nmi */ - leaq -1*8(%rsp), %rdx - movq %rdx, %rsp + subq $8, %rsp CFI_ADJUST_CFA_OFFSET 1*8 leaq -10*8(%rsp), %rdx pushq_cfi $__KERNEL_DS @@ -1733,6 +2280,7 @@ nested_nmi_out: CFI_RESTORE rdx /* No need to check faults here */ +# pax_force_retaddr_bts INTERRUPT_RETURN CFI_RESTORE_STATE @@ -1849,6 +2397,8 @@ end_repeat_nmi: */ movq %cr2, %r12 + pax_enter_kernel_nmi + /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */ movq %rsp,%rdi movq $-1,%rsi @@ -1861,26 +2411,31 @@ end_repeat_nmi: movq %r12, %cr2 1: - testl %ebx,%ebx /* swapgs needed? */ + testl $1,%ebx /* swapgs needed? */ jnz nmi_restore nmi_swapgs: SWAPGS_UNSAFE_STACK nmi_restore: + pax_exit_kernel_nmi /* Pop the extra iret frame at once */ RESTORE_ALL 6*8 + testb $3, 8(%rsp) + jnz 1f + pax_force_retaddr_bts +1: /* Clear the NMI executing stack variable */ movq $0, 5*8(%rsp) jmp irq_return CFI_ENDPROC -END(nmi) +ENDPROC(nmi) ENTRY(ignore_sysret) CFI_STARTPROC mov $-ENOSYS,%eax sysret CFI_ENDPROC -END(ignore_sysret) +ENDPROC(ignore_sysret) /* * End of kprobes section diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 42a392a..fbbd930 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -105,6 +105,8 @@ ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code, { unsigned char replaced[MCOUNT_INSN_SIZE]; + ip = ktla_ktva(ip); + /* * Note: Due to modules and __init, code can * disappear and change, we need to protect against faulting @@ -227,7 +229,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) unsigned char old[MCOUNT_INSN_SIZE], *new; int ret; - memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); + memcpy(old, (void *)ktla_ktva((unsigned long)ftrace_call), MCOUNT_INSN_SIZE); new = ftrace_call_replace(ip, (unsigned long)func); /* See comment above by declaration of modifying_ftrace_code */ @@ -238,7 +240,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) /* Also update the regs callback function */ if (!ret) { ip = (unsigned long)(&ftrace_regs_call); - memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE); + memcpy(old, ktla_ktva((void *)&ftrace_regs_call), MCOUNT_INSN_SIZE); new = ftrace_call_replace(ip, (unsigned long)func); ret = ftrace_modify_code(ip, old, new); } @@ -279,7 +281,7 @@ static int ftrace_write(unsigned long ip, const char *val, int size) * kernel identity mapping to modify code. */ if (within(ip, (unsigned long)_text, (unsigned long)_etext)) - ip = (unsigned long)__va(__pa_symbol(ip)); + ip = (unsigned long)__va(__pa_symbol(ktla_ktva(ip))); return probe_kernel_write((void *)ip, val, size); } @@ -289,7 +291,7 @@ static int add_break(unsigned long ip, const char *old) unsigned char replaced[MCOUNT_INSN_SIZE]; unsigned char brk = BREAKPOINT_INSTRUCTION; - if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) + if (probe_kernel_read(replaced, (void *)ktla_ktva(ip), MCOUNT_INSN_SIZE)) return -EFAULT; /* Make sure it is what we expect it to be */ @@ -637,7 +639,7 @@ ftrace_modify_code(unsigned long ip, unsigned const char *old_code, return ret; fail_update: - probe_kernel_write((void *)ip, &old_code[0], 1); + probe_kernel_write((void *)ktla_ktva(ip), &old_code[0], 1); goto out; } @@ -670,6 +672,8 @@ static int ftrace_mod_jmp(unsigned long ip, { unsigned char code[MCOUNT_INSN_SIZE]; + ip = ktla_ktva(ip); + if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) return -EFAULT; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 55b6761..a6456fc 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -67,12 +67,12 @@ again: pgd = *pgd_p; /* - * The use of __START_KERNEL_map rather than __PAGE_OFFSET here is - * critical -- __PAGE_OFFSET would point us back into the dynamic + * The use of __early_va rather than __va here is critical: + * __va would point us back into the dynamic * range and we might end up looping forever... */ if (pgd) - pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); + pud_p = (pudval_t *)(__early_va(pgd & PTE_PFN_MASK)); else { if (next_early_pgt >= EARLY_DYNAMIC_PAGE_TABLES) { reset_early_page_tables(); @@ -82,13 +82,13 @@ again: pud_p = (pudval_t *)early_dynamic_pgts[next_early_pgt++]; for (i = 0; i < PTRS_PER_PUD; i++) pud_p[i] = 0; - *pgd_p = (pgdval_t)pud_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE; + *pgd_p = (pgdval_t)__pa(pud_p) + _KERNPG_TABLE; } pud_p += pud_index(address); pud = *pud_p; if (pud) - pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); + pmd_p = (pmdval_t *)(__early_va(pud & PTE_PFN_MASK)); else { if (next_early_pgt >= EARLY_DYNAMIC_PAGE_TABLES) { reset_early_page_tables(); @@ -98,7 +98,7 @@ again: pmd_p = (pmdval_t *)early_dynamic_pgts[next_early_pgt++]; for (i = 0; i < PTRS_PER_PMD; i++) pmd_p[i] = 0; - *pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE; + *pud_p = (pudval_t)__pa(pmd_p) + _KERNPG_TABLE; } pmd = (physaddr & PMD_MASK) + early_pmd_flags; pmd_p[pmd_index(address)] = pmd; @@ -175,7 +175,6 @@ void __init x86_64_start_kernel(char * real_mode_data) if (console_loglevel == 10) early_printk("Kernel alive\n"); - clear_page(init_level4_pgt); /* set init_level4_pgt kernel high mapping*/ init_level4_pgt[511] = early_level4_pgt[511]; diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 73afd11..0ef46f2 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -26,6 +26,12 @@ /* Physical address */ #define pa(X) ((X) - __PAGE_OFFSET) +#ifdef CONFIG_PAX_KERNEXEC +#define ta(X) (X) +#else +#define ta(X) ((X) - __PAGE_OFFSET) +#endif + /* * References to members of the new_cpu_data structure. */ @@ -55,11 +61,7 @@ * and small than max_low_pfn, otherwise will waste some page table entries */ -#if PTRS_PER_PMD > 1 -#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) -#else -#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) -#endif +#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PTE) /* Number of possible pages in the lowmem region */ LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) @@ -78,6 +80,12 @@ INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE RESERVE_BRK(pagetables, INIT_MAP_SIZE) /* + * Real beginning of normal "text" segment + */ +ENTRY(stext) +ENTRY(_stext) + +/* * 32-bit kernel entrypoint; only used by the boot CPU. On entry, * %esi points to the real-mode code as a 32-bit pointer. * CS and DS must be 4 GB flat segments, but we don't depend on @@ -85,6 +93,13 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE) * can. */ __HEAD + +#ifdef CONFIG_PAX_KERNEXEC + jmp startup_32 +/* PaX: fill first page in .text with int3 to catch NULL derefs in kernel mode */ +.fill PAGE_SIZE-5,1,0xcc +#endif + ENTRY(startup_32) movl pa(stack_start),%ecx @@ -106,6 +121,59 @@ ENTRY(startup_32) 2: leal -__PAGE_OFFSET(%ecx),%esp +#ifdef CONFIG_SMP + movl $pa(cpu_gdt_table),%edi + movl $__per_cpu_load,%eax + movw %ax,GDT_ENTRY_PERCPU * 8 + 2(%edi) + rorl $16,%eax + movb %al,GDT_ENTRY_PERCPU * 8 + 4(%edi) + movb %ah,GDT_ENTRY_PERCPU * 8 + 7(%edi) + movl $__per_cpu_end - 1,%eax + subl $__per_cpu_start,%eax + movw %ax,GDT_ENTRY_PERCPU * 8 + 0(%edi) +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + movl $NR_CPUS,%ecx + movl $pa(cpu_gdt_table),%edi +1: + movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c09700),GDT_ENTRY_KERNEL_DS * 8 + 4(%edi) + movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c0fb00),GDT_ENTRY_DEFAULT_USER_CS * 8 + 4(%edi) + movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c0f300),GDT_ENTRY_DEFAULT_USER_DS * 8 + 4(%edi) + addl $PAGE_SIZE_asm,%edi + loop 1b +#endif + +#ifdef CONFIG_PAX_KERNEXEC + movl $pa(boot_gdt),%edi + movl $__LOAD_PHYSICAL_ADDR,%eax + movw %ax,GDT_ENTRY_BOOT_CS * 8 + 2(%edi) + rorl $16,%eax + movb %al,GDT_ENTRY_BOOT_CS * 8 + 4(%edi) + movb %ah,GDT_ENTRY_BOOT_CS * 8 + 7(%edi) + rorl $16,%eax + + ljmp $(__BOOT_CS),$1f +1: + + movl $NR_CPUS,%ecx + movl $pa(cpu_gdt_table),%edi + addl $__PAGE_OFFSET,%eax +1: + movb $0xc0,GDT_ENTRY_KERNEL_CS * 8 + 6(%edi) + movb $0xc0,GDT_ENTRY_KERNEXEC_KERNEL_CS * 8 + 6(%edi) + movw %ax,GDT_ENTRY_KERNEL_CS * 8 + 2(%edi) + movw %ax,GDT_ENTRY_KERNEXEC_KERNEL_CS * 8 + 2(%edi) + rorl $16,%eax + movb %al,GDT_ENTRY_KERNEL_CS * 8 + 4(%edi) + movb %al,GDT_ENTRY_KERNEXEC_KERNEL_CS * 8 + 4(%edi) + movb %ah,GDT_ENTRY_KERNEL_CS * 8 + 7(%edi) + movb %ah,GDT_ENTRY_KERNEXEC_KERNEL_CS * 8 + 7(%edi) + rorl $16,%eax + addl $PAGE_SIZE_asm,%edi + loop 1b +#endif + /* * Clear BSS first so that there are no surprises... */ @@ -201,8 +269,11 @@ ENTRY(startup_32) movl %eax, pa(max_pfn_mapped) /* Do early initialization of the fixmap area */ - movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax - movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) +#ifdef CONFIG_COMPAT_VDSO + movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR+_PAGE_USER,pa(initial_pg_pmd+0x1000*KPMDS-8) +#else + movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,pa(initial_pg_pmd+0x1000*KPMDS-8) +#endif #else /* Not PAE */ page_pde_offset = (__PAGE_OFFSET >> 20); @@ -232,8 +303,11 @@ page_pde_offset = (__PAGE_OFFSET >> 20); movl %eax, pa(max_pfn_mapped) /* Do early initialization of the fixmap area */ - movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax - movl %eax,pa(initial_page_table+0xffc) +#ifdef CONFIG_COMPAT_VDSO + movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR+_PAGE_USER,pa(initial_page_table+0xffc) +#else + movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,pa(initial_page_table+0xffc) +#endif #endif #ifdef CONFIG_PARAVIRT @@ -247,9 +321,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20); cmpl $num_subarch_entries, %eax jae bad_subarch - movl pa(subarch_entries)(,%eax,4), %eax - subl $__PAGE_OFFSET, %eax - jmp *%eax + jmp *pa(subarch_entries)(,%eax,4) bad_subarch: WEAK(lguest_entry) @@ -261,10 +333,10 @@ WEAK(xen_entry) __INITDATA subarch_entries: - .long default_entry /* normal x86/PC */ - .long lguest_entry /* lguest hypervisor */ - .long xen_entry /* Xen hypervisor */ - .long default_entry /* Moorestown MID */ + .long ta(default_entry) /* normal x86/PC */ + .long ta(lguest_entry) /* lguest hypervisor */ + .long ta(xen_entry) /* Xen hypervisor */ + .long ta(default_entry) /* Moorestown MID */ num_subarch_entries = (. - subarch_entries) / 4 .previous #else @@ -355,6 +427,7 @@ default_entry: movl pa(mmu_cr4_features),%eax movl %eax,%cr4 +#ifdef CONFIG_X86_PAE testb $X86_CR4_PAE, %al # check if PAE is enabled jz enable_paging @@ -383,6 +456,9 @@ default_entry: /* Make changes effective */ wrmsr + btsl $_PAGE_BIT_NX-32,pa(__supported_pte_mask+4) +#endif + enable_paging: /* @@ -451,14 +527,20 @@ is486: 1: movl $(__KERNEL_DS),%eax # reload all the segment registers movl %eax,%ss # after changing gdt. - movl $(__USER_DS),%eax # DS/ES contains default USER segment +# movl $(__KERNEL_DS),%eax # DS/ES contains default KERNEL segment movl %eax,%ds movl %eax,%es movl $(__KERNEL_PERCPU), %eax movl %eax,%fs # set this cpu's percpu +#ifdef CONFIG_CC_STACKPROTECTOR movl $(__KERNEL_STACK_CANARY),%eax +#elif defined(CONFIG_PAX_MEMORY_UDEREF) + movl $(__USER_DS),%eax +#else + xorl %eax,%eax +#endif movl %eax,%gs xorl %eax,%eax # Clear LDT @@ -534,8 +616,11 @@ setup_once: * relocation. Manually set base address in stack canary * segment descriptor. */ - movl $gdt_page,%eax + movl $cpu_gdt_table,%eax movl $stack_canary,%ecx +#ifdef CONFIG_SMP + addl $__per_cpu_load,%ecx +#endif movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) shrl $16, %ecx movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) @@ -566,7 +651,7 @@ ENDPROC(early_idt_handlers) /* This is global to keep gas from relaxing the jumps */ ENTRY(early_idt_handler) cld - cmpl $2,%ss:early_recursion_flag + cmpl $1,%ss:early_recursion_flag je hlt_loop incl %ss:early_recursion_flag @@ -604,8 +689,8 @@ ENTRY(early_idt_handler) pushl (20+6*4)(%esp) /* trapno */ pushl $fault_msg call printk -#endif call dump_stack +#endif hlt_loop: hlt jmp hlt_loop @@ -624,8 +709,11 @@ ENDPROC(early_idt_handler) /* This is the default interrupt "handler" :-) */ ALIGN ignore_int: - cld #ifdef CONFIG_PRINTK + cmpl $2,%ss:early_recursion_flag + je hlt_loop + incl %ss:early_recursion_flag + cld pushl %eax pushl %ecx pushl %edx @@ -634,9 +722,6 @@ ignore_int: movl $(__KERNEL_DS),%eax movl %eax,%ds movl %eax,%es - cmpl $2,early_recursion_flag - je hlt_loop - incl early_recursion_flag pushl 16(%esp) pushl 24(%esp) pushl 32(%esp) @@ -670,29 +755,43 @@ ENTRY(setup_once_ref) /* * BSS section */ -__PAGE_ALIGNED_BSS - .align PAGE_SIZE #ifdef CONFIG_X86_PAE +.section .initial_pg_pmd,"a",@progbits initial_pg_pmd: .fill 1024*KPMDS,4,0 #else +.section .initial_page_table,"a",@progbits ENTRY(initial_page_table) .fill 1024,4,0 #endif +.section .initial_pg_fixmap,"a",@progbits initial_pg_fixmap: .fill 1024,4,0 +.section .empty_zero_page,"a",@progbits ENTRY(empty_zero_page) .fill 4096,1,0 +.section .swapper_pg_dir,"a",@progbits ENTRY(swapper_pg_dir) +#ifdef CONFIG_X86_PAE + .fill 4,8,0 +#else .fill 1024,4,0 +#endif + +/* + * The IDT has to be page-aligned to simplify the Pentium + * F0 0F bug workaround.. We have a special link segment + * for this. + */ +.section .idt,"a",@progbits +ENTRY(idt_table) + .fill 256,8,0 /* * This starts the data section. */ #ifdef CONFIG_X86_PAE -__PAGE_ALIGNED_DATA - /* Page-aligned for the benefit of paravirt? */ - .align PAGE_SIZE +.section .initial_page_table,"a",@progbits ENTRY(initial_page_table) .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ # if KPMDS == 3 @@ -711,12 +810,20 @@ ENTRY(initial_page_table) # error "Kernel PMDs should be 1, 2 or 3" # endif .align PAGE_SIZE /* needs to be page-sized too */ + +#ifdef CONFIG_PAX_PER_CPU_PGD +ENTRY(cpu_pgd) + .rept 2*NR_CPUS + .fill 4,8,0 + .endr +#endif + #endif .data .balign 4 ENTRY(stack_start) - .long init_thread_union+THREAD_SIZE + .long init_thread_union+THREAD_SIZE-8 __INITRODATA int_msg: @@ -744,7 +851,7 @@ fault_msg: * segment size, and 32-bit linear address value: */ - .data +.section .rodata,"a",@progbits .globl boot_gdt_descr .globl idt_descr @@ -753,7 +860,7 @@ fault_msg: .word 0 # 32 bit align gdt_desc.address boot_gdt_descr: .word __BOOT_DS+7 - .long boot_gdt - __PAGE_OFFSET + .long pa(boot_gdt) .word 0 # 32-bit align idt_desc.address idt_descr: @@ -764,7 +871,7 @@ idt_descr: .word 0 # 32 bit align gdt_desc.address ENTRY(early_gdt_descr) .word GDT_ENTRIES*8-1 - .long gdt_page /* Overwritten for secondary CPUs */ + .long cpu_gdt_table /* Overwritten for secondary CPUs */ /* * The boot_gdt must mirror the equivalent in setup.S and is @@ -773,5 +880,65 @@ ENTRY(early_gdt_descr) .align L1_CACHE_BYTES ENTRY(boot_gdt) .fill GDT_ENTRY_BOOT_CS,8,0 - .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ - .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ + .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */ + .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */ + + .align PAGE_SIZE_asm +ENTRY(cpu_gdt_table) + .rept NR_CPUS + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x0000000000000000 /* 0x0b reserved */ + .quad 0x0000000000000000 /* 0x13 reserved */ + .quad 0x0000000000000000 /* 0x1b reserved */ + +#ifdef CONFIG_PAX_KERNEXEC + .quad 0x00cf9b000000ffff /* 0x20 alternate kernel 4GB code at 0x00000000 */ +#else + .quad 0x0000000000000000 /* 0x20 unused */ +#endif + + .quad 0x0000000000000000 /* 0x28 unused */ + .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ + .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ + .quad 0x0000000000000000 /* 0x43 TLS entry 3 */ + .quad 0x0000000000000000 /* 0x4b reserved */ + .quad 0x0000000000000000 /* 0x53 reserved */ + .quad 0x0000000000000000 /* 0x5b reserved */ + + .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ + .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ + .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */ + .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */ + + .quad 0x0000000000000000 /* 0x80 TSS descriptor */ + .quad 0x0000000000000000 /* 0x88 LDT descriptor */ + + /* + * Segments used for calling PnP BIOS have byte granularity. + * The code segments and data segments have fixed 64k limits, + * the transfer segment sizes are set at run time. + */ + .quad 0x00409b000000ffff /* 0x90 32-bit code */ + .quad 0x00009b000000ffff /* 0x98 16-bit code */ + .quad 0x000093000000ffff /* 0xa0 16-bit data */ + .quad 0x0000930000000000 /* 0xa8 16-bit data */ + .quad 0x0000930000000000 /* 0xb0 16-bit data */ + + /* + * The APM segments have byte granularity and their bases + * are set at run time. All have 64k limits. + */ + .quad 0x00409b000000ffff /* 0xb8 APM CS code */ + .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */ + .quad 0x004093000000ffff /* 0xc8 APM DS data */ + + .quad 0x00c0930000000000 /* 0xd0 - ESPFIX SS */ + .quad 0x0040930000000000 /* 0xd8 - PERCPU */ + .quad 0x0040910000000017 /* 0xe0 - STACK_CANARY */ + .quad 0x0000000000000000 /* 0xe8 - PCIBIOS_CS */ + .quad 0x0000000000000000 /* 0xf0 - PCIBIOS_DS */ + .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ + + /* Be sure this is zeroed to avoid false validations in Xen */ + .fill PAGE_SIZE_asm - GDT_SIZE,1,0 + .endr diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index a836860..1b5c665 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -20,6 +20,8 @@ #include #include #include +#include +#include #ifdef CONFIG_PARAVIRT #include @@ -41,6 +43,12 @@ L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET) L3_PAGE_OFFSET = pud_index(__PAGE_OFFSET) L4_START_KERNEL = pgd_index(__START_KERNEL_map) L3_START_KERNEL = pud_index(__START_KERNEL_map) +L4_VMALLOC_START = pgd_index(VMALLOC_START) +L3_VMALLOC_START = pud_index(VMALLOC_START) +L4_VMALLOC_END = pgd_index(VMALLOC_END) +L3_VMALLOC_END = pud_index(VMALLOC_END) +L4_VMEMMAP_START = pgd_index(VMEMMAP_START) +L3_VMEMMAP_START = pud_index(VMEMMAP_START) .text __HEAD @@ -89,11 +97,23 @@ startup_64: * Fixup the physical addresses in the page table */ addq %rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip) + addq %rbp, init_level4_pgt + (L4_PAGE_OFFSET*8)(%rip) + addq %rbp, init_level4_pgt + (L4_VMALLOC_START*8)(%rip) + addq %rbp, init_level4_pgt + (L4_VMALLOC_END*8)(%rip) + addq %rbp, init_level4_pgt + (L4_VMEMMAP_START*8)(%rip) + addq %rbp, init_level4_pgt + (L4_START_KERNEL*8)(%rip) - addq %rbp, level3_kernel_pgt + (510*8)(%rip) - addq %rbp, level3_kernel_pgt + (511*8)(%rip) + addq %rbp, level3_ident_pgt + (0*8)(%rip) +#ifndef CONFIG_XEN + addq %rbp, level3_ident_pgt + (1*8)(%rip) +#endif + + addq %rbp, level3_vmemmap_pgt + (L3_VMEMMAP_START*8)(%rip) - addq %rbp, level2_fixmap_pgt + (506*8)(%rip) + addq %rbp, level3_kernel_pgt + (L3_START_KERNEL*8)(%rip) + addq %rbp, level3_kernel_pgt + ((L3_START_KERNEL+1)*8)(%rip) + + addq %rbp, level2_fixmap_pgt + (507*8)(%rip) /* * Set up the identity mapping for the switchover. These @@ -177,8 +197,8 @@ ENTRY(secondary_startup_64) movq $(init_level4_pgt - __START_KERNEL_map), %rax 1: - /* Enable PAE mode and PGE */ - movl $(X86_CR4_PAE | X86_CR4_PGE), %ecx + /* Enable PAE mode and PSE/PGE */ + movl $(X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE), %ecx movq %rcx, %cr4 /* Setup early boot stage 4 level pagetables. */ @@ -199,10 +219,18 @@ ENTRY(secondary_startup_64) movl $MSR_EFER, %ecx rdmsr btsl $_EFER_SCE, %eax /* Enable System Call */ - btl $20,%edi /* No Execute supported? */ + btl $(X86_FEATURE_NX & 31),%edi /* No Execute supported? */ jnc 1f btsl $_EFER_NX, %eax btsq $_PAGE_BIT_NX,early_pmd_flags(%rip) + leaq init_level4_pgt(%rip), %rdi +#ifndef CONFIG_EFI + btsq $_PAGE_BIT_NX, 8*L4_PAGE_OFFSET(%rdi) +#endif + btsq $_PAGE_BIT_NX, 8*L4_VMALLOC_START(%rdi) + btsq $_PAGE_BIT_NX, 8*L4_VMALLOC_END(%rdi) + btsq $_PAGE_BIT_NX, 8*L4_VMEMMAP_START(%rdi) + btsq $_PAGE_BIT_NX, __supported_pte_mask(%rip) 1: wrmsr /* Make changes effective */ /* Setup cr0 */ @@ -282,6 +310,7 @@ ENTRY(secondary_startup_64) * REX.W + FF /5 JMP m16:64 Jump far, absolute indirect, * address given in m16:64. */ + pax_set_fptr_mask movq initial_code(%rip),%rax pushq $0 # fake return address to stop unwinder pushq $__KERNEL_CS # set correct cs @@ -388,7 +417,7 @@ ENTRY(early_idt_handler) call dump_stack #ifdef CONFIG_KALLSYMS leaq early_idt_ripmsg(%rip),%rdi - movq 40(%rsp),%rsi # %rip again + movq 88(%rsp),%rsi # %rip again call __print_symbol #endif #endif /* EARLY_PRINTK */ @@ -416,6 +445,7 @@ ENDPROC(early_idt_handler) early_recursion_flag: .long 0 + .section .rodata,"a",@progbits #ifdef CONFIG_EARLY_PRINTK early_idt_msg: .asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n" @@ -443,29 +473,52 @@ NEXT_PAGE(early_level4_pgt) NEXT_PAGE(early_dynamic_pgts) .fill 512*EARLY_DYNAMIC_PAGE_TABLES,8,0 - .data + .section .rodata,"a",@progbits -#ifndef CONFIG_XEN NEXT_PAGE(init_level4_pgt) - .fill 512,8,0 -#else -NEXT_PAGE(init_level4_pgt) - .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE .org init_level4_pgt + L4_PAGE_OFFSET*8, 0 .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE + .org init_level4_pgt + L4_VMALLOC_START*8, 0 + .quad level3_vmalloc_start_pgt - __START_KERNEL_map + _KERNPG_TABLE + .org init_level4_pgt + L4_VMALLOC_END*8, 0 + .quad level3_vmalloc_end_pgt - __START_KERNEL_map + _KERNPG_TABLE + .org init_level4_pgt + L4_VMEMMAP_START*8, 0 + .quad level3_vmemmap_pgt - __START_KERNEL_map + _KERNPG_TABLE .org init_level4_pgt + L4_START_KERNEL*8, 0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE +#ifdef CONFIG_PAX_PER_CPU_PGD +NEXT_PAGE(cpu_pgd) + .rept 2*NR_CPUS + .fill 512,8,0 + .endr +#endif + NEXT_PAGE(level3_ident_pgt) .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE +#ifdef CONFIG_XEN .fill 511, 8, 0 +#else + .quad level2_ident_pgt + PAGE_SIZE - __START_KERNEL_map + _KERNPG_TABLE + .fill 510,8,0 +#endif + +NEXT_PAGE(level3_vmalloc_start_pgt) + .fill 512,8,0 + +NEXT_PAGE(level3_vmalloc_end_pgt) + .fill 512,8,0 + +NEXT_PAGE(level3_vmemmap_pgt) + .fill L3_VMEMMAP_START,8,0 + .quad level2_vmemmap_pgt - __START_KERNEL_map + _KERNPG_TABLE + NEXT_PAGE(level2_ident_pgt) - /* Since I easily can, map the first 1G. + /* Since I easily can, map the first 2G. * Don't set NX because code runs from these pages. */ - PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD) -#endif + PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, 2*PTRS_PER_PMD) NEXT_PAGE(level3_kernel_pgt) .fill L3_START_KERNEL,8,0 @@ -473,6 +526,9 @@ NEXT_PAGE(level3_kernel_pgt) .quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE .quad level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE +NEXT_PAGE(level2_vmemmap_pgt) + .fill 512,8,0 + NEXT_PAGE(level2_kernel_pgt) /* * 512 MB kernel mapping. We spend a full page on this pagetable @@ -488,39 +544,70 @@ NEXT_PAGE(level2_kernel_pgt) KERNEL_IMAGE_SIZE/PMD_SIZE) NEXT_PAGE(level2_fixmap_pgt) - .fill 506,8,0 - .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE - /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */ - .fill 5,8,0 + .fill 507,8,0 + .quad level1_vsyscall_pgt - __START_KERNEL_map + _PAGE_TABLE + /* 6MB reserved for vsyscalls + a 2MB hole = 3 + 1 entries */ + .fill 4,8,0 -NEXT_PAGE(level1_fixmap_pgt) +NEXT_PAGE(level1_vsyscall_pgt) .fill 512,8,0 #undef PMDS - .data + .align PAGE_SIZE +ENTRY(cpu_gdt_table) + .rept NR_CPUS + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x00cf9b000000ffff /* __KERNEL32_CS */ + .quad 0x00af9b000000ffff /* __KERNEL_CS */ + .quad 0x00cf93000000ffff /* __KERNEL_DS */ + .quad 0x00cffb000000ffff /* __USER32_CS */ + .quad 0x00cff3000000ffff /* __USER_DS, __USER32_DS */ + .quad 0x00affb000000ffff /* __USER_CS */ + +#ifdef CONFIG_PAX_KERNEXEC + .quad 0x00af9b000000ffff /* __KERNEXEC_KERNEL_CS */ +#else + .quad 0x0 /* unused */ +#endif + + .quad 0,0 /* TSS */ + .quad 0,0 /* LDT */ + .quad 0,0,0 /* three TLS descriptors */ + .quad 0x0000f40000000000 /* node/CPU stored in limit */ + /* asm/segment.h:GDT_ENTRIES must match this */ + +#ifdef CONFIG_PAX_MEMORY_UDEREF + .quad 0x00cf93000000ffff /* __UDEREF_KERNEL_DS */ +#else + .quad 0x0 /* unused */ +#endif + + /* zero the remaining page */ + .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0 + .endr + .align 16 .globl early_gdt_descr early_gdt_descr: .word GDT_ENTRIES*8-1 early_gdt_descr_base: - .quad INIT_PER_CPU_VAR(gdt_page) + .quad cpu_gdt_table ENTRY(phys_base) /* This must match the first entry in level2_kernel_pgt */ .quad 0x0000000000000000 #include "../../x86/xen/xen-head.S" - - .section .bss, "aw", @nobits + + .section .rodata,"a",@progbits +NEXT_PAGE(empty_zero_page) + .skip PAGE_SIZE + .align PAGE_SIZE ENTRY(idt_table) - .skip IDT_ENTRIES * 16 + .fill 512,8,0 .align L1_CACHE_BYTES ENTRY(nmi_idt_table) - .skip IDT_ENTRIES * 16 - - __PAGE_ALIGNED_BSS -NEXT_PAGE(empty_zero_page) - .skip PAGE_SIZE + .fill 512,8,0 diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index 0fa6912..b37438b 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c @@ -20,8 +20,12 @@ extern void cmpxchg8b_emu(void); EXPORT_SYMBOL(cmpxchg8b_emu); #endif +EXPORT_SYMBOL_GPL(cpu_gdt_table); + /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_generic); +EXPORT_SYMBOL(csum_partial_copy_generic_to_user); +EXPORT_SYMBOL(csum_partial_copy_generic_from_user); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); @@ -37,3 +41,11 @@ EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(empty_zero_page); + +#ifdef CONFIG_PAX_KERNEXEC +EXPORT_SYMBOL(__LOAD_PHYSICAL_ADDR); +#endif + +#ifdef CONFIG_PAX_PER_CPU_PGD +EXPORT_SYMBOL(cpu_pgd); +#endif diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index f7ea30d..6318acc 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -51,7 +51,7 @@ static inline bool interrupted_kernel_fpu_idle(void) static inline bool interrupted_user_mode(void) { struct pt_regs *regs = get_irq_regs(); - return regs && user_mode_vm(regs); + return regs && user_mode(regs); } /* diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 9a5c460..84868423 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -110,7 +110,7 @@ static int i8259A_irq_pending(unsigned int irq) static void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); - io_apic_irqs &= ~(1< #include #include +#include #include #include #include @@ -28,6 +29,12 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) return -EINVAL; +#ifdef CONFIG_GRKERNSEC_IO + if (turn_on && grsec_disable_privio) { + gr_handle_ioperm(); + return -EPERM; + } +#endif if (turn_on && !capable(CAP_SYS_RAWIO)) return -EPERM; @@ -54,7 +61,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) * because the ->io_bitmap_max value must match the bitmap * contents: */ - tss = &per_cpu(init_tss, get_cpu()); + tss = init_tss + get_cpu(); if (turn_on) bitmap_clear(t->io_bitmap_ptr, from, num); @@ -103,6 +110,12 @@ SYSCALL_DEFINE1(iopl, unsigned int, level) return -EINVAL; /* Trying to gain more privileges? */ if (level > old) { +#ifdef CONFIG_GRKERNSEC_IO + if (grsec_disable_privio) { + gr_handle_iopl(); + return -EPERM; + } +#endif if (!capable(CAP_SYS_RAWIO)) return -EPERM; } diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index ac0631d..ff7cb62 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -18,7 +18,7 @@ #include #include -atomic_t irq_err_count; +atomic_unchecked_t irq_err_count; /* Function pointer for generic interrupt vector handling */ void (*x86_platform_ipi_callback)(void) = NULL; @@ -122,9 +122,9 @@ int arch_show_interrupts(struct seq_file *p, int prec) seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); seq_printf(p, " Machine check polls\n"); #endif - 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)); #if defined(CONFIG_X86_IO_APIC) - seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); + seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read_unchecked(&irq_mis_count)); #endif return 0; } @@ -164,7 +164,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) u64 arch_irq_stat(void) { - u64 sum = atomic_read(&irq_err_count); + u64 sum = atomic_read_unchecked(&irq_err_count); return sum; } diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 344faf8..355f60d 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -39,7 +39,7 @@ static int check_stack_overflow(void) __asm__ __volatile__("andl %%esp,%0" : "=r" (sp) : "0" (THREAD_SIZE - 1)); - return sp < (sizeof(struct thread_info) + STACK_WARN); + return sp < STACK_WARN; } static void print_stack_overflow(void) @@ -59,8 +59,8 @@ static inline void print_stack_overflow(void) { } * per-CPU IRQ handling contexts (thread information and stack) */ union irq_ctx { - struct thread_info tinfo; - u32 stack[THREAD_SIZE/sizeof(u32)]; + unsigned long previous_esp; + u32 stack[THREAD_SIZE/sizeof(u32)]; } __attribute__((aligned(THREAD_SIZE))); static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx); @@ -80,10 +80,9 @@ static void call_on_stack(void *func, void *stack) static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { - union irq_ctx *curctx, *irqctx; + union irq_ctx *irqctx; u32 *isp, arg1, arg2; - curctx = (union irq_ctx *) current_thread_info(); irqctx = __this_cpu_read(hardirq_ctx); /* @@ -92,16 +91,16 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) * handler) we can't do that and just have to keep using the * current stack (which is the irq stack already after all) */ - if (unlikely(curctx == irqctx)) + if (unlikely((void *)current_stack_pointer - (void *)irqctx < THREAD_SIZE)) return 0; /* build the stack frame on the IRQ stack */ - isp = (u32 *) ((char *)irqctx + sizeof(*irqctx)); - irqctx->tinfo.task = curctx->tinfo.task; - irqctx->tinfo.previous_esp = current_stack_pointer; + isp = (u32 *) ((char *)irqctx + sizeof(*irqctx) - 8); + irqctx->previous_esp = current_stack_pointer; - /* Copy the preempt_count so that the [soft]irq checks work. */ - irqctx->tinfo.preempt_count = curctx->tinfo.preempt_count; +#ifdef CONFIG_PAX_MEMORY_UDEREF + __set_fs(MAKE_MM_SEG(0)); +#endif if (unlikely(overflow)) call_on_stack(print_stack_overflow, isp); @@ -113,6 +112,11 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) : "0" (irq), "1" (desc), "2" (isp), "D" (desc->handle_irq) : "memory", "cc", "ecx"); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + __set_fs(current_thread_info()->addr_limit); +#endif + return 1; } @@ -121,29 +125,14 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) */ void __cpuinit irq_ctx_init(int cpu) { - union irq_ctx *irqctx; - if (per_cpu(hardirq_ctx, cpu)) return; - irqctx = page_address(alloc_pages_node(cpu_to_node(cpu), - THREADINFO_GFP, - THREAD_SIZE_ORDER)); - memset(&irqctx->tinfo, 0, sizeof(struct thread_info)); - irqctx->tinfo.cpu = cpu; - irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; - irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); - - per_cpu(hardirq_ctx, cpu) = irqctx; - - irqctx = page_address(alloc_pages_node(cpu_to_node(cpu), - THREADINFO_GFP, - THREAD_SIZE_ORDER)); - memset(&irqctx->tinfo, 0, sizeof(struct thread_info)); - irqctx->tinfo.cpu = cpu; - irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); - - per_cpu(softirq_ctx, cpu) = irqctx; + per_cpu(hardirq_ctx, cpu) = page_address(alloc_pages_node(cpu_to_node(cpu), THREADINFO_GFP, THREAD_SIZE_ORDER)); + per_cpu(softirq_ctx, cpu) = page_address(alloc_pages_node(cpu_to_node(cpu), THREADINFO_GFP, THREAD_SIZE_ORDER)); + + printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n", + cpu, per_cpu(hardirq_ctx, cpu), per_cpu(softirq_ctx, cpu)); printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n", cpu, per_cpu(hardirq_ctx, cpu), per_cpu(softirq_ctx, cpu)); @@ -152,7 +141,6 @@ void __cpuinit irq_ctx_init(int cpu) asmlinkage void do_softirq(void) { unsigned long flags; - struct thread_info *curctx; union irq_ctx *irqctx; u32 *isp; @@ -162,15 +150,22 @@ asmlinkage void do_softirq(void) local_irq_save(flags); if (local_softirq_pending()) { - curctx = current_thread_info(); irqctx = __this_cpu_read(softirq_ctx); - irqctx->tinfo.task = curctx->task; - irqctx->tinfo.previous_esp = current_stack_pointer; + irqctx->previous_esp = current_stack_pointer; /* build the stack frame on the softirq stack */ - isp = (u32 *) ((char *)irqctx + sizeof(*irqctx)); + isp = (u32 *) ((char *)irqctx + sizeof(*irqctx) - 8); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + __set_fs(MAKE_MM_SEG(0)); +#endif call_on_stack(__do_softirq, isp); + +#ifdef CONFIG_PAX_MEMORY_UDEREF + __set_fs(current_thread_info()->addr_limit); +#endif + /* * Shouldn't happen, we returned above if in_interrupt(): */ @@ -191,7 +186,7 @@ bool handle_irq(unsigned irq, struct pt_regs *regs) if (unlikely(!desc)) return false; - if (user_mode_vm(regs) || !execute_on_irq_stack(overflow, desc, irq)) { + if (user_mode(regs) || !execute_on_irq_stack(overflow, desc, irq)) { if (unlikely(overflow)) print_stack_overflow(); desc->handle_irq(irq, desc); diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index d04d3ec..ea4b374 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -44,7 +44,7 @@ static inline void stack_overflow_check(struct pt_regs *regs) u64 estack_top, estack_bottom; u64 curbase = (u64)task_stack_page(current); - if (user_mode_vm(regs)) + if (user_mode(regs)) return; if (regs->sp >= curbase + sizeof(struct thread_info) + diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c index dc1404b..bbc43e7 100644 --- a/arch/x86/kernel/kdebugfs.c +++ b/arch/x86/kernel/kdebugfs.c @@ -27,7 +27,7 @@ struct setup_data_node { u32 len; }; -static ssize_t setup_data_read(struct file *file, char __user *user_buf, +static ssize_t __size_overflow(3) setup_data_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct setup_data_node *node = file->private_data; diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 836f832..a8bda67 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -127,11 +127,11 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) #ifdef CONFIG_X86_32 switch (regno) { case GDB_SS: - if (!user_mode_vm(regs)) + if (!user_mode(regs)) *(unsigned long *)mem = __KERNEL_DS; break; case GDB_SP: - if (!user_mode_vm(regs)) + if (!user_mode(regs)) *(unsigned long *)mem = kernel_stack_pointer(regs); break; case GDB_GS: @@ -229,7 +229,10 @@ static void kgdb_correct_hw_break(void) bp->attr.bp_addr = breakinfo[breakno].addr; bp->attr.bp_len = breakinfo[breakno].len; bp->attr.bp_type = breakinfo[breakno].type; - info->address = breakinfo[breakno].addr; + if (breakinfo[breakno].type == X86_BREAKPOINT_EXECUTE) + info->address = ktla_ktva(breakinfo[breakno].addr); + else + info->address = breakinfo[breakno].addr; info->len = breakinfo[breakno].len; info->type = breakinfo[breakno].type; val = arch_install_hw_breakpoint(bp); @@ -476,12 +479,12 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, case 'k': /* clear the trace bit */ linux_regs->flags &= ~X86_EFLAGS_TF; - atomic_set(&kgdb_cpu_doing_single_step, -1); + atomic_set_unchecked(&kgdb_cpu_doing_single_step, -1); /* set the trace bit if we're stepping */ if (remcomInBuffer[0] == 's') { linux_regs->flags |= X86_EFLAGS_TF; - atomic_set(&kgdb_cpu_doing_single_step, + atomic_set_unchecked(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); } @@ -546,7 +549,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) switch (cmd) { case DIE_DEBUG: - if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { + if (atomic_read_unchecked(&kgdb_cpu_doing_single_step) != -1) { if (user_mode(regs)) return single_step_cont(regs, args); break; @@ -751,11 +754,11 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) #endif /* CONFIG_DEBUG_RODATA */ bpt->type = BP_BREAKPOINT; - err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, + err = probe_kernel_read(bpt->saved_instr, ktla_ktva((char *)bpt->bpt_addr), BREAK_INSTR_SIZE); if (err) return err; - err = probe_kernel_write((char *)bpt->bpt_addr, + err = probe_kernel_write(ktla_ktva((char *)bpt->bpt_addr), arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); #ifdef CONFIG_DEBUG_RODATA if (!err) @@ -768,7 +771,7 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) return -EBUSY; text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); - err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); + err = probe_kernel_read(opc, ktla_ktva((char *)bpt->bpt_addr), BREAK_INSTR_SIZE); if (err) return err; if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE)) @@ -793,13 +796,13 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) if (mutex_is_locked(&text_mutex)) goto knl_write; text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE); - err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE); + err = probe_kernel_read(opc, ktla_ktva((char *)bpt->bpt_addr), BREAK_INSTR_SIZE); if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE)) goto knl_write; return err; knl_write: #endif /* CONFIG_DEBUG_RODATA */ - return probe_kernel_write((char *)bpt->bpt_addr, + return probe_kernel_write(ktla_ktva((char *)bpt->bpt_addr), (char *)bpt->saved_instr, BREAK_INSTR_SIZE); } diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 211bce4..6e2580a 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -119,9 +119,12 @@ static void __kprobes __synthesize_relative_insn(void *from, void *to, u8 op) s32 raddr; } __packed *insn; - insn = (struct __arch_relative_insn *)from; + insn = (struct __arch_relative_insn *)ktla_ktva(from); + + pax_open_kernel(); insn->raddr = (s32)((long)(to) - ((long)(from) + 5)); insn->op = op; + pax_close_kernel(); } /* Insert a jump instruction at address 'from', which jumps to address 'to'.*/ @@ -164,7 +167,7 @@ int __kprobes can_boost(kprobe_opcode_t *opcodes) kprobe_opcode_t opcode; kprobe_opcode_t *orig_opcodes = opcodes; - if (search_exception_tables((unsigned long)opcodes)) + if (search_exception_tables(ktva_ktla((unsigned long)opcodes))) return 0; /* Page fault may occur on this address. */ retry: @@ -238,9 +241,9 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) * for the first byte, we can recover the original instruction * from it and kp->opcode. */ - memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + memcpy(buf, ktla_ktva(kp->addr), MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); buf[0] = kp->opcode; - return (unsigned long)buf; + return ktva_ktla((unsigned long)buf); } /* @@ -332,7 +335,9 @@ int __kprobes __copy_instruction(u8 *dest, u8 *src) /* Another subsystem puts a breakpoint, failed to recover */ if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) return 0; + pax_open_kernel(); memcpy(dest, insn.kaddr, insn.length); + pax_close_kernel(); #ifdef CONFIG_X86_64 if (insn_rip_relative(&insn)) { @@ -359,7 +364,9 @@ int __kprobes __copy_instruction(u8 *dest, u8 *src) return 0; } disp = (u8 *) dest + insn_offset_displacement(&insn); + pax_open_kernel(); *(s32 *) disp = (s32) newdisp; + pax_close_kernel(); } #endif return insn.length; @@ -498,7 +505,7 @@ setup_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *k * nor set current_kprobe, because it doesn't use single * stepping. */ - regs->ip = (unsigned long)p->ainsn.insn; + regs->ip = ktva_ktla((unsigned long)p->ainsn.insn); preempt_enable_no_resched(); return; } @@ -515,9 +522,9 @@ setup_singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *k regs->flags &= ~X86_EFLAGS_IF; /* single step inline if the instruction is an int3 */ if (p->opcode == BREAKPOINT_INSTRUCTION) - regs->ip = (unsigned long)p->addr; + regs->ip = ktla_ktva((unsigned long)p->addr); else - regs->ip = (unsigned long)p->ainsn.insn; + regs->ip = ktva_ktla((unsigned long)p->ainsn.insn); } /* @@ -596,7 +603,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) setup_singlestep(p, regs, kcb, 0); return 1; } - } else if (*addr != BREAKPOINT_INSTRUCTION) { + } else if (*(kprobe_opcode_t *)ktla_ktva((unsigned long)addr) != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right * after we hit it. Another cpu has removed @@ -642,6 +649,9 @@ static void __used __kprobes kretprobe_trampoline_holder(void) " movq %rax, 152(%rsp)\n" RESTORE_REGS_STRING " popfq\n" +#ifdef KERNEXEC_PLUGIN + " btsq $63,(%rsp)\n" +#endif #else " pushf\n" SAVE_REGS_STRING @@ -779,7 +789,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = stack_addr(regs); - unsigned long copy_ip = (unsigned long)p->ainsn.insn; + unsigned long copy_ip = ktva_ktla((unsigned long)p->ainsn.insn); unsigned long orig_ip = (unsigned long)p->addr; kprobe_opcode_t *insn = p->ainsn.insn; @@ -961,7 +971,7 @@ kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *d struct die_args *args = data; int ret = NOTIFY_DONE; - if (args->regs && user_mode_vm(args->regs)) + if (args->regs && user_mode(args->regs)) return ret; switch (val) { diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 76dc6f0..66bdfc3 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -79,6 +79,7 @@ found: /* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */ static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val) { + pax_open_kernel(); #ifdef CONFIG_X86_64 *addr++ = 0x48; *addr++ = 0xbf; @@ -86,6 +87,7 @@ static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long v *addr++ = 0xb8; #endif *(unsigned long *)addr = val; + pax_close_kernel(); } static void __used __kprobes kprobes_optinsn_template_holder(void) @@ -338,7 +340,7 @@ int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op) * Verify if the address gap is in 2GB range, because this uses * a relative jump. */ - rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE; + rel = (long)op->optinsn.insn - ktla_ktva((long)op->kp.addr) + RELATIVEJUMP_SIZE; if (abs(rel) > 0x7fffffff) return -ERANGE; @@ -353,16 +355,18 @@ int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op) op->optinsn.size = ret; /* Copy arch-dep-instance from template */ - memcpy(buf, &optprobe_template_entry, TMPL_END_IDX); + pax_open_kernel(); + memcpy(buf, ktla_ktva(&optprobe_template_entry), TMPL_END_IDX); + pax_close_kernel(); /* Set probe information */ synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op); /* Set probe function call */ - synthesize_relcall(buf + TMPL_CALL_IDX, optimized_callback); + synthesize_relcall(ktva_ktla(buf) + TMPL_CALL_IDX, optimized_callback); /* Set returning jmp instruction at the tail of out-of-line buffer */ - synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size, + synthesize_reljump(ktva_ktla(buf) + TMPL_END_IDX + op->optinsn.size, (u8 *)op->kp.addr + op->optinsn.size); flush_icache_range((unsigned long) buf, @@ -385,7 +389,7 @@ static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm, ((long)op->kp.addr + RELATIVEJUMP_SIZE)); /* Backup instructions which will be replaced by jump address */ - memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE, + memcpy(op->optinsn.copied_insn, ktla_ktva(op->kp.addr) + INT3_SIZE, RELATIVE_ADDR_SIZE); insn_buf[0] = RELATIVEJUMP_OPCODE; @@ -483,7 +487,7 @@ setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter) /* This kprobe is really able to run optimized path. */ op = container_of(p, struct optimized_kprobe, kp); /* Detour through copied instructions */ - regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX; + regs->ip = ktva_ktla((unsigned long)op->optinsn.insn) + TMPL_END_IDX; if (!reenter) reset_current_kprobe(); preempt_enable_no_resched(); diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index cd6d9a5..16245a4 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -455,7 +455,7 @@ static int __cpuinit kvm_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata kvm_cpu_notifier = { +static struct notifier_block kvm_cpu_notifier = { .notifier_call = kvm_cpu_notify, }; #endif diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index ebc9873..1b9724b 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c @@ -66,13 +66,13 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload) if (reload) { #ifdef CONFIG_SMP preempt_disable(); - load_LDT(pc); + load_LDT_nolock(pc); if (!cpumask_equal(mm_cpumask(current->mm), cpumask_of(smp_processor_id()))) smp_call_function(flush_ldt, current->mm, 1); preempt_enable(); #else - load_LDT(pc); + load_LDT_nolock(pc); #endif } if (oldsize) { @@ -94,7 +94,7 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old) return err; for (i = 0; i < old->size; i++) - write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE); + write_ldt_entry(new->ldt, i, old->ldt + i); return 0; } @@ -115,6 +115,24 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) retval = copy_ldt(&mm->context, &old_mm->context); mutex_unlock(&old_mm->context.lock); } + + if (tsk == current) { + mm->context.vdso = 0; + +#ifdef CONFIG_X86_32 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + mm->context.user_cs_base = 0UL; + mm->context.user_cs_limit = ~0UL; + +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) + cpus_clear(mm->context.cpu_user_cs_mask); +#endif + +#endif +#endif + + } + return retval; } @@ -229,6 +247,13 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) } } +#ifdef CONFIG_PAX_SEGMEXEC + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) { + error = -EINVAL; + goto out_unlock; + } +#endif + fill_ldt(&ldt, &ldt_info); if (oldmode) ldt.avl = 0; diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 5b19e4d..6476a76 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c @@ -26,7 +26,7 @@ #include #include -static void set_idt(void *newidt, __u16 limit) +static void set_idt(struct desc_struct *newidt, __u16 limit) { struct desc_ptr curidt; @@ -38,7 +38,7 @@ static void set_idt(void *newidt, __u16 limit) } -static void set_gdt(void *newgdt, __u16 limit) +static void set_gdt(struct desc_struct *newgdt, __u16 limit) { struct desc_ptr curgdt; @@ -216,7 +216,7 @@ void machine_kexec(struct kimage *image) } control_page = page_address(image->control_code_page); - memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); + memcpy(control_page, (void *)ktla_ktva((unsigned long)relocate_kernel), KEXEC_CONTROL_CODE_MAX_SIZE); relocate_kernel_ptr = control_page; page_list[PA_CONTROL_PAGE] = __pa(control_page); diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 22db92b..d546bec 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -513,7 +513,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __refdata mc_cpu_notifier = { +static struct notifier_block mc_cpu_notifier = { .notifier_call = mc_cpu_callback, }; diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 5fb2ceb..3ae90bb 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -293,13 +293,13 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device, static int get_ucode_user(void *to, const void *from, size_t n) { - return copy_from_user(to, from, n); + return copy_from_user(to, (const void __force_user *)from, n); } static enum ucode_state request_microcode_user(int cpu, const void __user *buf, size_t size) { - return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user); + return generic_load_microcode(cpu, (__force_kernel void *)buf, size, &get_ucode_user); } static void microcode_fini_cpu(int cpu) diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 216a4d7..228255a 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -43,15 +43,60 @@ do { \ } while (0) #endif -void *module_alloc(unsigned long size) +static inline void *__module_alloc(unsigned long size, pgprot_t prot) { - if (PAGE_ALIGN(size) > MODULES_LEN) + if (!size || PAGE_ALIGN(size) > MODULES_LEN) return NULL; return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, - GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC, + GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, prot, -1, __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 +#ifdef CONFIG_X86_32 +void *module_alloc_exec(unsigned long size) +{ + struct vm_struct *area; + + if (size == 0) + return NULL; + + area = __get_vm_area(size, VM_ALLOC, (unsigned long)&MODULES_EXEC_VADDR, (unsigned long)&MODULES_EXEC_END); + return area ? area->addr : NULL; +} +EXPORT_SYMBOL(module_alloc_exec); + +void module_free_exec(struct module *mod, void *module_region) +{ + vunmap(module_region); +} +EXPORT_SYMBOL(module_free_exec); +#else +void module_free_exec(struct module *mod, void *module_region) +{ + module_free(mod, module_region); +} +EXPORT_SYMBOL(module_free_exec); + +void *module_alloc_exec(unsigned long size) +{ + return __module_alloc(size, PAGE_KERNEL_RX); +} +EXPORT_SYMBOL(module_alloc_exec); +#endif +#endif + #ifdef CONFIG_X86_32 int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, @@ -62,14 +107,16 @@ int apply_relocate(Elf32_Shdr *sechdrs, unsigned int i; Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; Elf32_Sym *sym; - uint32_t *location; + uint32_t *plocation, location; DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; + plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; + location = (uint32_t)plocation; + if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR) + plocation = ktla_ktva((void *)plocation); /* This is the symbol it is referring to. Note that all undefined symbols have been resolved. */ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr @@ -78,11 +125,15 @@ int apply_relocate(Elf32_Shdr *sechdrs, switch (ELF32_R_TYPE(rel[i].r_info)) { case R_386_32: /* We add the value into the location given */ - *location += sym->st_value; + pax_open_kernel(); + *plocation += sym->st_value; + pax_close_kernel(); break; case R_386_PC32: /* Add the value, subtract its position */ - *location += sym->st_value - (uint32_t)location; + pax_open_kernel(); + *plocation += sym->st_value - location; + pax_close_kernel(); break; default: pr_err("%s: Unknown relocation: %u\n", @@ -127,21 +178,30 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, case R_X86_64_NONE: break; case R_X86_64_64: + pax_open_kernel(); *(u64 *)loc = val; + pax_close_kernel(); break; case R_X86_64_32: + pax_open_kernel(); *(u32 *)loc = val; + pax_close_kernel(); if (val != *(u32 *)loc) goto overflow; break; case R_X86_64_32S: + pax_open_kernel(); *(s32 *)loc = val; + pax_close_kernel(); if ((s64)val != *(s32 *)loc) goto overflow; break; case R_X86_64_PC32: val -= (u64)loc; + pax_open_kernel(); *(u32 *)loc = val; + pax_close_kernel(); + #if 0 if ((s64)val != *(s32 *)loc) goto overflow; diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index ce13049..e2e9c3c 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -233,7 +233,7 @@ static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block __refdata msr_class_cpu_notifier = { +static struct notifier_block msr_class_cpu_notifier = { .notifier_call = msr_class_cpu_callback, }; diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 6030805..2d33f21 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -105,7 +105,7 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2 return handled; } -int __register_nmi_handler(unsigned int type, struct nmiaction *action) +int __register_nmi_handler(unsigned int type, const struct nmiaction *action) { struct nmi_desc *desc = nmi_to_desc(type); unsigned long flags; @@ -129,9 +129,9 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action) * event confuses some handlers (kdump uses this flag) */ if (action->flags & NMI_FLAG_FIRST) - list_add_rcu(&action->list, &desc->head); + pax_list_add_rcu((struct list_head *)&action->list, &desc->head); else - list_add_tail_rcu(&action->list, &desc->head); + pax_list_add_tail_rcu((struct list_head *)&action->list, &desc->head); spin_unlock_irqrestore(&desc->lock, flags); return 0; @@ -154,7 +154,7 @@ void unregister_nmi_handler(unsigned int type, const char *name) if (!strcmp(n->name, name)) { WARN(in_nmi(), "Trying to free NMI (%s) from NMI context!\n", n->name); - list_del_rcu(&n->list); + pax_list_del_rcu((struct list_head *)&n->list); break; } } @@ -479,6 +479,17 @@ static inline void nmi_nesting_postprocess(void) dotraplinkage notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code) { + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + if (!user_mode(regs)) { + unsigned long cs = regs->cs & 0xFFFF; + unsigned long ip = ktva_ktla(regs->ip); + + if ((cs == __KERNEL_CS || cs == __KERNEXEC_KERNEL_CS) && ip <= (unsigned long)_etext) + regs->ip = ip; + } +#endif + nmi_nesting_preprocess(regs); nmi_enter(); diff --git a/arch/x86/kernel/nmi_selftest.c b/arch/x86/kernel/nmi_selftest.c index 6d9582e..f746287 100644 --- a/arch/x86/kernel/nmi_selftest.c +++ b/arch/x86/kernel/nmi_selftest.c @@ -43,7 +43,7 @@ static void __init init_nmi_testsuite(void) { /* trap all the unknown NMIs we may generate */ register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk", - __initdata); + __initconst); } static void __init cleanup_nmi_testsuite(void) @@ -66,7 +66,7 @@ static void __init test_nmi_ipi(struct cpumask *mask) unsigned long timeout; if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, - NMI_FLAG_FIRST, "nmi_selftest", __initdata)) { + NMI_FLAG_FIRST, "nmi_selftest", __initconst)) { nmi_fail = FAILURE; return; } diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c index 676b8c7..870ba04 100644 --- a/arch/x86/kernel/paravirt-spinlocks.c +++ b/arch/x86/kernel/paravirt-spinlocks.c @@ -13,7 +13,7 @@ default_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags) arch_spin_lock(lock); } -struct pv_lock_ops pv_lock_ops = { +struct pv_lock_ops pv_lock_ops __read_only = { #ifdef CONFIG_SMP .spin_is_locked = __ticket_spin_is_locked, .spin_is_contended = __ticket_spin_is_contended, diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index cd6de64..27c6af0 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -55,6 +55,9 @@ u64 _paravirt_ident_64(u64 x) { return x; } +#if defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE) +PV_CALLEE_SAVE_REGS_THUNK(_paravirt_ident_64); +#endif void __init default_banner(void) { @@ -147,15 +150,19 @@ unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf, if (opfunc == NULL) /* If there's no function, patch it with a ud2a (BUG) */ ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a)); - else if (opfunc == _paravirt_nop) + else if (opfunc == (void *)_paravirt_nop) /* If the operation is a nop, then nop the callsite */ ret = paravirt_patch_nop(); /* identity functions just return their single argument */ - else if (opfunc == _paravirt_ident_32) + else if (opfunc == (void *)_paravirt_ident_32) ret = paravirt_patch_ident_32(insnbuf, len); - else if (opfunc == _paravirt_ident_64) + else if (opfunc == (void *)_paravirt_ident_64) + ret = paravirt_patch_ident_64(insnbuf, len); +#if defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE) + else if (opfunc == (void *)__raw_callee_save__paravirt_ident_64) ret = paravirt_patch_ident_64(insnbuf, len); +#endif else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) || type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) || @@ -180,7 +187,7 @@ unsigned paravirt_patch_insns(void *insnbuf, unsigned len, if (insn_len > len || start == NULL) insn_len = len; else - memcpy(insnbuf, start, insn_len); + memcpy(insnbuf, ktla_ktva(start), insn_len); return insn_len; } @@ -304,7 +311,7 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) return this_cpu_read(paravirt_lazy_mode); } -struct pv_info pv_info = { +struct pv_info pv_info __read_only = { .name = "bare hardware", .paravirt_enabled = 0, .kernel_rpl = 0, @@ -315,16 +322,16 @@ struct pv_info pv_info = { #endif }; -struct pv_init_ops pv_init_ops = { +struct pv_init_ops pv_init_ops __read_only = { .patch = native_patch, }; -struct pv_time_ops pv_time_ops = { +struct pv_time_ops pv_time_ops __read_only = { .sched_clock = native_sched_clock, .steal_clock = native_steal_clock, }; -struct pv_irq_ops pv_irq_ops = { +struct pv_irq_ops pv_irq_ops __read_only = { .save_fl = __PV_IS_CALLEE_SAVE(native_save_fl), .restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl), .irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable), @@ -336,7 +343,7 @@ struct pv_irq_ops pv_irq_ops = { #endif }; -struct pv_cpu_ops pv_cpu_ops = { +struct pv_cpu_ops pv_cpu_ops __read_only = { .cpuid = native_cpuid, .get_debugreg = native_get_debugreg, .set_debugreg = native_set_debugreg, @@ -394,21 +401,26 @@ struct pv_cpu_ops pv_cpu_ops = { .end_context_switch = paravirt_nop, }; -struct pv_apic_ops pv_apic_ops = { +struct pv_apic_ops pv_apic_ops __read_only= { #ifdef CONFIG_X86_LOCAL_APIC .startup_ipi_hook = paravirt_nop, #endif }; -#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) +#ifdef CONFIG_X86_32 +#ifdef CONFIG_X86_PAE +/* 64-bit pagetable entries */ +#define PTE_IDENT PV_CALLEE_SAVE(_paravirt_ident_64) +#else /* 32-bit pagetable entries */ #define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_32) +#endif #else /* 64-bit pagetable entries */ #define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_64) #endif -struct pv_mmu_ops pv_mmu_ops = { +struct pv_mmu_ops pv_mmu_ops __read_only = { .read_cr2 = native_read_cr2, .write_cr2 = native_write_cr2, @@ -458,6 +470,7 @@ struct pv_mmu_ops pv_mmu_ops = { .make_pud = PTE_IDENT, .set_pgd = native_set_pgd, + .set_pgd_batched = native_set_pgd_batched, #endif #endif /* PAGETABLE_LEVELS >= 3 */ @@ -478,6 +491,12 @@ struct pv_mmu_ops pv_mmu_ops = { }, .set_fixmap = native_set_fixmap, + +#ifdef CONFIG_PAX_KERNEXEC + .pax_open_kernel = native_pax_open_kernel, + .pax_close_kernel = native_pax_close_kernel, +#endif + }; EXPORT_SYMBOL_GPL(pv_time_ops); diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 299d493..2ccb0ee 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -1339,7 +1339,7 @@ static void __init get_tce_space_from_tar(void) tce_space = be64_to_cpu(readq(target)); tce_space = tce_space & TAR_SW_BITS; - tce_space = tce_space & (~specified_table_size); + tce_space = tce_space & (~(unsigned long)specified_table_size); info->tce_space = (u64 *)__va(tce_space); } } diff --git a/arch/x86/kernel/pci-iommu_table.c b/arch/x86/kernel/pci-iommu_table.c index 35ccf75..7a15747 100644 --- a/arch/x86/kernel/pci-iommu_table.c +++ b/arch/x86/kernel/pci-iommu_table.c @@ -2,7 +2,7 @@ #include #include #include - +#include #define DEBUG 1 diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c index 6c483ba..d10ce2f 100644 --- a/arch/x86/kernel/pci-swiotlb.c +++ b/arch/x86/kernel/pci-swiotlb.c @@ -32,7 +32,7 @@ static void x86_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_addr, struct dma_attrs *attrs) { - swiotlb_free_coherent(dev, size, vaddr, dma_addr); + swiotlb_free_coherent(dev, size, vaddr, dma_addr, attrs); } static struct dma_map_ops swiotlb_dma_ops = { diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 81a5f5e..20f8b58 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -36,7 +36,8 @@ * section. Since TSS's are completely CPU-local, we want them * on exact cacheline boundaries, to eliminate cacheline ping-pong. */ -DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; +struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS }; +EXPORT_SYMBOL(init_tss); #ifdef CONFIG_X86_64 static DEFINE_PER_CPU(unsigned char, is_idle); @@ -92,7 +93,7 @@ void arch_task_cache_init(void) task_xstate_cachep = kmem_cache_create("task_xstate", xstate_size, __alignof__(union thread_xstate), - SLAB_PANIC | SLAB_NOTRACK, NULL); + SLAB_PANIC | SLAB_NOTRACK | SLAB_USERCOPY, NULL); } /* @@ -105,7 +106,7 @@ void exit_thread(void) unsigned long *bp = t->io_bitmap_ptr; if (bp) { - struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); + struct tss_struct *tss = init_tss + get_cpu(); t->io_bitmap_ptr = NULL; clear_thread_flag(TIF_IO_BITMAP); @@ -125,6 +126,9 @@ void flush_thread(void) { struct task_struct *tsk = current; +#if defined(CONFIG_X86_32) && !defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_PAX_MEMORY_UDEREF) + loadsegment(gs, 0); +#endif flush_ptrace_hw_breakpoint(tsk); memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); drop_init_fpu(tsk); @@ -271,7 +275,7 @@ static void __exit_idle(void) void exit_idle(void) { /* idle loop has pid 0 */ - if (current->pid) + if (task_pid_nr(current)) return; __exit_idle(); } @@ -327,7 +331,7 @@ bool xen_set_default_idle(void) return ret; } #endif -void stop_this_cpu(void *dummy) +__noreturn void stop_this_cpu(void *dummy) { local_irq_disable(); /* @@ -456,16 +460,37 @@ static int __init idle_setup(char *str) } early_param("idle", idle_setup); -unsigned long arch_align_stack(unsigned long sp) +#ifdef CONFIG_PAX_RANDKSTACK +void pax_randomize_kstack(struct pt_regs *regs) { - if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) - sp -= get_random_int() % 8192; - return sp & ~0xf; -} + struct thread_struct *thread = ¤t->thread; + unsigned long time; -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; -} + if (!randomize_va_space) + return; + + if (v8086_mode(regs)) + return; + rdtscl(time); + + /* P4 seems to return a 0 LSB, ignore it */ +#ifdef CONFIG_MPENTIUM4 + time &= 0x3EUL; + time <<= 2; +#elif defined(CONFIG_X86_64) + time &= 0xFUL; + time <<= 4; +#else + time &= 0x1FUL; + time <<= 3; +#endif + + thread->sp0 ^= time; + load_sp0(init_tss + smp_processor_id(), thread); + +#ifdef CONFIG_X86_64 + this_cpu_write(kernel_stack, thread->sp0); +#endif +} +#endif diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 7305f7d..22f73d6 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -65,6 +65,7 @@ asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); unsigned long thread_saved_pc(struct task_struct *tsk) { return ((unsigned long *)tsk->thread.sp)[3]; +//XXX return tsk->thread.eip; } void __show_regs(struct pt_regs *regs, int all) @@ -74,19 +75,18 @@ void __show_regs(struct pt_regs *regs, int all) unsigned long sp; unsigned short ss, gs; - if (user_mode_vm(regs)) { + if (user_mode(regs)) { sp = regs->sp; ss = regs->ss & 0xffff; - gs = get_user_gs(regs); } else { sp = kernel_stack_pointer(regs); savesegment(ss, ss); - savesegment(gs, gs); } + gs = get_user_gs(regs); printk(KERN_DEFAULT "EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n", (u16)regs->cs, regs->ip, regs->flags, - smp_processor_id()); + raw_smp_processor_id()); print_symbol("EIP is at %s\n", regs->ip); printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", @@ -128,20 +128,21 @@ void release_thread(struct task_struct *dead_task) int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, struct task_struct *p) { - struct pt_regs *childregs = task_pt_regs(p); + struct pt_regs *childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8; struct task_struct *tsk; int err; p->thread.sp = (unsigned long) childregs; p->thread.sp0 = (unsigned long) (childregs+1); + p->tinfo.lowest_stack = (unsigned long)task_stack_page(p); if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ memset(childregs, 0, sizeof(struct pt_regs)); p->thread.ip = (unsigned long) ret_from_kernel_thread; - task_user_gs(p) = __KERNEL_STACK_CANARY; - childregs->ds = __USER_DS; - childregs->es = __USER_DS; + savesegment(gs, childregs->gs); + childregs->ds = __KERNEL_DS; + childregs->es = __KERNEL_DS; childregs->fs = __KERNEL_PERCPU; childregs->bx = sp; /* function */ childregs->bp = arg; @@ -248,7 +249,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; int cpu = smp_processor_id(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = init_tss + cpu; fpu_switch_t fpu; /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ @@ -272,6 +273,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ lazy_save_gs(prev->gs); +#ifdef CONFIG_PAX_MEMORY_UDEREF + __set_fs(task_thread_info(next_p)->addr_limit); +#endif + /* * Load the per-thread Thread-Local Storage descriptor. */ @@ -302,6 +307,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ arch_end_context_switch(next_p); + this_cpu_write(current_task, next_p); + this_cpu_write(current_tinfo, &next_p->tinfo); + /* * Restore %gs if needed (which is common) */ @@ -310,8 +318,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) switch_fpu_finish(next_p, fpu); - this_cpu_write(current_task, next_p); - return prev_p; } @@ -341,4 +347,3 @@ unsigned long get_wchan(struct task_struct *p) } while (count++ < 16); return 0; } - diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 355ae06..560fbbe 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -151,10 +151,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, struct pt_regs *childregs; struct task_struct *me = current; - p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE; + p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE - 16; childregs = task_pt_regs(p); p->thread.sp = (unsigned long) childregs; p->thread.usersp = me->thread.usersp; + p->tinfo.lowest_stack = (unsigned long)task_stack_page(p); set_tsk_thread_flag(p, TIF_FORK); p->fpu_counter = 0; p->thread.io_bitmap_ptr = NULL; @@ -165,6 +166,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; savesegment(es, p->thread.es); savesegment(ds, p->thread.ds); + savesegment(ss, p->thread.ss); + BUG_ON(p->thread.ss == __UDEREF_KERNEL_DS); memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); if (unlikely(p->flags & PF_KTHREAD)) { @@ -273,7 +276,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) struct thread_struct *prev = &prev_p->thread; struct thread_struct *next = &next_p->thread; int cpu = smp_processor_id(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = init_tss + cpu; unsigned fsindex, gsindex; fpu_switch_t fpu; @@ -296,6 +299,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) if (unlikely(next->ds | prev->ds)) loadsegment(ds, next->ds); + savesegment(ss, prev->ss); + if (unlikely(next->ss != prev->ss)) + loadsegment(ss, next->ss); /* We must save %fs and %gs before load_TLS() because * %fs and %gs may be cleared by load_TLS(). @@ -355,10 +361,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) prev->usersp = this_cpu_read(old_rsp); this_cpu_write(old_rsp, next->usersp); this_cpu_write(current_task, next_p); + this_cpu_write(current_tinfo, &next_p->tinfo); - this_cpu_write(kernel_stack, - (unsigned long)task_stack_page(next_p) + - THREAD_SIZE - KERNEL_STACK_OFFSET); + this_cpu_write(kernel_stack, next->sp0); /* * Now maybe reload the debug registers and handle I/O bitmaps @@ -427,12 +432,11 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; stack = (unsigned long)task_stack_page(p); - if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) + if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE-16-sizeof(u64)) return 0; fp = *(u64 *)(p->thread.sp); do { - if (fp < (unsigned long)stack || - fp >= (unsigned long)stack+THREAD_SIZE) + if (fp < stack || fp > stack+THREAD_SIZE-16-sizeof(u64)) return 0; ip = *(u64 *)(fp+8); if (!in_sched_functions(ip)) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 29a8120..a50b5ee 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -184,14 +184,13 @@ unsigned long kernel_stack_pointer(struct pt_regs *regs) { unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); unsigned long sp = (unsigned long)®s->sp; - struct thread_info *tinfo; - if (context == (sp & ~(THREAD_SIZE - 1))) + if (context == ((sp + 8) & ~(THREAD_SIZE - 1))) return sp; - tinfo = (struct thread_info *)context; - if (tinfo->previous_esp) - return tinfo->previous_esp; + sp = *(unsigned long *)context; + if (sp) + return sp; return (unsigned long)regs; } @@ -588,7 +587,7 @@ static void ptrace_triggered(struct perf_event *bp, static unsigned long ptrace_get_dr7(struct perf_event *bp[]) { int i; - int dr7 = 0; + unsigned long dr7 = 0; struct arch_hw_breakpoint *info; for (i = 0; i < HBP_NUM; i++) { @@ -856,7 +855,7 @@ long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { int ret; - unsigned long __user *datap = (unsigned long __user *)data; + unsigned long __user *datap = (__force unsigned long __user *)data; switch (request) { /* read the word at location addr in the USER area. */ @@ -941,14 +940,14 @@ long arch_ptrace(struct task_struct *child, long request, if ((int) addr < 0) return -EIO; ret = do_get_thread_area(child, addr, - (struct user_desc __user *)data); + (__force struct user_desc __user *) data); break; case PTRACE_SET_THREAD_AREA: if ((int) addr < 0) return -EIO; ret = do_set_thread_area(child, addr, - (struct user_desc __user *)data, 0); + (__force struct user_desc __user *) data, 0); break; #endif @@ -1326,7 +1325,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, #ifdef CONFIG_X86_64 -static struct user_regset x86_64_regsets[] __read_mostly = { +static user_regset_no_const x86_64_regsets[] __read_only = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, .n = sizeof(struct user_regs_struct) / sizeof(long), @@ -1367,7 +1366,7 @@ static const struct user_regset_view user_x86_64_view = { #endif /* CONFIG_X86_64 */ #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION -static struct user_regset x86_32_regsets[] __read_mostly = { +static user_regset_no_const x86_32_regsets[] __read_only = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, .n = sizeof(struct user_regs_struct32) / sizeof(u32), @@ -1420,7 +1419,7 @@ static const struct user_regset_view user_x86_32_view = { */ u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; -void update_regset_xstate_info(unsigned int size, u64 xstate_mask) +void __init update_regset_xstate_info(unsigned int size, u64 xstate_mask) { #ifdef CONFIG_X86_64 x86_64_regsets[REGSET_XSTATE].n = size / sizeof(u64); @@ -1455,7 +1454,7 @@ static void fill_sigtrap_info(struct task_struct *tsk, memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; info->si_code = si_code; - info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL; + info->si_addr = user_mode(regs) ? (__force void __user *)regs->ip : NULL; } void user_single_step_siginfo(struct task_struct *tsk, @@ -1484,6 +1483,10 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, # define IS_IA32 0 #endif +#ifdef CONFIG_GRKERNSEC_SETXID +extern void gr_delayed_cred_worker(void); +#endif + /* * We must return the syscall number to actually look up in the table. * This can be -1L to skip running any syscall at all. @@ -1494,6 +1497,11 @@ long syscall_trace_enter(struct pt_regs *regs) user_exit(); +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + /* * If we stepped into a sysenter/syscall insn, it trapped in * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. @@ -1549,6 +1557,11 @@ void syscall_trace_leave(struct pt_regs *regs) */ user_exit(); +#ifdef CONFIG_GRKERNSEC_SETXID + if (unlikely(test_and_clear_thread_flag(TIF_GRSEC_SETXID))) + gr_delayed_cred_worker(); +#endif + audit_syscall_exit(regs); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index 2cb9470..ff1fd80 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c @@ -43,11 +43,11 @@ unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src) return pv_tsc_khz; } -static atomic64_t last_value = ATOMIC64_INIT(0); +static atomic64_unchecked_t last_value = ATOMIC64_INIT(0); void pvclock_resume(void) { - atomic64_set(&last_value, 0); + atomic64_set_unchecked(&last_value, 0); } u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src) @@ -92,11 +92,11 @@ cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src) * updating at the same time, and one of them could be slightly behind, * making the assumption that last_value always go forward fail to hold. */ - last = atomic64_read(&last_value); + last = atomic64_read_unchecked(&last_value); do { if (ret < last) return last; - last = atomic64_cmpxchg(&last_value, last, ret); + last = atomic64_cmpxchg_unchecked(&last_value, last, ret); } while (unlikely(last != ret)); return ret; diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 76fa1e9..abf09ea 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -36,7 +36,7 @@ void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); static const struct desc_ptr no_idt = {}; -static int reboot_mode; +static unsigned short reboot_mode; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; @@ -157,6 +157,11 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) void __noreturn machine_real_restart(unsigned int type) { + +#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF)) + struct desc_struct *gdt; +#endif + local_irq_disable(); /* @@ -184,7 +189,29 @@ void __noreturn machine_real_restart(unsigned int type) /* Jump to the identity-mapped low memory code */ #ifdef CONFIG_X86_32 - asm volatile("jmpl *%0" : : + +#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) + gdt = get_cpu_gdt_table(smp_processor_id()); + pax_open_kernel(); +#ifdef CONFIG_PAX_MEMORY_UDEREF + gdt[GDT_ENTRY_KERNEL_DS].type = 3; + gdt[GDT_ENTRY_KERNEL_DS].limit = 0xf; + loadsegment(ds, __KERNEL_DS); + loadsegment(es, __KERNEL_DS); + loadsegment(ss, __KERNEL_DS); +#endif +#ifdef CONFIG_PAX_KERNEXEC + gdt[GDT_ENTRY_KERNEL_CS].base0 = 0; + gdt[GDT_ENTRY_KERNEL_CS].base1 = 0; + gdt[GDT_ENTRY_KERNEL_CS].base2 = 0; + gdt[GDT_ENTRY_KERNEL_CS].limit0 = 0xffff; + gdt[GDT_ENTRY_KERNEL_CS].limit = 0xf; + gdt[GDT_ENTRY_KERNEL_CS].g = 1; +#endif + pax_close_kernel(); +#endif + + asm volatile("ljmpl *%0" : : "rm" (real_mode_header->machine_real_restart_asm), "a" (type)); #else @@ -531,7 +558,7 @@ void __attribute__((weak)) mach_reboot_fixups(void) * try to force a triple fault and then cycle between hitting the keyboard * controller and doing that */ -static void native_machine_emergency_restart(void) +static void __noreturn native_machine_emergency_restart(void) { int i; int attempt = 0; @@ -654,13 +681,13 @@ void native_machine_shutdown(void) #endif } -static void __machine_emergency_restart(int emergency) +static void __noreturn __machine_emergency_restart(int emergency) { reboot_emergency = emergency; machine_ops.emergency_restart(); } -static void native_machine_restart(char *__unused) +static void __noreturn native_machine_restart(char *__unused) { pr_notice("machine restart\n"); @@ -669,7 +696,7 @@ static void native_machine_restart(char *__unused) __machine_emergency_restart(0); } -static void native_machine_halt(void) +static void __noreturn native_machine_halt(void) { /* Stop other cpus and apics */ machine_shutdown(); @@ -679,7 +706,7 @@ static void native_machine_halt(void) stop_this_cpu(NULL); } -static void native_machine_power_off(void) +static void __noreturn native_machine_power_off(void) { if (pm_power_off) { if (!reboot_force) @@ -688,9 +715,10 @@ static void native_machine_power_off(void) } /* A fallback in case there is no PM info available */ tboot_shutdown(TB_SHUTDOWN_HALT); + unreachable(); } -struct machine_ops machine_ops = { +struct machine_ops machine_ops __read_only = { .power_off = native_machine_power_off, .shutdown = native_machine_shutdown, .emergency_restart = native_machine_emergency_restart, diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index c8e41e9..64049ef 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c @@ -57,7 +57,7 @@ struct device_fixup { unsigned int vendor; unsigned int device; void (*reboot_fixup)(struct pci_dev *); -}; +} __do_const; /* * PCI ids solely used for fixups_table go here diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index f2bb9c9..bed145d7 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -11,6 +11,7 @@ #include #include #include +#include /* * Must be relocatable PIC code callable as a C function @@ -167,6 +168,7 @@ identity_mapped: xorq %r14, %r14 xorq %r15, %r15 + pax_force_retaddr 0, 1 ret 1: diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 56f7fcf..2cfe4f1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -110,6 +110,7 @@ #include #include #include +#include /* * max_low_pfn_mapped: highest direct mapped pfn under 4GB @@ -205,12 +206,50 @@ EXPORT_SYMBOL(boot_cpu_data); #endif -#if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64) -unsigned long mmu_cr4_features; +#ifdef CONFIG_X86_64 +unsigned long mmu_cr4_features __read_only = X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE; +#elif defined(CONFIG_X86_PAE) +unsigned long mmu_cr4_features __read_only = X86_CR4_PAE; #else -unsigned long mmu_cr4_features = X86_CR4_PAE; +unsigned long mmu_cr4_features __read_only; #endif +void set_in_cr4(unsigned long mask) +{ + unsigned long cr4 = read_cr4(); + + if ((cr4 & mask) == mask && cr4 == mmu_cr4_features) + return; + + pax_open_kernel(); + mmu_cr4_features |= mask; + pax_close_kernel(); + + if (trampoline_cr4_features) + *trampoline_cr4_features = mmu_cr4_features; + cr4 |= mask; + write_cr4(cr4); +} +EXPORT_SYMBOL(set_in_cr4); + +void clear_in_cr4(unsigned long mask) +{ + unsigned long cr4 = read_cr4(); + + if (!(cr4 & mask) && cr4 == mmu_cr4_features) + return; + + pax_open_kernel(); + mmu_cr4_features &= ~mask; + pax_close_kernel(); + + if (trampoline_cr4_features) + *trampoline_cr4_features = mmu_cr4_features; + cr4 &= ~mask; + write_cr4(cr4); +} +EXPORT_SYMBOL(clear_in_cr4); + /* Boot loader ID and version as integers, for the benefit of proc_dointvec */ int bootloader_type, bootloader_version; @@ -444,7 +483,7 @@ static void __init parse_setup_data(void) switch (data->type) { case SETUP_E820_EXT: - parse_e820_ext(data); + parse_e820_ext((struct setup_data __force_kernel *)data); break; case SETUP_DTB: add_dtb(pa_data); @@ -771,7 +810,7 @@ static void __init trim_bios_range(void) * area (640->1Mb) as ram even though it is not. * take them out. */ - e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); + e820_remove_range(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS, E820_RAM, 1); sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } @@ -779,7 +818,7 @@ static void __init trim_bios_range(void) /* called before trim_bios_range() to spare extra sanitize */ static void __init e820_add_kernel_range(void) { - u64 start = __pa_symbol(_text); + u64 start = __pa_symbol(ktla_ktva(_text)); u64 size = __pa_symbol(_end) - start; /* @@ -841,8 +880,12 @@ static void __init trim_low_memory_range(void) void __init setup_arch(char **cmdline_p) { +#ifdef CONFIG_X86_32 + memblock_reserve(LOAD_PHYSICAL_ADDR, __pa_symbol(__bss_stop) - LOAD_PHYSICAL_ADDR); +#else memblock_reserve(__pa_symbol(_text), (unsigned long)__bss_stop - (unsigned long)_text); +#endif early_reserve_initrd(); @@ -934,14 +977,14 @@ void __init setup_arch(char **cmdline_p) if (!boot_params.hdr.root_flags) root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; + init_mm.start_code = ktla_ktva((unsigned long) _text); + init_mm.end_code = ktla_ktva((unsigned long) _etext); init_mm.end_data = (unsigned long) _edata; init_mm.brk = _brk_end; - code_resource.start = __pa_symbol(_text); - code_resource.end = __pa_symbol(_etext)-1; - data_resource.start = __pa_symbol(_etext); + code_resource.start = __pa_symbol(ktla_ktva(_text)); + code_resource.end = __pa_symbol(ktla_ktva(_etext))-1; + data_resource.start = __pa_symbol(_sdata); data_resource.end = __pa_symbol(_edata)-1; bss_resource.start = __pa_symbol(__bss_start); bss_resource.end = __pa_symbol(__bss_stop)-1; diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 5cdff03..80fa283 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -21,19 +21,17 @@ #include #include -DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number); +#ifdef CONFIG_SMP +DEFINE_PER_CPU_READ_MOSTLY(unsigned int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); +#endif -#ifdef CONFIG_X86_64 #define BOOT_PERCPU_OFFSET ((unsigned long)__per_cpu_load) -#else -#define BOOT_PERCPU_OFFSET 0 -#endif DEFINE_PER_CPU(unsigned long, this_cpu_off) = BOOT_PERCPU_OFFSET; EXPORT_PER_CPU_SYMBOL(this_cpu_off); -unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { +unsigned long __per_cpu_offset[NR_CPUS] __read_only = { [0 ... NR_CPUS-1] = BOOT_PERCPU_OFFSET, }; EXPORT_SYMBOL(__per_cpu_offset); @@ -66,7 +64,7 @@ static bool __init pcpu_need_numa(void) { #ifdef CONFIG_NEED_MULTIPLE_NODES pg_data_t *last = NULL; - unsigned int cpu; + int cpu; for_each_possible_cpu(cpu) { int node = early_cpu_to_node(cpu); @@ -155,10 +153,10 @@ static inline void setup_percpu_segment(int cpu) { #ifdef CONFIG_X86_32 struct desc_struct gdt; + unsigned long base = per_cpu_offset(cpu); - pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF, - 0x2 | DESCTYPE_S, 0x8); - gdt.s = 1; + pack_descriptor(&gdt, base, (VMALLOC_END - base - 1) >> PAGE_SHIFT, + 0x83 | DESCTYPE_S, 0xC); write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); #endif @@ -219,6 +217,11 @@ void __init setup_per_cpu_areas(void) /* alrighty, percpu areas up and running */ delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; for_each_possible_cpu(cpu) { +#ifdef CONFIG_CC_STACKPROTECTOR +#ifdef CONFIG_X86_32 + unsigned long canary = per_cpu(stack_canary.canary, cpu); +#endif +#endif per_cpu_offset(cpu) = delta + pcpu_unit_offsets[cpu]; per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); per_cpu(cpu_number, cpu) = cpu; @@ -259,6 +262,12 @@ void __init setup_per_cpu_areas(void) */ set_cpu_numa_node(cpu, early_cpu_to_node(cpu)); #endif +#ifdef CONFIG_CC_STACKPROTECTOR +#ifdef CONFIG_X86_32 + if (!cpu) + per_cpu(stack_canary.canary, cpu) = canary; +#endif +#endif /* * Up to this point, the boot CPU has been using .init.data * area. Reload any changed state for the boot CPU. diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 087ab2a..f798055 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -196,7 +196,7 @@ static unsigned long align_sigframe(unsigned long sp) * Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ - sp = ((sp + 4) & -16ul) - 4; + sp = ((sp - 12) & -16ul) - 4; #else /* !CONFIG_X86_32 */ sp = round_down(sp, 16) - 8; #endif @@ -304,9 +304,9 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set, } if (current->mm->context.vdso) - restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); + restorer = (__force void __user *)VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); else - restorer = &frame->retcode; + restorer = (void __user *)&frame->retcode; if (ksig->ka.sa.sa_flags & SA_RESTORER) restorer = ksig->ka.sa.sa_restorer; @@ -320,7 +320,7 @@ __setup_frame(int sig, struct ksignal *ksig, sigset_t *set, * reasons and because gdb uses it as a signature to notice * signal handler stack frames. */ - err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode); + err |= __put_user(*((u64 *)&retcode), (u64 __user *)frame->retcode); if (err) return -EFAULT; @@ -367,7 +367,10 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, save_altstack_ex(&frame->uc.uc_stack, regs->sp); /* Set up to return from userspace. */ - restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); + if (current->mm->context.vdso) + restorer = (__force void __user *)VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); + else + restorer = (void __user *)&frame->retcode; if (ksig->ka.sa.sa_flags & SA_RESTORER) restorer = ksig->ka.sa.sa_restorer; put_user_ex(restorer, &frame->pretcode); @@ -379,7 +382,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, * reasons and because gdb uses it as a signature to notice * signal handler stack frames. */ - put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); + put_user_ex(*((u64 *)&rt_retcode), (u64 __user *)frame->retcode); } put_user_catch(err); err |= copy_siginfo_to_user(&frame->info, &ksig->info); @@ -615,7 +618,12 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) { int usig = signr_convert(ksig->sig); sigset_t *set = sigmask_to_save(); - compat_sigset_t *cset = (compat_sigset_t *) set; + sigset_t sigcopy; + compat_sigset_t *cset; + + sigcopy = *set; + + cset = (compat_sigset_t *) &sigcopy; /* Set up the stack frame */ if (is_ia32_frame()) { @@ -626,7 +634,7 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) } else if (is_x32_frame()) { return x32_setup_rt_frame(ksig, cset, regs); } else { - return __setup_rt_frame(ksig->sig, ksig, set, regs); + return __setup_rt_frame(ksig->sig, ksig, &sigcopy, regs); } } diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 48d2b7d..90d328a 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -285,7 +285,7 @@ static int __init nonmi_ipi_setup(char *str) __setup("nonmi_ipi", nonmi_ipi_setup); -struct smp_ops smp_ops = { +struct smp_ops smp_ops __read_only = { .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, .smp_prepare_cpus = native_smp_prepare_cpus, .smp_cpus_done = native_smp_cpus_done, diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index bfd348e..914f323 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -251,14 +251,18 @@ notrace static void __cpuinit start_secondary(void *unused) enable_start_cpu0 = 0; -#ifdef CONFIG_X86_32 + /* otherwise gcc will move up smp_processor_id before the cpu_init */ + barrier(); + /* switch away from the initial page table */ +#ifdef CONFIG_PAX_PER_CPU_PGD + load_cr3(get_cpu_pgd(smp_processor_id(), kernel)); + __flush_tlb_all(); +#elif defined(CONFIG_X86_32) load_cr3(swapper_pg_dir); __flush_tlb_all(); #endif - /* otherwise gcc will move up smp_processor_id before the cpu_init */ - barrier(); /* * Check TSC synchronization with the BP: */ @@ -748,6 +752,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) idle->thread.sp = (unsigned long) (((struct pt_regs *) (THREAD_SIZE + task_stack_page(idle))) - 1); per_cpu(current_task, cpu) = idle; + per_cpu(current_tinfo, cpu) = &idle->tinfo; #ifdef CONFIG_X86_32 /* Stack for startup_32 can be just as for start_secondary onwards */ @@ -755,11 +760,13 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) #else clear_tsk_thread_flag(idle, TIF_FORK); initial_gs = per_cpu_offset(cpu); - per_cpu(kernel_stack, cpu) = - (unsigned long)task_stack_page(idle) - - KERNEL_STACK_OFFSET + THREAD_SIZE; + per_cpu(kernel_stack, cpu) = (unsigned long)task_stack_page(idle) - 16 + THREAD_SIZE; #endif + + pax_open_kernel(); early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); + pax_close_kernel(); + initial_code = (unsigned long)start_secondary; stack_start = idle->thread.sp; @@ -908,6 +915,15 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) /* the FPU context is blank, nobody can own it */ __cpu_disable_lazy_restore(cpu); +#ifdef CONFIG_PAX_PER_CPU_PGD + clone_pgd_range(get_cpu_pgd(cpu, kernel) + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); + clone_pgd_range(get_cpu_pgd(cpu, user) + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); +#endif + err = do_boot_cpu(apicid, cpu, tidle); if (err) { pr_debug("do_boot_cpu failed %d\n", err); diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 9b4d51d..5d28b58 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -27,10 +27,10 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re struct desc_struct *desc; unsigned long base; - seg &= ~7UL; + seg >>= 3; mutex_lock(&child->mm->context.lock); - if (unlikely((seg >> 3) >= child->mm->context.size)) + if (unlikely(seg >= child->mm->context.size)) addr = -1L; /* bogus selector, access would fault */ else { desc = child->mm->context.ldt + seg; @@ -42,7 +42,8 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re addr += base; } mutex_unlock(&child->mm->context.lock); - } + } else if (seg == __KERNEL_CS || seg == __KERNEXEC_KERNEL_CS) + addr = ktla_ktva(addr); return addr; } @@ -53,6 +54,9 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs) unsigned char opcode[15]; unsigned long addr = convert_ip_to_linear(child, regs); + if (addr == -EINVAL) + return 0; + copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); for (i = 0; i < copied; i++) { switch (opcode[i]) { diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c new file mode 100644 index 0000000..5877189 --- /dev/null +++ b/arch/x86/kernel/sys_i386_32.c @@ -0,0 +1,189 @@ +/* + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/i386 + * platform. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) +{ + unsigned long pax_task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) + pax_task_size = SEGMEXEC_TASK_SIZE; +#endif + + if (flags & MAP_FIXED) + if (len > pax_task_size || addr > pax_task_size - len) + return -EINVAL; + + return 0; +} + +/* + * Align a virtual address to avoid aliasing in the I$ on AMD F15h. + */ +static unsigned long get_align_mask(void) +{ + if (va_align.flags < 0 || !(va_align.flags & ALIGN_VA_32)) + return 0; + + if (!(current->flags & PF_RANDOMIZE)) + return 0; + + return va_align.mask; +} + +unsigned long +arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long pax_task_size = TASK_SIZE; + struct vm_unmapped_area_info info; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + pax_task_size = SEGMEXEC_TASK_SIZE; +#endif + + pax_task_size -= PAGE_SIZE; + + if (len > pax_task_size) + return -ENOMEM; + + if (flags & MAP_FIXED) + return addr; + +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + + if (addr) { + addr = PAGE_ALIGN(addr); + if (pax_task_size - len >= addr) { + vma = find_vma(mm, addr); + if (check_heap_stack_gap(vma, addr, len, offset)) + return addr; + } + } + + info.flags = 0; + info.length = len; + info.align_mask = filp ? get_align_mask() : 0; + info.align_offset = pgoff << PAGE_SHIFT; + info.threadstack_offset = offset; + +#ifdef CONFIG_PAX_PAGEEXEC + if (!(__supported_pte_mask & _PAGE_NX) && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE)) { + info.low_limit = 0x00110000UL; + info.high_limit = mm->start_code; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += mm->delta_mmap & 0x03FFF000UL; +#endif + + if (info.low_limit < info.high_limit) { + addr = vm_unmapped_area(&info); + if (!IS_ERR_VALUE(addr)) + return addr; + } + } else +#endif + + info.low_limit = mm->mmap_base; + info.high_limit = pax_task_size; + + return vm_unmapped_area(&info); +} + +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) +{ + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0, pax_task_size = TASK_SIZE; + struct vm_unmapped_area_info info; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + pax_task_size = SEGMEXEC_TASK_SIZE; +#endif + + pax_task_size -= PAGE_SIZE; + + /* requested length too big for entire address space */ + if (len > pax_task_size) + return -ENOMEM; + + if (flags & MAP_FIXED) + return addr; + +#ifdef CONFIG_PAX_PAGEEXEC + if (!(__supported_pte_mask & _PAGE_NX) && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE)) + goto bottomup; +#endif + +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); + if (pax_task_size - len >= addr) { + vma = find_vma(mm, addr); + if (check_heap_stack_gap(vma, addr, len, offset)) + return addr; + } + } + + info.flags = VM_UNMAPPED_AREA_TOPDOWN; + info.length = len; + info.low_limit = PAGE_SIZE; + info.high_limit = mm->mmap_base; + info.align_mask = filp ? get_align_mask() : 0; + info.align_offset = pgoff << PAGE_SHIFT; + info.threadstack_offset = offset; + + addr = vm_unmapped_area(&info); + if (!(addr & ~PAGE_MASK)) + return addr; + VM_BUG_ON(addr != -ENOMEM); + +bottomup: + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + return arch_get_unmapped_area(filp, addr0, len, pgoff, flags); +} diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 30277e2..5664a29 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -81,8 +81,8 @@ out: return error; } -static void find_start_end(unsigned long flags, unsigned long *begin, - unsigned long *end) +static void find_start_end(struct mm_struct *mm, unsigned long flags, + unsigned long *begin, unsigned long *end) { if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT)) { unsigned long new_begin; @@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin, *begin = new_begin; } } else { - *begin = current->mm->mmap_legacy_base; + *begin = mm->mmap_legacy_base; *end = TASK_SIZE; } } @@ -114,20 +114,24 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma; struct vm_unmapped_area_info info; unsigned long begin, end; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); if (flags & MAP_FIXED) return addr; - find_start_end(flags, &begin, &end); + find_start_end(mm, flags, &begin, &end); if (len > end) return -ENOMEM; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); - if (end - len >= addr && - (!vma || addr + len <= vma->vm_start)) + if (end - len >= addr && check_heap_stack_gap(vma, addr, len, offset)) return addr; } @@ -137,6 +141,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, info.high_limit = end; info.align_mask = filp ? get_align_mask() : 0; info.align_offset = pgoff << PAGE_SHIFT; + info.threadstack_offset = offset; return vm_unmapped_area(&info); } @@ -149,6 +154,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, struct mm_struct *mm = current->mm; unsigned long addr = addr0; struct vm_unmapped_area_info info; + unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags); /* requested length too big for entire address space */ if (len > TASK_SIZE) @@ -161,12 +167,15 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (!test_thread_flag(TIF_ADDR32) && (flags & MAP_32BIT)) goto bottomup; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + /* requesting a specific address */ if (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; } @@ -176,6 +185,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.high_limit = mm->mmap_base; info.align_mask = filp ? get_align_mask() : 0; info.align_offset = pgoff << PAGE_SHIFT; + info.threadstack_offset = offset; addr = vm_unmapped_area(&info); if (!(addr & ~PAGE_MASK)) return addr; diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index f84fe00..f41d9f1 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -220,7 +220,7 @@ static int tboot_setup_sleep(void) void tboot_shutdown(u32 shutdown_type) { - void (*shutdown)(void); + void (* __noreturn shutdown)(void); if (!tboot_enabled()) return; @@ -242,7 +242,7 @@ void tboot_shutdown(u32 shutdown_type) switch_to_tboot_pt(); - shutdown = (void(*)(void))(unsigned long)tboot->shutdown_entry; + shutdown = (void *)tboot->shutdown_entry; shutdown(); /* should not reach here */ @@ -300,7 +300,7 @@ static int tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control) return 0; } -static atomic_t ap_wfs_count; +static atomic_unchecked_t ap_wfs_count; static int tboot_wait_for_aps(int num_aps) { @@ -324,16 +324,16 @@ static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb, { switch (action) { case CPU_DYING: - atomic_inc(&ap_wfs_count); + atomic_inc_unchecked(&ap_wfs_count); if (num_online_cpus() == 1) - if (tboot_wait_for_aps(atomic_read(&ap_wfs_count))) + if (tboot_wait_for_aps(atomic_read_unchecked(&ap_wfs_count))) return NOTIFY_BAD; break; } return NOTIFY_OK; } -static struct notifier_block tboot_cpu_notifier __cpuinitdata = +static struct notifier_block tboot_cpu_notifier = { .notifier_call = tboot_cpu_callback, }; @@ -345,7 +345,7 @@ static __init int tboot_late_init(void) tboot_create_trampoline(); - atomic_set(&ap_wfs_count, 0); + atomic_set_unchecked(&ap_wfs_count, 0); register_hotcpu_notifier(&tboot_cpu_notifier); acpi_os_set_prepare_sleep(&tboot_sleep); diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c index 24d3c91..d06b473 100644 --- a/arch/x86/kernel/time.c +++ b/arch/x86/kernel/time.c @@ -30,9 +30,9 @@ unsigned long profile_pc(struct pt_regs *regs) { unsigned long pc = instruction_pointer(regs); - if (!user_mode_vm(regs) && in_lock_functions(pc)) { + if (!user_mode(regs) && in_lock_functions(pc)) { #ifdef CONFIG_FRAME_POINTER - return *(unsigned long *)(regs->bp + sizeof(long)); + return ktla_ktva(*(unsigned long *)(regs->bp + sizeof(long))); #else unsigned long *sp = (unsigned long *)kernel_stack_pointer(regs); @@ -41,11 +41,17 @@ unsigned long profile_pc(struct pt_regs *regs) * or above a saved flags. Eflags has bits 22-31 zero, * kernel addresses don't. */ + +#ifdef CONFIG_PAX_KERNEXEC + return ktla_ktva(sp[0]); +#else if (sp[0] >> 22) return sp[0]; if (sp[1] >> 22) return sp[1]; #endif + +#endif } return pc; } diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index f7fec09..9991981 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -84,6 +84,11 @@ int do_set_thread_area(struct task_struct *p, int idx, if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) return -EINVAL; +#ifdef CONFIG_PAX_SEGMEXEC + if ((p->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE)) + return -EINVAL; +#endif + set_tls_desc(p, idx, &info, 1); return 0; @@ -200,7 +205,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset, if (kbuf) info = kbuf; - else if (__copy_from_user(infobuf, ubuf, count)) + else if (count > sizeof infobuf || __copy_from_user(infobuf, ubuf, count)) return -EFAULT; else info = infobuf; diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 772e2a8..bad5bf6 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -68,12 +68,6 @@ #include asmlinkage int system_call(void); - -/* - * The IDT has to be page-aligned to simplify the Pentium - * F0 0F bug workaround. - */ -gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, }; #endif DECLARE_BITMAP(used_vectors, NR_VECTORS); @@ -106,11 +100,11 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) } static int __kprobes -do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, +do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, struct pt_regs *regs, long error_code) { #ifdef CONFIG_X86_32 - if (regs->flags & X86_VM_MASK) { + if (v8086_mode(regs)) { /* * Traps 0, 1, 3, 4, and 5 should be forwarded to vm86. * On nmi (interrupt 2), do_trap should not be called. @@ -123,12 +117,24 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, return -1; } #endif - if (!user_mode(regs)) { + if (!user_mode_novm(regs)) { if (!fixup_exception(regs)) { tsk->thread.error_code = error_code; tsk->thread.trap_nr = trapnr; + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + if (trapnr == 12 && ((regs->cs & 0xFFFF) == __KERNEL_CS || (regs->cs & 0xFFFF) == __KERNEXEC_KERNEL_CS)) + str = "PAX: suspicious stack segment fault"; +#endif + die(str, regs, error_code); } + +#ifdef CONFIG_PAX_REFCOUNT + if (trapnr == 4) + pax_report_refcount_overflow(regs); +#endif + return 0; } @@ -136,7 +142,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, } static void __kprobes -do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, +do_trap(int trapnr, int signr, const char *str, struct pt_regs *regs, long error_code, siginfo_t *info) { struct task_struct *tsk = current; @@ -160,7 +166,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, if (show_unhandled_signals && unhandled_signal(tsk, signr) && printk_ratelimit()) { pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx", - tsk->comm, tsk->pid, str, + tsk->comm, task_pid_nr(tsk), str, regs->ip, regs->sp, error_code); print_vma_addr(" in ", regs->ip); pr_cont("\n"); @@ -273,7 +279,7 @@ do_general_protection(struct pt_regs *regs, long error_code) conditional_sti(regs); #ifdef CONFIG_X86_32 - if (regs->flags & X86_VM_MASK) { + if (v8086_mode(regs)) { local_irq_enable(); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); goto exit; @@ -281,18 +287,42 @@ do_general_protection(struct pt_regs *regs, long error_code) #endif tsk = current; - if (!user_mode(regs)) { + if (!user_mode_novm(regs)) { if (fixup_exception(regs)) goto exit; tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; if (notify_die(DIE_GPF, "general protection fault", regs, error_code, - X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) + X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) { + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + if ((regs->cs & 0xFFFF) == __KERNEL_CS || (regs->cs & 0xFFFF) == __KERNEXEC_KERNEL_CS) + die("PAX: suspicious general protection fault", regs, error_code); + else +#endif + die("general protection fault", regs, error_code); + } goto exit; } +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) + if (!(__supported_pte_mask & _PAGE_NX) && tsk->mm && (tsk->mm->pax_flags & MF_PAX_PAGEEXEC)) { + struct mm_struct *mm = tsk->mm; + unsigned long limit; + + down_write(&mm->mmap_sem); + limit = mm->context.user_cs_limit; + if (limit < TASK_SIZE) { + track_exec_limit(mm, limit, TASK_SIZE, VM_EXEC); + up_write(&mm->mmap_sem); + return; + } + up_write(&mm->mmap_sem); + } +#endif + tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; @@ -450,7 +480,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) /* It's safe to allow irq's after DR6 has been saved */ preempt_conditional_sti(regs); - if (regs->flags & X86_VM_MASK) { + if (v8086_mode(regs)) { handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, X86_TRAP_DB); preempt_conditional_cli(regs); @@ -465,7 +495,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) * We already checked v86 mode above, so we can check for kernel mode * by just checking the CPL of CS. */ - if ((dr6 & DR_STEP) && !user_mode(regs)) { + if ((dr6 & DR_STEP) && !user_mode_novm(regs)) { tsk->thread.debugreg6 &= ~DR_STEP; set_tsk_thread_flag(tsk, TIF_SINGLESTEP); regs->flags &= ~X86_EFLAGS_TF; @@ -497,7 +527,7 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr) return; conditional_sti(regs); - if (!user_mode_vm(regs)) + if (!user_mode(regs)) { if (!fixup_exception(regs)) { task->thread.error_code = error_code; diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 2ed8459..7cf329f 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -629,7 +629,7 @@ int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, int ret = NOTIFY_DONE; /* We are only interested in userspace traps */ - if (regs && !user_mode_vm(regs)) + if (regs && !user_mode(regs)) return NOTIFY_DONE; switch (val) { @@ -719,7 +719,7 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs if (ncopied != rasize) { pr_err("uprobe: return address clobbered: pid=%d, %%sp=%#lx, " - "%%ip=%#lx\n", current->pid, regs->sp, regs->ip); + "%%ip=%#lx\n", task_pid_nr(current), regs->sp, regs->ip); force_sig_info(SIGSEGV, SEND_SIG_FORCED, current); } diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S index b9242ba..50c5edd 100644 --- a/arch/x86/kernel/verify_cpu.S +++ b/arch/x86/kernel/verify_cpu.S @@ -20,6 +20,7 @@ * arch/x86/boot/compressed/head_64.S: Boot cpu verification * arch/x86/kernel/trampoline_64.S: secondary processor verification * arch/x86/kernel/head_32.S: processor startup + * arch/x86/kernel/acpi/realmode/wakeup.S: 32bit processor resume * * verify_cpu, returns the status of longmode and SSE in register %eax. * 0: Success 1: Failure diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index e8edcf5..27f9344 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -150,7 +151,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) do_exit(SIGSEGV); } - tss = &per_cpu(init_tss, get_cpu()); + tss = init_tss + get_cpu(); current->thread.sp0 = current->thread.saved_sp0; current->thread.sysenter_cs = __KERNEL_CS; load_sp0(tss, ¤t->thread); @@ -214,6 +215,14 @@ SYSCALL_DEFINE1(vm86old, struct vm86_struct __user *, v86) if (tsk->thread.saved_sp0) return -EPERM; + +#ifdef CONFIG_GRKERNSEC_VM86 + if (!capable(CAP_SYS_RAWIO)) { + gr_handle_vm86(); + return -EPERM; + } +#endif + tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, offsetof(struct kernel_vm86_struct, vm86plus) - sizeof(info.regs)); @@ -238,6 +247,13 @@ SYSCALL_DEFINE2(vm86, unsigned long, cmd, unsigned long, arg) int tmp; struct vm86plus_struct __user *v86; +#ifdef CONFIG_GRKERNSEC_VM86 + if (!capable(CAP_SYS_RAWIO)) { + gr_handle_vm86(); + return -EPERM; + } +#endif + tsk = current; switch (cmd) { case VM86_REQUEST_IRQ: @@ -318,7 +334,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk tsk->thread.saved_fs = info->regs32->fs; tsk->thread.saved_gs = get_user_gs(info->regs32); - tss = &per_cpu(init_tss, get_cpu()); + tss = init_tss + get_cpu(); tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0; if (cpu_has_sep) tsk->thread.sysenter_cs = 0; @@ -525,7 +541,7 @@ static void do_int(struct kernel_vm86_regs *regs, int i, goto cannot_handle; if (i == 0x21 && is_revectored(AH(regs), &KVM86->int21_revectored)) goto cannot_handle; - intr_ptr = (unsigned long __user *) (i << 2); + intr_ptr = (__force unsigned long __user *) (i << 2); if (get_user(segoffs, intr_ptr)) goto cannot_handle; if ((segoffs >> 16) == BIOSSEG) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 10c4f30..57377c2 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -26,6 +26,13 @@ #include #include #include +#include + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) +#define __KERNEL_TEXT_OFFSET (LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR) +#else +#define __KERNEL_TEXT_OFFSET 0 +#endif #undef i386 /* in case the preprocessor is a 32bit one */ @@ -69,30 +76,43 @@ jiffies_64 = jiffies; PHDRS { text PT_LOAD FLAGS(5); /* R_E */ +#ifdef CONFIG_X86_32 + module PT_LOAD FLAGS(5); /* R_E */ +#endif +#ifdef CONFIG_XEN + rodata PT_LOAD FLAGS(5); /* R_E */ +#else + rodata PT_LOAD FLAGS(4); /* R__ */ +#endif data PT_LOAD FLAGS(6); /* RW_ */ -#ifdef CONFIG_X86_64 + init.begin PT_LOAD FLAGS(6); /* RW_ */ #ifdef CONFIG_SMP percpu PT_LOAD FLAGS(6); /* RW_ */ #endif + text.init PT_LOAD FLAGS(5); /* R_E */ + text.exit PT_LOAD FLAGS(5); /* R_E */ init PT_LOAD FLAGS(7); /* RWE */ -#endif note PT_NOTE FLAGS(0); /* ___ */ } SECTIONS { #ifdef CONFIG_X86_32 - . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR; - phys_startup_32 = startup_32 - LOAD_OFFSET; + . = LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR; #else - . = __START_KERNEL; - phys_startup_64 = startup_64 - LOAD_OFFSET; + . = __START_KERNEL; #endif /* Text and read-only data */ - .text : AT(ADDR(.text) - LOAD_OFFSET) { - _text = .; + .text (. - __KERNEL_TEXT_OFFSET): AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { /* bootstrapping code */ +#ifdef CONFIG_X86_32 + phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET; +#else + phys_startup_64 = startup_64 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET; +#endif + __LOAD_PHYSICAL_ADDR = . - LOAD_OFFSET + __KERNEL_TEXT_OFFSET; + _text = .; HEAD_TEXT . = ALIGN(8); _stext = .; @@ -104,13 +124,48 @@ SECTIONS IRQENTRY_TEXT *(.fixup) *(.gnu.warning) - /* End of text section */ - _etext = .; } :text = 0x9090 - NOTES :text :note + . += __KERNEL_TEXT_OFFSET; - EXCEPTION_TABLE(16) :text = 0x9090 +#ifdef CONFIG_X86_32 + . = ALIGN(PAGE_SIZE); + .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) { + +#ifdef CONFIG_PAX_KERNEXEC + MODULES_EXEC_VADDR = .; + BYTE(0) + . += (CONFIG_PAX_KERNEXEC_MODULE_TEXT * 1024 * 1024); + . = ALIGN(HPAGE_SIZE) - 1; + MODULES_EXEC_END = .; +#endif + + } :module +#endif + + .text.end : AT(ADDR(.text.end) - LOAD_OFFSET) { + /* End of text section */ + BYTE(0) + _etext = . - __KERNEL_TEXT_OFFSET; + } + +#ifdef CONFIG_X86_32 + . = ALIGN(PAGE_SIZE); + .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) { + *(.idt) + . = ALIGN(PAGE_SIZE); + *(.empty_zero_page) + *(.initial_pg_fixmap) + *(.initial_pg_pmd) + *(.initial_page_table) + *(.swapper_pg_dir) + } :rodata +#endif + + . = ALIGN(PAGE_SIZE); + NOTES :rodata :note + + EXCEPTION_TABLE(16) :rodata #if defined(CONFIG_DEBUG_RODATA) /* .text should occupy whole number of pages */ @@ -122,16 +177,20 @@ SECTIONS /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { + +#ifdef CONFIG_PAX_KERNEXEC + . = ALIGN(HPAGE_SIZE); +#else + . = ALIGN(PAGE_SIZE); +#endif + /* Start of data section */ _sdata = .; /* init_task */ INIT_TASK_DATA(THREAD_SIZE) -#ifdef CONFIG_X86_32 - /* 32 bit has nosave before _edata */ NOSAVE_DATA -#endif PAGE_ALIGNED_DATA(PAGE_SIZE) @@ -172,12 +231,19 @@ SECTIONS #endif /* CONFIG_X86_64 */ /* Init code and data - will be freed after init */ - . = ALIGN(PAGE_SIZE); .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) { + BYTE(0) + +#ifdef CONFIG_PAX_KERNEXEC + . = ALIGN(HPAGE_SIZE); +#else + . = ALIGN(PAGE_SIZE); +#endif + __init_begin = .; /* paired with __init_end */ - } + } :init.begin -#if defined(CONFIG_X86_64) && defined(CONFIG_SMP) +#ifdef CONFIG_SMP /* * percpu offsets are zero-based on SMP. PERCPU_VADDR() changes the * output PHDR, so the next output section - .init.text - should @@ -186,12 +252,27 @@ SECTIONS PERCPU_VADDR(INTERNODE_CACHE_BYTES, 0, :percpu) #endif - INIT_TEXT_SECTION(PAGE_SIZE) -#ifdef CONFIG_X86_64 - :init -#endif + . = ALIGN(PAGE_SIZE); + init_begin = .; + .init.text (. - __KERNEL_TEXT_OFFSET): AT(init_begin - LOAD_OFFSET) { + VMLINUX_SYMBOL(_sinittext) = .; + INIT_TEXT + VMLINUX_SYMBOL(_einittext) = .; + . = ALIGN(PAGE_SIZE); + } :text.init - INIT_DATA_SECTION(16) + /* + * .exit.text is discard at runtime, not link time, to deal with + * references from .altinstructions and .eh_frame + */ + .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { + EXIT_TEXT + . = ALIGN(16); + } :text.exit + . = init_begin + SIZEOF(.init.text) + SIZEOF(.exit.text); + + . = ALIGN(PAGE_SIZE); + INIT_DATA_SECTION(16) :init .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { __x86_cpu_dev_start = .; @@ -253,19 +334,12 @@ SECTIONS } . = ALIGN(8); - /* - * .exit.text is discard at runtime, not link time, to deal with - * references from .altinstructions and .eh_frame - */ - .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { - EXIT_TEXT - } .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA } -#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP) +#ifndef CONFIG_SMP PERCPU_SECTION(INTERNODE_CACHE_BYTES) #endif @@ -284,16 +358,10 @@ SECTIONS .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { __smp_locks = .; *(.smp_locks) - . = ALIGN(PAGE_SIZE); __smp_locks_end = .; + . = ALIGN(PAGE_SIZE); } -#ifdef CONFIG_X86_64 - .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { - NOSAVE_DATA - } -#endif - /* BSS */ . = ALIGN(PAGE_SIZE); .bss : AT(ADDR(.bss) - LOAD_OFFSET) { @@ -309,6 +377,7 @@ SECTIONS __brk_base = .; . += 64 * 1024; /* 64k alignment slop space */ *(.brk_reservation) /* areas brk users have reserved */ + . = ALIGN(HPAGE_SIZE); __brk_limit = .; } @@ -335,13 +404,12 @@ SECTIONS * for the boot processor. */ #define INIT_PER_CPU(x) init_per_cpu__##x = x + __per_cpu_load -INIT_PER_CPU(gdt_page); INIT_PER_CPU(irq_stack_union); /* * Build-time check on the image size: */ -. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE), +. = ASSERT((_end - _text - __KERNEL_TEXT_OFFSET <= KERNEL_IMAGE_SIZE), "kernel image bigger than KERNEL_IMAGE_SIZE"); #ifdef CONFIG_SMP diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 9a907a6..f83f921 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -56,15 +56,13 @@ DEFINE_VVAR(int, vgetcpu_mode); DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data); -static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE; +static enum { EMULATE, NONE } vsyscall_mode = EMULATE; static int __init vsyscall_setup(char *str) { if (str) { if (!strcmp("emulate", str)) vsyscall_mode = EMULATE; - else if (!strcmp("native", str)) - vsyscall_mode = NATIVE; else if (!strcmp("none", str)) vsyscall_mode = NONE; else @@ -323,8 +321,7 @@ do_ret: return true; sigsegv: - force_sig(SIGSEGV, current); - return true; + do_group_exit(SIGKILL); } /* @@ -377,10 +374,7 @@ void __init map_vsyscall(void) extern char __vvar_page; unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page); - __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall, - vsyscall_mode == NATIVE - ? PAGE_KERNEL_VSYSCALL - : PAGE_KERNEL_VVAR); + __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall, PAGE_KERNEL_VVAR); BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_FIRST_PAGE) != (unsigned long)VSYSCALL_START); diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index b014d94..e775258 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c @@ -34,8 +34,6 @@ EXPORT_SYMBOL(copy_user_generic_string); EXPORT_SYMBOL(copy_user_generic_unrolled); EXPORT_SYMBOL(copy_user_enhanced_fast_string); EXPORT_SYMBOL(__copy_user_nocache); -EXPORT_SYMBOL(_copy_from_user); -EXPORT_SYMBOL(_copy_to_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(clear_page); @@ -66,3 +64,7 @@ EXPORT_SYMBOL(empty_zero_page); #ifndef CONFIG_PARAVIRT EXPORT_SYMBOL(native_load_gs_index); #endif + +#ifdef CONFIG_PAX_PER_CPU_PGD +EXPORT_SYMBOL(cpu_pgd); +#endif diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 45a14db..075bb9b 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -85,7 +85,7 @@ struct x86_init_ops x86_init __initdata = { }, }; -struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { +struct x86_cpuinit_ops x86_cpuinit __cpuinitconst = { .early_percpu_clock_init = x86_init_noop, .setup_percpu_clockev = setup_secondary_APIC_clock, }; @@ -93,7 +93,7 @@ struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { static void default_nmi_init(void) { }; static int default_i8042_detect(void) { return 1; }; -struct x86_platform_ops x86_platform = { +struct x86_platform_ops x86_platform __read_only = { .calibrate_tsc = native_calibrate_tsc, .get_wallclock = mach_get_cmos_time, .set_wallclock = mach_set_rtc_mmss, @@ -107,7 +107,7 @@ struct x86_platform_ops x86_platform = { }; EXPORT_SYMBOL_GPL(x86_platform); -struct x86_msi_ops x86_msi = { +struct x86_msi_ops x86_msi __read_only = { .setup_msi_irqs = native_setup_msi_irqs, .compose_msi_msg = native_compose_msi_msg, .teardown_msi_irq = native_teardown_msi_irq, @@ -116,7 +116,7 @@ struct x86_msi_ops x86_msi = { .setup_hpet_msi = default_setup_hpet_msi, }; -struct x86_io_apic_ops x86_io_apic_ops = { +struct x86_io_apic_ops x86_io_apic_ops __read_only = { .init = native_io_apic_init_mappings, .read = native_io_apic_read, .write = native_io_apic_write, diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index ada87a3..afea76d 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -199,6 +199,7 @@ static inline int save_user_xstate(struct xsave_struct __user *buf) { int err; + buf = (struct xsave_struct __user *)____m(buf); if (use_xsave()) err = xsave_user(buf); else if (use_fxsr()) @@ -311,6 +312,7 @@ sanitize_restored_xstate(struct task_struct *tsk, */ static inline int restore_user_xstate(void __user *buf, u64 xbv, int fx_only) { + buf = (void __user *)____m(buf); if (use_xsave()) { if ((unsigned long)buf % 64 || fx_only) { u64 init_bv = pcntxt_mask & ~XSTATE_FPSSE; diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index a20ecb5..d0e2194 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -124,15 +124,20 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 __user *entries) { - int r; + int r, i; r = -E2BIG; if (cpuid->nent > KVM_MAX_CPUID_ENTRIES) goto out; r = -EFAULT; - if (copy_from_user(&vcpu->arch.cpuid_entries, entries, - cpuid->nent * sizeof(struct kvm_cpuid_entry2))) + if (!access_ok(VERIFY_READ, entries, cpuid->nent * sizeof(struct kvm_cpuid_entry2))) goto out; + for (i = 0; i < cpuid->nent; ++i) { + struct kvm_cpuid_entry2 cpuid_entry; + if (__copy_from_user(&cpuid_entry, entries + i, sizeof(cpuid_entry))) + goto out; + vcpu->arch.cpuid_entries[i] = cpuid_entry; + } vcpu->arch.cpuid_nent = cpuid->nent; kvm_apic_set_version(vcpu); kvm_x86_ops->cpuid_update(vcpu); @@ -147,15 +152,19 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 __user *entries) { - int r; + int r, i; r = -E2BIG; if (cpuid->nent < vcpu->arch.cpuid_nent) goto out; r = -EFAULT; - if (copy_to_user(entries, &vcpu->arch.cpuid_entries, - vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) + if (!access_ok(VERIFY_WRITE, entries, vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) goto out; + for (i = 0; i < vcpu->arch.cpuid_nent; ++i) { + struct kvm_cpuid_entry2 cpuid_entry = vcpu->arch.cpuid_entries[i]; + if (__copy_to_user(entries + i, &cpuid_entry, sizeof(cpuid_entry))) + goto out; + } return 0; out: diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 5953dce..f11a7d2 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -329,6 +329,7 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt) #define ____emulate_2op(ctxt, _op, _x, _y, _suffix, _dsttype) \ do { \ + unsigned long _tmp; \ __asm__ __volatile__ ( \ _PRE_EFLAGS("0", "4", "2") \ _op _suffix " %"_x"3,%1; " \ @@ -343,8 +344,6 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt) /* Raw emulation: instruction has two explicit operands. */ #define __emulate_2op_nobyte(ctxt,_op,_wx,_wy,_lx,_ly,_qx,_qy) \ do { \ - unsigned long _tmp; \ - \ switch ((ctxt)->dst.bytes) { \ case 2: \ ____emulate_2op(ctxt,_op,_wx,_wy,"w",u16); \ @@ -360,7 +359,6 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt) #define __emulate_2op(ctxt,_op,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ do { \ - unsigned long _tmp; \ switch ((ctxt)->dst.bytes) { \ case 1: \ ____emulate_2op(ctxt,_op,_bx,_by,"b",u8); \ diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 0eee2c8..94a32c3 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -55,7 +55,7 @@ #define APIC_BUS_CYCLE_NS 1 /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */ -#define apic_debug(fmt, arg...) +#define apic_debug(fmt, arg...) do {} while (0) #define APIC_LVT_NUM 6 /* 14 is the version for Xeon and Pentium 8.4.8*/ diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index da20860..d19fdf5 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -208,7 +208,7 @@ retry_walk: if (unlikely(kvm_is_error_hva(host_addr))) goto error; - ptep_user = (pt_element_t __user *)((void *)host_addr + offset); + ptep_user = (pt_element_t __force_user *)((void *)host_addr + offset); if (unlikely(__copy_from_user(&pte, ptep_user, sizeof(pte)))) goto error; walker->ptep_user[walker->level - 1] = ptep_user; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a14a6ea..dc86cf0 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3493,7 +3493,11 @@ static void reload_tss(struct kvm_vcpu *vcpu) int cpu = raw_smp_processor_id(); struct svm_cpu_data *sd = per_cpu(svm_data, cpu); + + pax_open_kernel(); sd->tss_desc->type = 9; /* available 32/64-bit TSS */ + pax_close_kernel(); + load_TR_desc(); } @@ -3894,6 +3898,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) #endif #endif +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF) + __set_fs(current_thread_info()->addr_limit); +#endif + reload_tss(vcpu); local_irq_disable(); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5402c94..c3bdeee 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1311,12 +1311,12 @@ static void vmcs_write64(unsigned long field, u64 value) #endif } -static void vmcs_clear_bits(unsigned long field, u32 mask) +static void vmcs_clear_bits(unsigned long field, unsigned long mask) { vmcs_writel(field, vmcs_readl(field) & ~mask); } -static void vmcs_set_bits(unsigned long field, u32 mask) +static void vmcs_set_bits(unsigned long field, unsigned long mask) { vmcs_writel(field, vmcs_readl(field) | mask); } @@ -1517,7 +1517,11 @@ static void reload_tss(void) struct desc_struct *descs; descs = (void *)gdt->address; + + pax_open_kernel(); descs[GDT_ENTRY_TSS].type = 9; /* available TSS */ + pax_close_kernel(); + load_TR_desc(); } @@ -1741,6 +1745,10 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) vmcs_writel(HOST_TR_BASE, kvm_read_tr_base()); /* 22.2.4 */ vmcs_writel(HOST_GDTR_BASE, gdt->address); /* 22.2.4 */ +#ifdef CONFIG_PAX_PER_CPU_PGD + vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ +#endif + rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp); vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */ vmx->loaded_vmcs->cpu = cpu; @@ -2935,8 +2943,11 @@ static __init int hardware_setup(void) if (!cpu_has_vmx_flexpriority()) flexpriority_enabled = 0; - if (!cpu_has_vmx_tpr_shadow()) - kvm_x86_ops->update_cr8_intercept = NULL; + if (!cpu_has_vmx_tpr_shadow()) { + pax_open_kernel(); + *(void **)&kvm_x86_ops->update_cr8_intercept = NULL; + pax_close_kernel(); + } if (enable_ept && !cpu_has_vmx_ept_2m_page()) kvm_disable_largepages(); @@ -2947,13 +2958,15 @@ static __init int hardware_setup(void) if (!cpu_has_vmx_apicv()) enable_apicv = 0; + pax_open_kernel(); if (enable_apicv) - kvm_x86_ops->update_cr8_intercept = NULL; + *(void **)&kvm_x86_ops->update_cr8_intercept = NULL; else { - kvm_x86_ops->hwapic_irr_update = NULL; - kvm_x86_ops->deliver_posted_interrupt = NULL; - kvm_x86_ops->sync_pir_to_irr = vmx_sync_pir_to_irr_dummy; + *(void **)&kvm_x86_ops->hwapic_irr_update = NULL; + *(void **)&kvm_x86_ops->deliver_posted_interrupt = NULL; + *(void **)&kvm_x86_ops->sync_pir_to_irr = vmx_sync_pir_to_irr_dummy; } + pax_close_kernel(); if (nested) nested_vmx_setup_ctls_msrs(); @@ -4076,7 +4089,10 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx) vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */ vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ + +#ifndef CONFIG_PAX_PER_CPU_PGD vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ +#endif vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ #ifdef CONFIG_X86_64 @@ -4098,7 +4114,7 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx) vmcs_writel(HOST_IDTR_BASE, dt.address); /* 22.2.4 */ vmx->host_idt_base = dt.address; - vmcs_writel(HOST_RIP, vmx_return); /* 22.2.5 */ + vmcs_writel(HOST_RIP, ktla_ktva(vmx_return)); /* 22.2.5 */ rdmsr(MSR_IA32_SYSENTER_CS, low32, high32); vmcs_write32(HOST_IA32_SYSENTER_CS, low32); @@ -7030,6 +7046,12 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) "jmp 2f \n\t" "1: " __ex(ASM_VMX_VMRESUME) "\n\t" "2: " + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + "ljmp %[cs],$3f\n\t" + "3: " +#endif + /* Save guest registers, load host registers, keep flags */ "mov %0, %c[wordsize](%%" _ASM_SP ") \n\t" "pop %0 \n\t" @@ -7082,6 +7104,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) #endif [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)), [wordsize]"i"(sizeof(ulong)) + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + ,[cs]"i"(__KERNEL_CS) +#endif + : "cc", "memory" #ifdef CONFIG_X86_64 , "rax", "rbx", "rdi", "rsi" @@ -7095,7 +7122,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) if (debugctlmsr) update_debugctlmsr(debugctlmsr); -#ifndef CONFIG_X86_64 +#ifdef CONFIG_X86_32 /* * The sysexit path does not restore ds/es, so we must set them to * a reasonable value ourselves. @@ -7104,8 +7131,18 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) * may be executed in interrupt context, which saves and restore segments * around it, nullifying its effect. */ - loadsegment(ds, __USER_DS); - loadsegment(es, __USER_DS); + loadsegment(ds, __KERNEL_DS); + loadsegment(es, __KERNEL_DS); + loadsegment(ss, __KERNEL_DS); + +#ifdef CONFIG_PAX_KERNEXEC + loadsegment(fs, __KERNEL_PERCPU); +#endif + +#ifdef CONFIG_PAX_MEMORY_UDEREF + __set_fs(current_thread_info()->addr_limit); +#endif + #endif vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e8ba99c..ee9d7d9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1725,8 +1725,8 @@ static int xen_hvm_config(struct kvm_vcpu *vcpu, u64 data) { struct kvm *kvm = vcpu->kvm; int lm = is_long_mode(vcpu); - u8 *blob_addr = lm ? (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_64 - : (u8 *)(long)kvm->arch.xen_hvm_config.blob_addr_32; + u8 __user *blob_addr = lm ? (u8 __user *)(long)kvm->arch.xen_hvm_config.blob_addr_64 + : (u8 __user *)(long)kvm->arch.xen_hvm_config.blob_addr_32; u8 blob_size = lm ? kvm->arch.xen_hvm_config.blob_size_64 : kvm->arch.xen_hvm_config.blob_size_32; u32 page_num = data & ~PAGE_MASK; @@ -2609,6 +2609,8 @@ long kvm_arch_dev_ioctl(struct file *filp, if (n < msr_list.nmsrs) goto out; r = -EFAULT; + if (num_msrs_to_save > ARRAY_SIZE(msrs_to_save)) + goto out; if (copy_to_user(user_msr_list->indices, &msrs_to_save, num_msrs_to_save * sizeof(u32))) goto out; @@ -5297,7 +5299,7 @@ static struct notifier_block pvclock_gtod_notifier = { }; #endif -int kvm_arch_init(void *opaque) +int kvm_arch_init(const void *opaque) { int r; struct kvm_x86_ops *ops = (struct kvm_x86_ops *)opaque; diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 7114c63..a1018fc 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1201,9 +1201,10 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) * Rebooting also tells the Host we're finished, but the RESTART flag tells the * Launcher to reboot us. */ -static void lguest_restart(char *reason) +static __noreturn void lguest_restart(char *reason) { hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0, 0); + BUG(); } /*G:050 diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 00933d5..3a64af9 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -48,6 +48,10 @@ BEGIN(read) movl (v), %eax movl 4(v), %edx RET_ENDP +BEGIN(read_unchecked) + movl (v), %eax + movl 4(v), %edx +RET_ENDP #undef v #define v %esi @@ -55,6 +59,10 @@ BEGIN(set) movl %ebx, (v) movl %ecx, 4(v) RET_ENDP +BEGIN(set_unchecked) + movl %ebx, (v) + movl %ecx, 4(v) +RET_ENDP #undef v #define v %esi @@ -70,6 +78,20 @@ RET_ENDP BEGIN(add) addl %eax, (v) adcl %edx, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT + jno 0f + subl %eax, (v) + sbbl %edx, 4(v) + int $4 +0: + _ASM_EXTABLE(0b, 0b) +#endif + +RET_ENDP +BEGIN(add_unchecked) + addl %eax, (v) + adcl %edx, 4(v) RET_ENDP #undef v @@ -77,6 +99,24 @@ RET_ENDP BEGIN(add_return) addl (v), %eax adcl 4(v), %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + + movl %eax, (v) + movl %edx, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT +2: +#endif + +RET_ENDP +BEGIN(add_return_unchecked) + addl (v), %eax + adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) RET_ENDP @@ -86,6 +126,20 @@ RET_ENDP BEGIN(sub) subl %eax, (v) sbbl %edx, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT + jno 0f + addl %eax, (v) + adcl %edx, 4(v) + int $4 +0: + _ASM_EXTABLE(0b, 0b) +#endif + +RET_ENDP +BEGIN(sub_unchecked) + subl %eax, (v) + sbbl %edx, 4(v) RET_ENDP #undef v @@ -96,6 +150,27 @@ BEGIN(sub_return) sbbl $0, %edx addl (v), %eax adcl 4(v), %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + + movl %eax, (v) + movl %edx, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT +2: +#endif + +RET_ENDP +BEGIN(sub_return_unchecked) + negl %edx + negl %eax + sbbl $0, %edx + addl (v), %eax + adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) RET_ENDP @@ -105,6 +180,20 @@ RET_ENDP BEGIN(inc) addl $1, (v) adcl $0, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT + jno 0f + subl $1, (v) + sbbl $0, 4(v) + int $4 +0: + _ASM_EXTABLE(0b, 0b) +#endif + +RET_ENDP +BEGIN(inc_unchecked) + addl $1, (v) + adcl $0, 4(v) RET_ENDP #undef v @@ -114,6 +203,26 @@ BEGIN(inc_return) movl 4(v), %edx addl $1, %eax adcl $0, %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + + movl %eax, (v) + movl %edx, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT +2: +#endif + +RET_ENDP +BEGIN(inc_return_unchecked) + movl (v), %eax + movl 4(v), %edx + addl $1, %eax + adcl $0, %edx movl %eax, (v) movl %edx, 4(v) RET_ENDP @@ -123,6 +232,20 @@ RET_ENDP BEGIN(dec) subl $1, (v) sbbl $0, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT + jno 0f + addl $1, (v) + adcl $0, 4(v) + int $4 +0: + _ASM_EXTABLE(0b, 0b) +#endif + +RET_ENDP +BEGIN(dec_unchecked) + subl $1, (v) + sbbl $0, 4(v) RET_ENDP #undef v @@ -132,6 +255,26 @@ BEGIN(dec_return) movl 4(v), %edx subl $1, %eax sbbl $0, %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + + movl %eax, (v) + movl %edx, 4(v) + +#ifdef CONFIG_PAX_REFCOUNT +2: +#endif + +RET_ENDP +BEGIN(dec_return_unchecked) + movl (v), %eax + movl 4(v), %edx + subl $1, %eax + sbbl $0, %edx movl %eax, (v) movl %edx, 4(v) RET_ENDP @@ -143,6 +286,13 @@ BEGIN(add_unless) adcl %edx, %edi addl (v), %eax adcl 4(v), %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + cmpl %eax, %ecx je 3f 1: @@ -168,6 +318,13 @@ BEGIN(inc_not_zero) 1: addl $1, %eax adcl $0, %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + movl %eax, (v) movl %edx, 4(v) movl $1, %eax @@ -186,6 +343,13 @@ BEGIN(dec_if_positive) movl 4(v), %edx subl $1, %eax sbbl $0, %edx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 1f) +#endif + js 1f movl %eax, (v) movl %edx, 4(v) diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S index f5cc9eb..51fa319 100644 --- a/arch/x86/lib/atomic64_cx8_32.S +++ b/arch/x86/lib/atomic64_cx8_32.S @@ -35,10 +35,20 @@ ENTRY(atomic64_read_cx8) CFI_STARTPROC read64 %ecx + pax_force_retaddr ret CFI_ENDPROC ENDPROC(atomic64_read_cx8) +ENTRY(atomic64_read_unchecked_cx8) + CFI_STARTPROC + + read64 %ecx + pax_force_retaddr + ret + CFI_ENDPROC +ENDPROC(atomic64_read_unchecked_cx8) + ENTRY(atomic64_set_cx8) CFI_STARTPROC @@ -48,10 +58,25 @@ ENTRY(atomic64_set_cx8) cmpxchg8b (%esi) jne 1b + pax_force_retaddr ret CFI_ENDPROC ENDPROC(atomic64_set_cx8) +ENTRY(atomic64_set_unchecked_cx8) + CFI_STARTPROC + +1: +/* we don't need LOCK_PREFIX since aligned 64-bit writes + * are atomic on 586 and newer */ + cmpxchg8b (%esi) + jne 1b + + pax_force_retaddr + ret + CFI_ENDPROC +ENDPROC(atomic64_set_unchecked_cx8) + ENTRY(atomic64_xchg_cx8) CFI_STARTPROC @@ -60,12 +85,13 @@ ENTRY(atomic64_xchg_cx8) cmpxchg8b (%esi) jne 1b + pax_force_retaddr ret CFI_ENDPROC ENDPROC(atomic64_xchg_cx8) -.macro addsub_return func ins insc -ENTRY(atomic64_\func\()_return_cx8) +.macro addsub_return func ins insc unchecked="" +ENTRY(atomic64_\func\()_return\unchecked\()_cx8) CFI_STARTPROC SAVE ebp SAVE ebx @@ -82,27 +108,44 @@ ENTRY(atomic64_\func\()_return_cx8) movl %edx, %ecx \ins\()l %esi, %ebx \insc\()l %edi, %ecx + +.ifb \unchecked +#ifdef CONFIG_PAX_REFCOUNT + into +2: + _ASM_EXTABLE(2b, 3f) +#endif +.endif + LOCK_PREFIX cmpxchg8b (%ebp) jne 1b - -10: movl %ebx, %eax movl %ecx, %edx + +.ifb \unchecked +#ifdef CONFIG_PAX_REFCOUNT +3: +#endif +.endif + RESTORE edi RESTORE esi RESTORE ebx RESTORE ebp + pax_force_retaddr ret CFI_ENDPROC -ENDPROC(atomic64_\func\()_return_cx8) +ENDPROC(atomic64_\func\()_return\unchecked\()_cx8) .endm addsub_return add add adc addsub_return sub sub sbb +addsub_return add add adc _unchecked +addsub_return sub sub sbb _unchecked -.macro incdec_return func ins insc -ENTRY(atomic64_\func\()_return_cx8) +.macro incdec_return func ins insc unchecked="" +ENTRY(atomic64_\func\()_return\unchecked\()_cx8) CFI_STARTPROC SAVE ebx @@ -112,21 +155,39 @@ ENTRY(atomic64_\func\()_return_cx8) movl %edx, %ecx \ins\()l $1, %ebx \insc\()l $0, %ecx + +.ifb \unchecked +#ifdef CONFIG_PAX_REFCOUNT + into +2: + _ASM_EXTABLE(2b, 3f) +#endif +.endif + LOCK_PREFIX cmpxchg8b (%esi) jne 1b -10: movl %ebx, %eax movl %ecx, %edx + +.ifb \unchecked +#ifdef CONFIG_PAX_REFCOUNT +3: +#endif +.endif + RESTORE ebx + pax_force_retaddr ret CFI_ENDPROC -ENDPROC(atomic64_\func\()_return_cx8) +ENDPROC(atomic64_\func\()_return\unchecked\()_cx8) .endm incdec_return inc add adc incdec_return dec sub sbb +incdec_return inc add adc _unchecked +incdec_return dec sub sbb _unchecked ENTRY(atomic64_dec_if_positive_cx8) CFI_STARTPROC @@ -138,6 +199,13 @@ ENTRY(atomic64_dec_if_positive_cx8) movl %edx, %ecx subl $1, %ebx sbb $0, %ecx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 2f) +#endif + js 2f LOCK_PREFIX cmpxchg8b (%esi) @@ -147,6 +215,7 @@ ENTRY(atomic64_dec_if_positive_cx8) movl %ebx, %eax movl %ecx, %edx RESTORE ebx + pax_force_retaddr ret CFI_ENDPROC ENDPROC(atomic64_dec_if_positive_cx8) @@ -171,6 +240,13 @@ ENTRY(atomic64_add_unless_cx8) movl %edx, %ecx addl %ebp, %ebx adcl %edi, %ecx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 3f) +#endif + LOCK_PREFIX cmpxchg8b (%esi) jne 1b @@ -181,6 +257,7 @@ ENTRY(atomic64_add_unless_cx8) CFI_ADJUST_CFA_OFFSET -8 RESTORE ebx RESTORE ebp + pax_force_retaddr ret 4: cmpl %edx, 4(%esp) @@ -203,6 +280,13 @@ ENTRY(atomic64_inc_not_zero_cx8) xorl %ecx, %ecx addl $1, %ebx adcl %edx, %ecx + +#ifdef CONFIG_PAX_REFCOUNT + into +1234: + _ASM_EXTABLE(1234b, 3f) +#endif + LOCK_PREFIX cmpxchg8b (%esi) jne 1b @@ -210,6 +294,7 @@ ENTRY(atomic64_inc_not_zero_cx8) movl $1, %eax 3: RESTORE ebx + pax_force_retaddr ret CFI_ENDPROC ENDPROC(atomic64_inc_not_zero_cx8) diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S index e78b8ee..7e173a8 100644 --- a/arch/x86/lib/checksum_32.S +++ b/arch/x86/lib/checksum_32.S @@ -29,7 +29,8 @@ #include #include #include - +#include + /* * computes a partial checksum, e.g. for TCP/UDP fragments */ @@ -293,9 +294,24 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst, #define ARGBASE 16 #define FP 12 - -ENTRY(csum_partial_copy_generic) + +ENTRY(csum_partial_copy_generic_to_user) CFI_STARTPROC + +#ifdef CONFIG_PAX_MEMORY_UDEREF + pushl_cfi %gs + popl_cfi %es + jmp csum_partial_copy_generic +#endif + +ENTRY(csum_partial_copy_generic_from_user) + +#ifdef CONFIG_PAX_MEMORY_UDEREF + pushl_cfi %gs + popl_cfi %ds +#endif + +ENTRY(csum_partial_copy_generic) subl $4,%esp CFI_ADJUST_CFA_OFFSET 4 pushl_cfi %edi @@ -317,7 +333,7 @@ ENTRY(csum_partial_copy_generic) jmp 4f SRC(1: movw (%esi), %bx ) addl $2, %esi -DST( movw %bx, (%edi) ) +DST( movw %bx, %es:(%edi) ) addl $2, %edi addw %bx, %ax adcl $0, %eax @@ -329,30 +345,30 @@ DST( movw %bx, (%edi) ) SRC(1: movl (%esi), %ebx ) SRC( movl 4(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, (%edi) ) +DST( movl %ebx, %es:(%edi) ) adcl %edx, %eax -DST( movl %edx, 4(%edi) ) +DST( movl %edx, %es:4(%edi) ) SRC( movl 8(%esi), %ebx ) SRC( movl 12(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, 8(%edi) ) +DST( movl %ebx, %es:8(%edi) ) adcl %edx, %eax -DST( movl %edx, 12(%edi) ) +DST( movl %edx, %es:12(%edi) ) SRC( movl 16(%esi), %ebx ) SRC( movl 20(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, 16(%edi) ) +DST( movl %ebx, %es:16(%edi) ) adcl %edx, %eax -DST( movl %edx, 20(%edi) ) +DST( movl %edx, %es:20(%edi) ) SRC( movl 24(%esi), %ebx ) SRC( movl 28(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, 24(%edi) ) +DST( movl %ebx, %es:24(%edi) ) adcl %edx, %eax -DST( movl %edx, 28(%edi) ) +DST( movl %edx, %es:28(%edi) ) lea 32(%esi), %esi lea 32(%edi), %edi @@ -366,7 +382,7 @@ DST( movl %edx, 28(%edi) ) shrl $2, %edx # This clears CF SRC(3: movl (%esi), %ebx ) adcl %ebx, %eax -DST( movl %ebx, (%edi) ) +DST( movl %ebx, %es:(%edi) ) lea 4(%esi), %esi lea 4(%edi), %edi dec %edx @@ -378,12 +394,12 @@ DST( movl %ebx, (%edi) ) jb 5f SRC( movw (%esi), %cx ) leal 2(%esi), %esi -DST( movw %cx, (%edi) ) +DST( movw %cx, %es:(%edi) ) leal 2(%edi), %edi je 6f shll $16,%ecx SRC(5: movb (%esi), %cl ) -DST( movb %cl, (%edi) ) +DST( movb %cl, %es:(%edi) ) 6: addl %ecx, %eax adcl $0, %eax 7: @@ -394,7 +410,7 @@ DST( movb %cl, (%edi) ) 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr - movl $-EFAULT, (%ebx) + movl $-EFAULT, %ss:(%ebx) # zero the complete destination - computing the rest # is too much work @@ -407,11 +423,15 @@ DST( movb %cl, (%edi) ) 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr - movl $-EFAULT,(%ebx) + movl $-EFAULT,%ss:(%ebx) jmp 5000b .previous + pushl_cfi %ss + popl_cfi %ds + pushl_cfi %ss + popl_cfi %es popl_cfi %ebx CFI_RESTORE ebx popl_cfi %esi @@ -421,26 +441,43 @@ DST( movb %cl, (%edi) ) popl_cfi %ecx # equivalent to addl $4,%esp ret CFI_ENDPROC -ENDPROC(csum_partial_copy_generic) +ENDPROC(csum_partial_copy_generic_to_user) #else /* Version for PentiumII/PPro */ #define ROUND1(x) \ + nop; nop; nop; \ SRC(movl x(%esi), %ebx ) ; \ addl %ebx, %eax ; \ - DST(movl %ebx, x(%edi) ) ; + DST(movl %ebx, %es:x(%edi)) ; #define ROUND(x) \ + nop; nop; nop; \ SRC(movl x(%esi), %ebx ) ; \ adcl %ebx, %eax ; \ - DST(movl %ebx, x(%edi) ) ; + DST(movl %ebx, %es:x(%edi)) ; #define ARGBASE 12 - -ENTRY(csum_partial_copy_generic) + +ENTRY(csum_partial_copy_generic_to_user) CFI_STARTPROC + +#ifdef CONFIG_PAX_MEMORY_UDEREF + pushl_cfi %gs + popl_cfi %es + jmp csum_partial_copy_generic +#endif + +ENTRY(csum_partial_copy_generic_from_user) + +#ifdef CONFIG_PAX_MEMORY_UDEREF + pushl_cfi %gs + popl_cfi %ds +#endif + +ENTRY(csum_partial_copy_generic) pushl_cfi %ebx CFI_REL_OFFSET ebx, 0 pushl_cfi %edi @@ -461,7 +498,7 @@ ENTRY(csum_partial_copy_generic) subl %ebx, %edi lea -1(%esi),%edx andl $-32,%edx - lea 3f(%ebx,%ebx), %ebx + lea 3f(%ebx,%ebx,2), %ebx testl %esi, %esi jmp *%ebx 1: addl $64,%esi @@ -482,19 +519,19 @@ ENTRY(csum_partial_copy_generic) jb 5f SRC( movw (%esi), %dx ) leal 2(%esi), %esi -DST( movw %dx, (%edi) ) +DST( movw %dx, %es:(%edi) ) leal 2(%edi), %edi je 6f shll $16,%edx 5: SRC( movb (%esi), %dl ) -DST( movb %dl, (%edi) ) +DST( movb %dl, %es:(%edi) ) 6: addl %edx, %eax adcl $0, %eax 7: .section .fixup, "ax" 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr - movl $-EFAULT, (%ebx) + movl $-EFAULT, %ss:(%ebx) # zero the complete destination (computing the rest is too much work) movl ARGBASE+8(%esp),%edi # dst movl ARGBASE+12(%esp),%ecx # len @@ -502,10 +539,17 @@ DST( movb %dl, (%edi) ) rep; stosb jmp 7b 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr - movl $-EFAULT, (%ebx) + movl $-EFAULT, %ss:(%ebx) jmp 7b .previous +#ifdef CONFIG_PAX_MEMORY_UDEREF + pushl_cfi %ss + popl_cfi %ds + pushl_cfi %ss + popl_cfi %es +#endif + popl_cfi %esi CFI_RESTORE esi popl_cfi %edi @@ -514,7 +558,7 @@ DST( movb %dl, (%edi) ) CFI_RESTORE ebx ret CFI_ENDPROC -ENDPROC(csum_partial_copy_generic) +ENDPROC(csum_partial_copy_generic_to_user) #undef ROUND #undef ROUND1 diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S index f2145cf..cea889d 100644 --- a/arch/x86/lib/clear_page_64.S +++ b/arch/x86/lib/clear_page_64.S @@ -11,6 +11,7 @@ ENTRY(clear_page_c) movl $4096/8,%ecx xorl %eax,%eax rep stosq + pax_force_retaddr ret CFI_ENDPROC ENDPROC(clear_page_c) @@ -20,6 +21,7 @@ ENTRY(clear_page_c_e) movl $4096,%ecx xorl %eax,%eax rep stosb + pax_force_retaddr ret CFI_ENDPROC ENDPROC(clear_page_c_e) @@ -43,6 +45,7 @@ ENTRY(clear_page) leaq 64(%rdi),%rdi jnz .Lloop nop + pax_force_retaddr ret CFI_ENDPROC .Lclear_page_end: @@ -58,7 +61,7 @@ ENDPROC(clear_page) #include - .section .altinstr_replacement,"ax" + .section .altinstr_replacement,"a" 1: .byte 0xeb /* jmp */ .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */ 2: .byte 0xeb /* jmp */ diff --git a/arch/x86/lib/cmpxchg16b_emu.S b/arch/x86/lib/cmpxchg16b_emu.S index 1e572c5..2a162cd 100644 --- a/arch/x86/lib/cmpxchg16b_emu.S +++ b/arch/x86/lib/cmpxchg16b_emu.S @@ -53,11 +53,13 @@ this_cpu_cmpxchg16b_emu: popf mov $1, %al + pax_force_retaddr ret not_same: popf xor %al,%al + pax_force_retaddr ret CFI_ENDPROC diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S index 176cca6..1166c50 100644 --- a/arch/x86/lib/copy_page_64.S +++ b/arch/x86/lib/copy_page_64.S @@ -9,6 +9,7 @@ copy_page_rep: CFI_STARTPROC movl $4096/8, %ecx rep movsq + pax_force_retaddr ret CFI_ENDPROC ENDPROC(copy_page_rep) @@ -20,12 +21,14 @@ ENDPROC(copy_page_rep) ENTRY(copy_page) CFI_STARTPROC - subq $2*8, %rsp - CFI_ADJUST_CFA_OFFSET 2*8 + subq $3*8, %rsp + CFI_ADJUST_CFA_OFFSET 3*8 movq %rbx, (%rsp) CFI_REL_OFFSET rbx, 0 movq %r12, 1*8(%rsp) CFI_REL_OFFSET r12, 1*8 + movq %r13, 2*8(%rsp) + CFI_REL_OFFSET r13, 2*8 movl $(4096/64)-5, %ecx .p2align 4 @@ -36,7 +39,7 @@ ENTRY(copy_page) movq 0x8*2(%rsi), %rdx movq 0x8*3(%rsi), %r8 movq 0x8*4(%rsi), %r9 - movq 0x8*5(%rsi), %r10 + movq 0x8*5(%rsi), %r13 movq 0x8*6(%rsi), %r11 movq 0x8*7(%rsi), %r12 @@ -47,7 +50,7 @@ ENTRY(copy_page) movq %rdx, 0x8*2(%rdi) movq %r8, 0x8*3(%rdi) movq %r9, 0x8*4(%rdi) - movq %r10, 0x8*5(%rdi) + movq %r13, 0x8*5(%rdi) movq %r11, 0x8*6(%rdi) movq %r12, 0x8*7(%rdi) @@ -66,7 +69,7 @@ ENTRY(copy_page) movq 0x8*2(%rsi), %rdx movq 0x8*3(%rsi), %r8 movq 0x8*4(%rsi), %r9 - movq 0x8*5(%rsi), %r10 + movq 0x8*5(%rsi), %r13 movq 0x8*6(%rsi), %r11 movq 0x8*7(%rsi), %r12 @@ -75,7 +78,7 @@ ENTRY(copy_page) movq %rdx, 0x8*2(%rdi) movq %r8, 0x8*3(%rdi) movq %r9, 0x8*4(%rdi) - movq %r10, 0x8*5(%rdi) + movq %r13, 0x8*5(%rdi) movq %r11, 0x8*6(%rdi) movq %r12, 0x8*7(%rdi) @@ -87,8 +90,11 @@ ENTRY(copy_page) CFI_RESTORE rbx movq 1*8(%rsp), %r12 CFI_RESTORE r12 - addq $2*8, %rsp - CFI_ADJUST_CFA_OFFSET -2*8 + movq 2*8(%rsp), %r13 + CFI_RESTORE r13 + addq $3*8, %rsp + CFI_ADJUST_CFA_OFFSET -3*8 + pax_force_retaddr ret .Lcopy_page_end: CFI_ENDPROC @@ -99,7 +105,7 @@ ENDPROC(copy_page) #include - .section .altinstr_replacement,"ax" + .section .altinstr_replacement,"a" 1: .byte 0xeb /* jmp */ .byte (copy_page_rep - copy_page) - (2f - 1b) /* offset */ 2: diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index a30ca15..6b3f4e1 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -18,31 +18,7 @@ #include #include #include - -/* - * By placing feature2 after feature1 in altinstructions section, we logically - * implement: - * If CPU has feature2, jmp to alt2 is used - * else if CPU has feature1, jmp to alt1 is used - * else jmp to orig is used. - */ - .macro ALTERNATIVE_JUMP feature1,feature2,orig,alt1,alt2 -0: - .byte 0xe9 /* 32bit jump */ - .long \orig-1f /* by default jump to orig */ -1: - .section .altinstr_replacement,"ax" -2: .byte 0xe9 /* near jump with 32bit immediate */ - .long \alt1-1b /* offset */ /* or alternatively to alt1 */ -3: .byte 0xe9 /* near jump with 32bit immediate */ - .long \alt2-1b /* offset */ /* or alternatively to alt2 */ - .previous - - .section .altinstructions,"a" - altinstruction_entry 0b,2b,\feature1,5,5 - altinstruction_entry 0b,3b,\feature2,5,5 - .previous - .endm +#include .macro ALIGN_DESTINATION #ifdef FIX_ALIGNMENT @@ -70,52 +46,6 @@ #endif .endm -/* Standard copy_to_user with segment limit checking */ -ENTRY(_copy_to_user) - CFI_STARTPROC - GET_THREAD_INFO(%rax) - movq %rdi,%rcx - addq %rdx,%rcx - jc bad_to_user - cmpq TI_addr_limit(%rax),%rcx - ja bad_to_user - ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \ - copy_user_generic_unrolled,copy_user_generic_string, \ - copy_user_enhanced_fast_string - CFI_ENDPROC -ENDPROC(_copy_to_user) - -/* Standard copy_from_user with segment limit checking */ -ENTRY(_copy_from_user) - CFI_STARTPROC - GET_THREAD_INFO(%rax) - movq %rsi,%rcx - addq %rdx,%rcx - jc bad_from_user - cmpq TI_addr_limit(%rax),%rcx - ja bad_from_user - ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,X86_FEATURE_ERMS, \ - copy_user_generic_unrolled,copy_user_generic_string, \ - copy_user_enhanced_fast_string - CFI_ENDPROC -ENDPROC(_copy_from_user) - - .section .fixup,"ax" - /* must zero dest */ -ENTRY(bad_from_user) -bad_from_user: - CFI_STARTPROC - movl %edx,%ecx - xorl %eax,%eax - rep - stosb -bad_to_user: - movl %edx,%eax - ret - CFI_ENDPROC -ENDPROC(bad_from_user) - .previous - /* * copy_user_generic_unrolled - memory copy with exception handling. * This version is for CPUs like P4 that don't have efficient micro @@ -131,6 +61,7 @@ ENDPROC(bad_from_user) */ ENTRY(copy_user_generic_unrolled) CFI_STARTPROC + ASM_PAX_OPEN_USERLAND ASM_STAC cmpl $8,%edx jb 20f /* less then 8 bytes, go to byte copy loop */ @@ -141,19 +72,19 @@ ENTRY(copy_user_generic_unrolled) jz 17f 1: movq (%rsi),%r8 2: movq 1*8(%rsi),%r9 -3: movq 2*8(%rsi),%r10 +3: movq 2*8(%rsi),%rax 4: movq 3*8(%rsi),%r11 5: movq %r8,(%rdi) 6: movq %r9,1*8(%rdi) -7: movq %r10,2*8(%rdi) +7: movq %rax,2*8(%rdi) 8: movq %r11,3*8(%rdi) 9: movq 4*8(%rsi),%r8 10: movq 5*8(%rsi),%r9 -11: movq 6*8(%rsi),%r10 +11: movq 6*8(%rsi),%rax 12: movq 7*8(%rsi),%r11 13: movq %r8,4*8(%rdi) 14: movq %r9,5*8(%rdi) -15: movq %r10,6*8(%rdi) +15: movq %rax,6*8(%rdi) 16: movq %r11,7*8(%rdi) leaq 64(%rsi),%rsi leaq 64(%rdi),%rdi @@ -180,6 +111,8 @@ ENTRY(copy_user_generic_unrolled) jnz 21b 23: xor %eax,%eax ASM_CLAC + ASM_PAX_CLOSE_USERLAND + pax_force_retaddr ret .section .fixup,"ax" @@ -235,6 +168,7 @@ ENDPROC(copy_user_generic_unrolled) */ ENTRY(copy_user_generic_string) CFI_STARTPROC + ASM_PAX_OPEN_USERLAND ASM_STAC andl %edx,%edx jz 4f @@ -251,6 +185,8 @@ ENTRY(copy_user_generic_string) movsb 4: xorl %eax,%eax ASM_CLAC + ASM_PAX_CLOSE_USERLAND + pax_force_retaddr ret .section .fixup,"ax" @@ -278,6 +214,7 @@ ENDPROC(copy_user_generic_string) */ ENTRY(copy_user_enhanced_fast_string) CFI_STARTPROC + ASM_PAX_OPEN_USERLAND ASM_STAC andl %edx,%edx jz 2f @@ -286,6 +223,8 @@ ENTRY(copy_user_enhanced_fast_string) movsb 2: xorl %eax,%eax ASM_CLAC + ASM_PAX_CLOSE_USERLAND + pax_force_retaddr ret .section .fixup,"ax" diff --git a/arch/x86/lib/copy_user_nocache_64.S b/arch/x86/lib/copy_user_nocache_64.S index 6a4f43c..55d26f2 100644 --- a/arch/x86/lib/copy_user_nocache_64.S +++ b/arch/x86/lib/copy_user_nocache_64.S @@ -8,6 +8,7 @@ #include #include +#include #define FIX_ALIGNMENT 1 @@ -16,6 +17,7 @@ #include #include #include +#include .macro ALIGN_DESTINATION #ifdef FIX_ALIGNMENT @@ -49,6 +51,16 @@ */ ENTRY(__copy_user_nocache) CFI_STARTPROC + +#ifdef CONFIG_PAX_MEMORY_UDEREF + mov pax_user_shadow_base,%rcx + cmp %rcx,%rsi + jae 1f + add %rcx,%rsi +1: +#endif + + ASM_PAX_OPEN_USERLAND ASM_STAC cmpl $8,%edx jb 20f /* less then 8 bytes, go to byte copy loop */ @@ -59,19 +71,19 @@ ENTRY(__copy_user_nocache) jz 17f 1: movq (%rsi),%r8 2: movq 1*8(%rsi),%r9 -3: movq 2*8(%rsi),%r10 +3: movq 2*8(%rsi),%rax 4: movq 3*8(%rsi),%r11 5: movnti %r8,(%rdi) 6: movnti %r9,1*8(%rdi) -7: movnti %r10,2*8(%rdi) +7: movnti %rax,2*8(%rdi) 8: movnti %r11,3*8(%rdi) 9: movq 4*8(%rsi),%r8 10: movq 5*8(%rsi),%r9 -11: movq 6*8(%rsi),%r10 +11: movq 6*8(%rsi),%rax 12: movq 7*8(%rsi),%r11 13: movnti %r8,4*8(%rdi) 14: movnti %r9,5*8(%rdi) -15: movnti %r10,6*8(%rdi) +15: movnti %rax,6*8(%rdi) 16: movnti %r11,7*8(%rdi) leaq 64(%rsi),%rsi leaq 64(%rdi),%rdi @@ -98,7 +110,9 @@ ENTRY(__copy_user_nocache) jnz 21b 23: xorl %eax,%eax ASM_CLAC + ASM_PAX_CLOSE_USERLAND sfence + pax_force_retaddr ret .section .fixup,"ax" diff --git a/arch/x86/lib/csum-copy_64.S b/arch/x86/lib/csum-copy_64.S index 2419d5f..953ee51 100644 --- a/arch/x86/lib/csum-copy_64.S +++ b/arch/x86/lib/csum-copy_64.S @@ -9,6 +9,7 @@ #include #include #include +#include /* * Checksum copy with exception handling. @@ -220,6 +221,7 @@ ENTRY(csum_partial_copy_generic) CFI_RESTORE rbp addq $7*8, %rsp CFI_ADJUST_CFA_OFFSET -7*8 + pax_force_retaddr 0, 1 ret CFI_RESTORE_STATE diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index 7609e0e..69641b5 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -53,10 +53,12 @@ csum_partial_copy_from_user(const void __user *src, void *dst, len -= 2; } } + pax_open_userland(); stac(); - isum = csum_partial_copy_generic((__force const void *)src, + isum = csum_partial_copy_generic((const void __force_kernel *)____m(src), dst, len, isum, errp, NULL); clac(); + pax_close_userland(); if (unlikely(*errp)) goto out_err; @@ -110,11 +112,21 @@ csum_partial_copy_to_user(const void *src, void __user *dst, } *errp = 0; +<<<<<<< HEAD + pax_open_userland(); + stac(); + isum = csum_partial_copy_generic(src, (void __force_kernel *)____m(dst), + len, isum, NULL, errp); + clac(); + pax_close_userland(); + return isum; +======= stac(); ret = csum_partial_copy_generic(src, (void __force *)dst, len, isum, NULL, errp); clac(); return ret; +>>>>>>> origin/linux-3.10.y } EXPORT_SYMBOL(csum_partial_copy_to_user); diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S index a451235..1daa956 100644 --- a/arch/x86/lib/getuser.S +++ b/arch/x86/lib/getuser.S @@ -33,17 +33,40 @@ #include #include #include +#include +#include +#include + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define __copyuser_seg gs; +#else +#define __copyuser_seg +#endif .text ENTRY(__get_user_1) CFI_STARTPROC + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) GET_THREAD_INFO(%_ASM_DX) cmp TI_addr_limit(%_ASM_DX),%_ASM_AX jae bad_get_user ASM_STAC -1: movzbl (%_ASM_AX),%edx + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_DX + cmp %_ASM_DX,%_ASM_AX + jae 1234f + add %_ASM_DX,%_ASM_AX +1234: +#endif + +#endif + +1: __copyuser_seg movzbl (%_ASM_AX),%edx xor %eax,%eax ASM_CLAC + pax_force_retaddr ret CFI_ENDPROC ENDPROC(__get_user_1) @@ -51,14 +74,28 @@ ENDPROC(__get_user_1) ENTRY(__get_user_2) CFI_STARTPROC add $1,%_ASM_AX + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) jc bad_get_user GET_THREAD_INFO(%_ASM_DX) cmp TI_addr_limit(%_ASM_DX),%_ASM_AX jae bad_get_user ASM_STAC -2: movzwl -1(%_ASM_AX),%edx + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_DX + cmp %_ASM_DX,%_ASM_AX + jae 1234f + add %_ASM_DX,%_ASM_AX +1234: +#endif + +#endif + +2: __copyuser_seg movzwl -1(%_ASM_AX),%edx xor %eax,%eax ASM_CLAC + pax_force_retaddr ret CFI_ENDPROC ENDPROC(__get_user_2) @@ -66,14 +103,28 @@ ENDPROC(__get_user_2) ENTRY(__get_user_4) CFI_STARTPROC add $3,%_ASM_AX + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) jc bad_get_user GET_THREAD_INFO(%_ASM_DX) cmp TI_addr_limit(%_ASM_DX),%_ASM_AX jae bad_get_user ASM_STAC -3: movl -3(%_ASM_AX),%edx + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_DX + cmp %_ASM_DX,%_ASM_AX + jae 1234f + add %_ASM_DX,%_ASM_AX +1234: +#endif + +#endif + +3: __copyuser_seg movl -3(%_ASM_AX),%edx xor %eax,%eax ASM_CLAC + pax_force_retaddr ret CFI_ENDPROC ENDPROC(__get_user_4) @@ -86,10 +137,20 @@ ENTRY(__get_user_8) GET_THREAD_INFO(%_ASM_DX) cmp TI_addr_limit(%_ASM_DX),%_ASM_AX jae bad_get_user + +#ifdef CONFIG_PAX_MEMORY_UDEREF + mov pax_user_shadow_base,%_ASM_DX + cmp %_ASM_DX,%_ASM_AX + jae 1234f + add %_ASM_DX,%_ASM_AX +1234: +#endif + ASM_STAC 4: movq -7(%_ASM_AX),%rdx xor %eax,%eax ASM_CLAC + pax_force_retaddr ret #else add $7,%_ASM_AX @@ -98,10 +159,11 @@ ENTRY(__get_user_8) cmp TI_addr_limit(%_ASM_DX),%_ASM_AX jae bad_get_user_8 ASM_STAC -4: movl -7(%_ASM_AX),%edx -5: movl -3(%_ASM_AX),%ecx +4: __copyuser_seg movl -7(%_ASM_AX),%edx +5: __copyuser_seg movl -3(%_ASM_AX),%ecx xor %eax,%eax ASM_CLAC + pax_force_retaddr ret #endif CFI_ENDPROC @@ -113,6 +175,7 @@ bad_get_user: xor %edx,%edx mov $(-EFAULT),%_ASM_AX ASM_CLAC + pax_force_retaddr ret CFI_ENDPROC END(bad_get_user) @@ -124,6 +187,7 @@ bad_get_user_8: xor %ecx,%ecx mov $(-EFAULT),%_ASM_AX ASM_CLAC + pax_force_retaddr ret CFI_ENDPROC END(bad_get_user_8) diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 54fcffe..7be149e 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c @@ -20,8 +20,10 @@ #ifdef __KERNEL__ #include +#include #else #include +#define ktla_ktva(addr) addr #endif #include #include @@ -53,8 +55,8 @@ void insn_init(struct insn *insn, const void *kaddr, int x86_64) { memset(insn, 0, sizeof(*insn)); - insn->kaddr = kaddr; - insn->next_byte = kaddr; + insn->kaddr = ktla_ktva(kaddr); + insn->next_byte = ktla_ktva(kaddr); insn->x86_64 = x86_64 ? 1 : 0; insn->opnd_bytes = 4; if (x86_64) diff --git a/arch/x86/lib/iomap_copy_64.S b/arch/x86/lib/iomap_copy_64.S index 05a95e7..326f2fa 100644 --- a/arch/x86/lib/iomap_copy_64.S +++ b/arch/x86/lib/iomap_copy_64.S @@ -17,6 +17,7 @@ #include #include +#include /* * override generic version in lib/iomap_copy.c @@ -25,6 +26,7 @@ ENTRY(__iowrite32_copy) CFI_STARTPROC movl %edx,%ecx rep movsd + pax_force_retaddr ret CFI_ENDPROC ENDPROC(__iowrite32_copy) diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index 56313a3..9b59269 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S @@ -24,7 +24,7 @@ * This gets patched over the unrolled variant (below) via the * alternative instructions framework: */ - .section .altinstr_replacement, "ax", @progbits + .section .altinstr_replacement, "a", @progbits .Lmemcpy_c: movq %rdi, %rax movq %rdx, %rcx @@ -33,6 +33,7 @@ rep movsq movl %edx, %ecx rep movsb + pax_force_retaddr ret .Lmemcpy_e: .previous @@ -44,11 +45,12 @@ * This gets patched over the unrolled variant (below) via the * alternative instructions framework: */ - .section .altinstr_replacement, "ax", @progbits + .section .altinstr_replacement, "a", @progbits .Lmemcpy_c_e: movq %rdi, %rax movq %rdx, %rcx rep movsb + pax_force_retaddr ret .Lmemcpy_e_e: .previous @@ -76,13 +78,13 @@ ENTRY(memcpy) */ movq 0*8(%rsi), %r8 movq 1*8(%rsi), %r9 - movq 2*8(%rsi), %r10 + movq 2*8(%rsi), %rcx movq 3*8(%rsi), %r11 leaq 4*8(%rsi), %rsi movq %r8, 0*8(%rdi) movq %r9, 1*8(%rdi) - movq %r10, 2*8(%rdi) + movq %rcx, 2*8(%rdi) movq %r11, 3*8(%rdi) leaq 4*8(%rdi), %rdi jae .Lcopy_forward_loop @@ -105,12 +107,12 @@ ENTRY(memcpy) subq $0x20, %rdx movq -1*8(%rsi), %r8 movq -2*8(%rsi), %r9 - movq -3*8(%rsi), %r10 + movq -3*8(%rsi), %rcx movq -4*8(%rsi), %r11 leaq -4*8(%rsi), %rsi movq %r8, -1*8(%rdi) movq %r9, -2*8(%rdi) - movq %r10, -3*8(%rdi) + movq %rcx, -3*8(%rdi) movq %r11, -4*8(%rdi) leaq -4*8(%rdi), %rdi jae .Lcopy_backward_loop @@ -130,12 +132,13 @@ ENTRY(memcpy) */ movq 0*8(%rsi), %r8 movq 1*8(%rsi), %r9 - movq -2*8(%rsi, %rdx), %r10 + movq -2*8(%rsi, %rdx), %rcx movq -1*8(%rsi, %rdx), %r11 movq %r8, 0*8(%rdi) movq %r9, 1*8(%rdi) - movq %r10, -2*8(%rdi, %rdx) + movq %rcx, -2*8(%rdi, %rdx) movq %r11, -1*8(%rdi, %rdx) + pax_force_retaddr retq .p2align 4 .Lless_16bytes: @@ -148,6 +151,7 @@ ENTRY(memcpy) movq -1*8(%rsi, %rdx), %r9 movq %r8, 0*8(%rdi) movq %r9, -1*8(%rdi, %rdx) + pax_force_retaddr retq .p2align 4 .Lless_8bytes: @@ -161,6 +165,7 @@ ENTRY(memcpy) movl -4(%rsi, %rdx), %r8d movl %ecx, (%rdi) movl %r8d, -4(%rdi, %rdx) + pax_force_retaddr retq .p2align 4 .Lless_3bytes: @@ -179,6 +184,7 @@ ENTRY(memcpy) movb %cl, (%rdi) .Lend: + pax_force_retaddr retq CFI_ENDPROC ENDPROC(memcpy) diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S index 65268a6..5aa7815 100644 --- a/arch/x86/lib/memmove_64.S +++ b/arch/x86/lib/memmove_64.S @@ -61,13 +61,13 @@ ENTRY(memmove) 5: sub $0x20, %rdx movq 0*8(%rsi), %r11 - movq 1*8(%rsi), %r10 + movq 1*8(%rsi), %rcx movq 2*8(%rsi), %r9 movq 3*8(%rsi), %r8 leaq 4*8(%rsi), %rsi movq %r11, 0*8(%rdi) - movq %r10, 1*8(%rdi) + movq %rcx, 1*8(%rdi) movq %r9, 2*8(%rdi) movq %r8, 3*8(%rdi) leaq 4*8(%rdi), %rdi @@ -81,10 +81,10 @@ ENTRY(memmove) 4: movq %rdx, %rcx movq -8(%rsi, %rdx), %r11 - lea -8(%rdi, %rdx), %r10 + lea -8(%rdi, %rdx), %r9 shrq $3, %rcx rep movsq - movq %r11, (%r10) + movq %r11, (%r9) jmp 13f .Lmemmove_end_forward: @@ -95,14 +95,14 @@ ENTRY(memmove) 7: movq %rdx, %rcx movq (%rsi), %r11 - movq %rdi, %r10 + movq %rdi, %r9 leaq -8(%rsi, %rdx), %rsi leaq -8(%rdi, %rdx), %rdi shrq $3, %rcx std rep movsq cld - movq %r11, (%r10) + movq %r11, (%r9) jmp 13f /* @@ -127,13 +127,13 @@ ENTRY(memmove) 8: subq $0x20, %rdx movq -1*8(%rsi), %r11 - movq -2*8(%rsi), %r10 + movq -2*8(%rsi), %rcx movq -3*8(%rsi), %r9 movq -4*8(%rsi), %r8 leaq -4*8(%rsi), %rsi movq %r11, -1*8(%rdi) - movq %r10, -2*8(%rdi) + movq %rcx, -2*8(%rdi) movq %r9, -3*8(%rdi) movq %r8, -4*8(%rdi) leaq -4*8(%rdi), %rdi @@ -151,11 +151,11 @@ ENTRY(memmove) * Move data from 16 bytes to 31 bytes. */ movq 0*8(%rsi), %r11 - movq 1*8(%rsi), %r10 + movq 1*8(%rsi), %rcx movq -2*8(%rsi, %rdx), %r9 movq -1*8(%rsi, %rdx), %r8 movq %r11, 0*8(%rdi) - movq %r10, 1*8(%rdi) + movq %rcx, 1*8(%rdi) movq %r9, -2*8(%rdi, %rdx) movq %r8, -1*8(%rdi, %rdx) jmp 13f @@ -167,9 +167,9 @@ ENTRY(memmove) * Move data from 8 bytes to 15 bytes. */ movq 0*8(%rsi), %r11 - movq -1*8(%rsi, %rdx), %r10 + movq -1*8(%rsi, %rdx), %r9 movq %r11, 0*8(%rdi) - movq %r10, -1*8(%rdi, %rdx) + movq %r9, -1*8(%rdi, %rdx) jmp 13f 10: cmpq $4, %rdx @@ -178,9 +178,9 @@ ENTRY(memmove) * Move data from 4 bytes to 7 bytes. */ movl (%rsi), %r11d - movl -4(%rsi, %rdx), %r10d + movl -4(%rsi, %rdx), %r9d movl %r11d, (%rdi) - movl %r10d, -4(%rdi, %rdx) + movl %r9d, -4(%rdi, %rdx) jmp 13f 11: cmp $2, %rdx @@ -189,9 +189,9 @@ ENTRY(memmove) * Move data from 2 bytes to 3 bytes. */ movw (%rsi), %r11w - movw -2(%rsi, %rdx), %r10w + movw -2(%rsi, %rdx), %r9w movw %r11w, (%rdi) - movw %r10w, -2(%rdi, %rdx) + movw %r9w, -2(%rdi, %rdx) jmp 13f 12: cmp $1, %rdx @@ -202,14 +202,16 @@ ENTRY(memmove) movb (%rsi), %r11b movb %r11b, (%rdi) 13: + pax_force_retaddr retq CFI_ENDPROC - .section .altinstr_replacement,"ax" + .section .altinstr_replacement,"a" .Lmemmove_begin_forward_efs: /* Forward moving data. */ movq %rdx, %rcx rep movsb + pax_force_retaddr retq .Lmemmove_end_forward_efs: .previous diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S index 2dcb380..50a78bc 100644 --- a/arch/x86/lib/memset_64.S +++ b/arch/x86/lib/memset_64.S @@ -16,7 +16,7 @@ * * rax original destination */ - .section .altinstr_replacement, "ax", @progbits + .section .altinstr_replacement, "a", @progbits .Lmemset_c: movq %rdi,%r9 movq %rdx,%rcx @@ -30,6 +30,7 @@ movl %edx,%ecx rep stosb movq %r9,%rax + pax_force_retaddr ret .Lmemset_e: .previous @@ -45,13 +46,14 @@ * * rax original destination */ - .section .altinstr_replacement, "ax", @progbits + .section .altinstr_replacement, "a", @progbits .Lmemset_c_e: movq %rdi,%r9 movb %sil,%al movq %rdx,%rcx rep stosb movq %r9,%rax + pax_force_retaddr ret .Lmemset_e_e: .previous @@ -59,7 +61,7 @@ ENTRY(memset) ENTRY(__memset) CFI_STARTPROC - movq %rdi,%r10 + movq %rdi,%r11 /* expand byte value */ movzbl %sil,%ecx @@ -117,7 +119,8 @@ ENTRY(__memset) jnz .Lloop_1 .Lende: - movq %r10,%rax + movq %r11,%rax + pax_force_retaddr ret CFI_RESTORE_STATE diff --git a/arch/x86/lib/mmx_32.c b/arch/x86/lib/mmx_32.c index c9f2d9b..e7fd2c0 100644 --- a/arch/x86/lib/mmx_32.c +++ b/arch/x86/lib/mmx_32.c @@ -29,6 +29,7 @@ void *_mmx_memcpy(void *to, const void *from, size_t len) { void *p; int i; + unsigned long cr0; if (unlikely(in_interrupt())) return __memcpy(to, from, len); @@ -39,44 +40,72 @@ void *_mmx_memcpy(void *to, const void *from, size_t len) kernel_fpu_begin(); __asm__ __volatile__ ( - "1: prefetch (%0)\n" /* This set is 28 bytes */ - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" + "1: prefetch (%1)\n" /* This set is 28 bytes */ + " prefetch 64(%1)\n" + " prefetch 128(%1)\n" + " prefetch 192(%1)\n" + " prefetch 256(%1)\n" "2: \n" ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + "3: \n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" _ASM_EXTABLE(1b, 3b) - : : "r" (from)); + : "=&r" (cr0) : "r" (from) : "ax"); for ( ; i > 5; i--) { __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movq 8(%0), %%mm1\n" - " movq 16(%0), %%mm2\n" - " movq 24(%0), %%mm3\n" - " movq %%mm0, (%1)\n" - " movq %%mm1, 8(%1)\n" - " movq %%mm2, 16(%1)\n" - " movq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm0\n" - " movq 40(%0), %%mm1\n" - " movq 48(%0), %%mm2\n" - " movq 56(%0), %%mm3\n" - " movq %%mm0, 32(%1)\n" - " movq %%mm1, 40(%1)\n" - " movq %%mm2, 48(%1)\n" - " movq %%mm3, 56(%1)\n" + "1: prefetch 320(%1)\n" + "2: movq (%1), %%mm0\n" + " movq 8(%1), %%mm1\n" + " movq 16(%1), %%mm2\n" + " movq 24(%1), %%mm3\n" + " movq %%mm0, (%2)\n" + " movq %%mm1, 8(%2)\n" + " movq %%mm2, 16(%2)\n" + " movq %%mm3, 24(%2)\n" + " movq 32(%1), %%mm0\n" + " movq 40(%1), %%mm1\n" + " movq 48(%1), %%mm2\n" + " movq 56(%1), %%mm3\n" + " movq %%mm0, 32(%2)\n" + " movq %%mm1, 40(%2)\n" + " movq %%mm2, 48(%2)\n" + " movq %%mm3, 56(%2)\n" ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + "3:\n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" _ASM_EXTABLE(1b, 3b) - : : "r" (from), "r" (to) : "memory"); + : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); from += 64; to += 64; @@ -158,6 +187,7 @@ static void fast_clear_page(void *page) static void fast_copy_page(void *to, void *from) { int i; + unsigned long cr0; kernel_fpu_begin(); @@ -166,42 +196,70 @@ static void fast_copy_page(void *to, void *from) * but that is for later. -AV */ __asm__ __volatile__( - "1: prefetch (%0)\n" - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" + "1: prefetch (%1)\n" + " prefetch 64(%1)\n" + " prefetch 128(%1)\n" + " prefetch 192(%1)\n" + " prefetch 256(%1)\n" "2: \n" ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + "3: \n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" - _ASM_EXTABLE(1b, 3b) : : "r" (from)); + _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from) : "ax"); for (i = 0; i < (4096-320)/64; i++) { __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movntq %%mm0, (%1)\n" - " movq 8(%0), %%mm1\n" - " movntq %%mm1, 8(%1)\n" - " movq 16(%0), %%mm2\n" - " movntq %%mm2, 16(%1)\n" - " movq 24(%0), %%mm3\n" - " movntq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm4\n" - " movntq %%mm4, 32(%1)\n" - " movq 40(%0), %%mm5\n" - " movntq %%mm5, 40(%1)\n" - " movq 48(%0), %%mm6\n" - " movntq %%mm6, 48(%1)\n" - " movq 56(%0), %%mm7\n" - " movntq %%mm7, 56(%1)\n" + "1: prefetch 320(%1)\n" + "2: movq (%1), %%mm0\n" + " movntq %%mm0, (%2)\n" + " movq 8(%1), %%mm1\n" + " movntq %%mm1, 8(%2)\n" + " movq 16(%1), %%mm2\n" + " movntq %%mm2, 16(%2)\n" + " movq 24(%1), %%mm3\n" + " movntq %%mm3, 24(%2)\n" + " movq 32(%1), %%mm4\n" + " movntq %%mm4, 32(%2)\n" + " movq 40(%1), %%mm5\n" + " movntq %%mm5, 40(%2)\n" + " movq 48(%1), %%mm6\n" + " movntq %%mm6, 48(%2)\n" + " movq 56(%1), %%mm7\n" + " movntq %%mm7, 56(%2)\n" ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + "3:\n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" - _ASM_EXTABLE(1b, 3b) : : "r" (from), "r" (to) : "memory"); + _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); from += 64; to += 64; @@ -280,47 +338,76 @@ static void fast_clear_page(void *page) static void fast_copy_page(void *to, void *from) { int i; + unsigned long cr0; kernel_fpu_begin(); __asm__ __volatile__ ( - "1: prefetch (%0)\n" - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" + "1: prefetch (%1)\n" + " prefetch 64(%1)\n" + " prefetch 128(%1)\n" + " prefetch 192(%1)\n" + " prefetch 256(%1)\n" "2: \n" ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + "3: \n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" - _ASM_EXTABLE(1b, 3b) : : "r" (from)); + _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from) : "ax"); for (i = 0; i < 4096/64; i++) { __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movq 8(%0), %%mm1\n" - " movq 16(%0), %%mm2\n" - " movq 24(%0), %%mm3\n" - " movq %%mm0, (%1)\n" - " movq %%mm1, 8(%1)\n" - " movq %%mm2, 16(%1)\n" - " movq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm0\n" - " movq 40(%0), %%mm1\n" - " movq 48(%0), %%mm2\n" - " movq 56(%0), %%mm3\n" - " movq %%mm0, 32(%1)\n" - " movq %%mm1, 40(%1)\n" - " movq %%mm2, 48(%1)\n" - " movq %%mm3, 56(%1)\n" + "1: prefetch 320(%1)\n" + "2: movq (%1), %%mm0\n" + " movq 8(%1), %%mm1\n" + " movq 16(%1), %%mm2\n" + " movq 24(%1), %%mm3\n" + " movq %%mm0, (%2)\n" + " movq %%mm1, 8(%2)\n" + " movq %%mm2, 16(%2)\n" + " movq %%mm3, 24(%2)\n" + " movq 32(%1), %%mm0\n" + " movq 40(%1), %%mm1\n" + " movq 48(%1), %%mm2\n" + " movq 56(%1), %%mm3\n" + " movq %%mm0, 32(%2)\n" + " movq %%mm1, 40(%2)\n" + " movq %%mm2, 48(%2)\n" + " movq %%mm3, 56(%2)\n" ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + "3:\n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" _ASM_EXTABLE(1b, 3b) - : : "r" (from), "r" (to) : "memory"); + : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); from += 64; to += 64; diff --git a/arch/x86/lib/msr-reg.S b/arch/x86/lib/msr-reg.S index f6d13ee..aca5f0b 100644 --- a/arch/x86/lib/msr-reg.S +++ b/arch/x86/lib/msr-reg.S @@ -3,6 +3,7 @@ #include #include #include +#include #ifdef CONFIG_X86_64 /* @@ -16,7 +17,7 @@ ENTRY(\op\()_safe_regs) CFI_STARTPROC pushq_cfi %rbx pushq_cfi %rbp - movq %rdi, %r10 /* Save pointer */ + movq %rdi, %r9 /* Save pointer */ xorl %r11d, %r11d /* Return value */ movl (%rdi), %eax movl 4(%rdi), %ecx @@ -27,16 +28,17 @@ ENTRY(\op\()_safe_regs) movl 28(%rdi), %edi CFI_REMEMBER_STATE 1: \op -2: movl %eax, (%r10) +2: movl %eax, (%r9) movl %r11d, %eax /* Return value */ - movl %ecx, 4(%r10) - movl %edx, 8(%r10) - movl %ebx, 12(%r10) - movl %ebp, 20(%r10) - movl %esi, 24(%r10) - movl %edi, 28(%r10) + movl %ecx, 4(%r9) + movl %edx, 8(%r9) + movl %ebx, 12(%r9) + movl %ebp, 20(%r9) + movl %esi, 24(%r9) + movl %edi, 28(%r9) popq_cfi %rbp popq_cfi %rbx + pax_force_retaddr ret 3: CFI_RESTORE_STATE diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S index fc6ba17..d4d989d 100644 --- a/arch/x86/lib/putuser.S +++ b/arch/x86/lib/putuser.S @@ -16,7 +16,9 @@ #include #include #include - +#include +#include +#include /* * __put_user_X @@ -30,57 +32,125 @@ * as they get called from within inline assembly. */ -#define ENTER CFI_STARTPROC ; \ - GET_THREAD_INFO(%_ASM_BX) -#define EXIT ASM_CLAC ; \ - ret ; \ +#define ENTER CFI_STARTPROC +#define EXIT ASM_CLAC ; \ + pax_force_retaddr ; \ + ret ; \ CFI_ENDPROC +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define _DEST %_ASM_CX,%_ASM_BX +#else +#define _DEST %_ASM_CX +#endif + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_MEMORY_UDEREF) +#define __copyuser_seg gs; +#else +#define __copyuser_seg +#endif + .text ENTRY(__put_user_1) ENTER + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) + GET_THREAD_INFO(%_ASM_BX) cmp TI_addr_limit(%_ASM_BX),%_ASM_CX jae bad_put_user ASM_STAC -1: movb %al,(%_ASM_CX) + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_BX + cmp %_ASM_BX,%_ASM_CX + jb 1234f + xor %ebx,%ebx +1234: +#endif + +#endif + +1: __copyuser_seg movb %al,(_DEST) xor %eax,%eax EXIT ENDPROC(__put_user_1) ENTRY(__put_user_2) ENTER + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) + GET_THREAD_INFO(%_ASM_BX) mov TI_addr_limit(%_ASM_BX),%_ASM_BX sub $1,%_ASM_BX cmp %_ASM_BX,%_ASM_CX jae bad_put_user ASM_STAC -2: movw %ax,(%_ASM_CX) + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_BX + cmp %_ASM_BX,%_ASM_CX + jb 1234f + xor %ebx,%ebx +1234: +#endif + +#endif + +2: __copyuser_seg movw %ax,(_DEST) xor %eax,%eax EXIT ENDPROC(__put_user_2) ENTRY(__put_user_4) ENTER + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) + GET_THREAD_INFO(%_ASM_BX) mov TI_addr_limit(%_ASM_BX),%_ASM_BX sub $3,%_ASM_BX cmp %_ASM_BX,%_ASM_CX jae bad_put_user ASM_STAC -3: movl %eax,(%_ASM_CX) + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_BX + cmp %_ASM_BX,%_ASM_CX + jb 1234f + xor %ebx,%ebx +1234: +#endif + +#endif + +3: __copyuser_seg movl %eax,(_DEST) xor %eax,%eax EXIT ENDPROC(__put_user_4) ENTRY(__put_user_8) ENTER + +#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_MEMORY_UDEREF) + GET_THREAD_INFO(%_ASM_BX) mov TI_addr_limit(%_ASM_BX),%_ASM_BX sub $7,%_ASM_BX cmp %_ASM_BX,%_ASM_CX jae bad_put_user ASM_STAC -4: mov %_ASM_AX,(%_ASM_CX) + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + mov pax_user_shadow_base,%_ASM_BX + cmp %_ASM_BX,%_ASM_CX + jb 1234f + xor %ebx,%ebx +1234: +#endif + +#endif + +4: __copyuser_seg mov %_ASM_AX,(_DEST) #ifdef CONFIG_X86_32 -5: movl %edx,4(%_ASM_CX) +5: __copyuser_seg movl %edx,4(_DEST) #endif xor %eax,%eax EXIT diff --git a/arch/x86/lib/rwlock.S b/arch/x86/lib/rwlock.S index 1cad221..de671ee 100644 --- a/arch/x86/lib/rwlock.S +++ b/arch/x86/lib/rwlock.S @@ -16,13 +16,34 @@ ENTRY(__write_lock_failed) FRAME 0: LOCK_PREFIX WRITE_LOCK_ADD($RW_LOCK_BIAS) (%__lock_ptr) + +#ifdef CONFIG_PAX_REFCOUNT + jno 1234f + LOCK_PREFIX + WRITE_LOCK_SUB($RW_LOCK_BIAS) (%__lock_ptr) + int $4 +1234: + _ASM_EXTABLE(1234b, 1234b) +#endif + 1: rep; nop cmpl $WRITE_LOCK_CMP, (%__lock_ptr) jne 1b LOCK_PREFIX WRITE_LOCK_SUB($RW_LOCK_BIAS) (%__lock_ptr) + +#ifdef CONFIG_PAX_REFCOUNT + jno 1234f + LOCK_PREFIX + WRITE_LOCK_ADD($RW_LOCK_BIAS) (%__lock_ptr) + int $4 +1234: + _ASM_EXTABLE(1234b, 1234b) +#endif + jnz 0b ENDFRAME + pax_force_retaddr ret CFI_ENDPROC END(__write_lock_failed) @@ -32,13 +53,34 @@ ENTRY(__read_lock_failed) FRAME 0: LOCK_PREFIX READ_LOCK_SIZE(inc) (%__lock_ptr) + +#ifdef CONFIG_PAX_REFCOUNT + jno 1234f + LOCK_PREFIX + READ_LOCK_SIZE(dec) (%__lock_ptr) + int $4 +1234: + _ASM_EXTABLE(1234b, 1234b) +#endif + 1: rep; nop READ_LOCK_SIZE(cmp) $1, (%__lock_ptr) js 1b LOCK_PREFIX READ_LOCK_SIZE(dec) (%__lock_ptr) + +#ifdef CONFIG_PAX_REFCOUNT + jno 1234f + LOCK_PREFIX + READ_LOCK_SIZE(inc) (%__lock_ptr) + int $4 +1234: + _ASM_EXTABLE(1234b, 1234b) +#endif + js 0b ENDFRAME + pax_force_retaddr ret CFI_ENDPROC END(__read_lock_failed) diff --git a/arch/x86/lib/rwsem.S b/arch/x86/lib/rwsem.S index 5dff5f0..cadebf4 100644 --- a/arch/x86/lib/rwsem.S +++ b/arch/x86/lib/rwsem.S @@ -94,6 +94,7 @@ ENTRY(call_rwsem_down_read_failed) __ASM_SIZE(pop,_cfi) %__ASM_REG(dx) CFI_RESTORE __ASM_REG(dx) restore_common_regs + pax_force_retaddr ret CFI_ENDPROC ENDPROC(call_rwsem_down_read_failed) @@ -104,6 +105,7 @@ ENTRY(call_rwsem_down_write_failed) movq %rax,%rdi call rwsem_down_write_failed restore_common_regs + pax_force_retaddr ret CFI_ENDPROC ENDPROC(call_rwsem_down_write_failed) @@ -117,7 +119,8 @@ ENTRY(call_rwsem_wake) movq %rax,%rdi call rwsem_wake restore_common_regs -1: ret +1: pax_force_retaddr + ret CFI_ENDPROC ENDPROC(call_rwsem_wake) @@ -131,6 +134,7 @@ ENTRY(call_rwsem_downgrade_wake) __ASM_SIZE(pop,_cfi) %__ASM_REG(dx) CFI_RESTORE __ASM_REG(dx) restore_common_regs + pax_force_retaddr ret CFI_ENDPROC ENDPROC(call_rwsem_downgrade_wake) diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S index a63efd6..ccecad8 100644 --- a/arch/x86/lib/thunk_64.S +++ b/arch/x86/lib/thunk_64.S @@ -8,6 +8,7 @@ #include #include #include +#include /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ .macro THUNK name, func, put_ret_addr_in_rdi=0 @@ -41,5 +42,6 @@ SAVE_ARGS restore: RESTORE_ARGS + pax_force_retaddr ret CFI_ENDPROC diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 3eb18ac..6890bc3 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c @@ -42,11 +42,13 @@ do { \ int __d0; \ might_fault(); \ __asm__ __volatile__( \ + __COPYUSER_SET_ES \ ASM_STAC "\n" \ "0: rep; stosl\n" \ " movl %2,%0\n" \ "1: rep; stosb\n" \ "2: " ASM_CLAC "\n" \ + __COPYUSER_RESTORE_ES \ ".section .fixup,\"ax\"\n" \ "3: lea 0(%2,%0,4),%0\n" \ " jmp 2b\n" \ @@ -98,7 +100,7 @@ EXPORT_SYMBOL(__clear_user); #ifdef CONFIG_X86_INTEL_USERCOPY static unsigned long -__copy_user_intel(void __user *to, const void *from, unsigned long size) +__generic_copy_to_user_intel(void __user *to, const void *from, unsigned long size) { int d0, d1; __asm__ __volatile__( @@ -110,36 +112,36 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size) " .align 2,0x90\n" "3: movl 0(%4), %%eax\n" "4: movl 4(%4), %%edx\n" - "5: movl %%eax, 0(%3)\n" - "6: movl %%edx, 4(%3)\n" + "5: "__copyuser_seg" movl %%eax, 0(%3)\n" + "6: "__copyuser_seg" movl %%edx, 4(%3)\n" "7: movl 8(%4), %%eax\n" "8: movl 12(%4),%%edx\n" - "9: movl %%eax, 8(%3)\n" - "10: movl %%edx, 12(%3)\n" + "9: "__copyuser_seg" movl %%eax, 8(%3)\n" + "10: "__copyuser_seg" movl %%edx, 12(%3)\n" "11: movl 16(%4), %%eax\n" "12: movl 20(%4), %%edx\n" - "13: movl %%eax, 16(%3)\n" - "14: movl %%edx, 20(%3)\n" + "13: "__copyuser_seg" movl %%eax, 16(%3)\n" + "14: "__copyuser_seg" movl %%edx, 20(%3)\n" "15: movl 24(%4), %%eax\n" "16: movl 28(%4), %%edx\n" - "17: movl %%eax, 24(%3)\n" - "18: movl %%edx, 28(%3)\n" + "17: "__copyuser_seg" movl %%eax, 24(%3)\n" + "18: "__copyuser_seg" movl %%edx, 28(%3)\n" "19: movl 32(%4), %%eax\n" "20: movl 36(%4), %%edx\n" - "21: movl %%eax, 32(%3)\n" - "22: movl %%edx, 36(%3)\n" + "21: "__copyuser_seg" movl %%eax, 32(%3)\n" + "22: "__copyuser_seg" movl %%edx, 36(%3)\n" "23: movl 40(%4), %%eax\n" "24: movl 44(%4), %%edx\n" - "25: movl %%eax, 40(%3)\n" - "26: movl %%edx, 44(%3)\n" + "25: "__copyuser_seg" movl %%eax, 40(%3)\n" + "26: "__copyuser_seg" movl %%edx, 44(%3)\n" "27: movl 48(%4), %%eax\n" "28: movl 52(%4), %%edx\n" - "29: movl %%eax, 48(%3)\n" - "30: movl %%edx, 52(%3)\n" + "29: "__copyuser_seg" movl %%eax, 48(%3)\n" + "30: "__copyuser_seg" movl %%edx, 52(%3)\n" "31: movl 56(%4), %%eax\n" "32: movl 60(%4), %%edx\n" - "33: movl %%eax, 56(%3)\n" - "34: movl %%edx, 60(%3)\n" + "33: "__copyuser_seg" movl %%eax, 56(%3)\n" + "34: "__copyuser_seg" movl %%edx, 60(%3)\n" " addl $-64, %0\n" " addl $64, %4\n" " addl $64, %3\n" @@ -149,10 +151,12 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size) " shrl $2, %0\n" " andl $3, %%eax\n" " cld\n" + __COPYUSER_SET_ES "99: rep; movsl\n" "36: movl %%eax, %0\n" "37: rep; movsb\n" "100:\n" + __COPYUSER_RESTORE_ES ".section .fixup,\"ax\"\n" "101: lea 0(%%eax,%0,4),%0\n" " jmp 100b\n" @@ -202,46 +206,150 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size) } static unsigned long +__generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size) +{ + int d0, d1; + __asm__ __volatile__( + " .align 2,0x90\n" + "1: "__copyuser_seg" movl 32(%4), %%eax\n" + " cmpl $67, %0\n" + " jbe 3f\n" + "2: "__copyuser_seg" movl 64(%4), %%eax\n" + " .align 2,0x90\n" + "3: "__copyuser_seg" movl 0(%4), %%eax\n" + "4: "__copyuser_seg" movl 4(%4), %%edx\n" + "5: movl %%eax, 0(%3)\n" + "6: movl %%edx, 4(%3)\n" + "7: "__copyuser_seg" movl 8(%4), %%eax\n" + "8: "__copyuser_seg" movl 12(%4),%%edx\n" + "9: movl %%eax, 8(%3)\n" + "10: movl %%edx, 12(%3)\n" + "11: "__copyuser_seg" movl 16(%4), %%eax\n" + "12: "__copyuser_seg" movl 20(%4), %%edx\n" + "13: movl %%eax, 16(%3)\n" + "14: movl %%edx, 20(%3)\n" + "15: "__copyuser_seg" movl 24(%4), %%eax\n" + "16: "__copyuser_seg" movl 28(%4), %%edx\n" + "17: movl %%eax, 24(%3)\n" + "18: movl %%edx, 28(%3)\n" + "19: "__copyuser_seg" movl 32(%4), %%eax\n" + "20: "__copyuser_seg" movl 36(%4), %%edx\n" + "21: movl %%eax, 32(%3)\n" + "22: movl %%edx, 36(%3)\n" + "23: "__copyuser_seg" movl 40(%4), %%eax\n" + "24: "__copyuser_seg" movl 44(%4), %%edx\n" + "25: movl %%eax, 40(%3)\n" + "26: movl %%edx, 44(%3)\n" + "27: "__copyuser_seg" movl 48(%4), %%eax\n" + "28: "__copyuser_seg" movl 52(%4), %%edx\n" + "29: movl %%eax, 48(%3)\n" + "30: movl %%edx, 52(%3)\n" + "31: "__copyuser_seg" movl 56(%4), %%eax\n" + "32: "__copyuser_seg" movl 60(%4), %%edx\n" + "33: movl %%eax, 56(%3)\n" + "34: movl %%edx, 60(%3)\n" + " addl $-64, %0\n" + " addl $64, %4\n" + " addl $64, %3\n" + " cmpl $63, %0\n" + " ja 1b\n" + "35: movl %0, %%eax\n" + " shrl $2, %0\n" + " andl $3, %%eax\n" + " cld\n" + "99: rep; "__copyuser_seg" movsl\n" + "36: movl %%eax, %0\n" + "37: rep; "__copyuser_seg" movsb\n" + "100:\n" + ".section .fixup,\"ax\"\n" + "101: lea 0(%%eax,%0,4),%0\n" + " jmp 100b\n" + ".previous\n" + _ASM_EXTABLE(1b,100b) + _ASM_EXTABLE(2b,100b) + _ASM_EXTABLE(3b,100b) + _ASM_EXTABLE(4b,100b) + _ASM_EXTABLE(5b,100b) + _ASM_EXTABLE(6b,100b) + _ASM_EXTABLE(7b,100b) + _ASM_EXTABLE(8b,100b) + _ASM_EXTABLE(9b,100b) + _ASM_EXTABLE(10b,100b) + _ASM_EXTABLE(11b,100b) + _ASM_EXTABLE(12b,100b) + _ASM_EXTABLE(13b,100b) + _ASM_EXTABLE(14b,100b) + _ASM_EXTABLE(15b,100b) + _ASM_EXTABLE(16b,100b) + _ASM_EXTABLE(17b,100b) + _ASM_EXTABLE(18b,100b) + _ASM_EXTABLE(19b,100b) + _ASM_EXTABLE(20b,100b) + _ASM_EXTABLE(21b,100b) + _ASM_EXTABLE(22b,100b) + _ASM_EXTABLE(23b,100b) + _ASM_EXTABLE(24b,100b) + _ASM_EXTABLE(25b,100b) + _ASM_EXTABLE(26b,100b) + _ASM_EXTABLE(27b,100b) + _ASM_EXTABLE(28b,100b) + _ASM_EXTABLE(29b,100b) + _ASM_EXTABLE(30b,100b) + _ASM_EXTABLE(31b,100b) + _ASM_EXTABLE(32b,100b) + _ASM_EXTABLE(33b,100b) + _ASM_EXTABLE(34b,100b) + _ASM_EXTABLE(35b,100b) + _ASM_EXTABLE(36b,100b) + _ASM_EXTABLE(37b,100b) + _ASM_EXTABLE(99b,101b) + : "=&c"(size), "=&D" (d0), "=&S" (d1) + : "1"(to), "2"(from), "0"(size) + : "eax", "edx", "memory"); + return size; +} + +static unsigned long __size_overflow(3) __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size) { int d0, d1; __asm__ __volatile__( " .align 2,0x90\n" - "0: movl 32(%4), %%eax\n" + "0: "__copyuser_seg" movl 32(%4), %%eax\n" " cmpl $67, %0\n" " jbe 2f\n" - "1: movl 64(%4), %%eax\n" + "1: "__copyuser_seg" movl 64(%4), %%eax\n" " .align 2,0x90\n" - "2: movl 0(%4), %%eax\n" - "21: movl 4(%4), %%edx\n" + "2: "__copyuser_seg" movl 0(%4), %%eax\n" + "21: "__copyuser_seg" movl 4(%4), %%edx\n" " movl %%eax, 0(%3)\n" " movl %%edx, 4(%3)\n" - "3: movl 8(%4), %%eax\n" - "31: movl 12(%4),%%edx\n" + "3: "__copyuser_seg" movl 8(%4), %%eax\n" + "31: "__copyuser_seg" movl 12(%4),%%edx\n" " movl %%eax, 8(%3)\n" " movl %%edx, 12(%3)\n" - "4: movl 16(%4), %%eax\n" - "41: movl 20(%4), %%edx\n" + "4: "__copyuser_seg" movl 16(%4), %%eax\n" + "41: "__copyuser_seg" movl 20(%4), %%edx\n" " movl %%eax, 16(%3)\n" " movl %%edx, 20(%3)\n" - "10: movl 24(%4), %%eax\n" - "51: movl 28(%4), %%edx\n" + "10: "__copyuser_seg" movl 24(%4), %%eax\n" + "51: "__copyuser_seg" movl 28(%4), %%edx\n" " movl %%eax, 24(%3)\n" " movl %%edx, 28(%3)\n" - "11: movl 32(%4), %%eax\n" - "61: movl 36(%4), %%edx\n" + "11: "__copyuser_seg" movl 32(%4), %%eax\n" + "61: "__copyuser_seg" movl 36(%4), %%edx\n" " movl %%eax, 32(%3)\n" " movl %%edx, 36(%3)\n" - "12: movl 40(%4), %%eax\n" - "71: movl 44(%4), %%edx\n" + "12: "__copyuser_seg" movl 40(%4), %%eax\n" + "71: "__copyuser_seg" movl 44(%4), %%edx\n" " movl %%eax, 40(%3)\n" " movl %%edx, 44(%3)\n" - "13: movl 48(%4), %%eax\n" - "81: movl 52(%4), %%edx\n" + "13: "__copyuser_seg" movl 48(%4), %%eax\n" + "81: "__copyuser_seg" movl 52(%4), %%edx\n" " movl %%eax, 48(%3)\n" " movl %%edx, 52(%3)\n" - "14: movl 56(%4), %%eax\n" - "91: movl 60(%4), %%edx\n" + "14: "__copyuser_seg" movl 56(%4), %%eax\n" + "91: "__copyuser_seg" movl 60(%4), %%edx\n" " movl %%eax, 56(%3)\n" " movl %%edx, 60(%3)\n" " addl $-64, %0\n" @@ -253,9 +361,9 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size) " shrl $2, %0\n" " andl $3, %%eax\n" " cld\n" - "6: rep; movsl\n" + "6: rep; "__copyuser_seg" movsl\n" " movl %%eax,%0\n" - "7: rep; movsb\n" + "7: rep; "__copyuser_seg" movsb\n" "8:\n" ".section .fixup,\"ax\"\n" "9: lea 0(%%eax,%0,4),%0\n" @@ -298,48 +406,48 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size) * hyoshiok@miraclelinux.com */ -static unsigned long __copy_user_zeroing_intel_nocache(void *to, +static unsigned long __size_overflow(3) __copy_user_zeroing_intel_nocache(void *to, const void __user *from, unsigned long size) { int d0, d1; __asm__ __volatile__( " .align 2,0x90\n" - "0: movl 32(%4), %%eax\n" + "0: "__copyuser_seg" movl 32(%4), %%eax\n" " cmpl $67, %0\n" " jbe 2f\n" - "1: movl 64(%4), %%eax\n" + "1: "__copyuser_seg" movl 64(%4), %%eax\n" " .align 2,0x90\n" - "2: movl 0(%4), %%eax\n" - "21: movl 4(%4), %%edx\n" + "2: "__copyuser_seg" movl 0(%4), %%eax\n" + "21: "__copyuser_seg" movl 4(%4), %%edx\n" " movnti %%eax, 0(%3)\n" " movnti %%edx, 4(%3)\n" - "3: movl 8(%4), %%eax\n" - "31: movl 12(%4),%%edx\n" + "3: "__copyuser_seg" movl 8(%4), %%eax\n" + "31: "__copyuser_seg" movl 12(%4),%%edx\n" " movnti %%eax, 8(%3)\n" " movnti %%edx, 12(%3)\n" - "4: movl 16(%4), %%eax\n" - "41: movl 20(%4), %%edx\n" + "4: "__copyuser_seg" movl 16(%4), %%eax\n" + "41: "__copyuser_seg" movl 20(%4), %%edx\n" " movnti %%eax, 16(%3)\n" " movnti %%edx, 20(%3)\n" - "10: movl 24(%4), %%eax\n" - "51: movl 28(%4), %%edx\n" + "10: "__copyuser_seg" movl 24(%4), %%eax\n" + "51: "__copyuser_seg" movl 28(%4), %%edx\n" " movnti %%eax, 24(%3)\n" " movnti %%edx, 28(%3)\n" - "11: movl 32(%4), %%eax\n" - "61: movl 36(%4), %%edx\n" + "11: "__copyuser_seg" movl 32(%4), %%eax\n" + "61: "__copyuser_seg" movl 36(%4), %%edx\n" " movnti %%eax, 32(%3)\n" " movnti %%edx, 36(%3)\n" - "12: movl 40(%4), %%eax\n" - "71: movl 44(%4), %%edx\n" + "12: "__copyuser_seg" movl 40(%4), %%eax\n" + "71: "__copyuser_seg" movl 44(%4), %%edx\n" " movnti %%eax, 40(%3)\n" " movnti %%edx, 44(%3)\n" - "13: movl 48(%4), %%eax\n" - "81: movl 52(%4), %%edx\n" + "13: "__copyuser_seg" movl 48(%4), %%eax\n" + "81: "__copyuser_seg" movl 52(%4), %%edx\n" " movnti %%eax, 48(%3)\n" " movnti %%edx, 52(%3)\n" - "14: movl 56(%4), %%eax\n" - "91: movl 60(%4), %%edx\n" + "14: "__copyuser_seg" movl 56(%4), %%eax\n" + "91: "__copyuser_seg" movl 60(%4), %%edx\n" " movnti %%eax, 56(%3)\n" " movnti %%edx, 60(%3)\n" " addl $-64, %0\n" @@ -352,9 +460,9 @@ static unsigned long __copy_user_zeroing_intel_nocache(void *to, " shrl $2, %0\n" " andl $3, %%eax\n" " cld\n" - "6: rep; movsl\n" + "6: rep; "__copyuser_seg" movsl\n" " movl %%eax,%0\n" - "7: rep; movsb\n" + "7: rep; "__copyuser_seg" movsb\n" "8:\n" ".section .fixup,\"ax\"\n" "9: lea 0(%%eax,%0,4),%0\n" @@ -392,48 +500,48 @@ static unsigned long __copy_user_zeroing_intel_nocache(void *to, return size; } -static unsigned long __copy_user_intel_nocache(void *to, +static unsigned long __size_overflow(3) __copy_user_intel_nocache(void *to, const void __user *from, unsigned long size) { int d0, d1; __asm__ __volatile__( " .align 2,0x90\n" - "0: movl 32(%4), %%eax\n" + "0: "__copyuser_seg" movl 32(%4), %%eax\n" " cmpl $67, %0\n" " jbe 2f\n" - "1: movl 64(%4), %%eax\n" + "1: "__copyuser_seg" movl 64(%4), %%eax\n" " .align 2,0x90\n" - "2: movl 0(%4), %%eax\n" - "21: movl 4(%4), %%edx\n" + "2: "__copyuser_seg" movl 0(%4), %%eax\n" + "21: "__copyuser_seg" movl 4(%4), %%edx\n" " movnti %%eax, 0(%3)\n" " movnti %%edx, 4(%3)\n" - "3: movl 8(%4), %%eax\n" - "31: movl 12(%4),%%edx\n" + "3: "__copyuser_seg" movl 8(%4), %%eax\n" + "31: "__copyuser_seg" movl 12(%4),%%edx\n" " movnti %%eax, 8(%3)\n" " movnti %%edx, 12(%3)\n" - "4: movl 16(%4), %%eax\n" - "41: movl 20(%4), %%edx\n" + "4: "__copyuser_seg" movl 16(%4), %%eax\n" + "41: "__copyuser_seg" movl 20(%4), %%edx\n" " movnti %%eax, 16(%3)\n" " movnti %%edx, 20(%3)\n" - "10: movl 24(%4), %%eax\n" - "51: movl 28(%4), %%edx\n" + "10: "__copyuser_seg" movl 24(%4), %%eax\n" + "51: "__copyuser_seg" movl 28(%4), %%edx\n" " movnti %%eax, 24(%3)\n" " movnti %%edx, 28(%3)\n" - "11: movl 32(%4), %%eax\n" - "61: movl 36(%4), %%edx\n" + "11: "__copyuser_seg" movl 32(%4), %%eax\n" + "61: "__copyuser_seg" movl 36(%4), %%edx\n" " movnti %%eax, 32(%3)\n" " movnti %%edx, 36(%3)\n" - "12: movl 40(%4), %%eax\n" - "71: movl 44(%4), %%edx\n" + "12: "__copyuser_seg" movl 40(%4), %%eax\n" + "71: "__copyuser_seg" movl 44(%4), %%edx\n" " movnti %%eax, 40(%3)\n" " movnti %%edx, 44(%3)\n" - "13: movl 48(%4), %%eax\n" - "81: movl 52(%4), %%edx\n" + "13: "__copyuser_seg" movl 48(%4), %%eax\n" + "81: "__copyuser_seg" movl 52(%4), %%edx\n" " movnti %%eax, 48(%3)\n" " movnti %%edx, 52(%3)\n" - "14: movl 56(%4), %%eax\n" - "91: movl 60(%4), %%edx\n" + "14: "__copyuser_seg" movl 56(%4), %%eax\n" + "91: "__copyuser_seg" movl 60(%4), %%edx\n" " movnti %%eax, 56(%3)\n" " movnti %%edx, 60(%3)\n" " addl $-64, %0\n" @@ -446,9 +554,9 @@ static unsigned long __copy_user_intel_nocache(void *to, " shrl $2, %0\n" " andl $3, %%eax\n" " cld\n" - "6: rep; movsl\n" + "6: rep; "__copyuser_seg" movsl\n" " movl %%eax,%0\n" - "7: rep; movsb\n" + "7: rep; "__copyuser_seg" movsb\n" "8:\n" ".section .fixup,\"ax\"\n" "9: lea 0(%%eax,%0,4),%0\n" @@ -488,32 +596,36 @@ static unsigned long __copy_user_intel_nocache(void *to, */ unsigned long __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size); -unsigned long __copy_user_intel(void __user *to, const void *from, +unsigned long __generic_copy_to_user_intel(void __user *to, const void *from, + unsigned long size); +unsigned long __generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size); unsigned long __copy_user_zeroing_intel_nocache(void *to, const void __user *from, unsigned long size); #endif /* CONFIG_X86_INTEL_USERCOPY */ /* Generic arbitrary sized copy. */ -#define __copy_user(to, from, size) \ +#define __copy_user(to, from, size, prefix, set, restore) \ do { \ int __d0, __d1, __d2; \ __asm__ __volatile__( \ + set \ " cmp $7,%0\n" \ " jbe 1f\n" \ " movl %1,%0\n" \ " negl %0\n" \ " andl $7,%0\n" \ " subl %0,%3\n" \ - "4: rep; movsb\n" \ + "4: rep; "prefix"movsb\n" \ " movl %3,%0\n" \ " shrl $2,%0\n" \ " andl $3,%3\n" \ " .align 2,0x90\n" \ - "0: rep; movsl\n" \ + "0: rep; "prefix"movsl\n" \ " movl %3,%0\n" \ - "1: rep; movsb\n" \ + "1: rep; "prefix"movsb\n" \ "2:\n" \ + restore \ ".section .fixup,\"ax\"\n" \ "5: addl %3,%0\n" \ " jmp 2b\n" \ @@ -538,14 +650,14 @@ do { \ " negl %0\n" \ " andl $7,%0\n" \ " subl %0,%3\n" \ - "4: rep; movsb\n" \ + "4: rep; "__copyuser_seg"movsb\n" \ " movl %3,%0\n" \ " shrl $2,%0\n" \ " andl $3,%3\n" \ " .align 2,0x90\n" \ - "0: rep; movsl\n" \ + "0: rep; "__copyuser_seg"movsl\n" \ " movl %3,%0\n" \ - "1: rep; movsb\n" \ + "1: rep; "__copyuser_seg"movsb\n" \ "2:\n" \ ".section .fixup,\"ax\"\n" \ "5: addl %3,%0\n" \ @@ -572,9 +684,9 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from, { stac(); if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); + __copy_user(to, from, n, "", __COPYUSER_SET_ES, __COPYUSER_RESTORE_ES); else - n = __copy_user_intel(to, from, n); + n = __generic_copy_to_user_intel(to, from, n); clac(); return n; } @@ -598,10 +710,9 @@ unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from, { stac(); if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); + __copy_user(to, from, n, __copyuser_seg, "", ""); else - n = __copy_user_intel((void __user *)to, - (const void *)from, n); + n = __generic_copy_from_user_intel(to, from, n); clac(); return n; } @@ -632,60 +743,38 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr if (n > 64 && cpu_has_xmm2) n = __copy_user_intel_nocache(to, from, n); else - __copy_user(to, from, n); + __copy_user(to, from, n, __copyuser_seg, "", ""); #else - __copy_user(to, from, n); + __copy_user(to, from, n, __copyuser_seg, "", ""); #endif clac(); return n; } EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero); -/** - * copy_to_user: - Copy a block of data into user space. - * @to: Destination address, in user space. - * @from: Source address, in kernel space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep. - * - * Copy data from kernel space to user space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -unsigned long -copy_to_user(void __user *to, const void *from, unsigned long n) +#ifdef CONFIG_PAX_MEMORY_UDEREF +void __set_fs(mm_segment_t x) { - if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); - return n; + switch (x.seg) { + case 0: + loadsegment(gs, 0); + break; + case TASK_SIZE_MAX: + loadsegment(gs, __USER_DS); + break; + case -1UL: + loadsegment(gs, __KERNEL_DS); + break; + default: + BUG(); + } } -EXPORT_SYMBOL(copy_to_user); +EXPORT_SYMBOL(__set_fs); -/** - * copy_from_user: - Copy a block of data from user space. - * @to: Destination address, in kernel space. - * @from: Source address, in user space. - * @n: Number of bytes to copy. - * - * Context: User context only. This function may sleep. - * - * Copy data from user space to kernel space. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -unsigned long -_copy_from_user(void *to, const void __user *from, unsigned long n) +void set_fs(mm_segment_t x) { - if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); - else - memset(to, 0, n); - return n; + current_thread_info()->addr_limit = x; + __set_fs(x); } -EXPORT_SYMBOL(_copy_from_user); +EXPORT_SYMBOL(set_fs); +#endif diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c index 906fea3..0194a18 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c @@ -18,6 +18,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size) might_fault(); /* no memory constraint because it doesn't change any memory gcc knows about */ + pax_open_userland(); stac(); asm volatile( " testq %[size8],%[size8]\n" @@ -39,9 +40,10 @@ unsigned long __clear_user(void __user *addr, unsigned long size) _ASM_EXTABLE(0b,3b) _ASM_EXTABLE(1b,2b) : [size8] "=&c"(size), [dst] "=&D" (__d0) - : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr), + : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(____m(addr)), [zero] "r" (0UL), [eight] "r" (8UL)); clac(); + pax_close_userland(); return size; } EXPORT_SYMBOL(__clear_user); @@ -54,12 +56,11 @@ unsigned long clear_user(void __user *to, unsigned long n) } EXPORT_SYMBOL(clear_user); -unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len) +unsigned long copy_in_user(void __user *to, const void __user *from, unsigned long len) { - if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) { - return copy_user_generic((__force void *)to, (__force void *)from, len); - } - return len; + if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) + return copy_user_generic((void __force_kernel *)____m(to), (void __force_kernel *)____m(from), len); + return len; } EXPORT_SYMBOL(copy_in_user); @@ -69,11 +70,13 @@ EXPORT_SYMBOL(copy_in_user); * it is not necessary to optimize tail handling. */ unsigned long -copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest) +copy_user_handle_tail(char __user *to, char __user *from, unsigned long len, unsigned zerorest) { char c; unsigned zero_len; + clac(); + pax_close_userland(); for (; len; --len, to++) { if (__get_user_nocheck(c, from++, sizeof(char))) break; @@ -84,6 +87,5 @@ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest) for (c = 0, zero_len = len; zerorest && zero_len; --zero_len) if (__put_user_nocheck(c, to++, sizeof(char))) break; - clac(); return len; } diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 23d8e5f..9ccc13a 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -28,3 +28,7 @@ obj-$(CONFIG_ACPI_NUMA) += srat.o obj-$(CONFIG_NUMA_EMU) += numa_emulation.o obj-$(CONFIG_MEMTEST) += memtest.o + +quote:=" +obj-$(CONFIG_X86_64) += uderef_64.o +CFLAGS_uderef_64.o := $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 903ec1e..c4166b2 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -6,12 +6,24 @@ static inline unsigned long ex_insn_addr(const struct exception_table_entry *x) { - return (unsigned long)&x->insn + x->insn; + unsigned long reloc = 0; + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + reloc = ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; +#endif + + return (unsigned long)&x->insn + x->insn + reloc; } static inline unsigned long ex_fixup_addr(const struct exception_table_entry *x) { - return (unsigned long)&x->fixup + x->fixup; + unsigned long reloc = 0; + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + reloc = ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; +#endif + + return (unsigned long)&x->fixup + x->fixup + reloc; } int fixup_exception(struct pt_regs *regs) @@ -20,7 +32,7 @@ int fixup_exception(struct pt_regs *regs) unsigned long new_ip; #ifdef CONFIG_PNPBIOS - if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) { + if (unlikely(!v8086_mode(regs) && SEGMENT_IS_PNP_CODE(regs->cs))) { extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; extern u32 pnp_bios_is_utter_crap; pnp_bios_is_utter_crap = 1; @@ -145,6 +157,13 @@ void sort_extable(struct exception_table_entry *start, i += 4; p->fixup -= i; i += 4; + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + BUILD_BUG_ON(!IS_ENABLED(CONFIG_BUILDTIME_EXTABLE_SORT)); + p->insn -= ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; + p->fixup -= ____LOAD_PHYSICAL_ADDR - LOAD_PHYSICAL_ADDR; +#endif + } } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 654be4a..a4a3da1 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -14,11 +14,18 @@ #include /* hstate_index_to_shift */ #include /* prefetchw */ #include /* exception_enter(), ... */ +#include +#include #include /* dotraplinkage, ... */ #include /* pgd_*(), ... */ #include /* kmemcheck_*(), ... */ #include /* VSYSCALL_START */ +#include + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +#include +#endif /* * Page fault error code bits: @@ -56,7 +63,7 @@ static inline int __kprobes notify_page_fault(struct pt_regs *regs) int ret = 0; /* kprobe_running() needs smp_processor_id() */ - if (kprobes_built_in() && !user_mode_vm(regs)) { + if (kprobes_built_in() && !user_mode(regs)) { preempt_disable(); if (kprobe_running() && kprobe_fault_handler(regs, 14)) ret = 1; @@ -117,7 +124,10 @@ check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr, return !instr_lo || (instr_lo>>1) == 1; case 0x00: /* Prefetch instruction is 0x0F0D or 0x0F18 */ - if (probe_kernel_address(instr, opcode)) + if (user_mode(regs)) { + if (__copy_from_user_inatomic(&opcode, (unsigned char __force_user *)(instr), 1)) + return 0; + } else if (probe_kernel_address(instr, opcode)) return 0; *prefetch = (instr_lo == 0xF) && @@ -151,7 +161,10 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr) while (instr < max_instr) { unsigned char opcode; - if (probe_kernel_address(instr, opcode)) + if (user_mode(regs)) { + if (__copy_from_user_inatomic(&opcode, (unsigned char __force_user *)(instr), 1)) + break; + } else if (probe_kernel_address(instr, opcode)) break; instr++; @@ -182,6 +195,34 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address, force_sig_info(si_signo, &info, tsk); } +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) +static bool pax_is_fetch_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address); +#endif + +#ifdef CONFIG_PAX_EMUTRAMP +static int pax_handle_fetch_fault(struct pt_regs *regs); +#endif + +#ifdef CONFIG_PAX_PAGEEXEC +static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + pgd = pgd_offset(mm, address); + if (!pgd_present(*pgd)) + return NULL; + pud = pud_offset(pgd, address); + if (!pud_present(*pud)) + return NULL; + pmd = pmd_offset(pud, address); + if (!pmd_present(*pmd)) + return NULL; + return pmd; +} +#endif + DEFINE_SPINLOCK(pgd_lock); LIST_HEAD(pgd_list); @@ -232,10 +273,27 @@ void vmalloc_sync_all(void) for (address = VMALLOC_START & PMD_MASK; address >= TASK_SIZE && address < FIXADDR_TOP; address += PMD_SIZE) { + +#ifdef CONFIG_PAX_PER_CPU_PGD + unsigned long cpu; +#else struct page *page; +#endif spin_lock(&pgd_lock); + +#ifdef CONFIG_PAX_PER_CPU_PGD + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { + pgd_t *pgd = get_cpu_pgd(cpu, user); + pmd_t *ret; + + ret = vmalloc_sync_one(pgd, address); + if (!ret) + break; + pgd = get_cpu_pgd(cpu, kernel); +#else list_for_each_entry(page, &pgd_list, lru) { + pgd_t *pgd; spinlock_t *pgt_lock; pmd_t *ret; @@ -243,8 +301,14 @@ void vmalloc_sync_all(void) pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); - ret = vmalloc_sync_one(page_address(page), address); + pgd = page_address(page); +#endif + + ret = vmalloc_sync_one(pgd, address); + +#ifndef CONFIG_PAX_PER_CPU_PGD spin_unlock(pgt_lock); +#endif if (!ret) break; @@ -278,6 +342,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) * an interrupt in the middle of a task switch.. */ pgd_paddr = read_cr3(); + +#ifdef CONFIG_PAX_PER_CPU_PGD + BUG_ON(__pa(get_cpu_pgd(smp_processor_id(), kernel)) != (pgd_paddr & __PHYSICAL_MASK)); + vmalloc_sync_one(__va(pgd_paddr + PAGE_SIZE), address); +#endif + pmd_k = vmalloc_sync_one(__va(pgd_paddr), address); if (!pmd_k) return -1; @@ -373,11 +443,25 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) * happen within a race in page table update. In the later * case just flush: */ - pgd = pgd_offset(current->active_mm, address); + pgd_ref = pgd_offset_k(address); if (pgd_none(*pgd_ref)) return -1; +#ifdef CONFIG_PAX_PER_CPU_PGD + BUG_ON(__pa(get_cpu_pgd(smp_processor_id(), kernel)) != (read_cr3() & __PHYSICAL_MASK)); + pgd = pgd_offset_cpu(smp_processor_id(), user, address); + if (pgd_none(*pgd)) { + set_pgd(pgd, *pgd_ref); + arch_flush_lazy_mmu_mode(); + } else { + BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); + } + pgd = pgd_offset_cpu(smp_processor_id(), kernel, address); +#else + pgd = pgd_offset(current->active_mm, address); +#endif + if (pgd_none(*pgd)) { set_pgd(pgd, *pgd_ref); arch_flush_lazy_mmu_mode(); @@ -543,7 +627,7 @@ static int is_errata93(struct pt_regs *regs, unsigned long address) static int is_errata100(struct pt_regs *regs, unsigned long address) { #ifdef CONFIG_X86_64 - if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && (address >> 32)) + if ((regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT)) && (address >> 32)) return 1; #endif return 0; @@ -570,7 +654,7 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address) } static const char nx_warning[] = KERN_CRIT -"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n"; +"kernel tried to execute NX-protected page - exploit attempt? (uid: %d, task: %s, pid: %d)\n"; static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, @@ -579,14 +663,26 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, if (!oops_may_print()) return; - if (error_code & PF_INSTR) { + if ((__supported_pte_mask & _PAGE_NX) && (error_code & PF_INSTR)) { unsigned int level; pte_t *pte = lookup_address(address, &level); if (pte && pte_present(*pte) && !pte_exec(*pte)) - printk(nx_warning, from_kuid(&init_user_ns, current_uid())); + printk(nx_warning, from_kuid_munged(&init_user_ns, current_uid()), current->comm, task_pid_nr(current)); + } + +#ifdef CONFIG_PAX_KERNEXEC + if (init_mm.start_code <= address && address < init_mm.end_code) { + if (current->signal->curr_ip) + printk(KERN_ERR "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_ERR "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 printk(KERN_ALERT "BUG: unable to handle kernel "); if (address < PAGE_SIZE) @@ -750,6 +846,22 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, return; } #endif + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (pax_is_fetch_fault(regs, error_code, address)) { + +#ifdef CONFIG_PAX_EMUTRAMP + switch (pax_handle_fetch_fault(regs)) { + case 2: + return; + } +#endif + + pax_report_fault(regs, (void *)regs->ip, (void *)regs->sp); + do_group_exit(SIGKILL); + } +#endif + /* Kernel addresses are always protection faults: */ if (address >= TASK_SIZE) error_code |= PF_PROT; @@ -835,7 +947,7 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { printk(KERN_ERR "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", - tsk->comm, tsk->pid, address); + tsk->comm, task_pid_nr(tsk), address); code = BUS_MCEERR_AR; } #endif @@ -898,6 +1010,99 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte) return 1; } +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) +static int pax_handle_pageexec_fault(struct pt_regs *regs, struct mm_struct *mm, unsigned long address, unsigned long error_code) +{ + pte_t *pte; + pmd_t *pmd; + spinlock_t *ptl; + unsigned char pte_mask; + + if ((__supported_pte_mask & _PAGE_NX) || (error_code & (PF_PROT|PF_USER)) != (PF_PROT|PF_USER) || v8086_mode(regs) || + !(mm->pax_flags & MF_PAX_PAGEEXEC)) + return 0; + + /* PaX: it's our fault, let's handle it if we can */ + + /* PaX: take a look at read faults before acquiring any locks */ + if (unlikely(!(error_code & PF_WRITE) && (regs->ip == address))) { + /* instruction fetch attempt from a protected page in user mode */ + up_read(&mm->mmap_sem); + +#ifdef CONFIG_PAX_EMUTRAMP + switch (pax_handle_fetch_fault(regs)) { + case 2: + return 1; + } +#endif + + pax_report_fault(regs, (void *)regs->ip, (void *)regs->sp); + do_group_exit(SIGKILL); + } + + pmd = pax_get_pmd(mm, address); + if (unlikely(!pmd)) + return 0; + + pte = pte_offset_map_lock(mm, pmd, address, &ptl); + if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) { + pte_unmap_unlock(pte, ptl); + return 0; + } + + if (unlikely((error_code & PF_WRITE) && !pte_write(*pte))) { + /* write attempt to a protected page in user mode */ + pte_unmap_unlock(pte, ptl); + return 0; + } + +#ifdef CONFIG_SMP + if (likely(address > get_limit(regs->cs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask))) +#else + if (likely(address > get_limit(regs->cs))) +#endif + { + set_pte(pte, pte_mkread(*pte)); + __flush_tlb_one(address); + pte_unmap_unlock(pte, ptl); + up_read(&mm->mmap_sem); + return 1; + } + + pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & PF_WRITE) << (_PAGE_BIT_DIRTY-1)); + + /* + * PaX: fill DTLB with user rights and retry + */ + __asm__ __volatile__ ( + "orb %2,(%1)\n" +#if defined(CONFIG_M586) || defined(CONFIG_M586TSC) +/* + * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's + * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any* + * page fault when examined during a TLB load attempt. this is true not only + * for PTEs holding a non-present entry but also present entries that will + * raise a page fault (such as those set up by PaX, or the copy-on-write + * mechanism). in effect it means that we do *not* need to flush the TLBs + * for our target pages since their PTEs are simply not in the TLBs at all. + + * the best thing in omitting it is that we gain around 15-20% speed in the + * fast path of the page fault handler and can get rid of tracing since we + * can no longer flush unintended entries. + */ + "invlpg (%0)\n" +#endif + __copyuser_seg"testb $0,(%0)\n" + "xorb %3,(%1)\n" + : + : "r" (address), "r" (pte), "q" (pte_mask), "i" (_PAGE_USER) + : "memory", "cc"); + pte_unmap_unlock(pte, ptl); + up_read(&mm->mmap_sem); + return 1; +} +#endif + /* * Handle a spurious fault caused by a stale TLB entry. * @@ -964,6 +1169,9 @@ int show_unhandled_signals = 1; static inline int access_error(unsigned long error_code, struct vm_area_struct *vma) { + if ((__supported_pte_mask & _PAGE_NX) && (error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC)) + return 1; + if (error_code & PF_WRITE) { /* write, present and write, not present: */ if (unlikely(!(vma->vm_flags & VM_WRITE))) @@ -992,7 +1200,7 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) if (error_code & PF_USER) return false; - if (!user_mode_vm(regs) && (regs->flags & X86_EFLAGS_AC)) + if (!user_mode(regs) && (regs->flags & X86_EFLAGS_AC)) return false; return true; @@ -1008,19 +1216,34 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) { struct vm_area_struct *vma; struct task_struct *tsk; - unsigned long address; struct mm_struct *mm; int fault; int write = error_code & PF_WRITE; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | (write ? FAULT_FLAG_WRITE : 0); + /* Get the faulting address: */ + unsigned long address = read_cr2(); + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + if (!user_mode(regs) && address < 2 * pax_user_shadow_base) { + if (!search_exception_tables(regs->ip)) { + printk(KERN_ERR "PAX: please report this to pageexec@freemail.hu\n"); + bad_area_nosemaphore(regs, error_code, address); + return; + } + if (address < pax_user_shadow_base) { + printk(KERN_ERR "PAX: please report this to pageexec@freemail.hu\n"); + printk(KERN_ERR "PAX: faulting IP: %pS\n", (void *)regs->ip); + show_trace_log_lvl(NULL, NULL, (void *)regs->sp, regs->bp, KERN_ERR); + } else + address -= pax_user_shadow_base; + } +#endif + tsk = current; mm = tsk->mm; - /* Get the faulting address: */ - address = read_cr2(); - /* * Detect and handle instructions that would cause a page fault for * both a tracked kernel page and a userspace page. @@ -1080,7 +1303,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code) * User-mode registers count as a user access even for any * potential system fault or CPU buglet: */ - if (user_mode_vm(regs)) { + if (user_mode(regs)) { local_irq_enable(); error_code |= PF_USER; } else { @@ -1142,6 +1365,11 @@ retry: might_sleep(); } +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) + if (pax_handle_pageexec_fault(regs, mm, address, error_code)) + return; +#endif + vma = find_vma(mm, address); if (unlikely(!vma)) { bad_area(regs, error_code, address); @@ -1153,18 +1381,24 @@ retry: bad_area(regs, error_code, address); return; } - if (error_code & PF_USER) { - /* - * Accessing the stack below %sp is always a bug. - * The large cushion allows instructions like enter - * and pusha to work. ("enter $65535, $31" pushes - * 32 pointers and then decrements %sp by 65535.) - */ - if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) { - bad_area(regs, error_code, address); - return; - } + /* + * Accessing the stack below %sp is always a bug. + * The large cushion allows instructions like enter + * and pusha to work. ("enter $65535, $31" pushes + * 32 pointers and then decrements %sp by 65535.) + */ + if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < task_pt_regs(tsk)->sp)) { + bad_area(regs, error_code, address); + return; } + +#ifdef CONFIG_PAX_SEGMEXEC + if (unlikely((mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end - SEGMEXEC_TASK_SIZE - 1 < address - SEGMEXEC_TASK_SIZE - 1)) { + bad_area(regs, error_code, address); + return; + } +#endif + if (unlikely(expand_stack(vma, address))) { bad_area(regs, error_code, address); return; @@ -1230,3 +1464,292 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) __do_page_fault(regs, error_code); exception_exit(prev_state); } + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) +static bool pax_is_fetch_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address) +{ + struct mm_struct *mm = current->mm; + unsigned long ip = regs->ip; + + if (v8086_mode(regs)) + ip = ((regs->cs & 0xffff) << 4) + (ip & 0xffff); + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm->pax_flags & MF_PAX_PAGEEXEC) { + if ((__supported_pte_mask & _PAGE_NX) && (error_code & PF_INSTR)) + return true; + if (!(error_code & (PF_PROT | PF_WRITE)) && ip == address) + return true; + return false; + } +#endif + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) { + if (!(error_code & (PF_PROT | PF_WRITE)) && (ip + SEGMEXEC_TASK_SIZE == address)) + return true; + return false; + } +#endif + + return false; +} +#endif + +#ifdef CONFIG_PAX_EMUTRAMP +static int pax_handle_fetch_fault_32(struct pt_regs *regs) +{ + int err; + + do { /* PaX: libffi trampoline emulation */ + unsigned char mov, jmp; + unsigned int addr1, addr2; + +#ifdef CONFIG_X86_64 + if ((regs->ip + 9) >> 32) + break; +#endif + + err = get_user(mov, (unsigned char __user *)regs->ip); + err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1)); + err |= get_user(jmp, (unsigned char __user *)(regs->ip + 5)); + err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6)); + + if (err) + break; + + if (mov == 0xB8 && jmp == 0xE9) { + regs->ax = addr1; + regs->ip = (unsigned int)(regs->ip + addr2 + 10); + return 2; + } + } while (0); + + do { /* PaX: gcc trampoline emulation #1 */ + unsigned char mov1, mov2; + unsigned short jmp; + unsigned int addr1, addr2; + +#ifdef CONFIG_X86_64 + if ((regs->ip + 11) >> 32) + break; +#endif + + err = get_user(mov1, (unsigned char __user *)regs->ip); + err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1)); + err |= get_user(mov2, (unsigned char __user *)(regs->ip + 5)); + err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6)); + err |= get_user(jmp, (unsigned short __user *)(regs->ip + 10)); + + if (err) + break; + + if (mov1 == 0xB9 && mov2 == 0xB8 && jmp == 0xE0FF) { + regs->cx = addr1; + regs->ax = addr2; + regs->ip = addr2; + return 2; + } + } while (0); + + do { /* PaX: gcc trampoline emulation #2 */ + unsigned char mov, jmp; + unsigned int addr1, addr2; + +#ifdef CONFIG_X86_64 + if ((regs->ip + 9) >> 32) + break; +#endif + + err = get_user(mov, (unsigned char __user *)regs->ip); + err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1)); + err |= get_user(jmp, (unsigned char __user *)(regs->ip + 5)); + err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6)); + + if (err) + break; + + if (mov == 0xB9 && jmp == 0xE9) { + regs->cx = addr1; + regs->ip = (unsigned int)(regs->ip + addr2 + 10); + return 2; + } + } while (0); + + return 1; /* PaX in action */ +} + +#ifdef CONFIG_X86_64 +static int pax_handle_fetch_fault_64(struct pt_regs *regs) +{ + int err; + + do { /* PaX: libffi trampoline emulation */ + unsigned short mov1, mov2, jmp1; + unsigned char stcclc, jmp2; + unsigned long addr1, addr2; + + err = get_user(mov1, (unsigned short __user *)regs->ip); + err |= get_user(addr1, (unsigned long __user *)(regs->ip + 2)); + err |= get_user(mov2, (unsigned short __user *)(regs->ip + 10)); + err |= get_user(addr2, (unsigned long __user *)(regs->ip + 12)); + err |= get_user(stcclc, (unsigned char __user *)(regs->ip + 20)); + err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 21)); + err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 23)); + + if (err) + break; + + if (mov1 == 0xBB49 && mov2 == 0xBA49 && (stcclc == 0xF8 || stcclc == 0xF9) && jmp1 == 0xFF49 && jmp2 == 0xE3) { + regs->r11 = addr1; + regs->r10 = addr2; + if (stcclc == 0xF8) + regs->flags &= ~X86_EFLAGS_CF; + else + regs->flags |= X86_EFLAGS_CF; + regs->ip = addr1; + return 2; + } + } while (0); + + do { /* PaX: gcc trampoline emulation #1 */ + unsigned short mov1, mov2, jmp1; + unsigned char jmp2; + unsigned int addr1; + unsigned long addr2; + + err = get_user(mov1, (unsigned short __user *)regs->ip); + err |= get_user(addr1, (unsigned int __user *)(regs->ip + 2)); + err |= get_user(mov2, (unsigned short __user *)(regs->ip + 6)); + err |= get_user(addr2, (unsigned long __user *)(regs->ip + 8)); + err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 16)); + err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 18)); + + if (err) + break; + + if (mov1 == 0xBB41 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) { + regs->r11 = addr1; + regs->r10 = addr2; + regs->ip = addr1; + return 2; + } + } while (0); + + do { /* PaX: gcc trampoline emulation #2 */ + unsigned short mov1, mov2, jmp1; + unsigned char jmp2; + unsigned long addr1, addr2; + + err = get_user(mov1, (unsigned short __user *)regs->ip); + err |= get_user(addr1, (unsigned long __user *)(regs->ip + 2)); + err |= get_user(mov2, (unsigned short __user *)(regs->ip + 10)); + err |= get_user(addr2, (unsigned long __user *)(regs->ip + 12)); + err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 20)); + err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 22)); + + if (err) + break; + + if (mov1 == 0xBB49 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) { + regs->r11 = addr1; + regs->r10 = addr2; + regs->ip = addr1; + return 2; + } + } while (0); + + return 1; /* PaX in action */ +} +#endif + +/* + * PaX: decide what to do with offenders (regs->ip = fault address) + * + * returns 1 when task should be killed + * 2 when gcc trampoline was detected + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + if (v8086_mode(regs)) + return 1; + + if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP)) + return 1; + +#ifdef CONFIG_X86_32 + return pax_handle_fetch_fault_32(regs); +#else + if (regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT)) + return pax_handle_fetch_fault_32(regs); + else + return pax_handle_fetch_fault_64(regs); +#endif +} +#endif + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) +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, (unsigned char __force_user *)pc+i)) + printk(KERN_CONT "?? "); + else + printk(KERN_CONT "%02x ", c); + } + printk("\n"); + + printk(KERN_ERR "PAX: bytes at SP-%lu: ", (unsigned long)sizeof(long)); + for (i = -1; i < 80 / (long)sizeof(long); i++) { + unsigned long c; + if (get_user(c, (unsigned long __force_user *)sp+i)) { +#ifdef CONFIG_X86_32 + printk(KERN_CONT "???????? "); +#else + if ((regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT))) + printk(KERN_CONT "???????? ???????? "); + else + printk(KERN_CONT "???????????????? "); +#endif + } else { +#ifdef CONFIG_X86_64 + if ((regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT))) { + printk(KERN_CONT "%08x ", (unsigned int)c); + printk(KERN_CONT "%08x ", (unsigned int)(c >> 32)); + } else +#endif + printk(KERN_CONT "%0*lx ", 2 * (int)sizeof(long), c); + } + } + printk("\n"); +} +#endif + +/** + * probe_kernel_write(): safely attempt to write to a location + * @dst: address to write to + * @src: pointer to the data that shall be written + * @size: size of the data chunk + * + * Safely write to address @dst from the buffer at @src. If a kernel fault + * happens, handle that and return -EFAULT. + */ +long notrace probe_kernel_write(void *dst, const void *src, size_t size) +{ + long ret; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + pagefault_disable(); + pax_open_kernel(); + ret = __copy_to_user_inatomic((void __force_user *)dst, src, size); + pax_close_kernel(); + pagefault_enable(); + set_fs(old_fs); + + return ret ? -EFAULT : 0; +} diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index dd74e46..7d26398 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -255,7 +255,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, + if (unlikely(!__access_ok(write ? VERIFY_WRITE : VERIFY_READ, (void __user *)start, len))) return 0; diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 252b8f5..4dcfdc1 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -44,7 +44,11 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot) idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); BUG_ON(!pte_none(*(kmap_pte-idx))); + + pax_open_kernel(); set_pte(kmap_pte-idx, mk_pte(page, prot)); + pax_close_kernel(); + arch_flush_lazy_mmu_mode(); return (void *)vaddr; diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index ae1aa71..d9bea75 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -271,23 +271,30 @@ follow_huge_pud(struct mm_struct *mm, unsigned long address, #ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr, unsigned long len, - unsigned long pgoff, unsigned long flags) + unsigned long pgoff, unsigned long flags, unsigned long offset) { struct hstate *h = hstate_file(file); struct vm_unmapped_area_info info; - + info.flags = 0; info.length = len; info.low_limit = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (current->mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += current->mm->delta_mmap; +#endif + info.high_limit = TASK_SIZE; info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; + info.threadstack_offset = offset; return vm_unmapped_area(&info); } static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr0, unsigned long len, - unsigned long pgoff, unsigned long flags) + unsigned long pgoff, unsigned long flags, unsigned long offset) { struct hstate *h = hstate_file(file); struct vm_unmapped_area_info info; @@ -299,6 +306,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, info.high_limit = current->mm->mmap_base; info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; + info.threadstack_offset = offset; addr = vm_unmapped_area(&info); /* @@ -311,6 +319,12 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (current->mm->pax_flags & MF_PAX_RANDMMAP) + info.low_limit += current->mm->delta_mmap; +#endif + info.high_limit = TASK_SIZE; addr = vm_unmapped_area(&info); } @@ -325,10 +339,20 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, struct hstate *h = hstate_file(file); struct mm_struct *mm = current->mm; struct vm_area_struct *vma; + unsigned long pax_task_size = TASK_SIZE; + unsigned long offset = gr_rand_threadstack_offset(mm, file, flags); if (len & ~huge_page_mask(h)) return -EINVAL; - if (len > TASK_SIZE) + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + pax_task_size = SEGMEXEC_TASK_SIZE; +#endif + + pax_task_size -= PAGE_SIZE; + + if (len > pax_task_size) return -ENOMEM; if (flags & MAP_FIXED) { @@ -337,19 +361,22 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, return addr; } +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { addr = ALIGN(addr, huge_page_size(h)); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && - (!vma || addr + len <= vma->vm_start)) + if (pax_task_size - len >= addr && check_heap_stack_gap(vma, addr, len, offset)) return addr; } if (mm->get_unmapped_area == arch_get_unmapped_area) return hugetlb_get_unmapped_area_bottomup(file, addr, len, - pgoff, flags); + pgoff, flags, offset); else return hugetlb_get_unmapped_area_topdown(file, addr, len, - pgoff, flags); + pgoff, flags, offset); } #endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 7a5bf1b..c96ab0d 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -4,6 +4,7 @@ #include #include #include /* for max_low_pfn */ +#include #include #include @@ -17,6 +18,8 @@ #include #include /* for MAX_DMA_PFN */ #include +#include +#include #include "mm_internal.h" @@ -465,7 +468,18 @@ void __init init_mem_mapping(void) early_ioremap_page_table_range_init(); #endif +#ifdef CONFIG_PAX_PER_CPU_PGD + clone_pgd_range(get_cpu_pgd(0, kernel) + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); + clone_pgd_range(get_cpu_pgd(0, user) + KERNEL_PGD_BOUNDARY, + swapper_pg_dir + KERNEL_PGD_BOUNDARY, + KERNEL_PGD_PTRS); + load_cr3(get_cpu_pgd(0, kernel)); +#else load_cr3(swapper_pg_dir); +#endif + __flush_tlb_all(); early_memtest(0, max_pfn_mapped << PAGE_SHIFT); @@ -481,10 +495,40 @@ void __init init_mem_mapping(void) * Access has to be given to non-kernel-ram areas as well, these contain the PCI * mmio resources as well as potential bios/acpi data regions. */ + +#ifdef CONFIG_GRKERNSEC_KMEM +static unsigned int ebda_start __read_only; +static unsigned int ebda_end __read_only; +#endif + int devmem_is_allowed(unsigned long pagenr) { - if (pagenr < 256) +#ifdef CONFIG_GRKERNSEC_KMEM + /* allow BDA */ + if (!pagenr) + return 1; + /* allow EBDA */ + if (pagenr >= ebda_start && pagenr < ebda_end) return 1; + /* if tboot is in use, allow access to its hardcoded serial log range */ + if (tboot_enabled() && ((0x60000 >> PAGE_SHIFT) <= pagenr) && (pagenr < (0x68000 >> PAGE_SHIFT))) + return 1; +#else + if (!pagenr) + return 1; +#ifdef CONFIG_VM86 + if (pagenr < (ISA_START_ADDRESS >> PAGE_SHIFT)) + return 1; +#endif +#endif + + if ((ISA_START_ADDRESS >> PAGE_SHIFT) <= pagenr && pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT)) + return 1; +#ifdef CONFIG_GRKERNSEC_KMEM + /* throw out everything else below 1MB */ + if (pagenr <= 256) + return 0; +#endif if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) return 0; if (!page_is_ram(pagenr)) @@ -538,8 +582,117 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) #endif } +#ifdef CONFIG_GRKERNSEC_KMEM +static inline void gr_init_ebda(void) +{ + unsigned int ebda_addr; + unsigned int ebda_size = 0; + + ebda_addr = get_bios_ebda(); + if (ebda_addr) { + ebda_size = *(unsigned char *)phys_to_virt(ebda_addr); + ebda_size <<= 10; + } + if (ebda_addr && ebda_size) { + ebda_start = ebda_addr >> PAGE_SHIFT; + ebda_end = min((unsigned int)PAGE_ALIGN(ebda_addr + ebda_size), (unsigned int)0xa0000) >> PAGE_SHIFT; + } else { + ebda_start = 0x9f000 >> PAGE_SHIFT; + ebda_end = 0xa0000 >> PAGE_SHIFT; + } +} +#else +static inline void gr_init_ebda(void) { } +#endif + void free_initmem(void) { +#ifdef CONFIG_PAX_KERNEXEC +#ifdef CONFIG_X86_32 + /* PaX: limit KERNEL_CS to actual size */ + unsigned long addr, limit; + struct desc_struct d; + int cpu; +#else + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + unsigned long addr, end; +#endif +#endif + + gr_init_ebda(); + +#ifdef CONFIG_PAX_KERNEXEC +#ifdef CONFIG_X86_32 + limit = paravirt_enabled() ? ktva_ktla(0xffffffff) : (unsigned long)&_etext; + limit = (limit - 1UL) >> PAGE_SHIFT; + + memset(__LOAD_PHYSICAL_ADDR + PAGE_OFFSET, POISON_FREE_INITMEM, PAGE_SIZE); + for (cpu = 0; cpu < nr_cpu_ids; cpu++) { + pack_descriptor(&d, get_desc_base(&get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS]), limit, 0x9B, 0xC); + write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_KERNEL_CS, &d, DESCTYPE_S); + write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_KERNEXEC_KERNEL_CS, &d, DESCTYPE_S); + } + + /* PaX: make KERNEL_CS read-only */ + addr = PFN_ALIGN(ktla_ktva((unsigned long)&_text)); + if (!paravirt_enabled()) + set_memory_ro(addr, (PFN_ALIGN(_sdata) - addr) >> PAGE_SHIFT); +/* + for (addr = ktla_ktva((unsigned long)&_text); addr < (unsigned long)&_sdata; addr += PMD_SIZE) { + pgd = pgd_offset_k(addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); + } +*/ +#ifdef CONFIG_X86_PAE + set_memory_nx(PFN_ALIGN(__init_begin), (PFN_ALIGN(__init_end) - PFN_ALIGN(__init_begin)) >> PAGE_SHIFT); +/* + for (addr = (unsigned long)&__init_begin; addr < (unsigned long)&__init_end; addr += PMD_SIZE) { + pgd = pgd_offset_k(addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask))); + } +*/ +#endif + +#ifdef CONFIG_MODULES + set_memory_4k((unsigned long)MODULES_EXEC_VADDR, (MODULES_EXEC_END - MODULES_EXEC_VADDR) >> PAGE_SHIFT); +#endif + +#else + /* PaX: make kernel code/rodata read-only, rest non-executable */ + for (addr = __START_KERNEL_map; addr < __START_KERNEL_map + KERNEL_IMAGE_SIZE; addr += PMD_SIZE) { + pgd = pgd_offset_k(addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + if (!pmd_present(*pmd)) + continue; + if ((unsigned long)_text <= addr && addr < (unsigned long)_sdata) + set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); + else + set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask))); + } + + addr = (unsigned long)__va(__pa(__START_KERNEL_map)); + end = addr + KERNEL_IMAGE_SIZE; + for (; addr < end; addr += PMD_SIZE) { + pgd = pgd_offset_k(addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + if (!pmd_present(*pmd)) + continue; + if ((unsigned long)__va(__pa(_text)) <= addr && addr < (unsigned long)__va(__pa(_sdata))) + set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); + } +#endif + + flush_tlb_all(); +#endif + free_init_pages("unused kernel memory", (unsigned long)(&__init_begin), (unsigned long)(&__init_end)); diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 3ac7e31..89611b7 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -62,33 +62,6 @@ static noinline int do_test_wp_bit(void); bool __read_mostly __vmalloc_start_set = false; /* - * Creates a middle page table and puts a pointer to it in the - * given global directory entry. This only returns the gd entry - * in non-PAE compilation mode, since the middle layer is folded. - */ -static pmd_t * __init one_md_table_init(pgd_t *pgd) -{ - pud_t *pud; - pmd_t *pmd_table; - -#ifdef CONFIG_X86_PAE - if (!(pgd_val(*pgd) & _PAGE_PRESENT)) { - pmd_table = (pmd_t *)alloc_low_page(); - paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT); - set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); - pud = pud_offset(pgd, 0); - BUG_ON(pmd_table != pmd_offset(pud, 0)); - - return pmd_table; - } -#endif - pud = pud_offset(pgd, 0); - pmd_table = pmd_offset(pud, 0); - - return pmd_table; -} - -/* * Create a page table and place a pointer to it in a middle page * directory entry: */ @@ -98,13 +71,28 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) pte_t *page_table = (pte_t *)alloc_low_page(); paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT); +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE)); +#else set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); +#endif BUG_ON(page_table != pte_offset_kernel(pmd, 0)); } return pte_offset_kernel(pmd, 0); } +static pmd_t * __init one_md_table_init(pgd_t *pgd) +{ + pud_t *pud; + pmd_t *pmd_table; + + pud = pud_offset(pgd, 0); + pmd_table = pmd_offset(pud, 0); + + return pmd_table; +} + pmd_t * __init populate_extra_pmd(unsigned long vaddr) { int pgd_idx = pgd_index(vaddr); @@ -208,6 +196,7 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) int pgd_idx, pmd_idx; unsigned long vaddr; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte = NULL; unsigned long count = page_table_range_init_count(start, end); @@ -222,8 +211,13 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) pgd = pgd_base + pgd_idx; for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { - pmd = one_md_table_init(pgd); - pmd = pmd + pmd_index(vaddr); + pud = pud_offset(pgd, vaddr); + pmd = pmd_offset(pud, vaddr); + +#ifdef CONFIG_X86_PAE + paravirt_alloc_pmd(&init_mm, __pa(pmd) >> PAGE_SHIFT); +#endif + for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) { pte = page_table_kmap_check(one_page_table_init(pmd), @@ -235,11 +229,20 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) } } -static inline int is_kernel_text(unsigned long addr) +static inline int is_kernel_text(unsigned long start, unsigned long end) { - if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end) - return 1; - return 0; + if ((start > ktla_ktva((unsigned long)_etext) || + end <= ktla_ktva((unsigned long)_stext)) && + (start > ktla_ktva((unsigned long)_einittext) || + end <= ktla_ktva((unsigned long)_sinittext)) && + +#ifdef CONFIG_ACPI_SLEEP + (start > (unsigned long)__va(acpi_wakeup_address) + 0x4000 || end <= (unsigned long)__va(acpi_wakeup_address)) && +#endif + + (start > (unsigned long)__va(0xfffff) || end <= (unsigned long)__va(0xc0000))) + return 0; + return 1; } /* @@ -256,9 +259,10 @@ kernel_physical_mapping_init(unsigned long start, unsigned long last_map_addr = end; unsigned long start_pfn, end_pfn; pgd_t *pgd_base = swapper_pg_dir; - int pgd_idx, pmd_idx, pte_ofs; + unsigned int pgd_idx, pmd_idx, pte_ofs; unsigned long pfn; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; unsigned pages_2m, pages_4k; @@ -291,8 +295,13 @@ repeat: pfn = start_pfn; pgd_idx = pgd_index((pfn<> PAGE_SHIFT); +#endif if (pfn >= end_pfn) continue; @@ -304,14 +313,13 @@ repeat: #endif for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn; pmd++, pmd_idx++) { - unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET; + unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET; /* * Map with big pages if possible, otherwise * create normal page tables: */ if (use_pse) { - unsigned int addr2; pgprot_t prot = PAGE_KERNEL_LARGE; /* * first pass will use the same initial @@ -322,11 +330,7 @@ repeat: _PAGE_PSE); pfn &= PMD_MASK >> PAGE_SHIFT; - addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE + - PAGE_OFFSET + PAGE_SIZE-1; - - if (is_kernel_text(addr) || - is_kernel_text(addr2)) + if (is_kernel_text(address, address + PMD_SIZE)) prot = PAGE_KERNEL_LARGE_EXEC; pages_2m++; @@ -343,7 +347,7 @@ repeat: pte_ofs = pte_index((pfn<> 10, - (unsigned long)&_etext, (unsigned long)&_edata, - ((unsigned long)&_edata - (unsigned long)&_etext) >> 10, + (unsigned long)&_sdata, (unsigned long)&_edata, + ((unsigned long)&_edata - (unsigned long)&_sdata) >> 10, - (unsigned long)&_text, (unsigned long)&_etext, + ktla_ktva((unsigned long)&_text), ktla_ktva((unsigned long)&_etext), ((unsigned long)&_etext - (unsigned long)&_text) >> 10); /* @@ -906,6 +908,7 @@ void set_kernel_text_rw(void) if (!kernel_set_to_readonly) return; + start = ktla_ktva(start); pr_debug("Set kernel text: %lx - %lx for read write\n", start, start+size); @@ -920,6 +923,7 @@ void set_kernel_text_ro(void) if (!kernel_set_to_readonly) return; + start = ktla_ktva(start); pr_debug("Set kernel text: %lx - %lx for read only\n", start, start+size); @@ -948,6 +952,7 @@ void mark_rodata_ro(void) unsigned long start = PFN_ALIGN(_text); unsigned long size = PFN_ALIGN(_etext) - start; + start = ktla_ktva(start); set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); printk(KERN_INFO "Write protecting the kernel text: %luk\n", size >> 10); diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index bb00c46..bf91a67 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -151,7 +151,7 @@ early_param("gbpages", parse_direct_gbpages_on); * around without checking the pgd every time. */ -pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP; +pteval_t __supported_pte_mask __read_only = ~(_PAGE_NX | _PAGE_IOMAP); EXPORT_SYMBOL_GPL(__supported_pte_mask); int force_personality32; @@ -184,12 +184,29 @@ void sync_global_pgds(unsigned long start, unsigned long end) for (address = start; address <= end; address += PGDIR_SIZE) { const pgd_t *pgd_ref = pgd_offset_k(address); + +#ifdef CONFIG_PAX_PER_CPU_PGD + unsigned long cpu; +#else struct page *page; +#endif if (pgd_none(*pgd_ref)) continue; spin_lock(&pgd_lock); + +#ifdef CONFIG_PAX_PER_CPU_PGD + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { + pgd_t *pgd = pgd_offset_cpu(cpu, user, address); + + if (pgd_none(*pgd)) + set_pgd(pgd, *pgd_ref); + else + BUG_ON(pgd_page_vaddr(*pgd) + != pgd_page_vaddr(*pgd_ref)); + pgd = pgd_offset_cpu(cpu, kernel, address); +#else list_for_each_entry(page, &pgd_list, lru) { pgd_t *pgd; spinlock_t *pgt_lock; @@ -198,6 +215,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) /* the pgt_lock only for Xen */ pgt_lock = &pgd_page_get_mm(page)->page_table_lock; spin_lock(pgt_lock); +#endif if (pgd_none(*pgd)) set_pgd(pgd, *pgd_ref); @@ -205,7 +223,10 @@ void sync_global_pgds(unsigned long start, unsigned long end) BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); +#ifndef CONFIG_PAX_PER_CPU_PGD spin_unlock(pgt_lock); +#endif + } spin_unlock(&pgd_lock); } @@ -238,7 +259,7 @@ static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) { if (pgd_none(*pgd)) { pud_t *pud = (pud_t *)spp_getpage(); - pgd_populate(&init_mm, pgd, pud); + pgd_populate_kernel(&init_mm, pgd, pud); if (pud != pud_offset(pgd, 0)) printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n", pud, pud_offset(pgd, 0)); @@ -250,7 +271,7 @@ static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) { if (pud_none(*pud)) { pmd_t *pmd = (pmd_t *) spp_getpage(); - pud_populate(&init_mm, pud, pmd); + pud_populate_kernel(&init_mm, pud, pmd); if (pmd != pmd_offset(pud, 0)) printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud, 0)); @@ -279,7 +300,9 @@ void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) pmd = fill_pmd(pud, vaddr); pte = fill_pte(pmd, vaddr); + pax_open_kernel(); set_pte(pte, new_pte); + pax_close_kernel(); /* * It's enough to flush this one mapping. @@ -338,14 +361,12 @@ static void __init __init_extra_mapping(unsigned long phys, unsigned long size, pgd = pgd_offset_k((unsigned long)__va(phys)); if (pgd_none(*pgd)) { pud = (pud_t *) spp_getpage(); - set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE | - _PAGE_USER)); + set_pgd(pgd, __pgd(__pa(pud) | _PAGE_TABLE)); } pud = pud_offset(pgd, (unsigned long)__va(phys)); if (pud_none(*pud)) { pmd = (pmd_t *) spp_getpage(); - set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | - _PAGE_USER)); + set_pud(pud, __pud(__pa(pmd) | _PAGE_TABLE)); } pmd = pmd_offset(pud, phys); BUG_ON(!pmd_none(*pmd)); @@ -586,7 +607,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, prot); spin_lock(&init_mm.page_table_lock); - pud_populate(&init_mm, pud, pmd); + pud_populate_kernel(&init_mm, pud, pmd); spin_unlock(&init_mm.page_table_lock); } __flush_tlb_all(); @@ -627,7 +648,7 @@ kernel_physical_mapping_init(unsigned long start, page_size_mask); spin_lock(&init_mm.page_table_lock); - pgd_populate(&init_mm, pgd, pud); + pgd_populate_kernel(&init_mm, pgd, pud); spin_unlock(&init_mm.page_table_lock); pgd_changed = true; } @@ -1221,8 +1242,8 @@ int kern_addr_valid(unsigned long addr) static struct vm_area_struct gate_vma = { .vm_start = VSYSCALL_START, .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE), - .vm_page_prot = PAGE_READONLY_EXEC, - .vm_flags = VM_READ | VM_EXEC + .vm_page_prot = PAGE_READONLY, + .vm_flags = VM_READ }; struct vm_area_struct *get_gate_vma(struct mm_struct *mm) @@ -1256,7 +1277,7 @@ int in_gate_area_no_mm(unsigned long addr) const char *arch_vma_name(struct vm_area_struct *vma) { - if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) + if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso) return "[vdso]"; if (vma == &gate_vma) return "[vsyscall]"; diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 7b179b4..6bd1777 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -64,7 +64,11 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot) type = kmap_atomic_idx_push(); idx = type + KM_TYPE_NR * smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + + pax_open_kernel(); set_pte(kmap_pte - idx, pfn_pte(pfn, prot)); + pax_close_kernel(); + arch_flush_lazy_mmu_mode(); return (void *)vaddr; diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 9a1e658..da003f3 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -97,7 +97,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, for (pfn = phys_addr >> PAGE_SHIFT; pfn <= last_pfn; pfn++) { int is_ram = page_is_ram(pfn); - if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn))) + if (is_ram && pfn_valid(pfn) && (pfn >= 0x100 || !PageReserved(pfn_to_page(pfn)))) return NULL; WARN_ON_ONCE(is_ram); } @@ -256,7 +256,7 @@ EXPORT_SYMBOL(ioremap_prot); * * Caller must ensure there is only one unmapping for the same pointer. */ -void iounmap(volatile void __iomem *addr) +void iounmap(const volatile void __iomem *addr) { struct vm_struct *p, *o; @@ -310,6 +310,9 @@ void *xlate_dev_mem_ptr(unsigned long phys) /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */ if (page_is_ram(start >> PAGE_SHIFT)) +#ifdef CONFIG_HIGHMEM + if ((start >> PAGE_SHIFT) < max_low_pfn) +#endif return __va(phys); addr = (void __force *)ioremap_cache(start, PAGE_SIZE); @@ -322,6 +325,9 @@ void *xlate_dev_mem_ptr(unsigned long phys) void unxlate_dev_mem_ptr(unsigned long phys, void *addr) { if (page_is_ram(phys >> PAGE_SHIFT)) +#ifdef CONFIG_HIGHMEM + if ((phys >> PAGE_SHIFT) < max_low_pfn) +#endif return; iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK)); @@ -339,7 +345,7 @@ static int __init early_ioremap_debug_setup(char *str) early_param("early_ioremap_debug", early_ioremap_debug_setup); static __initdata int after_paging_init; -static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss; +static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __read_only __aligned(PAGE_SIZE); static inline pmd_t * __init early_ioremap_pmd(unsigned long addr) { @@ -376,8 +382,7 @@ void __init early_ioremap_init(void) slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); - memset(bm_pte, 0, sizeof(bm_pte)); - pmd_populate_kernel(&init_mm, pmd, bm_pte); + pmd_populate_user(&init_mm, pmd, bm_pte); /* * The boot-ioremap range spans multiple pmds, for which diff --git a/arch/x86/mm/kmemcheck/kmemcheck.c b/arch/x86/mm/kmemcheck/kmemcheck.c index d87dd6d..bf3fa66 100644 --- a/arch/x86/mm/kmemcheck/kmemcheck.c +++ b/arch/x86/mm/kmemcheck/kmemcheck.c @@ -622,9 +622,9 @@ bool kmemcheck_fault(struct pt_regs *regs, unsigned long address, * memory (e.g. tracked pages)? For now, we need this to avoid * invoking kmemcheck for PnP BIOS calls. */ - if (regs->flags & X86_VM_MASK) + if (v8086_mode(regs)) return false; - if (regs->cs != __KERNEL_CS) + if (regs->cs != __KERNEL_CS && regs->cs != __KERNEXEC_KERNEL_CS) return false; pte = kmemcheck_pte_lookup(address); diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 5c1ae28..45f4ac9 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -52,7 +52,7 @@ static unsigned int stack_maxrandom_size(void) * Leave an at least ~128 MB hole with possible stack randomization. */ #define MIN_GAP (128*1024*1024UL + stack_maxrandom_size()) -#define MAX_GAP (TASK_SIZE/6*5) +#define MAX_GAP (pax_task_size/6*5) static int mmap_is_legacy(void) { @@ -82,27 +82,40 @@ static unsigned long mmap_rnd(void) return rnd << PAGE_SHIFT; } -static unsigned long mmap_base(void) +static unsigned long mmap_base(struct mm_struct *mm) { unsigned long gap = rlimit(RLIMIT_STACK); + unsigned long pax_task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + pax_task_size = SEGMEXEC_TASK_SIZE; +#endif if (gap < MIN_GAP) gap = MIN_GAP; else if (gap > MAX_GAP) gap = MAX_GAP; - return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd()); + return PAGE_ALIGN(pax_task_size - gap - mmap_rnd()); } /* * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 * does, but not when emulating X86_32 */ -static unsigned long mmap_legacy_base(void) +static unsigned long mmap_legacy_base(struct mm_struct *mm) { - if (mmap_is_ia32()) + if (mmap_is_ia32()) { + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + return SEGMEXEC_TASK_UNMAPPED_BASE; + else +#endif + return TASK_UNMAPPED_BASE; - else + } else return TASK_UNMAPPED_BASE + mmap_rnd(); } @@ -112,8 +125,15 @@ static unsigned long mmap_legacy_base(void) */ void arch_pick_mmap_layout(struct mm_struct *mm) { - mm->mmap_legacy_base = mmap_legacy_base(); - mm->mmap_base = mmap_base(); + mm->mmap_legacy_base = mmap_legacy_base(mm); + mm->mmap_base = mmap_base(mm); + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) { + mm->mmap_legacy_base += mm->delta_mmap; + mm->mmap_base -= mm->delta_mmap + mm->delta_stack; + } +#endif if (mmap_is_legacy()) { mm->mmap_base = mm->mmap_legacy_base; diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index dc0b727..f612039 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c @@ -194,7 +194,7 @@ static void pre(struct kmmio_probe *p, struct pt_regs *regs, break; default: { - unsigned char *ip = (unsigned char *)instptr; + unsigned char *ip = (unsigned char *)ktla_ktva(instptr); my_trace->opcode = MMIO_UNKNOWN_OP; my_trace->width = 0; my_trace->value = (*ip) << 16 | *(ip + 1) << 8 | @@ -234,7 +234,7 @@ static void post(struct kmmio_probe *p, unsigned long condition, static void ioremap_trace_core(resource_size_t offset, unsigned long size, void __iomem *addr) { - static atomic_t next_id; + static atomic_unchecked_t next_id; struct remap_trace *trace = kmalloc(sizeof(*trace), GFP_KERNEL); /* These are page-unaligned. */ struct mmiotrace_map map = { @@ -258,7 +258,7 @@ static void ioremap_trace_core(resource_size_t offset, unsigned long size, .private = trace }, .phys = offset, - .id = atomic_inc_return(&next_id) + .id = atomic_inc_return_unchecked(&next_id) }; map.map_id = trace->id; @@ -290,7 +290,7 @@ void mmiotrace_ioremap(resource_size_t offset, unsigned long size, ioremap_trace_core(offset, size, addr); } -static void iounmap_trace_core(volatile void __iomem *addr) +static void iounmap_trace_core(const volatile void __iomem *addr) { struct mmiotrace_map map = { .phys = 0, @@ -328,7 +328,7 @@ not_enabled: } } -void mmiotrace_iounmap(volatile void __iomem *addr) +void mmiotrace_iounmap(const volatile void __iomem *addr) { might_sleep(); if (is_enabled()) /* recheck and proper locking in *_core() */ diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index a71c4e2..301ae44 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -474,7 +474,7 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi) return true; } -static int __init numa_register_memblks(struct numa_meminfo *mi) +static int __init __intentional_overflow(-1) numa_register_memblks(struct numa_meminfo *mi) { unsigned long uninitialized_var(pfn_align); int i, nid; diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index d0b1773..4c3327c 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c @@ -36,7 +36,7 @@ enum { static int pte_testbit(pte_t pte) { - return pte_flags(pte) & _PAGE_UNUSED1; + return pte_flags(pte) & _PAGE_CPA_TEST; } struct split_state { diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index bb32480..75f2f5e 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -261,7 +261,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, */ #ifdef CONFIG_PCI_BIOS if (pcibios_enabled && within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) - pgprot_val(forbidden) |= _PAGE_NX; + pgprot_val(forbidden) |= _PAGE_NX & __supported_pte_mask; #endif /* @@ -269,9 +269,10 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, * Does not cover __inittext since that is gone later on. On * 64bit we do not enforce !NX on the low mapping */ - if (within(address, (unsigned long)_text, (unsigned long)_etext)) - pgprot_val(forbidden) |= _PAGE_NX; + if (within(address, ktla_ktva((unsigned long)_text), ktla_ktva((unsigned long)_etext))) + pgprot_val(forbidden) |= _PAGE_NX & __supported_pte_mask; +#ifdef CONFIG_DEBUG_RODATA /* * The .rodata section needs to be read-only. Using the pfn * catches all aliases. @@ -279,6 +280,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, if (within(pfn, __pa_symbol(__start_rodata) >> PAGE_SHIFT, __pa_symbol(__end_rodata) >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_RW; +#endif #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) /* @@ -317,6 +319,13 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, } #endif +#ifdef CONFIG_PAX_KERNEXEC + if (within(pfn, __pa(ktla_ktva((unsigned long)&_text)), __pa((unsigned long)&_sdata))) { + pgprot_val(forbidden) |= _PAGE_RW; + pgprot_val(forbidden) |= _PAGE_NX & __supported_pte_mask; + } +#endif + prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); return prot; @@ -400,23 +409,37 @@ EXPORT_SYMBOL_GPL(slow_virt_to_phys); static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) { /* change init_mm */ + pax_open_kernel(); set_pte_atomic(kpte, pte); + #ifdef CONFIG_X86_32 if (!SHARED_KERNEL_PMD) { + +#ifdef CONFIG_PAX_PER_CPU_PGD + unsigned long cpu; +#else struct page *page; +#endif +#ifdef CONFIG_PAX_PER_CPU_PGD + for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { + pgd_t *pgd = get_cpu_pgd(cpu, kernel); +#else list_for_each_entry(page, &pgd_list, lru) { - pgd_t *pgd; + pgd_t *pgd = (pgd_t *)page_address(page); +#endif + pud_t *pud; pmd_t *pmd; - pgd = (pgd_t *)page_address(page) + pgd_index(address); + pgd += pgd_index(address); pud = pud_offset(pgd, address); pmd = pmd_offset(pud, address); set_pte_atomic((pte_t *)pmd, pte); } } #endif + pax_close_kernel(); } static int diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 6574388..87e9bef 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -376,7 +376,7 @@ int free_memtype(u64 start, u64 end) if (!entry) { printk(KERN_INFO "%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n", - current->comm, current->pid, start, end - 1); + current->comm, task_pid_nr(current), start, end - 1); return -EINVAL; } @@ -506,8 +506,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) while (cursor < to) { if (!devmem_is_allowed(pfn)) { - printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx]\n", - current->comm, from, to - 1); + printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx] (%#010Lx)\n", + current->comm, from, to - 1, cursor); return 0; } cursor += PAGE_SIZE; @@ -577,7 +577,7 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags) if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) { printk(KERN_INFO "%s:%d ioremap_change_attr failed %s " "for [mem %#010Lx-%#010Lx]\n", - current->comm, current->pid, + current->comm, task_pid_nr(current), cattr_name(flags), base, (unsigned long long)(base + size-1)); return -EINVAL; @@ -612,7 +612,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, flags = lookup_memtype(paddr); if (want_flags != flags) { printk(KERN_WARNING "%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n", - current->comm, current->pid, + current->comm, task_pid_nr(current), cattr_name(want_flags), (unsigned long long)paddr, (unsigned long long)(paddr + size - 1), @@ -634,7 +634,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, free_memtype(paddr, paddr + size); printk(KERN_ERR "%s:%d map pfn expected mapping type %s" " for [mem %#010Lx-%#010Lx], got %s\n", - current->comm, current->pid, + current->comm, task_pid_nr(current), cattr_name(want_flags), (unsigned long long)paddr, (unsigned long long)(paddr + size - 1), diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c index 415f6c4..d319983 100644 --- a/arch/x86/mm/pat_rbtree.c +++ b/arch/x86/mm/pat_rbtree.c @@ -160,7 +160,7 @@ success: failure: printk(KERN_INFO "%s:%d conflicting memory types " - "%Lx-%Lx %s<->%s\n", current->comm, current->pid, start, + "%Lx-%Lx %s<->%s\n", current->comm, task_pid_nr(current), start, end, cattr_name(found_type), cattr_name(match->type)); return -EBUSY; } diff --git a/arch/x86/mm/pf_in.c b/arch/x86/mm/pf_in.c index 9f0614d..92ae64a 100644 --- a/arch/x86/mm/pf_in.c +++ b/arch/x86/mm/pf_in.c @@ -148,7 +148,7 @@ enum reason_type get_ins_type(unsigned long ins_addr) int i; enum reason_type rv = OTHERS; - p = (unsigned char *)ins_addr; + p = (unsigned char *)ktla_ktva(ins_addr); p += skip_prefix(p, &prf); p += get_opcode(p, &opcode); @@ -168,7 +168,7 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr) struct prefix_bits prf; int i; - p = (unsigned char *)ins_addr; + p = (unsigned char *)ktla_ktva(ins_addr); p += skip_prefix(p, &prf); p += get_opcode(p, &opcode); @@ -191,7 +191,7 @@ unsigned int get_ins_mem_width(unsigned long ins_addr) struct prefix_bits prf; int i; - p = (unsigned char *)ins_addr; + p = (unsigned char *)ktla_ktva(ins_addr); p += skip_prefix(p, &prf); p += get_opcode(p, &opcode); @@ -415,7 +415,7 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs) struct prefix_bits prf; int i; - p = (unsigned char *)ins_addr; + p = (unsigned char *)ktla_ktva(ins_addr); p += skip_prefix(p, &prf); p += get_opcode(p, &opcode); for (i = 0; i < ARRAY_SIZE(reg_rop); i++) @@ -470,7 +470,7 @@ unsigned long get_ins_imm_val(unsigned long ins_addr) struct prefix_bits prf; int i; - p = (unsigned char *)ins_addr; + p = (unsigned char *)ktla_ktva(ins_addr); p += skip_prefix(p, &prf); p += get_opcode(p, &opcode); for (i = 0; i < ARRAY_SIZE(imm_wop); i++) diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 17fda6a..f7d54a0 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -91,10 +91,67 @@ static inline void pgd_list_del(pgd_t *pgd) list_del(&page->lru); } -#define UNSHARED_PTRS_PER_PGD \ - (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD) +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) +pgdval_t clone_pgd_mask __read_only = ~_PAGE_PRESENT; +void __shadow_user_pgds(pgd_t *dst, const pgd_t *src) +{ + unsigned int count = USER_PGD_PTRS; + + if (!pax_user_shadow_base) + return; + + while (count--) + *dst++ = __pgd((pgd_val(*src++) | (_PAGE_NX & __supported_pte_mask)) & ~_PAGE_USER); +} +#endif + +#ifdef CONFIG_PAX_PER_CPU_PGD +void __clone_user_pgds(pgd_t *dst, const pgd_t *src) +{ + unsigned int count = USER_PGD_PTRS; + + while (count--) { + pgd_t pgd; + +#ifdef CONFIG_X86_64 + pgd = __pgd(pgd_val(*src++) | _PAGE_USER); +#else + pgd = *src++; +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF) + pgd = __pgd(pgd_val(pgd) & clone_pgd_mask); +#endif + *dst++ = pgd; + } + +} +#endif + +#ifdef CONFIG_X86_64 +#define pxd_t pud_t +#define pyd_t pgd_t +#define paravirt_release_pxd(pfn) paravirt_release_pud(pfn) +#define pxd_free(mm, pud) pud_free((mm), (pud)) +#define pyd_populate(mm, pgd, pud) pgd_populate((mm), (pgd), (pud)) +#define pyd_offset(mm, address) pgd_offset((mm), (address)) +#define PYD_SIZE PGDIR_SIZE +#else +#define pxd_t pmd_t +#define pyd_t pud_t +#define paravirt_release_pxd(pfn) paravirt_release_pmd(pfn) +#define pxd_free(mm, pud) pmd_free((mm), (pud)) +#define pyd_populate(mm, pgd, pud) pud_populate((mm), (pgd), (pud)) +#define pyd_offset(mm, address) pud_offset((mm), (address)) +#define PYD_SIZE PUD_SIZE +#endif + +#ifdef CONFIG_PAX_PER_CPU_PGD +static inline void pgd_ctor(struct mm_struct *mm, pgd_t *pgd) {} +static inline void pgd_dtor(pgd_t *pgd) {} +#else static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm) { BUILD_BUG_ON(sizeof(virt_to_page(pgd)->index) < sizeof(mm)); @@ -135,6 +192,7 @@ static void pgd_dtor(pgd_t *pgd) pgd_list_del(pgd); spin_unlock(&pgd_lock); } +#endif /* * List of all pgd's needed for non-PAE so it can invalidate entries @@ -147,7 +205,7 @@ static void pgd_dtor(pgd_t *pgd) * -- nyc */ -#ifdef CONFIG_X86_PAE +#if defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE) /* * In PAE mode, we need to do a cr3 reload (=tlb flush) when * updating the top-level pagetable entries to guarantee the @@ -159,7 +217,7 @@ static void pgd_dtor(pgd_t *pgd) * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate * and initialize the kernel pmds here. */ -#define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD +#define PREALLOCATED_PXDS (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD) void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) { @@ -177,36 +235,38 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) */ flush_tlb_mm(mm); } +#elif defined(CONFIG_X86_64) && defined(CONFIG_PAX_PER_CPU_PGD) +#define PREALLOCATED_PXDS USER_PGD_PTRS #else /* !CONFIG_X86_PAE */ /* No need to prepopulate any pagetable entries in non-PAE modes. */ -#define PREALLOCATED_PMDS 0 +#define PREALLOCATED_PXDS 0 #endif /* CONFIG_X86_PAE */ -static void free_pmds(pmd_t *pmds[]) +static void free_pxds(pxd_t *pxds[]) { int i; - for(i = 0; i < PREALLOCATED_PMDS; i++) - if (pmds[i]) - free_page((unsigned long)pmds[i]); + for(i = 0; i < PREALLOCATED_PXDS; i++) + if (pxds[i]) + free_page((unsigned long)pxds[i]); } -static int preallocate_pmds(pmd_t *pmds[]) +static int preallocate_pxds(pxd_t *pxds[]) { int i; bool failed = false; - for(i = 0; i < PREALLOCATED_PMDS; i++) { - pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP); - if (pmd == NULL) + for(i = 0; i < PREALLOCATED_PXDS; i++) { + pxd_t *pxd = (pxd_t *)__get_free_page(PGALLOC_GFP); + if (pxd == NULL) failed = true; - pmds[i] = pmd; + pxds[i] = pxd; } if (failed) { - free_pmds(pmds); + free_pxds(pxds); return -ENOMEM; } @@ -219,51 +279,55 @@ static int preallocate_pmds(pmd_t *pmds[]) * preallocate which never got a corresponding vma will need to be * freed manually. */ -static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp) +static void pgd_mop_up_pxds(struct mm_struct *mm, pgd_t *pgdp) { int i; - for(i = 0; i < PREALLOCATED_PMDS; i++) { + for(i = 0; i < PREALLOCATED_PXDS; i++) { pgd_t pgd = pgdp[i]; if (pgd_val(pgd) != 0) { - pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd); + pxd_t *pxd = (pxd_t *)pgd_page_vaddr(pgd); - pgdp[i] = native_make_pgd(0); + set_pgd(pgdp + i, native_make_pgd(0)); - paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT); - pmd_free(mm, pmd); + paravirt_release_pxd(pgd_val(pgd) >> PAGE_SHIFT); + pxd_free(mm, pxd); } } } -static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[]) +static void pgd_prepopulate_pxd(struct mm_struct *mm, pgd_t *pgd, pxd_t *pxds[]) { - pud_t *pud; + pyd_t *pyd; unsigned long addr; int i; - if (PREALLOCATED_PMDS == 0) /* Work around gcc-3.4.x bug */ + if (PREALLOCATED_PXDS == 0) /* Work around gcc-3.4.x bug */ return; - pud = pud_offset(pgd, 0); +#ifdef CONFIG_X86_64 + pyd = pyd_offset(mm, 0L); +#else + pyd = pyd_offset(pgd, 0L); +#endif - for (addr = i = 0; i < PREALLOCATED_PMDS; - i++, pud++, addr += PUD_SIZE) { - pmd_t *pmd = pmds[i]; + for (addr = i = 0; i < PREALLOCATED_PXDS; + i++, pyd++, addr += PYD_SIZE) { + pxd_t *pxd = pxds[i]; if (i >= KERNEL_PGD_BOUNDARY) - memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]), - sizeof(pmd_t) * PTRS_PER_PMD); + memcpy(pxd, (pxd_t *)pgd_page_vaddr(swapper_pg_dir[i]), + sizeof(pxd_t) * PTRS_PER_PMD); - pud_populate(mm, pud, pmd); + pyd_populate(mm, pyd, pxd); } } pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *pgd; - pmd_t *pmds[PREALLOCATED_PMDS]; + pxd_t *pxds[PREALLOCATED_PXDS]; pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); @@ -272,11 +336,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm) mm->pgd = pgd; - if (preallocate_pmds(pmds) != 0) + if (preallocate_pxds(pxds) != 0) goto out_free_pgd; if (paravirt_pgd_alloc(mm) != 0) - goto out_free_pmds; + goto out_free_pxds; /* * Make sure that pre-populating the pmds is atomic with @@ -286,14 +350,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm) spin_lock(&pgd_lock); pgd_ctor(mm, pgd); - pgd_prepopulate_pmd(mm, pgd, pmds); + pgd_prepopulate_pxd(mm, pgd, pxds); spin_unlock(&pgd_lock); return pgd; -out_free_pmds: - free_pmds(pmds); +out_free_pxds: + free_pxds(pxds); out_free_pgd: free_page((unsigned long)pgd); out: @@ -302,7 +366,7 @@ out: void pgd_free(struct mm_struct *mm, pgd_t *pgd) { - pgd_mop_up_pmds(mm, pgd); + pgd_mop_up_pxds(mm, pgd); pgd_dtor(pgd); paravirt_pgd_free(mm, pgd); free_page((unsigned long)pgd); diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index a69bcb8..19068ab 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c @@ -47,10 +47,13 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pteval) return; } pte = pte_offset_kernel(pmd, vaddr); + + pax_open_kernel(); if (pte_val(pteval)) set_pte_at(&init_mm, vaddr, pte, pteval); else pte_clear(&init_mm, vaddr, pte); + pax_close_kernel(); /* * It's enough to flush this one mapping. diff --git a/arch/x86/mm/physaddr.c b/arch/x86/mm/physaddr.c index e666cbb..61788c45 100644 --- a/arch/x86/mm/physaddr.c +++ b/arch/x86/mm/physaddr.c @@ -10,7 +10,7 @@ #ifdef CONFIG_X86_64 #ifdef CONFIG_DEBUG_VIRTUAL -unsigned long __phys_addr(unsigned long x) +unsigned long __intentional_overflow(-1) __phys_addr(unsigned long x) { unsigned long y = x - __START_KERNEL_map; @@ -67,7 +67,7 @@ EXPORT_SYMBOL(__virt_addr_valid); #else #ifdef CONFIG_DEBUG_VIRTUAL -unsigned long __phys_addr(unsigned long x) +unsigned long __intentional_overflow(-1) __phys_addr(unsigned long x) { unsigned long phys_addr = x - PAGE_OFFSET; /* VMALLOC_* aren't constants */ diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 410531d..0f16030 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -5,8 +5,10 @@ #include #include +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) static int disable_nx __cpuinitdata; +#ifndef CONFIG_PAX_PAGEEXEC /* * noexec = on|off * @@ -28,12 +30,17 @@ static int __init noexec_setup(char *str) return 0; } early_param("noexec", noexec_setup); +#endif + +#endif void __cpuinit x86_configure_nx(void) { +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) if (cpu_has_nx && !disable_nx) __supported_pte_mask |= _PAGE_NX; else +#endif __supported_pte_mask &= ~_PAGE_NX; } diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 282375f..e03a98f 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -48,7 +48,11 @@ void leave_mm(int cpu) BUG(); if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) { cpumask_clear_cpu(cpu, mm_cpumask(active_mm)); + +#ifndef CONFIG_PAX_PER_CPU_PGD load_cr3(swapper_pg_dir); +#endif + } } EXPORT_SYMBOL_GPL(leave_mm); diff --git a/arch/x86/mm/uderef_64.c b/arch/x86/mm/uderef_64.c new file mode 100644 index 0000000..dace51c --- /dev/null +++ b/arch/x86/mm/uderef_64.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#ifdef CONFIG_PAX_MEMORY_UDEREF +/* PaX: due to the special call convention these functions must + * - remain leaf functions under all configurations, + * - never be called directly, only dereferenced from the wrappers. + */ +void __pax_open_userland(void) +{ + unsigned int cpu; + + if (unlikely(!segment_eq(get_fs(), USER_DS))) + return; + + cpu = raw_get_cpu(); + BUG_ON((read_cr3() & ~PAGE_MASK) != PCID_KERNEL); + write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER | PCID_NOFLUSH); + raw_put_cpu_no_resched(); +} +EXPORT_SYMBOL(__pax_open_userland); + +void __pax_close_userland(void) +{ + unsigned int cpu; + + if (unlikely(!segment_eq(get_fs(), USER_DS))) + return; + + cpu = raw_get_cpu(); + BUG_ON((read_cr3() & ~PAGE_MASK) != PCID_USER); + write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL | PCID_NOFLUSH); + raw_put_cpu_no_resched(); +} +EXPORT_SYMBOL(__pax_close_userland); +#endif diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S index 877b9a1..a8ecf42 100644 --- a/arch/x86/net/bpf_jit.S +++ b/arch/x86/net/bpf_jit.S @@ -9,6 +9,7 @@ */ #include #include +#include /* * Calling convention : @@ -35,6 +36,7 @@ sk_load_word_positive_offset: jle bpf_slow_path_word mov (SKBDATA,%rsi),%eax bswap %eax /* ntohl() */ + pax_force_retaddr ret sk_load_half: @@ -52,6 +54,7 @@ sk_load_half_positive_offset: jle bpf_slow_path_half movzwl (SKBDATA,%rsi),%eax rol $8,%ax # ntohs() + pax_force_retaddr ret sk_load_byte: @@ -66,6 +69,7 @@ sk_load_byte_positive_offset: cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */ jle bpf_slow_path_byte movzbl (SKBDATA,%rsi),%eax + pax_force_retaddr ret /** @@ -87,6 +91,7 @@ sk_load_byte_msh_positive_offset: movzbl (SKBDATA,%rsi),%ebx and $15,%bl shl $2,%bl + pax_force_retaddr ret /* rsi contains offset and can be scratched */ @@ -109,6 +114,7 @@ bpf_slow_path_word: js bpf_error mov -12(%rbp),%eax bswap %eax + pax_force_retaddr ret bpf_slow_path_half: @@ -117,12 +123,14 @@ bpf_slow_path_half: mov -12(%rbp),%ax rol $8,%ax movzwl %ax,%eax + pax_force_retaddr ret bpf_slow_path_byte: bpf_slow_path_common(1) js bpf_error movzbl -12(%rbp),%eax + pax_force_retaddr ret bpf_slow_path_byte_msh: @@ -133,6 +141,7 @@ bpf_slow_path_byte_msh: and $15,%al shl $2,%al xchg %eax,%ebx + pax_force_retaddr ret #define sk_negative_common(SIZE) \ @@ -157,6 +166,7 @@ sk_load_word_negative_offset: sk_negative_common(4) mov (%rax), %eax bswap %eax + pax_force_retaddr ret bpf_slow_path_half_neg: @@ -168,6 +178,7 @@ sk_load_half_negative_offset: mov (%rax),%ax rol $8,%ax movzwl %ax,%eax + pax_force_retaddr ret bpf_slow_path_byte_neg: @@ -177,6 +188,7 @@ sk_load_byte_negative_offset: .globl sk_load_byte_negative_offset sk_negative_common(1) movzbl (%rax), %eax + pax_force_retaddr ret bpf_slow_path_byte_msh_neg: @@ -190,6 +202,7 @@ sk_load_byte_msh_negative_offset: and $15,%al shl $2,%al xchg %eax,%ebx + pax_force_retaddr ret bpf_error: @@ -197,4 +210,5 @@ bpf_error: xor %eax,%eax mov -8(%rbp),%rbx leaveq + pax_force_retaddr ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index f66b540..3e88dfb 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -12,6 +12,7 @@ #include #include #include +#include /* * Conventions : @@ -49,13 +50,90 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) return ptr + len; } +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN +#define MAX_INSTR_CODE_SIZE 96 +#else +#define MAX_INSTR_CODE_SIZE 64 +#endif + #define EMIT(bytes, len) do { prog = emit_code(prog, bytes, len); } while (0) #define EMIT1(b1) EMIT(b1, 1) #define EMIT2(b1, b2) EMIT((b1) + ((b2) << 8), 2) #define EMIT3(b1, b2, b3) EMIT((b1) + ((b2) << 8) + ((b3) << 16), 3) #define EMIT4(b1, b2, b3, b4) EMIT((b1) + ((b2) << 8) + ((b3) << 16) + ((b4) << 24), 4) + +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN +/* original constant will appear in ecx */ +#define DILUTE_CONST_SEQUENCE(_off, _key) \ +do { \ + /* mov ecx, randkey */ \ + EMIT1(0xb9); \ + EMIT(_key, 4); \ + /* xor ecx, randkey ^ off */ \ + EMIT2(0x81, 0xf1); \ + EMIT((_key) ^ (_off), 4); \ +} while (0) + +#define EMIT1_off32(b1, _off) \ +do { \ + switch (b1) { \ + case 0x05: /* add eax, imm32 */ \ + case 0x2d: /* sub eax, imm32 */ \ + case 0x25: /* and eax, imm32 */ \ + case 0x0d: /* or eax, imm32 */ \ + case 0xb8: /* mov eax, imm32 */ \ + case 0x35: /* xor eax, imm32 */ \ + case 0x3d: /* cmp eax, imm32 */ \ + case 0xa9: /* test eax, imm32 */ \ + DILUTE_CONST_SEQUENCE(_off, randkey); \ + EMIT2((b1) - 4, 0xc8); /* convert imm instruction to eax, ecx */\ + break; \ + case 0xbb: /* mov ebx, imm32 */ \ + DILUTE_CONST_SEQUENCE(_off, randkey); \ + /* mov ebx, ecx */ \ + EMIT2(0x89, 0xcb); \ + break; \ + case 0xbe: /* mov esi, imm32 */ \ + DILUTE_CONST_SEQUENCE(_off, randkey); \ + /* mov esi, ecx */ \ + EMIT2(0x89, 0xce); \ + break; \ + case 0xe8: /* call rel imm32, always to known funcs */ \ + EMIT1(b1); \ + EMIT(_off, 4); \ + break; \ + case 0xe9: /* jmp rel imm32 */ \ + EMIT1(b1); \ + EMIT(_off, 4); \ + /* prevent fall-through, we're not called if off = 0 */ \ + EMIT(0xcccccccc, 4); \ + EMIT(0xcccccccc, 4); \ + break; \ + default: \ + BUILD_BUG(); \ + } \ +} while (0) + +#define EMIT2_off32(b1, b2, _off) \ +do { \ + if ((b1) == 0x8d && (b2) == 0xb3) { /* lea esi, [rbx+imm32] */ \ + EMIT2(0x8d, 0xb3); /* lea esi, [rbx+randkey] */ \ + EMIT(randkey, 4); \ + EMIT2(0x8d, 0xb6); /* lea esi, [esi+off-randkey] */ \ + EMIT((_off) - randkey, 4); \ + } else if ((b1) == 0x69 && (b2) == 0xc0) { /* imul eax, imm32 */\ + DILUTE_CONST_SEQUENCE(_off, randkey); \ + /* imul eax, ecx */ \ + EMIT3(0x0f, 0xaf, 0xc1); \ + } else { \ + BUILD_BUG(); \ + } \ +} while (0) +#else #define EMIT1_off32(b1, off) do { EMIT1(b1); EMIT(off, 4);} while (0) +#define EMIT2_off32(b1, b2, off) do { EMIT2(b1, b2); EMIT(off, 4);} while (0) +#endif #define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */ #define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */ @@ -90,6 +168,24 @@ do { \ #define X86_JBE 0x76 #define X86_JA 0x77 +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN +#define APPEND_FLOW_VERIFY() \ +do { \ + /* mov ecx, randkey */ \ + EMIT1(0xb9); \ + EMIT(randkey, 4); \ + /* cmp ecx, randkey */ \ + EMIT2(0x81, 0xf9); \ + EMIT(randkey, 4); \ + /* jz after 8 int 3s */ \ + EMIT2(0x74, 0x08); \ + EMIT(0xcccccccc, 4); \ + EMIT(0xcccccccc, 4); \ +} while (0) +#else +#define APPEND_FLOW_VERIFY() do { } while (0) +#endif + #define EMIT_COND_JMP(op, offset) \ do { \ if (is_near(offset)) \ @@ -97,6 +193,7 @@ do { \ else { \ EMIT2(0x0f, op + 0x10); \ EMIT(offset, 4); /* jxx .+off32 */ \ + APPEND_FLOW_VERIFY(); \ } \ } while (0) @@ -121,6 +218,11 @@ static inline void bpf_flush_icache(void *start, void *end) set_fs(old_fs); } +struct bpf_jit_work { + struct work_struct work; + void *image; +}; + #define CHOOSE_LOAD_FUNC(K, func) \ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) @@ -146,7 +248,7 @@ static int pkt_type_offset(void) void bpf_jit_compile(struct sk_filter *fp) { - u8 temp[64]; + u8 temp[MAX_INSTR_CODE_SIZE]; u8 *prog; unsigned int proglen, oldproglen = 0; int ilen, i; @@ -159,6 +261,9 @@ void bpf_jit_compile(struct sk_filter *fp) unsigned int *addrs; const struct sock_filter *filter = fp->insns; int flen = fp->len; +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN + unsigned int randkey; +#endif if (!bpf_jit_enable) return; @@ -167,11 +272,19 @@ void bpf_jit_compile(struct sk_filter *fp) if (addrs == NULL) return; + fp->work = kmalloc(sizeof(*fp->work), GFP_KERNEL); + if (!fp->work) + goto out; + +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN + randkey = get_random_int(); +#endif + /* Before first pass, make a rough estimation of addrs[] - * each bpf instruction is translated to less than 64 bytes + * each bpf instruction is translated to less than MAX_INSTR_CODE_SIZE bytes */ for (proglen = 0, i = 0; i < flen; i++) { - proglen += 64; + proglen += MAX_INSTR_CODE_SIZE; addrs[i] = proglen; } cleanup_addr = proglen; /* epilogue address */ @@ -282,10 +395,8 @@ void bpf_jit_compile(struct sk_filter *fp) case BPF_S_ALU_MUL_K: /* A *= K */ if (is_imm8(K)) EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */ - else { - EMIT2(0x69, 0xc0); /* imul imm32,%eax */ - EMIT(K, 4); - } + else + EMIT2_off32(0x69, 0xc0, K); /* imul imm32,%eax */ break; case BPF_S_ALU_DIV_X: /* A /= X; */ seen |= SEEN_XREG; @@ -325,13 +436,23 @@ void bpf_jit_compile(struct sk_filter *fp) break; case BPF_S_ALU_MOD_K: /* A %= K; */ EMIT2(0x31, 0xd2); /* xor %edx,%edx */ +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN + DILUTE_CONST_SEQUENCE(K, randkey); +#else EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ +#endif EMIT2(0xf7, 0xf1); /* div %ecx */ EMIT2(0x89, 0xd0); /* mov %edx,%eax */ break; case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ +#ifdef CONFIG_GRKERNSEC_JIT_HARDEN + DILUTE_CONST_SEQUENCE(K, randkey); + // imul rax, rcx + EMIT4(0x48, 0x0f, 0xaf, 0xc1); +#else EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ EMIT(K, 4); +#endif EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ break; case BPF_S_ALU_AND_X: @@ -602,8 +723,7 @@ common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG; if (is_imm8(K)) { EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */ } else { - EMIT2(0x8d, 0xb3); /* lea imm32(%rbx),%esi */ - EMIT(K, 4); + EMIT2_off32(0x8d, 0xb3, K); /* lea imm32(%rbx),%esi */ } } else { EMIT2(0x89,0xde); /* mov %ebx,%esi */ @@ -686,17 +806,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; default: /* hmm, too complex filter, give up with jit compiler */ - goto out; + goto error; } ilen = prog - temp; if (image) { if (unlikely(proglen + ilen > oldproglen)) { pr_err("bpb_jit_compile fatal error\n"); - kfree(addrs); - module_free(NULL, image); - return; + module_free_exec(NULL, image); + goto error; } + pax_open_kernel(); memcpy(image + proglen, temp, ilen); + pax_close_kernel(); } proglen += ilen; addrs[i] = proglen; @@ -717,11 +838,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { - image = module_alloc(max_t(unsigned int, - proglen, - sizeof(struct work_struct))); + image = module_alloc_exec(proglen); if (!image) - goto out; + goto error; } oldproglen = proglen; } @@ -732,7 +851,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; if (image) { bpf_flush_icache(image, image + proglen); fp->bpf_func = (void *)image; - } + } else +error: + kfree(fp->work); + out: kfree(addrs); return; @@ -740,18 +862,20 @@ out: static void jit_free_defer(struct work_struct *arg) { - module_free(NULL, arg); + module_free_exec(NULL, ((struct bpf_jit_work *)arg)->image); + kfree(arg); } /* run from softirq, we must use a work_struct to call - * module_free() from process context + * module_free_exec() from process context */ void bpf_jit_free(struct sk_filter *fp) { if (fp->bpf_func != sk_run_filter) { - struct work_struct *work = (struct work_struct *)fp->bpf_func; + struct work_struct *work = &fp->work->work; INIT_WORK(work, jit_free_defer); + fp->work->image = fp->bpf_func; schedule_work(work); } } diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c index d6aa6e8..266395a 100644 --- a/arch/x86/oprofile/backtrace.c +++ b/arch/x86/oprofile/backtrace.c @@ -46,11 +46,11 @@ dump_user_backtrace_32(struct stack_frame_ia32 *head) struct stack_frame_ia32 *fp; unsigned long bytes; - bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); + bytes = copy_from_user_nmi(bufhead, (const char __force_user *)head, sizeof(bufhead)); if (bytes != sizeof(bufhead)) return NULL; - fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); + fp = (struct stack_frame_ia32 __force_kernel *) compat_ptr(bufhead[0].next_frame); oprofile_add_trace(bufhead[0].return_address); @@ -92,7 +92,7 @@ static struct stack_frame *dump_user_backtrace(struct stack_frame *head) struct stack_frame bufhead[2]; unsigned long bytes; - bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); + bytes = copy_from_user_nmi(bufhead, (const char __force_user *)head, sizeof(bufhead)); if (bytes != sizeof(bufhead)) return NULL; @@ -111,7 +111,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) { struct stack_frame *head = (struct stack_frame *)frame_pointer(regs); - if (!user_mode_vm(regs)) { + if (!user_mode(regs)) { unsigned long stack = kernel_stack_pointer(regs); if (depth) dump_trace(NULL, regs, (unsigned long *)stack, 0, diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 48768df..ba9143c 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "op_counter.h" #include "op_x86_model.h" @@ -774,8 +775,11 @@ int __init op_nmi_init(struct oprofile_operations *ops) if (ret) return ret; - if (!model->num_virt_counters) - model->num_virt_counters = model->num_counters; + if (!model->num_virt_counters) { + pax_open_kernel(); + *(unsigned int *)&model->num_virt_counters = model->num_counters; + pax_close_kernel(); + } mux_init(ops); diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index b2b9443..be58856 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -519,9 +519,11 @@ static int op_amd_init(struct oprofile_operations *ops) num_counters = AMD64_NUM_COUNTERS; } - op_amd_spec.num_counters = num_counters; - op_amd_spec.num_controls = num_counters; - op_amd_spec.num_virt_counters = max(num_counters, NUM_VIRT_COUNTERS); + pax_open_kernel(); + *(unsigned int *)&op_amd_spec.num_counters = num_counters; + *(unsigned int *)&op_amd_spec.num_controls = num_counters; + *(unsigned int *)&op_amd_spec.num_virt_counters = max(num_counters, NUM_VIRT_COUNTERS); + pax_close_kernel(); return 0; } diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index d90528e..0127e2b 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" @@ -221,8 +222,10 @@ static void arch_perfmon_setup_counters(void) num_counters = min((int)eax.split.num_counters, OP_MAX_COUNTER); - op_arch_perfmon_spec.num_counters = num_counters; - op_arch_perfmon_spec.num_controls = num_counters; + pax_open_kernel(); + *(unsigned int *)&op_arch_perfmon_spec.num_counters = num_counters; + *(unsigned int *)&op_arch_perfmon_spec.num_controls = num_counters; + pax_close_kernel(); } static int arch_perfmon_init(struct oprofile_operations *ignore) diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index 71e8a67..6a313bb 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -52,7 +52,7 @@ struct op_x86_model_spec { void (*switch_ctrl)(struct op_x86_model_spec const *model, struct op_msrs const * const msrs); #endif -}; +} __do_const; struct op_counter_config; diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index e9e6ed5..e47ae67 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -337,7 +337,7 @@ static int __cpuinit amd_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata amd_cpu_notifier = { +static struct notifier_block amd_cpu_notifier = { .notifier_call = amd_cpu_notify, }; diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 372e9b8..e775a6c 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -50,7 +50,7 @@ struct irq_router { struct irq_router_handler { u16 vendor; int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device); -}; +} __do_const; int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq; void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; @@ -794,7 +794,7 @@ static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router return 0; } -static __initdata struct irq_router_handler pirq_routers[] = { +static __initconst const struct irq_router_handler pirq_routers[] = { { PCI_VENDOR_ID_INTEL, intel_router_probe }, { PCI_VENDOR_ID_AL, ali_router_probe }, { PCI_VENDOR_ID_ITE, ite_router_probe }, @@ -821,7 +821,7 @@ static struct pci_dev *pirq_router_dev; static void __init pirq_find_router(struct irq_router *r) { struct irq_routing_table *rt = pirq_table; - struct irq_router_handler *h; + const struct irq_router_handler *h; #ifdef CONFIG_PCI_BIOS if (!rt->signature) { @@ -1094,7 +1094,7 @@ static int __init fix_acer_tm360_irqrouting(const struct dmi_system_id *d) return 0; } -static struct dmi_system_id __initdata pciirq_dmi_table[] = { +static const struct dmi_system_id __initconst pciirq_dmi_table[] = { { .callback = fix_broken_hp_bios_irq9, .ident = "HP Pavilion N5400 Series Laptop", diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 6eb18c4..20d83de 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -238,7 +238,9 @@ int __init pci_mrst_init(void) printk(KERN_INFO "Intel MID platform detected, using MID PCI ops\n"); pci_mmcfg_late_init(); pcibios_enable_irq = mrst_pci_irq_enable; - pci_root_ops = pci_mrst_ops; + pax_open_kernel(); + memcpy((void *)&pci_root_ops, &pci_mrst_ops, sizeof(pci_mrst_ops)); + pax_close_kernel(); pci_soc_mode = 1; /* Continue with standard init */ return 1; diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index c77b24a..c979855 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c @@ -79,7 +79,7 @@ union bios32 { static struct { unsigned long address; unsigned short segment; -} bios32_indirect = { 0, __KERNEL_CS }; +} bios32_indirect __read_only = { 0, __PCIBIOS_CS }; /* * Returns the entry point for the given service, NULL on error @@ -92,37 +92,80 @@ static unsigned long bios32_service(unsigned long service) unsigned long length; /* %ecx */ unsigned long entry; /* %edx */ unsigned long flags; + struct desc_struct d, *gdt; local_irq_save(flags); - __asm__("lcall *(%%edi); cld" + + gdt = get_cpu_gdt_table(smp_processor_id()); + + pack_descriptor(&d, 0UL, 0xFFFFFUL, 0x9B, 0xC); + write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_CS, &d, DESCTYPE_S); + pack_descriptor(&d, 0UL, 0xFFFFFUL, 0x93, 0xC); + write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_DS, &d, DESCTYPE_S); + + __asm__("movw %w7, %%ds; lcall *(%%edi); push %%ss; pop %%ds; cld" : "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry) : "0" (service), "1" (0), - "D" (&bios32_indirect)); + "D" (&bios32_indirect), + "r"(__PCIBIOS_DS) + : "memory"); + + pax_open_kernel(); + gdt[GDT_ENTRY_PCIBIOS_CS].a = 0; + gdt[GDT_ENTRY_PCIBIOS_CS].b = 0; + gdt[GDT_ENTRY_PCIBIOS_DS].a = 0; + gdt[GDT_ENTRY_PCIBIOS_DS].b = 0; + pax_close_kernel(); + local_irq_restore(flags); switch (return_code) { - case 0: - return address + entry; - case 0x80: /* Not present */ - printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); - return 0; - default: /* Shouldn't happen */ - printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", - service, return_code); + case 0: { + int cpu; + unsigned char flags; + + printk(KERN_INFO "bios32_service: base:%08lx length:%08lx entry:%08lx\n", address, length, entry); + if (address >= 0xFFFF0 || length > 0x100000 - address || length <= entry) { + printk(KERN_WARNING "bios32_service: not valid\n"); return 0; + } + address = address + PAGE_OFFSET; + length += 16UL; /* some BIOSs underreport this... */ + flags = 4; + if (length >= 64*1024*1024) { + length >>= PAGE_SHIFT; + flags |= 8; + } + + for (cpu = 0; cpu < nr_cpu_ids; cpu++) { + gdt = get_cpu_gdt_table(cpu); + pack_descriptor(&d, address, length, 0x9b, flags); + write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_CS, &d, DESCTYPE_S); + pack_descriptor(&d, address, length, 0x93, flags); + write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_DS, &d, DESCTYPE_S); + } + return entry; + } + case 0x80: /* Not present */ + printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); + return 0; + default: /* Shouldn't happen */ + printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", + service, return_code); + return 0; } } static struct { unsigned long address; unsigned short segment; -} pci_indirect = { 0, __KERNEL_CS }; +} pci_indirect __read_only = { 0, __PCIBIOS_CS }; -static int pci_bios_present; +static int pci_bios_present __read_only; static int check_pcibios(void) { @@ -131,11 +174,13 @@ static int check_pcibios(void) unsigned long flags, pcibios_entry; if ((pcibios_entry = bios32_service(PCI_SERVICE))) { - pci_indirect.address = pcibios_entry + PAGE_OFFSET; + pci_indirect.address = pcibios_entry; local_irq_save(flags); - __asm__( - "lcall *(%%edi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%edi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -144,7 +189,8 @@ static int check_pcibios(void) "=b" (ebx), "=c" (ecx) : "1" (PCIBIOS_PCI_BIOS_PRESENT), - "D" (&pci_indirect) + "D" (&pci_indirect), + "r" (__PCIBIOS_DS) : "memory"); local_irq_restore(flags); @@ -189,7 +235,10 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, switch (len) { case 1: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -198,7 +247,8 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, : "1" (PCIBIOS_READ_CONFIG_BYTE), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); /* * Zero-extend the result beyond 8 bits, do not trust the * BIOS having done it: @@ -206,7 +256,10 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, *value &= 0xff; break; case 2: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -215,7 +268,8 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, : "1" (PCIBIOS_READ_CONFIG_WORD), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); /* * Zero-extend the result beyond 16 bits, do not trust the * BIOS having done it: @@ -223,7 +277,10 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, *value &= 0xffff; break; case 4: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -232,7 +289,8 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, : "1" (PCIBIOS_READ_CONFIG_DWORD), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; } @@ -256,7 +314,10 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, switch (len) { case 1: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -265,10 +326,14 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, "c" (value), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; case 2: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -277,10 +342,14 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, "c" (value), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; case 4: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -289,7 +358,8 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, "c" (value), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; } @@ -394,10 +464,13 @@ struct irq_routing_table * pcibios_get_irq_routing_table(void) DBG("PCI: Fetching IRQ routing table... "); __asm__("push %%es\n\t" + "movw %w8, %%ds\n\t" "push %%ds\n\t" "pop %%es\n\t" - "lcall *(%%esi); cld\n\t" + "lcall *%%ss:(%%esi); cld\n\t" "pop %%es\n\t" + "push %%ss\n\t" + "pop %%ds\n" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -408,7 +481,8 @@ struct irq_routing_table * pcibios_get_irq_routing_table(void) "1" (0), "D" ((long) &opt), "S" (&pci_indirect), - "m" (opt) + "m" (opt), + "r" (__PCIBIOS_DS) : "memory"); DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map); if (ret & 0xff00) @@ -432,7 +506,10 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) { int ret; - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w5, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -440,7 +517,8 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) : "0" (PCIBIOS_SET_PCI_HW_INT), "b" ((dev->bus->number << 8) | dev->devfn), "c" ((irq << 8) | (pin + 10)), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); return !(ret & 0xff00); } EXPORT_SYMBOL(pcibios_set_irq_routing); diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 40e4469..d915bf9 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -44,11 +44,22 @@ void efi_call_phys_prelog(void) { struct desc_ptr gdt_descr; +#ifdef CONFIG_PAX_KERNEXEC + struct desc_struct d; +#endif + local_irq_save(efi_rt_eflags); load_cr3(initial_page_table); __flush_tlb_all(); +#ifdef CONFIG_PAX_KERNEXEC + pack_descriptor(&d, 0, 0xFFFFF, 0x9B, 0xC); + write_gdt_entry(get_cpu_gdt_table(0), GDT_ENTRY_KERNEXEC_EFI_CS, &d, DESCTYPE_S); + pack_descriptor(&d, 0, 0xFFFFF, 0x93, 0xC); + write_gdt_entry(get_cpu_gdt_table(0), GDT_ENTRY_KERNEXEC_EFI_DS, &d, DESCTYPE_S); +#endif + gdt_descr.address = __pa(get_cpu_gdt_table(0)); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); @@ -58,11 +69,24 @@ void efi_call_phys_epilog(void) { struct desc_ptr gdt_descr; +#ifdef CONFIG_PAX_KERNEXEC + struct desc_struct d; + + memset(&d, 0, sizeof d); + write_gdt_entry(get_cpu_gdt_table(0), GDT_ENTRY_KERNEXEC_EFI_CS, &d, DESCTYPE_S); + write_gdt_entry(get_cpu_gdt_table(0), GDT_ENTRY_KERNEXEC_EFI_DS, &d, DESCTYPE_S); +#endif + gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); +#ifdef CONFIG_PAX_PER_CPU_PGD + load_cr3(get_cpu_pgd(smp_processor_id(), kernel)); +#else load_cr3(swapper_pg_dir); +#endif + __flush_tlb_all(); local_irq_restore(efi_rt_eflags); diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 39a0e7f..872396e 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -76,6 +76,11 @@ void __init efi_call_phys_prelog(void) vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); } + +#ifdef CONFIG_PAX_PER_CPU_PGD + load_cr3(swapper_pg_dir); +#endif + __flush_tlb_all(); } @@ -89,6 +94,11 @@ void __init efi_call_phys_epilog(void) for (pgd = 0; pgd < n_pgds; pgd++) set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); kfree(save_pgd); + +#ifdef CONFIG_PAX_PER_CPU_PGD + load_cr3(get_cpu_pgd(smp_processor_id(), kernel)); +#endif + __flush_tlb_all(); local_irq_restore(efi_flags); early_code_mapping_set_exec(0); diff --git a/arch/x86/platform/efi/efi_stub_32.S b/arch/x86/platform/efi/efi_stub_32.S index fbe66e6..eae5e38 100644 --- a/arch/x86/platform/efi/efi_stub_32.S +++ b/arch/x86/platform/efi/efi_stub_32.S @@ -6,7 +6,9 @@ */ #include +#include #include +#include /* * efi_call_phys(void *, ...) is a function with variable parameters. @@ -20,7 +22,7 @@ * service functions will comply with gcc calling convention, too. */ -.text +__INIT ENTRY(efi_call_phys) /* * 0. The function can only be called in Linux kernel. So CS has been @@ -36,10 +38,24 @@ ENTRY(efi_call_phys) * The mapping of lower virtual memory has been created in prelog and * epilog. */ - movl $1f, %edx - subl $__PAGE_OFFSET, %edx - jmp *%edx +#ifdef CONFIG_PAX_KERNEXEC + movl $(__KERNEXEC_EFI_DS), %edx + mov %edx, %ds + mov %edx, %es + mov %edx, %ss + addl $2f,(1f) + ljmp *(1f) + +__INITDATA +1: .long __LOAD_PHYSICAL_ADDR, __KERNEXEC_EFI_CS +.previous + +2: + subl $2b,(1b) +#else + jmp 1f-__PAGE_OFFSET 1: +#endif /* * 2. Now on the top of stack is the return @@ -47,14 +63,8 @@ ENTRY(efi_call_phys) * parameter 2, ..., param n. To make things easy, we save the return * address of efi_call_phys in a global variable. */ - popl %edx - movl %edx, saved_return_addr - /* get the function pointer into ECX*/ - popl %ecx - movl %ecx, efi_rt_function_ptr - movl $2f, %edx - subl $__PAGE_OFFSET, %edx - pushl %edx + popl (saved_return_addr) + popl (efi_rt_function_ptr) /* * 3. Clear PG bit in %CR0. @@ -73,9 +83,8 @@ ENTRY(efi_call_phys) /* * 5. Call the physical function. */ - jmp *%ecx + call *(efi_rt_function_ptr-__PAGE_OFFSET) -2: /* * 6. After EFI runtime service returns, control will return to * following instruction. We'd better readjust stack pointer first. @@ -88,35 +97,36 @@ ENTRY(efi_call_phys) movl %cr0, %edx orl $0x80000000, %edx movl %edx, %cr0 - jmp 1f -1: + /* * 8. Now restore the virtual mode from flat mode by * adding EIP with PAGE_OFFSET. */ - movl $1f, %edx - jmp *%edx +#ifdef CONFIG_PAX_KERNEXEC + movl $(__KERNEL_DS), %edx + mov %edx, %ds + mov %edx, %es + mov %edx, %ss + ljmp $(__KERNEL_CS),$1f +#else + jmp 1f+__PAGE_OFFSET +#endif 1: /* * 9. Balance the stack. And because EAX contain the return value, * we'd better not clobber it. */ - leal efi_rt_function_ptr, %edx - movl (%edx), %ecx - pushl %ecx + pushl (efi_rt_function_ptr) /* - * 10. Push the saved return address onto the stack and return. + * 10. Return to the saved return address. */ - leal saved_return_addr, %edx - movl (%edx), %ecx - pushl %ecx - ret + jmpl *(saved_return_addr) ENDPROC(efi_call_phys) .previous -.data +__INITDATA saved_return_addr: .long 0 efi_rt_function_ptr: diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S index 4c07cca..2c8427d 100644 --- a/arch/x86/platform/efi/efi_stub_64.S +++ b/arch/x86/platform/efi/efi_stub_64.S @@ -7,6 +7,7 @@ */ #include +#include #define SAVE_XMM \ mov %rsp, %rax; \ @@ -40,6 +41,7 @@ ENTRY(efi_call0) call *%rdi addq $32, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call0) @@ -50,6 +52,7 @@ ENTRY(efi_call1) call *%rdi addq $32, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call1) @@ -60,6 +63,7 @@ ENTRY(efi_call2) call *%rdi addq $32, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call2) @@ -71,6 +75,7 @@ ENTRY(efi_call3) call *%rdi addq $32, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call3) @@ -83,6 +88,7 @@ ENTRY(efi_call4) call *%rdi addq $32, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call4) @@ -96,6 +102,7 @@ ENTRY(efi_call5) call *%rdi addq $48, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call5) @@ -112,5 +119,6 @@ ENTRY(efi_call6) call *%rdi addq $48, %rsp RESTORE_XMM + pax_force_retaddr 0, 1 ret ENDPROC(efi_call6) diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index a0a0a43..a48e233 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -78,13 +78,15 @@ struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; EXPORT_SYMBOL_GPL(sfi_mrtc_array); int sfi_mrtc_num; -static void mrst_power_off(void) +static __noreturn void mrst_power_off(void) { + BUG(); } -static void mrst_reboot(void) +static __noreturn void mrst_reboot(void) { intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); + BUG(); } /* parse all the mtimer info to a static mtimer array */ diff --git a/arch/x86/platform/olpc/olpc_dt.c b/arch/x86/platform/olpc/olpc_dt.c index d6ee929..3637cb5 100644 --- a/arch/x86/platform/olpc/olpc_dt.c +++ b/arch/x86/platform/olpc/olpc_dt.c @@ -156,7 +156,7 @@ void * __init prom_early_alloc(unsigned long size) return res; } -static struct of_pdt_ops prom_olpc_ops __initdata = { +static struct of_pdt_ops prom_olpc_ops __initconst = { .nextprop = olpc_dt_nextprop, .getproplen = olpc_dt_getproplen, .getproperty = olpc_dt_getproperty, diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 1cf5b30..fd45732 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -137,11 +137,8 @@ static void do_fpu_end(void) static void fix_processor_context(void) { int cpu = smp_processor_id(); - struct tss_struct *t = &per_cpu(init_tss, cpu); -#ifdef CONFIG_X86_64 - struct desc_struct *desc = get_cpu_gdt_table(cpu); - tss_desc tss; -#endif + struct tss_struct *t = init_tss + cpu; + set_tss_desc(cpu, t); /* * This just modifies memory; should not be * necessary. But... This is necessary, because @@ -150,10 +147,6 @@ static void fix_processor_context(void) */ #ifdef CONFIG_X86_64 - memcpy(&tss, &desc[GDT_ENTRY_TSS], sizeof(tss_desc)); - tss.type = 0x9; /* The available 64-bit TSS (see AMD vol 2, pg 91 */ - write_gdt_entry(desc, GDT_ENTRY_TSS, &tss, DESC_TSS); - syscall_init(); /* This sets MSR_*STAR and related */ #endif load_TR_desc(); /* This does ltr */ diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index a44f457..9140171 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -70,7 +70,13 @@ void __init setup_real_mode(void) __va(real_mode_header->trampoline_header); #ifdef CONFIG_X86_32 - trampoline_header->start = __pa_symbol(startup_32_smp); + trampoline_header->start = __pa_symbol(ktla_ktva(startup_32_smp)); + +#ifdef CONFIG_PAX_KERNEXEC + trampoline_header->start -= LOAD_PHYSICAL_ADDR; +#endif + + trampoline_header->boot_cs = __BOOT_CS; trampoline_header->gdt_limit = __BOOT_DS + 7; trampoline_header->gdt_base = __pa_symbol(boot_gdt); #else @@ -86,7 +92,7 @@ void __init setup_real_mode(void) *trampoline_cr4_features = read_cr4(); trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); - trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd; + trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd & ~_PAGE_NX; trampoline_pgd[511] = init_level4_pgt[511].pgd; #endif } diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index 8869287..d577672 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile @@ -78,5 +78,8 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \ $(call cc-option, -fno-unit-at-a-time)) \ $(call cc-option, -fno-stack-protector) \ $(call cc-option, -mpreferred-stack-boundary=2) +ifdef CONSTIFY_PLUGIN +KBUILD_CFLAGS += -fplugin-arg-constify_plugin-no-constify +endif KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ GCOV_PROFILE := n diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index a28221d..93c40f1 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S @@ -30,7 +30,9 @@ GLOBAL(real_mode_header) #endif /* APM/BIOS reboot */ .long pa_machine_real_restart_asm -#ifdef CONFIG_X86_64 +#ifdef CONFIG_X86_32 + .long __KERNEL_CS +#else .long __KERNEL32_CS #endif END(real_mode_header) diff --git a/arch/x86/realmode/rm/trampoline_32.S b/arch/x86/realmode/rm/trampoline_32.S index c1b2791..f9e31c7 100644 --- a/arch/x86/realmode/rm/trampoline_32.S +++ b/arch/x86/realmode/rm/trampoline_32.S @@ -25,6 +25,12 @@ #include #include "realmode.h" +#ifdef CONFIG_PAX_KERNEXEC +#define ta(X) (X) +#else +#define ta(X) (pa_ ## X) +#endif + .text .code16 @@ -39,8 +45,6 @@ ENTRY(trampoline_start) cli # We should be safe anyway - movl tr_start, %eax # where we need to go - movl $0xA5A5A5A5, trampoline_status # write marker for master knows we're running @@ -56,7 +60,7 @@ ENTRY(trampoline_start) movw $1, %dx # protected mode (PE) bit lmsw %dx # into protected mode - ljmpl $__BOOT_CS, $pa_startup_32 + ljmpl *(trampoline_header) .section ".text32","ax" .code32 @@ -67,7 +71,7 @@ ENTRY(startup_32) # note: also used from wakeup_asm.S .balign 8 GLOBAL(trampoline_header) tr_start: .space 4 - tr_gdt_pad: .space 2 + tr_boot_cs: .space 2 tr_gdt: .space 6 END(trampoline_header) diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index bb360dc..d0fd8f8 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S @@ -94,6 +94,7 @@ ENTRY(startup_32) movl %edx, %gs movl pa_tr_cr4, %eax + andl $~X86_CR4_PCIDE, %eax movl %eax, %cr4 # Enable PAE mode # Setup trampoline 4 level pagetables @@ -107,7 +108,7 @@ ENTRY(startup_32) wrmsr # Enable paging and in turn activate Long Mode - movl $(X86_CR0_PG | X86_CR0_WP | X86_CR0_PE), %eax + movl $(X86_CR0_PG | X86_CR0_PE), %eax movl %eax, %cr0 /* diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index e812034..c747134 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile @@ -37,7 +37,7 @@ $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/in $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c -HOST_EXTRACFLAGS += -I$(srctree)/tools/include +HOST_EXTRACFLAGS += -I$(srctree)/tools/include -ggdb hostprogs-y += relocs relocs-objs := relocs_32.o relocs_64.o relocs_common.o relocs: $(obj)/relocs diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index f7bab68..b6d9886 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -1,5 +1,7 @@ /* This is included from relocs_32/64.c */ +#include "../../../include/generated/autoconf.h" + #define ElfW(type) _ElfW(ELF_BITS, type) #define _ElfW(bits, type) __ElfW(bits, type) #define __ElfW(bits, type) Elf##bits##_##type @@ -11,6 +13,7 @@ #define Elf_Sym ElfW(Sym) static Elf_Ehdr ehdr; +static Elf_Phdr *phdr; struct relocs { uint32_t *offset; @@ -383,9 +386,39 @@ static void read_ehdr(FILE *fp) } } +static void read_phdrs(FILE *fp) +{ + unsigned int i; + + phdr = calloc(ehdr.e_phnum, sizeof(Elf_Phdr)); + if (!phdr) { + die("Unable to allocate %d program headers\n", + ehdr.e_phnum); + } + if (fseek(fp, ehdr.e_phoff, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + ehdr.e_phoff, strerror(errno)); + } + if (fread(phdr, sizeof(*phdr), ehdr.e_phnum, fp) != ehdr.e_phnum) { + die("Cannot read ELF program headers: %s\n", + strerror(errno)); + } + for(i = 0; i < ehdr.e_phnum; i++) { + phdr[i].p_type = elf_word_to_cpu(phdr[i].p_type); + phdr[i].p_offset = elf_off_to_cpu(phdr[i].p_offset); + phdr[i].p_vaddr = elf_addr_to_cpu(phdr[i].p_vaddr); + phdr[i].p_paddr = elf_addr_to_cpu(phdr[i].p_paddr); + phdr[i].p_filesz = elf_word_to_cpu(phdr[i].p_filesz); + phdr[i].p_memsz = elf_word_to_cpu(phdr[i].p_memsz); + phdr[i].p_flags = elf_word_to_cpu(phdr[i].p_flags); + phdr[i].p_align = elf_word_to_cpu(phdr[i].p_align); + } + +} + static void read_shdrs(FILE *fp) { - int i; + unsigned int i; Elf_Shdr shdr; secs = calloc(ehdr.e_shnum, sizeof(struct section)); @@ -420,7 +453,7 @@ static void read_shdrs(FILE *fp) static void read_strtabs(FILE *fp) { - int i; + unsigned int i; for (i = 0; i < ehdr.e_shnum; i++) { struct section *sec = &secs[i]; if (sec->shdr.sh_type != SHT_STRTAB) { @@ -445,7 +478,7 @@ static void read_strtabs(FILE *fp) static void read_symtabs(FILE *fp) { - int i,j; + unsigned int i,j; for (i = 0; i < ehdr.e_shnum; i++) { struct section *sec = &secs[i]; if (sec->shdr.sh_type != SHT_SYMTAB) { @@ -476,9 +509,11 @@ static void read_symtabs(FILE *fp) } -static void read_relocs(FILE *fp) +static void read_relocs(FILE *fp, int use_real_mode) { - int i,j; + unsigned int i,j; + uint32_t base; + for (i = 0; i < ehdr.e_shnum; i++) { struct section *sec = &secs[i]; if (sec->shdr.sh_type != SHT_REL_TYPE) { @@ -498,9 +533,22 @@ static void read_relocs(FILE *fp) die("Cannot read symbol table: %s\n", strerror(errno)); } + base = 0; + +#ifdef CONFIG_X86_32 + for (j = 0; !use_real_mode && j < ehdr.e_phnum; j++) { + if (phdr[j].p_type != PT_LOAD ) + continue; + if (secs[sec->shdr.sh_info].shdr.sh_offset < phdr[j].p_offset || secs[sec->shdr.sh_info].shdr.sh_offset >= phdr[j].p_offset + phdr[j].p_filesz) + continue; + base = CONFIG_PAGE_OFFSET + phdr[j].p_paddr - phdr[j].p_vaddr; + break; + } +#endif + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { Elf_Rel *rel = &sec->reltab[j]; - rel->r_offset = elf_addr_to_cpu(rel->r_offset); + rel->r_offset = elf_addr_to_cpu(rel->r_offset) + base; rel->r_info = elf_xword_to_cpu(rel->r_info); #if (SHT_REL_TYPE == SHT_RELA) rel->r_addend = elf_xword_to_cpu(rel->r_addend); @@ -512,7 +560,7 @@ static void read_relocs(FILE *fp) static void print_absolute_symbols(void) { - int i; + unsigned int i; const char *format; if (ELF_BITS == 64) @@ -525,7 +573,7 @@ static void print_absolute_symbols(void) for (i = 0; i < ehdr.e_shnum; i++) { struct section *sec = &secs[i]; char *sym_strtab; - int j; + unsigned int j; if (sec->shdr.sh_type != SHT_SYMTAB) { continue; @@ -552,7 +600,7 @@ static void print_absolute_symbols(void) static void print_absolute_relocs(void) { - int i, printed = 0; + unsigned int i, printed = 0; const char *format; if (ELF_BITS == 64) @@ -565,7 +613,7 @@ static void print_absolute_relocs(void) struct section *sec_applies, *sec_symtab; char *sym_strtab; Elf_Sym *sh_symtab; - int j; + unsigned int j; if (sec->shdr.sh_type != SHT_REL_TYPE) { continue; } @@ -642,13 +690,13 @@ static void add_reloc(struct relocs *r, uint32_t offset) static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname)) { - int i; + unsigned int i; /* Walk through the relocations */ for (i = 0; i < ehdr.e_shnum; i++) { char *sym_strtab; Elf_Sym *sh_symtab; struct section *sec_applies, *sec_symtab; - int j; + unsigned int j; struct section *sec = &secs[i]; if (sec->shdr.sh_type != SHT_REL_TYPE) { @@ -812,6 +860,23 @@ static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, { unsigned r_type = ELF32_R_TYPE(rel->r_info); int shn_abs = (sym->st_shndx == SHN_ABS) && !is_reloc(S_REL, symname); + char *sym_strtab = sec->link->link->strtab; + + /* Don't relocate actual per-cpu variables, they are absolute indices, not addresses */ + if (!strcmp(sec_name(sym->st_shndx), ".data..percpu") && strcmp(sym_name(sym_strtab, sym), "__per_cpu_load")) + return 0; + +#ifdef CONFIG_PAX_KERNEXEC + /* Don't relocate actual code, they are relocated implicitly by the base address of KERNEL_CS */ + if (!strcmp(sec_name(sym->st_shndx), ".text.end") && !strcmp(sym_name(sym_strtab, sym), "_etext")) + return 0; + if (!strcmp(sec_name(sym->st_shndx), ".init.text")) + return 0; + if (!strcmp(sec_name(sym->st_shndx), ".exit.text")) + return 0; + if (!strcmp(sec_name(sym->st_shndx), ".text") && strcmp(sym_name(sym_strtab, sym), "__LOAD_PHYSICAL_ADDR")) + return 0; +#endif switch (r_type) { case R_386_NONE: @@ -950,7 +1015,7 @@ static int write32_as_text(uint32_t v, FILE *f) static void emit_relocs(int as_text, int use_real_mode) { - int i; + unsigned int i; int (*write_reloc)(uint32_t, FILE *) = write32; int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname); @@ -1026,10 +1091,11 @@ void process(FILE *fp, int use_real_mode, int as_text, { regex_init(use_real_mode); read_ehdr(fp); + read_phdrs(fp); read_shdrs(fp); read_strtabs(fp); read_symtabs(fp); - read_relocs(fp); + read_relocs(fp, use_real_mode); if (ELF_BITS == 64) percpu_init(); if (show_absolute_syms) { diff --git a/arch/x86/um/tls_32.c b/arch/x86/um/tls_32.c index 80ffa5b..a33bd15 100644 --- a/arch/x86/um/tls_32.c +++ b/arch/x86/um/tls_32.c @@ -260,7 +260,7 @@ out: if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { printk(KERN_ERR "get_tls_entry: task with pid %d got here " - "without flushed TLS.", current->pid); + "without flushed TLS.", task_pid_nr(current)); } return 0; diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index fd14be1..e3c79c0 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -181,7 +181,7 @@ quiet_cmd_vdso = VDSO $@ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \ sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@' -VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) +VDSO_LDFLAGS = -fPIC -shared -Wl,--no-undefined $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) GCOV_PROFILE := n # diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c index 0faad64..39ef157 100644 --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -25,6 +25,7 @@ #include #include #include +#include enum { VDSO_DISABLED = 0, @@ -226,7 +227,7 @@ static inline void map_compat_vdso(int map) void enable_sep_cpu(void) { int cpu = get_cpu(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = init_tss + cpu; if (!boot_cpu_has(X86_FEATURE_SEP)) { put_cpu(); @@ -249,7 +250,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; } @@ -330,14 +331,14 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) if (compat) addr = VDSO_HIGH_BASE; else { - addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); + addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, MAP_EXECUTABLE); if (IS_ERR_VALUE(addr)) { ret = addr; goto up_fail; } } - current->mm->context.vdso = (void *)addr; + current->mm->context.vdso = addr; if (compat_uses_vma || !compat) { /* @@ -353,11 +354,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) } current_thread_info()->sysenter_return = - VDSO32_SYMBOL(addr, SYSENTER_RETURN); + (__force void __user *)VDSO32_SYMBOL(addr, SYSENTER_RETURN); up_fail: if (ret) - current->mm->context.vdso = NULL; + current->mm->context.vdso = 0; up_write(&mm->mmap_sem); @@ -404,8 +405,14 @@ __initcall(ia32_binfmt_init); const char *arch_vma_name(struct vm_area_struct *vma) { - if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) + if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso) return "[vdso]"; + +#ifdef CONFIG_PAX_SEGMEXEC + if (vma->vm_mm && vma->vm_mirror && vma->vm_mirror->vm_start == vma->vm_mm->context.vdso) + return "[vdso]"; +#endif + return NULL; } @@ -415,7 +422,7 @@ struct vm_area_struct *get_gate_vma(struct mm_struct *mm) * Check to see if the corresponding task was created in compat vdso * mode. */ - if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE) + if (mm && mm->context.vdso == VDSO_HIGH_BASE) return &gate_vma; return NULL; } diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c index 431e875..cbb23f3 100644 --- a/arch/x86/vdso/vma.c +++ b/arch/x86/vdso/vma.c @@ -16,8 +16,6 @@ #include #include -unsigned int __read_mostly vdso_enabled = 1; - extern char vdso_start[], vdso_end[]; extern unsigned short vdso_sync_cpuid; @@ -141,7 +139,6 @@ static unsigned long vdso_addr(unsigned long start, unsigned len) * unaligned here as a result of stack start randomization. */ addr = PAGE_ALIGN(addr); - addr = align_vdso_addr(addr); return addr; } @@ -154,30 +151,31 @@ static int setup_additional_pages(struct linux_binprm *bprm, unsigned size) { struct mm_struct *mm = current->mm; - unsigned long addr; + unsigned long addr = 0; int ret; - if (!vdso_enabled) - return 0; - down_write(&mm->mmap_sem); + +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + addr = vdso_addr(mm->start_stack, size); + addr = align_vdso_addr(addr); addr = get_unmapped_area(NULL, addr, size, 0, 0); if (IS_ERR_VALUE(addr)) { ret = addr; goto up_fail; } - current->mm->context.vdso = (void *)addr; + mm->context.vdso = addr; ret = install_special_mapping(mm, addr, size, VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, pages); - if (ret) { - current->mm->context.vdso = NULL; - goto up_fail; - } + if (ret) + mm->context.vdso = 0; up_fail: up_write(&mm->mmap_sem); @@ -197,10 +195,3 @@ int x32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) vdsox32_size); } #endif - -static __init int vdso_setup(char *s) -{ - vdso_enabled = simple_strtoul(s, NULL, 0); - return 0; -} -__setup("vdso=", vdso_setup); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a492be2..08678da 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -123,8 +123,6 @@ EXPORT_SYMBOL_GPL(xen_start_info); struct shared_info xen_dummy_shared_info; -void *xen_initial_gdt; - RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); __read_mostly int xen_have_vector_callback; EXPORT_SYMBOL_GPL(xen_have_vector_callback); @@ -542,8 +540,7 @@ static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long va = dtr->address; unsigned int size = dtr->size + 1; - unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; - unsigned long frames[pages]; + unsigned long frames[65536 / PAGE_SIZE]; int f; /* @@ -591,8 +588,7 @@ static void __init xen_load_gdt_boot(const struct desc_ptr *dtr) { unsigned long va = dtr->address; unsigned int size = dtr->size + 1; - unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; - unsigned long frames[pages]; + unsigned long frames[(GDT_SIZE + PAGE_SIZE - 1) / PAGE_SIZE]; int f; /* @@ -600,7 +596,7 @@ static void __init xen_load_gdt_boot(const struct desc_ptr *dtr) * 8-byte entries, or 16 4k pages.. */ - BUG_ON(size > 65536); + BUG_ON(size > GDT_SIZE); BUG_ON(va & ~PAGE_MASK); for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { @@ -985,7 +981,7 @@ static u32 xen_safe_apic_wait_icr_idle(void) return 0; } -static void set_xen_basic_apic_ops(void) +static void __init set_xen_basic_apic_ops(void) { apic->read = xen_apic_read; apic->write = xen_apic_write; @@ -1290,30 +1286,30 @@ static const struct pv_apic_ops xen_apic_ops __initconst = { #endif }; -static void xen_reboot(int reason) +static __noreturn void xen_reboot(int reason) { struct sched_shutdown r = { .reason = reason }; - if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r)) - BUG(); + HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); + BUG(); } -static void xen_restart(char *msg) +static __noreturn void xen_restart(char *msg) { xen_reboot(SHUTDOWN_reboot); } -static void xen_emergency_restart(void) +static __noreturn void xen_emergency_restart(void) { xen_reboot(SHUTDOWN_reboot); } -static void xen_machine_halt(void) +static __noreturn void xen_machine_halt(void) { xen_reboot(SHUTDOWN_poweroff); } -static void xen_machine_power_off(void) +static __noreturn void xen_machine_power_off(void) { if (pm_power_off) pm_power_off(); @@ -1464,7 +1460,17 @@ asmlinkage void __init xen_start_kernel(void) __userpte_alloc_gfp &= ~__GFP_HIGHMEM; /* Work out if we support NX */ - x86_configure_nx(); +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) + if ((cpuid_eax(0x80000000) & 0xffff0000) == 0x80000000 && + (cpuid_edx(0x80000001) & (1U << (X86_FEATURE_NX & 31)))) { + unsigned l, h; + + __supported_pte_mask |= _PAGE_NX; + rdmsr(MSR_EFER, l, h); + l |= EFER_NX; + wrmsr(MSR_EFER, l, h); + } +#endif xen_setup_features(); @@ -1495,13 +1501,6 @@ asmlinkage void __init xen_start_kernel(void) machine_ops = xen_machine_ops; - /* - * The only reliable way to retain the initial address of the - * percpu gdt_page is to remember it here, so we can go and - * mark it RW later, when the initial percpu area is freed. - */ - xen_initial_gdt = &per_cpu(gdt_page, 0); - xen_smp_init(); #ifdef CONFIG_ACPI_NUMA @@ -1700,7 +1699,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block xen_hvm_cpu_notifier __cpuinitdata = { +static struct notifier_block xen_hvm_cpu_notifier = { .notifier_call = xen_hvm_cpu_notify, }; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index fdc3ba2..3daee39 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1894,6 +1894,9 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) /* L3_k[510] -> level2_kernel_pgt * L3_i[511] -> level2_fixmap_pgt */ convert_pfn_mfn(level3_kernel_pgt); + convert_pfn_mfn(level3_vmalloc_start_pgt); + convert_pfn_mfn(level3_vmalloc_end_pgt); + convert_pfn_mfn(level3_vmemmap_pgt); /* We get [511][511] and have Xen's version of level2_kernel_pgt */ l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); @@ -1923,8 +1926,12 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); + set_page_prot(level3_vmalloc_start_pgt, PAGE_KERNEL_RO); + set_page_prot(level3_vmalloc_end_pgt, PAGE_KERNEL_RO); + set_page_prot(level3_vmemmap_pgt, PAGE_KERNEL_RO); set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); + set_page_prot(level2_vmemmap_pgt, PAGE_KERNEL_RO); set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); @@ -2108,6 +2115,7 @@ static void __init xen_post_allocator_init(void) pv_mmu_ops.set_pud = xen_set_pud; #if PAGETABLE_LEVELS == 4 pv_mmu_ops.set_pgd = xen_set_pgd; + pv_mmu_ops.set_pgd_batched = xen_set_pgd; #endif /* This will work as long as patching hasn't happened yet @@ -2186,6 +2194,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { .pud_val = PV_CALLEE_SAVE(xen_pud_val), .make_pud = PV_CALLEE_SAVE(xen_make_pud), .set_pgd = xen_set_pgd_hyper, + .set_pgd_batched = xen_set_pgd_hyper, .alloc_pud = xen_alloc_pmd_init, .release_pud = xen_release_pmd_init, diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index a1e58e1..9392ad8 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -240,11 +240,6 @@ static void __init xen_smp_prepare_boot_cpu(void) { BUG_ON(smp_processor_id() != 0); native_smp_prepare_boot_cpu(); - - /* We've switched to the "real" per-cpu gdt, so make sure the - old memory can be recycled */ - make_lowmem_page_readwrite(xen_initial_gdt); - xen_filter_cpu_maps(); xen_setup_vcpu_info_placement(); } @@ -314,7 +309,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) ctxt->user_regs.ss = __KERNEL_DS; #ifdef CONFIG_X86_32 ctxt->user_regs.fs = __KERNEL_PERCPU; - ctxt->user_regs.gs = __KERNEL_STACK_CANARY; + savesegment(gs, ctxt->user_regs.gs); #else ctxt->gs_base_kernel = per_cpu_offset(cpu); #endif @@ -324,8 +319,8 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) { ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ - ctxt->user_regs.ds = __USER_DS; - ctxt->user_regs.es = __USER_DS; + ctxt->user_regs.ds = __KERNEL_DS; + ctxt->user_regs.es = __KERNEL_DS; xen_copy_trap_info(ctxt->trap_ctxt); @@ -370,13 +365,12 @@ static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle) int rc; per_cpu(current_task, cpu) = idle; + per_cpu(current_tinfo, cpu) = &idle->tinfo; #ifdef CONFIG_X86_32 irq_ctx_init(cpu); #else clear_tsk_thread_flag(idle, TIF_FORK); - per_cpu(kernel_stack, cpu) = - (unsigned long)task_stack_page(idle) - - KERNEL_STACK_OFFSET + THREAD_SIZE; + per_cpu(kernel_stack, cpu) = (unsigned long)task_stack_page(idle) - 16 + THREAD_SIZE; #endif xen_setup_runstate_info(cpu); xen_setup_timer(cpu); @@ -651,7 +645,7 @@ static const struct smp_ops xen_smp_ops __initconst = { void __init xen_smp_init(void) { - smp_ops = xen_smp_ops; + memcpy((void *)&smp_ops, &xen_smp_ops, sizeof smp_ops); xen_fill_possible_map(); xen_init_spinlocks(); } diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 33ca6e4..0ded929 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -84,14 +84,14 @@ ENTRY(xen_iret) ESP_OFFSET=4 # bytes pushed onto stack /* - * Store vcpu_info pointer for easy access. Do it this way to - * avoid having to reload %fs + * Store vcpu_info pointer for easy access. */ #ifdef CONFIG_SMP - GET_THREAD_INFO(%eax) - movl %ss:TI_cpu(%eax), %eax - movl %ss:__per_cpu_offset(,%eax,4), %eax - mov %ss:xen_vcpu(%eax), %eax + push %fs + mov $(__KERNEL_PERCPU), %eax + mov %eax, %fs + mov PER_CPU_VAR(xen_vcpu), %eax + pop %fs #else movl %ss:xen_vcpu, %eax #endif diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index 7faed58..ba4427c 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S @@ -19,6 +19,17 @@ ENTRY(startup_xen) #ifdef CONFIG_X86_32 mov %esi,xen_start_info mov $init_thread_union+THREAD_SIZE,%esp +#ifdef CONFIG_SMP + movl $cpu_gdt_table,%edi + movl $__per_cpu_load,%eax + movw %ax,__KERNEL_PERCPU + 2(%edi) + rorl $16,%eax + movb %al,__KERNEL_PERCPU + 4(%edi) + movb %ah,__KERNEL_PERCPU + 7(%edi) + movl $__per_cpu_end - 1,%eax + subl $__per_cpu_start,%eax + movw %ax,__KERNEL_PERCPU + 0(%edi) +#endif #else mov %rsi,xen_start_info mov $init_thread_union+THREAD_SIZE,%rsp diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index a95b417..b6dbd0b 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -10,8 +10,6 @@ extern const char xen_hypervisor_callback[]; extern const char xen_failsafe_callback[]; -extern void *xen_initial_gdt; - struct trap_info; void xen_copy_trap_info(struct trap_info *traps); diff --git a/arch/xtensa/variants/dc232b/include/variant/core.h b/arch/xtensa/variants/dc232b/include/variant/core.h index 525bd3d..ef888b1 100644 --- a/arch/xtensa/variants/dc232b/include/variant/core.h +++ b/arch/xtensa/variants/dc232b/include/variant/core.h @@ -119,9 +119,9 @@ ----------------------------------------------------------------------*/ #define XCHAL_ICACHE_LINESIZE 32 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 32 /* D-cache line size in bytes */ #define XCHAL_ICACHE_LINEWIDTH 5 /* log2(I line size in bytes) */ #define XCHAL_DCACHE_LINEWIDTH 5 /* log2(D line size in bytes) */ +#define XCHAL_DCACHE_LINESIZE (_AC(1,UL) << XCHAL_DCACHE_LINEWIDTH) /* D-cache line size in bytes */ #define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ #define XCHAL_DCACHE_SIZE 16384 /* D-cache size in bytes or 0 */ diff --git a/arch/xtensa/variants/fsf/include/variant/core.h b/arch/xtensa/variants/fsf/include/variant/core.h index 2f33760..835e50a 100644 --- a/arch/xtensa/variants/fsf/include/variant/core.h +++ b/arch/xtensa/variants/fsf/include/variant/core.h @@ -11,6 +11,7 @@ #ifndef _XTENSA_CORE_H #define _XTENSA_CORE_H +#include /**************************************************************************** Parameters Useful for Any Code, USER or PRIVILEGED @@ -112,9 +113,9 @@ ----------------------------------------------------------------------*/ #define XCHAL_ICACHE_LINESIZE 16 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 16 /* D-cache line size in bytes */ #define XCHAL_ICACHE_LINEWIDTH 4 /* log2(I line size in bytes) */ #define XCHAL_DCACHE_LINEWIDTH 4 /* log2(D line size in bytes) */ +#define XCHAL_DCACHE_LINESIZE (_AC(1,UL) << XCHAL_DCACHE_LINEWIDTH) /* D-cache line size in bytes */ #define XCHAL_ICACHE_SIZE 8192 /* I-cache size in bytes or 0 */ #define XCHAL_DCACHE_SIZE 8192 /* D-cache size in bytes or 0 */ diff --git a/arch/xtensa/variants/s6000/include/variant/core.h b/arch/xtensa/variants/s6000/include/variant/core.h index af00795..2bb8105 100644 --- a/arch/xtensa/variants/s6000/include/variant/core.h +++ b/arch/xtensa/variants/s6000/include/variant/core.h @@ -11,6 +11,7 @@ #ifndef _XTENSA_CORE_CONFIGURATION_H #define _XTENSA_CORE_CONFIGURATION_H +#include /**************************************************************************** Parameters Useful for Any Code, USER or PRIVILEGED @@ -118,9 +119,9 @@ ----------------------------------------------------------------------*/ #define XCHAL_ICACHE_LINESIZE 16 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 16 /* D-cache line size in bytes */ #define XCHAL_ICACHE_LINEWIDTH 4 /* log2(I line size in bytes) */ #define XCHAL_DCACHE_LINEWIDTH 4 /* log2(D line size in bytes) */ +#define XCHAL_DCACHE_LINESIZE (_AC(1,UL) << XCHAL_DCACHE_LINEWIDTH) /* D-cache line size in bytes */ #define XCHAL_ICACHE_SIZE 32768 /* I-cache size in bytes or 0 */ #define XCHAL_DCACHE_SIZE 32768 /* D-cache size in bytes or 0 */ diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index e8918ff..b3ffc51 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -825,7 +825,7 @@ static void blkcg_css_free(struct cgroup *cgroup) static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup) { - static atomic64_t id_seq = ATOMIC64_INIT(0); + static atomic64_unchecked_t id_seq = ATOMIC64_INIT(0); struct blkcg *blkcg; struct cgroup *parent = cgroup->parent; @@ -840,7 +840,7 @@ static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup) blkcg->cfq_weight = CFQ_WEIGHT_DEFAULT; blkcg->cfq_leaf_weight = CFQ_WEIGHT_DEFAULT; - blkcg->id = atomic64_inc_return(&id_seq); /* root is 0, start from 1 */ + blkcg->id = atomic64_inc_return_unchecked(&id_seq); /* root is 0, start from 1 */ done: spin_lock_init(&blkcg->lock); INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_ATOMIC); diff --git a/block/blk-iopoll.c b/block/blk-iopoll.c index 58916af..eb9dbcf 100644 --- a/block/blk-iopoll.c +++ b/block/blk-iopoll.c @@ -77,7 +77,7 @@ void blk_iopoll_complete(struct blk_iopoll *iopoll) } EXPORT_SYMBOL(blk_iopoll_complete); -static void blk_iopoll_softirq(struct softirq_action *h) +static void blk_iopoll_softirq(void) { struct list_head *list = &__get_cpu_var(blk_cpu_iopoll); int rearm = 0, budget = blk_iopoll_budget; @@ -209,7 +209,7 @@ static int __cpuinit blk_iopoll_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata blk_iopoll_cpu_notifier = { +static struct notifier_block blk_iopoll_cpu_notifier = { .notifier_call = blk_iopoll_cpu_notify, }; diff --git a/block/blk-map.c b/block/blk-map.c index 623e1cd..ca1e109 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -302,7 +302,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, if (!len || !kbuf) return -EINVAL; - do_copy = !blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf); + do_copy = !blk_rq_aligned(q, addr, len) || object_starts_on_stack(kbuf); if (do_copy) bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading); else diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 467c8de..f3628c5 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -18,7 +18,7 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done); * Softirq action handler - move entries to local list and loop over them * while passing them to the queue registered handler. */ -static void blk_done_softirq(struct softirq_action *h) +static void blk_done_softirq(void) { struct list_head *cpu_list, local_list; @@ -98,7 +98,7 @@ static int __cpuinit blk_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata blk_cpu_notifier = { +static struct notifier_block blk_cpu_notifier = { .notifier_call = blk_cpu_notify, }; diff --git a/block/bsg.c b/block/bsg.c index 420a5a9..23834aa 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -176,16 +176,24 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, struct sg_io_v4 *hdr, struct bsg_device *bd, fmode_t has_write_perm) { + unsigned char tmpcmd[sizeof(rq->__cmd)]; + unsigned char *cmdptr; + if (hdr->request_len > BLK_MAX_CDB) { rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL); if (!rq->cmd) return -ENOMEM; - } + cmdptr = rq->cmd; + } else + cmdptr = tmpcmd; - if (copy_from_user(rq->cmd, (void __user *)(unsigned long)hdr->request, + if (copy_from_user(cmdptr, (void __user *)(unsigned long)hdr->request, hdr->request_len)) return -EFAULT; + if (cmdptr != rq->cmd) + memcpy(rq->cmd, cmdptr, hdr->request_len); + if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { if (blk_verify_command(rq->cmd, has_write_perm)) return -EPERM; diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 7c668c8..db3521c 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -340,7 +340,7 @@ static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, err |= __get_user(f->spec1, &uf->spec1); err |= __get_user(f->fmt_gap, &uf->fmt_gap); err |= __get_user(name, &uf->name); - f->name = compat_ptr(name); + f->name = (void __force_kernel *)compat_ptr(name); if (err) { err = -EFAULT; goto out; diff --git a/block/genhd.c b/block/genhd.c index cdeb527..10aa34d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -467,21 +467,24 @@ static char *bdevt_str(dev_t devt, char *buf) /* * Register device numbers dev..(dev+range-1) - * range must be nonzero + * Noop if @range is zero. * The hash chain is sorted on range, so that subranges can override. */ void blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), void *data) { - kobj_map(bdev_map, devt, range, module, probe, lock, data); + if (range) + kobj_map(bdev_map, devt, range, module, probe, lock, data); } EXPORT_SYMBOL(blk_register_region); +/* undo blk_register_region(), noop if @range is zero */ void blk_unregister_region(dev_t devt, unsigned long range) { - kobj_unmap(bdev_map, devt, range); + if (range) + kobj_unmap(bdev_map, devt, range); } EXPORT_SYMBOL(blk_unregister_region); diff --git a/block/partitions/efi.c b/block/partitions/efi.c index c85fc89..51e690b 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -234,14 +234,14 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, if (!gpt) return NULL; - count = le32_to_cpu(gpt->num_partition_entries) * - le32_to_cpu(gpt->sizeof_partition_entry); - if (!count) + if (!le32_to_cpu(gpt->num_partition_entries)) return NULL; - pte = kmalloc(count, GFP_KERNEL); + pte = kcalloc(le32_to_cpu(gpt->num_partition_entries), le32_to_cpu(gpt->sizeof_partition_entry), GFP_KERNEL); if (!pte) return NULL; + count = le32_to_cpu(gpt->num_partition_entries) * + le32_to_cpu(gpt->sizeof_partition_entry); if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba), (u8 *) pte, count) < count) { diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a5ffcc9..3cedc9c 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -224,8 +224,20 @@ EXPORT_SYMBOL(blk_verify_command); static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, struct sg_io_hdr *hdr, fmode_t mode) { - if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) + unsigned char tmpcmd[sizeof(rq->__cmd)]; + unsigned char *cmdptr; + + if (rq->cmd != rq->__cmd) + cmdptr = rq->cmd; + else + cmdptr = tmpcmd; + + if (copy_from_user(cmdptr, hdr->cmdp, hdr->cmd_len)) return -EFAULT; + + if (cmdptr != rq->cmd) + memcpy(rq->cmd, cmdptr, hdr->cmd_len); + if (blk_verify_command(rq->cmd, mode & FMODE_WRITE)) return -EPERM; @@ -434,6 +446,8 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, int err; unsigned int in_len, out_len, bytes, opcode, cmdlen; char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; + unsigned char tmpcmd[sizeof(rq->__cmd)]; + unsigned char *cmdptr; if (!sic) return -EINVAL; @@ -467,9 +481,18 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, */ err = -EFAULT; rq->cmd_len = cmdlen; - if (copy_from_user(rq->cmd, sic->data, cmdlen)) + + if (rq->cmd != rq->__cmd) + cmdptr = rq->cmd; + else + cmdptr = tmpcmd; + + if (copy_from_user(cmdptr, sic->data, cmdlen)) goto error; + if (rq->cmd != cmdptr) + memcpy(rq->cmd, cmdptr, cmdlen); + if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) goto error; diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 7bdd61b..afec999 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -63,7 +63,7 @@ struct cryptd_blkcipher_ctx { struct cryptd_blkcipher_request_ctx { crypto_completion_t complete; -}; +} __no_const; struct cryptd_hash_ctx { struct crypto_shash *child; @@ -80,7 +80,7 @@ struct cryptd_aead_ctx { struct cryptd_aead_request_ctx { crypto_completion_t complete; -}; +} __no_const; static void cryptd_queue_worker(struct work_struct *work); diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index b2c99dc..476c9fb 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -440,7 +440,7 @@ static int pcrypt_sysfs_add(struct padata_instance *pinst, const char *name) int ret; pinst->kobj.kset = pcrypt_kset; - ret = kobject_add(&pinst->kobj, NULL, name); + ret = kobject_add(&pinst->kobj, NULL, "%s", name); if (!ret) kobject_uevent(&pinst->kobj, KOBJ_ADD); @@ -455,8 +455,8 @@ static int pcrypt_init_padata(struct padata_pcrypt *pcrypt, get_online_cpus(); - pcrypt->wq = alloc_workqueue(name, - WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1); + pcrypt->wq = alloc_workqueue("%s", + WQ_MEM_RECLAIM | WQ_CPU_INTENSIVE, 1, name); if (!pcrypt->wq) goto err; diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index f220d64..d359ad6 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -20,7 +20,7 @@ typedef int (*apei_exec_ins_func_t)(struct apei_exec_context *ctx, struct apei_exec_ins_type { u32 flags; apei_exec_ins_func_t run; -}; +} __do_const; struct apei_exec_context { u32 ip; diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index 33dc6a0..4b24b47 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -39,12 +39,12 @@ */ u64 cper_next_record_id(void) { - static atomic64_t seq; + static atomic64_unchecked_t seq; - if (!atomic64_read(&seq)) - atomic64_set(&seq, ((u64)get_seconds()) << 32); + if (!atomic64_read_unchecked(&seq)) + atomic64_set_unchecked(&seq, ((u64)get_seconds()) << 32); - return atomic64_inc_return(&seq); + return atomic64_inc_return_unchecked(&seq); } EXPORT_SYMBOL_GPL(cper_next_record_id); diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index fcd7d91..6b2f1a3 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -468,7 +468,7 @@ static void __ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, const struct acpi_hest_generic_status *estatus) { - static atomic_t seqno; + static atomic_unchecked_t seqno; unsigned int curr_seqno; char pfx_seq[64]; @@ -479,7 +479,7 @@ static void __ghes_print_estatus(const char *pfx, else pfx = KERN_ERR; } - curr_seqno = atomic_inc_return(&seqno); + curr_seqno = atomic_inc_return_unchecked(&seqno); snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}" HW_ERR, pfx, curr_seqno); printk("%s""Hardware error from APEI Generic Hardware Error Source: %d\n", pfx_seq, generic->header.source_id); diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index be60399..778b33e8 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c @@ -87,8 +87,10 @@ static int __init bgrt_init(void) return -ENODEV; sysfs_bin_attr_init(&image_attr); - image_attr.private = bgrt_image; - image_attr.size = bgrt_image_size; + pax_open_kernel(); + *(void **)&image_attr.private = bgrt_image; + *(size_t *)&image_attr.size = bgrt_image_size; + pax_close_kernel(); bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); if (!bgrt_kobj) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index cb96296..b81293b 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -52,7 +52,7 @@ struct acpi_blacklist_item { u32 is_critical_error; }; -static struct dmi_system_id acpi_osi_dmi_table[] __initdata; +static const struct dmi_system_id acpi_osi_dmi_table[] __initconst; /* * POLICY: If *anything* doesn't work, put it on the blacklist. @@ -193,7 +193,7 @@ static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) return 0; } -static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { +static const struct dmi_system_id acpi_osi_dmi_table[] __initconst = { { .callback = dmi_disable_osi_vista, .ident = "Fujitsu Siemens", diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c index 7586544..636a2f0 100644 --- a/drivers/acpi/ec_sys.c +++ b/drivers/acpi/ec_sys.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "internal.h" MODULE_AUTHOR("Thomas Renninger "); @@ -34,7 +35,7 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf, * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private; */ unsigned int size = EC_SPACE_SIZE; - u8 *data = (u8 *) buf; + u8 data; loff_t init_off = *off; int err = 0; @@ -47,9 +48,11 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf, size = count; while (size) { - err = ec_read(*off, &data[*off - init_off]); + err = ec_read(*off, &data); if (err) return err; + if (put_user(data, &buf[*off - init_off])) + return -EFAULT; *off += 1; size--; } @@ -65,7 +68,6 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, unsigned int size = count; loff_t init_off = *off; - u8 *data = (u8 *) buf; int err = 0; if (*off >= EC_SPACE_SIZE) @@ -76,7 +78,9 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, } while (size) { - u8 byte_write = data[*off - init_off]; + u8 byte_write; + if (get_user(byte_write, &buf[*off - init_off])) + return -EFAULT; err = ec_write(*off, byte_write); if (err) return err; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index eb133c7..f571552 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -994,7 +994,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) { int i, count = CPUIDLE_DRIVER_STATE_START; struct acpi_processor_cx *cx; - struct cpuidle_state *state; + cpuidle_state_no_const *state; struct cpuidle_driver *drv = &acpi_idle_driver; if (!pr->flags.power_setup_done) diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index fcae5fa..e9f71ea 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -423,11 +423,11 @@ static u32 num_counters; static struct attribute **all_attrs; static u32 acpi_gpe_count; -static struct attribute_group interrupt_stats_attr_group = { +static attribute_group_no_const interrupt_stats_attr_group = { .name = "interrupts", }; -static struct kobj_attribute *counter_attrs; +static kobj_attribute_no_const *counter_attrs; static void delete_gpe_attr_array(void) { diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 7b9bdd8..37638ca 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1230,7 +1230,7 @@ int ahci_kick_engine(struct ata_port *ap) } EXPORT_SYMBOL_GPL(ahci_kick_engine); -static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, +static int __intentional_overflow(-1) ahci_exec_polled_cmd(struct ata_port *ap, int pmp, struct ata_taskfile *tf, int is_cmd, u16 flags, unsigned long timeout_msec) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index adf002a..06c46a7 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -98,7 +98,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev); static void ata_dev_xfermask(struct ata_device *dev); static unsigned long ata_dev_blacklisted(const struct ata_device *dev); -atomic_t ata_print_id = ATOMIC_INIT(0); +atomic_unchecked_t ata_print_id = ATOMIC_INIT(0); struct ata_force_param { const char *name; @@ -4792,7 +4792,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) struct ata_port *ap; unsigned int tag; - WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ + BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ ap = qc->ap; qc->flags = 0; @@ -4808,7 +4808,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) struct ata_port *ap; struct ata_link *link; - WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ + BUG_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE)); ap = qc->ap; link = qc->dev->link; @@ -5926,6 +5926,7 @@ static void ata_finalize_port_ops(struct ata_port_operations *ops) return; spin_lock(&lock); + pax_open_kernel(); for (cur = ops->inherits; cur; cur = cur->inherits) { void **inherit = (void **)cur; @@ -5939,8 +5940,9 @@ static void ata_finalize_port_ops(struct ata_port_operations *ops) if (IS_ERR(*pp)) *pp = NULL; - ops->inherits = NULL; + *(struct ata_port_operations **)&ops->inherits = NULL; + pax_close_kernel(); spin_unlock(&lock); } @@ -6133,7 +6135,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) /* give ports names and add SCSI hosts */ for (i = 0; i < host->n_ports; i++) - host->ports[i]->print_id = atomic_inc_return(&ata_print_id); + host->ports[i]->print_id = atomic_inc_return_unchecked(&ata_print_id); /* Create associated sysfs transport objects */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0101af5..c70c325 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4105,7 +4105,7 @@ int ata_sas_port_init(struct ata_port *ap) if (rc) return rc; - ap->print_id = atomic_inc_return(&ata_print_id); + ap->print_id = atomic_inc_return_unchecked(&ata_print_id); return 0; } EXPORT_SYMBOL_GPL(ata_sas_port_init); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 577d902b..cb4781e 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -53,7 +53,7 @@ enum { ATA_DNXFER_QUIET = (1 << 31), }; -extern atomic_t ata_print_id; +extern atomic_unchecked_t ata_print_id; extern int atapi_passthru16; extern int libata_fua; extern int libata_noacpi; diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 7638121..357a965 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -865,7 +865,9 @@ static int arasan_cf_probe(struct platform_device *pdev) /* Handle platform specific quirks */ if (quirk) { if (quirk & CF_BROKEN_PIO) { - ap->ops->set_piomode = NULL; + pax_open_kernel(); + *(void **)&ap->ops->set_piomode = NULL; + pax_close_kernel(); ap->pio_mask = 0; } if (quirk & CF_BROKEN_MWDMA) diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index f9b983a..887b9d8 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c @@ -114,7 +114,7 @@ adummy_send(struct atm_vcc *vcc, struct sk_buff *skb) vcc->pop(vcc, skb); else dev_kfree_skb_any(skb); - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); return 0; } diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 77a7480d..05cde58 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -454,7 +454,7 @@ static void tx_complete (amb_dev * dev, tx_out * tx) { PRINTD (DBG_FLOW|DBG_TX, "tx_complete %p %p", dev, tx); // VC layer stats - atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); + atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx); // free the descriptor kfree (tx_descr); @@ -495,7 +495,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { dump_skb ("<<<", vc, skb); // VC layer stats - atomic_inc(&atm_vcc->stats->rx); + atomic_inc_unchecked(&atm_vcc->stats->rx); __net_timestamp(skb); // end of our responsibility atm_vcc->push (atm_vcc, skb); @@ -510,7 +510,7 @@ static void rx_complete (amb_dev * dev, rx_out * rx) { } else { PRINTK (KERN_INFO, "dropped over-size frame"); // should we count this? - atomic_inc(&atm_vcc->stats->rx_drop); + atomic_inc_unchecked(&atm_vcc->stats->rx_drop); } } else { @@ -1338,7 +1338,7 @@ static int amb_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) { } if (check_area (skb->data, skb->len)) { - atomic_inc(&atm_vcc->stats->tx_err); + atomic_inc_unchecked(&atm_vcc->stats->tx_err); return -ENOMEM; // ? } diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index 0e3f8f9..765a7a5 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -206,7 +206,7 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); if (dev_data) return 0; - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); return -ENOLINK; } size = skb->len+sizeof(struct atmtcp_hdr); @@ -214,7 +214,7 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) if (!new_skb) { if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); return -ENOBUFS; } hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr)); @@ -225,8 +225,8 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); out_vcc->push(out_vcc,new_skb); - atomic_inc(&vcc->stats->tx); - atomic_inc(&out_vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->tx); + atomic_inc_unchecked(&out_vcc->stats->rx); return 0; } @@ -299,7 +299,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci)); read_unlock(&vcc_sklist_lock); if (!out_vcc) { - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); goto done; } skb_pull(skb,sizeof(struct atmtcp_hdr)); @@ -311,8 +311,8 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) __net_timestamp(new_skb); skb_copy_from_linear_data(skb, skb_put(new_skb, skb->len), skb->len); out_vcc->push(out_vcc,new_skb); - atomic_inc(&vcc->stats->tx); - atomic_inc(&out_vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->tx); + atomic_inc_unchecked(&out_vcc->stats->rx); done: if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index b1955ba..b179940 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -522,7 +522,7 @@ static int rx_aal0(struct atm_vcc *vcc) DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n", vcc->dev->number); length = 0; - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); } else { length = ATM_CELL_SIZE-1; /* no HEC */ @@ -577,7 +577,7 @@ static int rx_aal5(struct atm_vcc *vcc) size); } eff = length = 0; - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); } else { size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2); @@ -594,7 +594,7 @@ static int rx_aal5(struct atm_vcc *vcc) "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n", vcc->dev->number,vcc->vci,length,size << 2,descr); length = eff = 0; - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); } } skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL; @@ -767,7 +767,7 @@ rx_dequeued++; vcc->push(vcc,skb); pushed++; } - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); } wake_up(&eni_dev->rx_wait); } @@ -1227,7 +1227,7 @@ static void dequeue_tx(struct atm_dev *dev) PCI_DMA_TODEVICE); if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb_irq(skb); - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); wake_up(&eni_dev->tx_wait); dma_complete++; } diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index b41c948..a002b17 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -749,7 +749,7 @@ static void process_txdone_queue (struct fs_dev *dev, struct queue *q) } } - atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); + atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx); fs_dprintk (FS_DEBUG_TXMEM, "i"); fs_dprintk (FS_DEBUG_ALLOC, "Free t-skb: %p\n", skb); @@ -816,7 +816,7 @@ static void process_incoming (struct fs_dev *dev, struct queue *q) #endif skb_put (skb, qe->p1 & 0xffff); ATM_SKB(skb)->vcc = atm_vcc; - atomic_inc(&atm_vcc->stats->rx); + atomic_inc_unchecked(&atm_vcc->stats->rx); __net_timestamp(skb); fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb); atm_vcc->push (atm_vcc, skb); @@ -837,12 +837,12 @@ static void process_incoming (struct fs_dev *dev, struct queue *q) kfree (pe); } if (atm_vcc) - atomic_inc(&atm_vcc->stats->rx_drop); + atomic_inc_unchecked(&atm_vcc->stats->rx_drop); break; case 0x1f: /* Reassembly abort: no buffers. */ /* Silently increment error counter. */ if (atm_vcc) - atomic_inc(&atm_vcc->stats->rx_drop); + atomic_inc_unchecked(&atm_vcc->stats->rx_drop); break; default: /* Hmm. Haven't written the code to handle the others yet... -- REW */ printk (KERN_WARNING "Don't know what to do with RX status %x: %s.\n", diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 204814e..cede831 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -931,9 +931,9 @@ fore200e_tx_irq(struct fore200e* fore200e) #endif /* check error condition */ if (*entry->status & STATUS_ERROR) - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); else - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); } } @@ -1082,7 +1082,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp if (skb == NULL) { DPRINTK(2, "unable to alloc new skb, rx PDU length = %d\n", pdu_len); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); return -ENOMEM; } @@ -1125,14 +1125,14 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp dev_kfree_skb_any(skb); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); return -ENOMEM; } ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0); vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0); @@ -1210,7 +1210,7 @@ fore200e_rx_irq(struct fore200e* fore200e) DPRINTK(2, "damaged PDU on %d.%d.%d\n", fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); } } @@ -1655,7 +1655,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb) goto retry_here; } - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); fore200e->tx_sat++; DPRINTK(2, "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n", diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 507362a..a845e57 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -1698,7 +1698,7 @@ he_service_rbrq(struct he_dev *he_dev, int group) if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) { hprintk("HBUF_ERR! (cid 0x%x)\n", cid); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); goto return_host_buffers; } @@ -1725,7 +1725,7 @@ he_service_rbrq(struct he_dev *he_dev, int group) RBRQ_LEN_ERR(he_dev->rbrq_head) ? "LEN_ERR" : "", vcc->vpi, vcc->vci); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); goto return_host_buffers; } @@ -1777,7 +1777,7 @@ he_service_rbrq(struct he_dev *he_dev, int group) vcc->push(vcc, skb); spin_lock(&he_dev->global_lock); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); return_host_buffers: ++pdus_assembled; @@ -2103,7 +2103,7 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) tpd->vcc->pop(tpd->vcc, tpd->skb); else dev_kfree_skb_any(tpd->skb); - atomic_inc(&tpd->vcc->stats->tx_err); + atomic_inc_unchecked(&tpd->vcc->stats->tx_err); } pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); return; @@ -2515,7 +2515,7 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) vcc->pop(vcc, skb); else dev_kfree_skb_any(skb); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); return -EINVAL; } @@ -2526,7 +2526,7 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) vcc->pop(vcc, skb); else dev_kfree_skb_any(skb); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); return -EINVAL; } #endif @@ -2538,7 +2538,7 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) vcc->pop(vcc, skb); else dev_kfree_skb_any(skb); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); spin_unlock_irqrestore(&he_dev->global_lock, flags); return -ENOMEM; } @@ -2580,7 +2580,7 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) vcc->pop(vcc, skb); else dev_kfree_skb_any(skb); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); spin_unlock_irqrestore(&he_dev->global_lock, flags); return -ENOMEM; } @@ -2611,7 +2611,7 @@ he_send(struct atm_vcc *vcc, struct sk_buff *skb) __enqueue_tpd(he_dev, tpd, cid); spin_unlock_irqrestore(&he_dev->global_lock, flags); - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); return 0; } diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 1dc0519..1aadaf7 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -1034,7 +1034,7 @@ static void rx_schedule (hrz_dev * dev, int irq) { { struct atm_vcc * vcc = ATM_SKB(skb)->vcc; // VC layer stats - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); __net_timestamp(skb); // end of our responsibility vcc->push (vcc, skb); @@ -1186,7 +1186,7 @@ static void tx_schedule (hrz_dev * const dev, int irq) { dev->tx_iovec = NULL; // VC layer stats - atomic_inc(&ATM_SKB(skb)->vcc->stats->tx); + atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx); // free the skb hrz_kfree_skb (skb); diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 272f009..a18ba55 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -812,7 +812,7 @@ drain_scq(struct idt77252_dev *card, struct vc_map *vc) else dev_kfree_skb(skb); - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); } atomic_dec(&scq->used); @@ -1075,13 +1075,13 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) if ((sb = dev_alloc_skb(64)) == NULL) { printk("%s: Can't allocate buffers for aal0.\n", card->name); - atomic_add(i, &vcc->stats->rx_drop); + atomic_add_unchecked(i, &vcc->stats->rx_drop); break; } if (!atm_charge(vcc, sb->truesize)) { RXPRINTK("%s: atm_charge() dropped aal0 packets.\n", card->name); - atomic_add(i - 1, &vcc->stats->rx_drop); + atomic_add_unchecked(i - 1, &vcc->stats->rx_drop); dev_kfree_skb(sb); break; } @@ -1098,7 +1098,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) ATM_SKB(sb)->vcc = vcc; __net_timestamp(sb); vcc->push(vcc, sb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); cell += ATM_CELL_PAYLOAD; } @@ -1135,13 +1135,13 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) "(CDC: %08x)\n", card->name, len, rpp->len, readl(SAR_REG_CDC)); recycle_rx_pool_skb(card, rpp); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); return; } if (stat & SAR_RSQE_CRC) { RXPRINTK("%s: AAL5 CRC error.\n", card->name); recycle_rx_pool_skb(card, rpp); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); return; } if (skb_queue_len(&rpp->queue) > 1) { @@ -1152,7 +1152,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) RXPRINTK("%s: Can't alloc RX skb.\n", card->name); recycle_rx_pool_skb(card, rpp); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); return; } if (!atm_charge(vcc, skb->truesize)) { @@ -1171,7 +1171,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) __net_timestamp(skb); vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); return; } @@ -1193,7 +1193,7 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) __net_timestamp(skb); vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); if (skb->truesize > SAR_FB_SIZE_3) add_rx_skb(card, 3, SAR_FB_SIZE_3, 1); @@ -1304,14 +1304,14 @@ idt77252_rx_raw(struct idt77252_dev *card) if (vcc->qos.aal != ATM_AAL0) { RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n", card->name, vpi, vci); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); goto drop; } if ((sb = dev_alloc_skb(64)) == NULL) { printk("%s: Can't allocate buffers for AAL0.\n", card->name); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); goto drop; } @@ -1330,7 +1330,7 @@ idt77252_rx_raw(struct idt77252_dev *card) ATM_SKB(sb)->vcc = vcc; __net_timestamp(sb); vcc->push(vcc, sb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); drop: skb_pull(queue, 64); @@ -1955,13 +1955,13 @@ idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam) if (vc == NULL) { printk("%s: NULL connection in send().\n", card->name); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb(skb); return -EINVAL; } if (!test_bit(VCF_TX, &vc->flags)) { printk("%s: Trying to transmit on a non-tx VC.\n", card->name); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb(skb); return -EINVAL; } @@ -1973,14 +1973,14 @@ idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam) break; default: printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb(skb); return -EINVAL; } if (skb_shinfo(skb)->nr_frags != 0) { printk("%s: No scatter-gather yet.\n", card->name); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb(skb); return -EINVAL; } @@ -1988,7 +1988,7 @@ idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam) err = queue_skb(card, vc, skb, oam); if (err) { - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb(skb); return err; } @@ -2011,7 +2011,7 @@ idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags) skb = dev_alloc_skb(64); if (!skb) { printk("%s: Out of memory in send_oam().\n", card->name); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); return -ENOMEM; } atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 4217f29..88f547a 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -1145,7 +1145,7 @@ static int rx_pkt(struct atm_dev *dev) status = (u_short) (buf_desc_ptr->desc_mode); if (status & (RX_CER | RX_PTE | RX_OFL)) { - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); IF_ERR(printk("IA: bad packet, dropping it");) if (status & RX_CER) { IF_ERR(printk(" cause: packet CRC error\n");) @@ -1168,7 +1168,7 @@ static int rx_pkt(struct atm_dev *dev) len = dma_addr - buf_addr; if (len > iadev->rx_buf_sz) { printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); goto out_free_desc; } @@ -1318,7 +1318,7 @@ static void rx_dle_intr(struct atm_dev *dev) ia_vcc = INPH_IA_VCC(vcc); if (ia_vcc == NULL) { - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); atm_return(vcc, skb->truesize); dev_kfree_skb_any(skb); goto INCR_DLE; @@ -1330,7 +1330,7 @@ static void rx_dle_intr(struct atm_dev *dev) if ((length > iadev->rx_buf_sz) || (length > (skb->len - sizeof(struct cpcs_trailer)))) { - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)", length, skb->len);) atm_return(vcc, skb->truesize); @@ -1346,7 +1346,7 @@ static void rx_dle_intr(struct atm_dev *dev) IF_RX(printk("rx_dle_intr: skb push");) vcc->push(vcc,skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); iadev->rx_pkt_cnt++; } INCR_DLE: @@ -2826,15 +2826,15 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) { struct k_sonet_stats *stats; stats = &PRIV(_ia_dev[board])->sonet_stats; - printk("section_bip: %d\n", atomic_read(&stats->section_bip)); - printk("line_bip : %d\n", atomic_read(&stats->line_bip)); - printk("path_bip : %d\n", atomic_read(&stats->path_bip)); - printk("line_febe : %d\n", atomic_read(&stats->line_febe)); - printk("path_febe : %d\n", atomic_read(&stats->path_febe)); - printk("corr_hcs : %d\n", atomic_read(&stats->corr_hcs)); - printk("uncorr_hcs : %d\n", atomic_read(&stats->uncorr_hcs)); - printk("tx_cells : %d\n", atomic_read(&stats->tx_cells)); - printk("rx_cells : %d\n", atomic_read(&stats->rx_cells)); + printk("section_bip: %d\n", atomic_read_unchecked(&stats->section_bip)); + printk("line_bip : %d\n", atomic_read_unchecked(&stats->line_bip)); + printk("path_bip : %d\n", atomic_read_unchecked(&stats->path_bip)); + printk("line_febe : %d\n", atomic_read_unchecked(&stats->line_febe)); + printk("path_febe : %d\n", atomic_read_unchecked(&stats->path_febe)); + printk("corr_hcs : %d\n", atomic_read_unchecked(&stats->corr_hcs)); + printk("uncorr_hcs : %d\n", atomic_read_unchecked(&stats->uncorr_hcs)); + printk("tx_cells : %d\n", atomic_read_unchecked(&stats->tx_cells)); + printk("rx_cells : %d\n", atomic_read_unchecked(&stats->rx_cells)); } ia_cmds.status = 0; break; @@ -2939,7 +2939,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { if ((desc == 0) || (desc > iadev->num_tx_desc)) { IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);) - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); if (vcc->pop) vcc->pop(vcc, skb); else @@ -3044,14 +3044,14 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) { ATM_DESC(skb) = vcc->vci; skb_queue_tail(&iadev->tx_dma_q, skb); - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); iadev->tx_pkt_cnt++; /* Increment transaction counter */ writel(2, iadev->dma+IPHASE5575_TX_COUNTER); #if 0 /* add flow control logic */ - if (atomic_read(&vcc->stats->tx) % 20 == 0) { + if (atomic_read_unchecked(&vcc->stats->tx) % 20 == 0) { if (iavcc->vc_desc_cnt > 10) { vcc->tx_quota = vcc->tx_quota * 3 / 4; printk("Tx1: vcc->tx_quota = %d \n", (u32)vcc->tx_quota ); diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index fa7d701..1e404c7 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -1303,7 +1303,7 @@ static void lanai_send_one_aal5(struct lanai_dev *lanai, vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0); lanai_endtx(lanai, lvcc); lanai_free_skb(lvcc->tx.atmvcc, skb); - atomic_inc(&lvcc->tx.atmvcc->stats->tx); + atomic_inc_unchecked(&lvcc->tx.atmvcc->stats->tx); } /* Try to fill the buffer - don't call unless there is backlog */ @@ -1426,7 +1426,7 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr) ATM_SKB(skb)->vcc = lvcc->rx.atmvcc; __net_timestamp(skb); lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb); - atomic_inc(&lvcc->rx.atmvcc->stats->rx); + atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx); out: lvcc->rx.buf.ptr = end; cardvcc_write(lvcc, endptr, vcc_rxreadptr); @@ -1667,7 +1667,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s) DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 " "vcc %d\n", lanai->number, (unsigned int) s, vci); lanai->stats.service_rxnotaal5++; - atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); + atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err); return 0; } if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) { @@ -1679,7 +1679,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s) int bytes; read_unlock(&vcc_sklist_lock); DPRINTK("got trashed rx pdu on vci %d\n", vci); - atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); + atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err); lvcc->stats.x.aal5.service_trash++; bytes = (SERVICE_GET_END(s) * 16) - (((unsigned long) lvcc->rx.buf.ptr) - @@ -1691,7 +1691,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s) } if (s & SERVICE_STREAM) { read_unlock(&vcc_sklist_lock); - atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); + atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err); lvcc->stats.x.aal5.service_stream++; printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream " "PDU on VCI %d!\n", lanai->number, vci); @@ -1699,7 +1699,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s) return 0; } DPRINTK("got rx crc error on vci %d\n", vci); - atomic_inc(&lvcc->rx.atmvcc->stats->rx_err); + atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err); lvcc->stats.x.aal5.service_rxcrc++; lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4]; cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 6587dc2..149833d 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -1641,7 +1641,7 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) if ((vc = (vc_map *) vcc->dev_data) == NULL) { printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", card->index); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb_any(skb); return -EINVAL; } @@ -1649,7 +1649,7 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) if (!vc->tx) { printk("nicstar%d: Trying to transmit on a non-tx VC.\n", card->index); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb_any(skb); return -EINVAL; } @@ -1657,14 +1657,14 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0) { printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", card->index); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb_any(skb); return -EINVAL; } if (skb_shinfo(skb)->nr_frags != 0) { printk("nicstar%d: No scatter-gather yet.\n", card->index); - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb_any(skb); return -EINVAL; } @@ -1712,11 +1712,11 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) } if (push_scqe(card, vc, scq, &scqe, skb) != 0) { - atomic_inc(&vcc->stats->tx_err); + atomic_inc_unchecked(&vcc->stats->tx_err); dev_kfree_skb_any(skb); return -EIO; } - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); return 0; } @@ -2033,14 +2033,14 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) printk ("nicstar%d: Can't allocate buffers for aal0.\n", card->index); - atomic_add(i, &vcc->stats->rx_drop); + atomic_add_unchecked(i, &vcc->stats->rx_drop); break; } if (!atm_charge(vcc, sb->truesize)) { RXPRINTK ("nicstar%d: atm_charge() dropped aal0 packets.\n", card->index); - atomic_add(i - 1, &vcc->stats->rx_drop); /* already increased by 1 */ + atomic_add_unchecked(i - 1, &vcc->stats->rx_drop); /* already increased by 1 */ dev_kfree_skb_any(sb); break; } @@ -2055,7 +2055,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) ATM_SKB(sb)->vcc = vcc; __net_timestamp(sb); vcc->push(vcc, sb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); cell += ATM_CELL_PAYLOAD; } @@ -2072,7 +2072,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) if (iovb == NULL) { printk("nicstar%d: Out of iovec buffers.\n", card->index); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); recycle_rx_buf(card, skb); return; } @@ -2096,7 +2096,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) small or large buffer itself. */ } else if (NS_PRV_IOVCNT(iovb) >= NS_MAX_IOVECS) { printk("nicstar%d: received too big AAL5 SDU.\n", card->index); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, NS_MAX_IOVECS); NS_PRV_IOVCNT(iovb) = 0; @@ -2116,7 +2116,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) ("nicstar%d: Expected a small buffer, and this is not one.\n", card->index); which_list(card, skb); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); recycle_rx_buf(card, skb); vc->rx_iov = NULL; recycle_iov_buf(card, iovb); @@ -2129,7 +2129,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) ("nicstar%d: Expected a large buffer, and this is not one.\n", card->index); which_list(card, skb); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, NS_PRV_IOVCNT(iovb)); vc->rx_iov = NULL; @@ -2152,7 +2152,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) printk(" - PDU size mismatch.\n"); else printk(".\n"); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *)iovb->data, NS_PRV_IOVCNT(iovb)); vc->rx_iov = NULL; @@ -2166,7 +2166,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) /* skb points to a small buffer */ if (!atm_charge(vcc, skb->truesize)) { push_rxbufs(card, skb); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); } else { skb_put(skb, len); dequeue_sm_buf(card, skb); @@ -2176,7 +2176,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) ATM_SKB(skb)->vcc = vcc; __net_timestamp(skb); vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); } } else if (NS_PRV_IOVCNT(iovb) == 2) { /* One small plus one large buffer */ struct sk_buff *sb; @@ -2187,7 +2187,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) if (len <= NS_SMBUFSIZE) { if (!atm_charge(vcc, sb->truesize)) { push_rxbufs(card, sb); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); } else { skb_put(sb, len); dequeue_sm_buf(card, sb); @@ -2197,7 +2197,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) ATM_SKB(sb)->vcc = vcc; __net_timestamp(sb); vcc->push(vcc, sb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); } push_rxbufs(card, skb); @@ -2206,7 +2206,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) if (!atm_charge(vcc, skb->truesize)) { push_rxbufs(card, skb); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); } else { dequeue_lg_buf(card, skb); #ifdef NS_USE_DESTRUCTORS @@ -2219,7 +2219,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) ATM_SKB(skb)->vcc = vcc; __net_timestamp(skb); vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); } push_rxbufs(card, sb); @@ -2240,7 +2240,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) printk ("nicstar%d: Out of huge buffers.\n", card->index); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, @@ -2291,7 +2291,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) card->hbpool.count++; } else dev_kfree_skb_any(hb); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); } else { /* Copy the small buffer to the huge buffer */ sb = (struct sk_buff *)iov->iov_base; @@ -2328,7 +2328,7 @@ static void dequeue_rx(ns_dev * card, ns_rsqe * rsqe) #endif /* NS_USE_DESTRUCTORS */ __net_timestamp(hb); vcc->push(vcc, hb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); } } diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 32784d1..4a8434a 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -838,7 +838,7 @@ void solos_bh(unsigned long card_arg) } atm_charge(vcc, skb->truesize); vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); break; case PKT_STATUS: @@ -1116,7 +1116,7 @@ static uint32_t fpga_tx(struct solos_card *card) vcc = SKB_CB(oldskb)->vcc; if (vcc) { - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); solos_pop(vcc, oldskb); } else { dev_kfree_skb_irq(oldskb); diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c index 0215934..ce9f5b1 100644 --- a/drivers/atm/suni.c +++ b/drivers/atm/suni.c @@ -49,8 +49,8 @@ static DEFINE_SPINLOCK(sunis_lock); #define ADD_LIMITED(s,v) \ - atomic_add((v),&stats->s); \ - if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX); + atomic_add_unchecked((v),&stats->s); \ + if (atomic_read_unchecked(&stats->s) < 0) atomic_set_unchecked(&stats->s,INT_MAX); static void suni_hz(unsigned long from_timer) diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c index 5120a96..e2572bd 100644 --- a/drivers/atm/uPD98402.c +++ b/drivers/atm/uPD98402.c @@ -42,7 +42,7 @@ static int fetch_stats(struct atm_dev *dev,struct sonet_stats __user *arg,int ze struct sonet_stats tmp; int error = 0; - atomic_add(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs); + atomic_add_unchecked(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs); sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp); if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp)); if (zero && !error) { @@ -161,9 +161,9 @@ static int uPD98402_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) #define ADD_LIMITED(s,v) \ - { atomic_add(GET(v),&PRIV(dev)->sonet_stats.s); \ - if (atomic_read(&PRIV(dev)->sonet_stats.s) < 0) \ - atomic_set(&PRIV(dev)->sonet_stats.s,INT_MAX); } + { atomic_add_unchecked(GET(v),&PRIV(dev)->sonet_stats.s); \ + if (atomic_read_unchecked(&PRIV(dev)->sonet_stats.s) < 0) \ + atomic_set_unchecked(&PRIV(dev)->sonet_stats.s,INT_MAX); } static void stat_event(struct atm_dev *dev) @@ -194,7 +194,7 @@ static void uPD98402_int(struct atm_dev *dev) if (reason & uPD98402_INT_PFM) stat_event(dev); if (reason & uPD98402_INT_PCO) { (void) GET(PCOCR); /* clear interrupt cause */ - atomic_add(GET(HECCT), + atomic_add_unchecked(GET(HECCT), &PRIV(dev)->sonet_stats.uncorr_hcs); } if ((reason & uPD98402_INT_RFO) && @@ -222,9 +222,9 @@ static int uPD98402_start(struct atm_dev *dev) PUT(~(uPD98402_INT_PFM | uPD98402_INT_ALM | uPD98402_INT_RFO | uPD98402_INT_LOS),PIMR); /* enable them */ (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ - atomic_set(&PRIV(dev)->sonet_stats.corr_hcs,-1); - atomic_set(&PRIV(dev)->sonet_stats.tx_cells,-1); - atomic_set(&PRIV(dev)->sonet_stats.rx_cells,-1); + atomic_set_unchecked(&PRIV(dev)->sonet_stats.corr_hcs,-1); + atomic_set_unchecked(&PRIV(dev)->sonet_stats.tx_cells,-1); + atomic_set_unchecked(&PRIV(dev)->sonet_stats.rx_cells,-1); return 0; } diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index 969c3c2..9b72956 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -459,7 +459,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); } if (!size) { dev_kfree_skb_irq(skb); - if (vcc) atomic_inc(&vcc->stats->rx_err); + if (vcc) atomic_inc_unchecked(&vcc->stats->rx_err); continue; } if (!atm_charge(vcc,skb->truesize)) { @@ -469,7 +469,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]); skb->len = size; ATM_SKB(skb)->vcc = vcc; vcc->push(vcc,skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); } zout(pos & 0xffff,MTA(mbx)); #if 0 /* probably a stupid idea */ @@ -733,7 +733,7 @@ if (*ZATM_PRV_DSC(skb) != (uPD98401_TXPD_V | uPD98401_TXPD_DP | skb_queue_head(&zatm_vcc->backlog,skb); break; } - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); wake_up(&zatm_vcc->tx_wait); } diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index d78b204..ecc1929 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -167,7 +167,7 @@ attribute_container_add_device(struct device *dev, ic->classdev.parent = get_device(dev); ic->classdev.class = cont->class; cont->class->dev_release = attribute_container_release; - dev_set_name(&ic->classdev, dev_name(dev)); + dev_set_name(&ic->classdev, "%s", dev_name(dev)); if (fn) fn(cont, dev, &ic->classdev); else diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d414331..b4dd4ba 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -1163,7 +1163,7 @@ int subsys_interface_register(struct subsys_interface *sif) return -EINVAL; mutex_lock(&subsys->p->mutex); - list_add_tail(&sif->node, &subsys->p->interfaces); + pax_list_add_tail((struct list_head *)&sif->node, &subsys->p->interfaces); if (sif->add_dev) { subsys_dev_iter_init(&iter, subsys, NULL, NULL); while ((dev = subsys_dev_iter_next(&iter))) @@ -1188,7 +1188,7 @@ void subsys_interface_unregister(struct subsys_interface *sif) subsys = sif->subsys; mutex_lock(&subsys->p->mutex); - list_del_init(&sif->node); + pax_list_del_init((struct list_head *)&sif->node); if (sif->remove_dev) { subsys_dev_iter_init(&iter, subsys, NULL, NULL); while ((dev = subsys_dev_iter_next(&iter))) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 7413d06..79155fa 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -354,7 +354,7 @@ int devtmpfs_mount(const char *mntdir) if (!thread) return 0; - err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL); + err = sys_mount((char __force_user *)"devtmpfs", (char __force_user *)mntdir, (char __force_user *)"devtmpfs", MS_SILENT, NULL); if (err) printk(KERN_INFO "devtmpfs: error mounting %i\n", err); else @@ -380,11 +380,11 @@ static int devtmpfsd(void *p) *err = sys_unshare(CLONE_NEWNS); if (*err) goto out; - *err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options); + *err = sys_mount((char __force_user *)"devtmpfs", (char __force_user *)"/", (char __force_user *)"devtmpfs", MS_SILENT, (char __force_user *)options); if (*err) goto out; - sys_chdir("/.."); /* will traverse into overmounted root */ - sys_chroot("."); + sys_chdir((char __force_user *)"/.."); /* will traverse into overmounted root */ + sys_chroot((char __force_user *)"."); complete(&setup_done); while (1) { spin_lock(&req_lock); diff --git a/drivers/base/node.c b/drivers/base/node.c index 7616a77c..8f57f51 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -626,7 +626,7 @@ static ssize_t print_nodes_state(enum node_states state, char *buf) struct node_attr { struct device_attribute attr; enum node_states state; -}; +} __do_const; static ssize_t show_node_state(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7072404..76dcebd 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1850,7 +1850,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) { struct cpuidle_driver *cpuidle_drv; struct gpd_cpu_data *cpu_data; - struct cpuidle_state *idle_state; + cpuidle_state_no_const *idle_state; int ret = 0; if (IS_ERR_OR_NULL(genpd) || state < 0) @@ -1918,7 +1918,7 @@ int pm_genpd_name_attach_cpuidle(const char *name, int state) int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) { struct gpd_cpu_data *cpu_data; - struct cpuidle_state *idle_state; + cpuidle_state_no_const *idle_state; int ret = 0; if (IS_ERR_OR_NULL(genpd)) diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index a53ebd2..8f73eeb 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -185,7 +185,7 @@ static ssize_t rtpm_status_show(struct device *dev, return -EIO; } } - return sprintf(buf, p); + return sprintf(buf, "%s", p); } static DEVICE_ATTR(runtime_status, 0444, rtpm_status_show, NULL); diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 79715e7..df06b3b 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -29,14 +29,14 @@ bool events_check_enabled __read_mostly; * They need to be modified together atomically, so it's better to use one * atomic variable to hold them both. */ -static atomic_t combined_event_count = ATOMIC_INIT(0); +static atomic_unchecked_t combined_event_count = ATOMIC_INIT(0); #define IN_PROGRESS_BITS (sizeof(int) * 4) #define MAX_IN_PROGRESS ((1 << IN_PROGRESS_BITS) - 1) static void split_counters(unsigned int *cnt, unsigned int *inpr) { - unsigned int comb = atomic_read(&combined_event_count); + unsigned int comb = atomic_read_unchecked(&combined_event_count); *cnt = (comb >> IN_PROGRESS_BITS); *inpr = comb & MAX_IN_PROGRESS; @@ -395,7 +395,7 @@ static void wakeup_source_activate(struct wakeup_source *ws) ws->start_prevent_time = ws->last_time; /* Increment the counter of events in progress. */ - cec = atomic_inc_return(&combined_event_count); + cec = atomic_inc_return_unchecked(&combined_event_count); trace_wakeup_source_activate(ws->name, cec); } @@ -521,7 +521,7 @@ static void wakeup_source_deactivate(struct wakeup_source *ws) * Increment the counter of registered wakeup events and decrement the * couter of wakeup events in progress simultaneously. */ - cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count); + cec = atomic_add_return_unchecked(MAX_IN_PROGRESS, &combined_event_count); trace_wakeup_source_deactivate(ws->name, cec); split_counters(&cnt, &inpr); diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c index e8d11b6..7b1b36f 100644 --- a/drivers/base/syscore.c +++ b/drivers/base/syscore.c @@ -21,7 +21,7 @@ static DEFINE_MUTEX(syscore_ops_lock); void register_syscore_ops(struct syscore_ops *ops) { mutex_lock(&syscore_ops_lock); - list_add_tail(&ops->node, &syscore_ops_list); + pax_list_add_tail((struct list_head *)&ops->node, &syscore_ops_list); mutex_unlock(&syscore_ops_lock); } EXPORT_SYMBOL_GPL(register_syscore_ops); @@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(register_syscore_ops); void unregister_syscore_ops(struct syscore_ops *ops) { mutex_lock(&syscore_ops_lock); - list_del(&ops->node); + pax_list_del((struct list_head *)&ops->node); mutex_unlock(&syscore_ops_lock); } EXPORT_SYMBOL_GPL(unregister_syscore_ops); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 62b6c2c..4a11354 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1189,6 +1189,8 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, int err; u32 cp; + memset(&arg64, 0, sizeof(arg64)); + err = 0; err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, @@ -3010,7 +3012,7 @@ static void start_io(ctlr_info_t *h) while (!list_empty(&h->reqQ)) { c = list_entry(h->reqQ.next, CommandList_struct, list); /* can't do anything if fifo is full */ - if ((h->access.fifo_full(h))) { + if ((h->access->fifo_full(h))) { dev_warn(&h->pdev->dev, "fifo full\n"); break; } @@ -3020,7 +3022,7 @@ static void start_io(ctlr_info_t *h) h->Qdepth--; /* Tell the controller execute command */ - h->access.submit_command(h, c); + h->access->submit_command(h, c); /* Put job onto the completed Q */ addQ(&h->cmpQ, c); @@ -3446,17 +3448,17 @@ startio: static inline unsigned long get_next_completion(ctlr_info_t *h) { - return h->access.command_completed(h); + return h->access->command_completed(h); } static inline int interrupt_pending(ctlr_info_t *h) { - return h->access.intr_pending(h); + return h->access->intr_pending(h); } static inline long interrupt_not_for_us(ctlr_info_t *h) { - return ((h->access.intr_pending(h) == 0) || + return ((h->access->intr_pending(h) == 0) || (h->interrupts_enabled == 0)); } @@ -3489,7 +3491,7 @@ static inline u32 next_command(ctlr_info_t *h) u32 a; if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant))) - return h->access.command_completed(h); + return h->access->command_completed(h); if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { a = *(h->reply_pool_head); /* Next cmd in ring buffer */ @@ -4046,7 +4048,7 @@ static void cciss_put_controller_into_performant_mode(ctlr_info_t *h) trans_support & CFGTBL_Trans_use_short_tags); /* Change the access methods to the performant access methods */ - h->access = SA5_performant_access; + h->access = &SA5_performant_access; h->transMethod = CFGTBL_Trans_Performant; return; @@ -4319,7 +4321,7 @@ static int cciss_pci_init(ctlr_info_t *h) if (prod_index < 0) return -ENODEV; h->product_name = products[prod_index].product_name; - h->access = *(products[prod_index].access); + h->access = products[prod_index].access; if (cciss_board_disabled(h)) { dev_warn(&h->pdev->dev, "controller appears to be disabled\n"); @@ -5051,7 +5053,7 @@ reinit_after_soft_reset: } /* make sure the board interrupts are off */ - h->access.set_intr_mask(h, CCISS_INTR_OFF); + h->access->set_intr_mask(h, CCISS_INTR_OFF); rc = cciss_request_irq(h, do_cciss_msix_intr, do_cciss_intx); if (rc) goto clean2; @@ -5101,7 +5103,7 @@ reinit_after_soft_reset: * fake ones to scoop up any residual completions. */ spin_lock_irqsave(&h->lock, flags); - h->access.set_intr_mask(h, CCISS_INTR_OFF); + h->access->set_intr_mask(h, CCISS_INTR_OFF); spin_unlock_irqrestore(&h->lock, flags); free_irq(h->intr[h->intr_mode], h); rc = cciss_request_irq(h, cciss_msix_discard_completions, @@ -5121,9 +5123,9 @@ reinit_after_soft_reset: dev_info(&h->pdev->dev, "Board READY.\n"); dev_info(&h->pdev->dev, "Waiting for stale completions to drain.\n"); - h->access.set_intr_mask(h, CCISS_INTR_ON); + h->access->set_intr_mask(h, CCISS_INTR_ON); msleep(10000); - h->access.set_intr_mask(h, CCISS_INTR_OFF); + h->access->set_intr_mask(h, CCISS_INTR_OFF); rc = controller_reset_failed(h->cfgtable); if (rc) @@ -5146,7 +5148,7 @@ reinit_after_soft_reset: cciss_scsi_setup(h); /* Turn the interrupts on so we can service requests */ - h->access.set_intr_mask(h, CCISS_INTR_ON); + h->access->set_intr_mask(h, CCISS_INTR_ON); /* Get the firmware version */ inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL); @@ -5218,7 +5220,7 @@ static void cciss_shutdown(struct pci_dev *pdev) kfree(flush_buf); if (return_code != IO_OK) dev_warn(&h->pdev->dev, "Error flushing cache\n"); - h->access.set_intr_mask(h, CCISS_INTR_OFF); + h->access->set_intr_mask(h, CCISS_INTR_OFF); free_irq(h->intr[h->intr_mode], h); } diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 7fda30e..eb5dfe0 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -101,7 +101,7 @@ struct ctlr_info /* information about each logical volume */ drive_info_struct *drv[CISS_MAX_LUN]; - struct access_method access; + struct access_method *access; /* queue and queue Info */ struct list_head reqQ; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 639d26b..fd6ad1f 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -404,7 +404,7 @@ static int cpqarray_register_ctlr(int i, struct pci_dev *pdev) if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname)) { goto Enomem4; } - hba[i]->access.set_intr_mask(hba[i], 0); + hba[i]->access->set_intr_mask(hba[i], 0); if (request_irq(hba[i]->intr, do_ida_intr, IRQF_DISABLED|IRQF_SHARED, hba[i]->devname, hba[i])) { @@ -459,7 +459,7 @@ static int cpqarray_register_ctlr(int i, struct pci_dev *pdev) add_timer(&hba[i]->timer); /* Enable IRQ now that spinlock and rate limit timer are set up */ - hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY); + hba[i]->access->set_intr_mask(hba[i], FIFO_NOT_EMPTY); for(j=0; jproduct_name = products[i].product_name; - c->access = *(products[i].access); + c->access = products[i].access; break; } } @@ -792,7 +792,7 @@ static int cpqarray_eisa_detect(void) hba[ctlr]->intr = intr; sprintf(hba[ctlr]->devname, "ida%d", nr_ctlr); hba[ctlr]->product_name = products[j].product_name; - hba[ctlr]->access = *(products[j].access); + hba[ctlr]->access = products[j].access; hba[ctlr]->ctlr = ctlr; hba[ctlr]->board_id = board_id; hba[ctlr]->pci_dev = NULL; /* not PCI */ @@ -978,7 +978,7 @@ static void start_io(ctlr_info_t *h) while((c = h->reqQ) != NULL) { /* Can't do anything if we're busy */ - if (h->access.fifo_full(h) == 0) + if (h->access->fifo_full(h) == 0) return; /* Get the first entry from the request Q */ @@ -986,7 +986,7 @@ static void start_io(ctlr_info_t *h) h->Qdepth--; /* Tell the controller to do our bidding */ - h->access.submit_command(h, c); + h->access->submit_command(h, c); /* Get onto the completion Q */ addQ(&h->cmpQ, c); @@ -1048,7 +1048,7 @@ static irqreturn_t do_ida_intr(int irq, void *dev_id) unsigned long flags; __u32 a,a1; - istat = h->access.intr_pending(h); + istat = h->access->intr_pending(h); /* Is this interrupt for us? */ if (istat == 0) return IRQ_NONE; @@ -1059,7 +1059,7 @@ static irqreturn_t do_ida_intr(int irq, void *dev_id) */ spin_lock_irqsave(IDA_LOCK(h->ctlr), flags); if (istat & FIFO_NOT_EMPTY) { - while((a = h->access.command_completed(h))) { + while((a = h->access->command_completed(h))) { a1 = a; a &= ~3; if ((c = h->cmpQ) == NULL) { @@ -1193,6 +1193,7 @@ out_passthru: ida_pci_info_struct pciinfo; if (!arg) return -EINVAL; + memset(&pciinfo, 0, sizeof(pciinfo)); pciinfo.bus = host->pci_dev->bus->number; pciinfo.dev_fn = host->pci_dev->devfn; pciinfo.board_id = host->board_id; @@ -1447,11 +1448,11 @@ static int sendcmd( /* * Disable interrupt */ - info_p->access.set_intr_mask(info_p, 0); + info_p->access->set_intr_mask(info_p, 0); /* Make sure there is room in the command FIFO */ /* Actually it should be completely empty at this time. */ for (i = 200000; i > 0; i--) { - temp = info_p->access.fifo_full(info_p); + temp = info_p->access->fifo_full(info_p); if (temp != 0) { break; } @@ -1464,7 +1465,7 @@ DBG( /* * Send the cmd */ - info_p->access.submit_command(info_p, c); + info_p->access->submit_command(info_p, c); complete = pollcomplete(ctlr); pci_unmap_single(info_p->pci_dev, (dma_addr_t) c->req.sg[0].addr, @@ -1547,9 +1548,9 @@ static int revalidate_allvol(ctlr_info_t *host) * we check the new geometry. Then turn interrupts back on when * we're done. */ - host->access.set_intr_mask(host, 0); + host->access->set_intr_mask(host, 0); getgeometry(ctlr); - host->access.set_intr_mask(host, FIFO_NOT_EMPTY); + host->access->set_intr_mask(host, FIFO_NOT_EMPTY); for(i=0; i 0; i--) { - done = hba[ctlr]->access.command_completed(hba[ctlr]); + done = hba[ctlr]->access->command_completed(hba[ctlr]); if (done == 0) { udelay(10); /* a short fixed delay */ } else diff --git a/drivers/block/cpqarray.h b/drivers/block/cpqarray.h index be73e9d..7fbf140 100644 --- a/drivers/block/cpqarray.h +++ b/drivers/block/cpqarray.h @@ -99,7 +99,7 @@ struct ctlr_info { drv_info_t drv[NWD]; struct proc_dir_entry *proc; - struct access_method access; + struct access_method *access; cmdlist_t *reqQ; cmdlist_t *cmpQ; diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index f943aac..99bfd19 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -582,7 +582,7 @@ struct drbd_epoch { struct drbd_tconn *tconn; struct list_head list; unsigned int barrier_nr; - atomic_t epoch_size; /* increased on every request added. */ + atomic_unchecked_t epoch_size; /* increased on every request added. */ atomic_t active; /* increased on every req. added, and dec on every finished. */ unsigned long flags; }; @@ -1021,7 +1021,7 @@ struct drbd_conf { unsigned int al_tr_number; int al_tr_cycle; wait_queue_head_t seq_wait; - atomic_t packet_seq; + atomic_unchecked_t packet_seq; unsigned int peer_seq; spinlock_t peer_seq_lock; unsigned int minor; @@ -1562,7 +1562,7 @@ static inline int drbd_setsockopt(struct socket *sock, int level, int optname, char __user *uoptval; int err; - uoptval = (char __user __force *)optval; + uoptval = (char __force_user *)optval; set_fs(KERNEL_DS); if (level == SOL_SOCKET) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index a5dca6a..bb27967 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1317,7 +1317,7 @@ static int _drbd_send_ack(struct drbd_conf *mdev, enum drbd_packet cmd, p->sector = sector; p->block_id = block_id; p->blksize = blksize; - p->seq_num = cpu_to_be32(atomic_inc_return(&mdev->packet_seq)); + p->seq_num = cpu_to_be32(atomic_inc_return_unchecked(&mdev->packet_seq)); return drbd_send_command(mdev, sock, cmd, sizeof(*p), NULL, 0); } @@ -1619,7 +1619,7 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) return -EIO; p->sector = cpu_to_be64(req->i.sector); p->block_id = (unsigned long)req; - p->seq_num = cpu_to_be32(atomic_inc_return(&mdev->packet_seq)); + p->seq_num = cpu_to_be32(atomic_inc_return_unchecked(&mdev->packet_seq)); dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw); if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn <= C_PAUSED_SYNC_T) @@ -2574,8 +2574,8 @@ void conn_destroy(struct kref *kref) { struct drbd_tconn *tconn = container_of(kref, struct drbd_tconn, kref); - if (atomic_read(&tconn->current_epoch->epoch_size) != 0) - conn_err(tconn, "epoch_size:%d\n", atomic_read(&tconn->current_epoch->epoch_size)); + if (atomic_read_unchecked(&tconn->current_epoch->epoch_size) != 0) + conn_err(tconn, "epoch_size:%d\n", atomic_read_unchecked(&tconn->current_epoch->epoch_size)); kfree(tconn->current_epoch); idr_destroy(&tconn->volumes); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 9e3f441..4044d47 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -3339,7 +3339,7 @@ out: void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib) { - static atomic_t drbd_genl_seq = ATOMIC_INIT(2); /* two. */ + static atomic_unchecked_t drbd_genl_seq = ATOMIC_INIT(2); /* two. */ struct sk_buff *msg; struct drbd_genlmsghdr *d_out; unsigned seq; @@ -3352,7 +3352,7 @@ void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib) return; } - seq = atomic_inc_return(&drbd_genl_seq); + seq = atomic_inc_return_unchecked(&drbd_genl_seq); msg = genlmsg_new(NLMSG_GOODSIZE, GFP_NOIO); if (!msg) goto failed; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 4222aff..1f79506 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -834,7 +834,7 @@ int drbd_connected(struct drbd_conf *mdev) { int err; - atomic_set(&mdev->packet_seq, 0); + atomic_set_unchecked(&mdev->packet_seq, 0); mdev->peer_seq = 0; mdev->state_mutex = mdev->tconn->agreed_pro_version < 100 ? @@ -1193,7 +1193,7 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn, do { next_epoch = NULL; - epoch_size = atomic_read(&epoch->epoch_size); + epoch_size = atomic_read_unchecked(&epoch->epoch_size); switch (ev & ~EV_CLEANUP) { case EV_PUT: @@ -1233,7 +1233,7 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_tconn *tconn, rv = FE_DESTROYED; } else { epoch->flags = 0; - atomic_set(&epoch->epoch_size, 0); + atomic_set_unchecked(&epoch->epoch_size, 0); /* atomic_set(&epoch->active, 0); is already zero */ if (rv == FE_STILL_LIVE) rv = FE_RECYCLED; @@ -1451,7 +1451,7 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi) conn_wait_active_ee_empty(tconn); drbd_flush(tconn); - if (atomic_read(&tconn->current_epoch->epoch_size)) { + if (atomic_read_unchecked(&tconn->current_epoch->epoch_size)) { epoch = kmalloc(sizeof(struct drbd_epoch), GFP_NOIO); if (epoch) break; @@ -1464,11 +1464,11 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi) } epoch->flags = 0; - atomic_set(&epoch->epoch_size, 0); + atomic_set_unchecked(&epoch->epoch_size, 0); atomic_set(&epoch->active, 0); spin_lock(&tconn->epoch_lock); - if (atomic_read(&tconn->current_epoch->epoch_size)) { + if (atomic_read_unchecked(&tconn->current_epoch->epoch_size)) { list_add(&epoch->list, &tconn->current_epoch->list); tconn->current_epoch = epoch; tconn->epochs++; @@ -2172,7 +2172,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi) err = wait_for_and_update_peer_seq(mdev, peer_seq); drbd_send_ack_dp(mdev, P_NEG_ACK, p, pi->size); - atomic_inc(&tconn->current_epoch->epoch_size); + atomic_inc_unchecked(&tconn->current_epoch->epoch_size); err2 = drbd_drain_block(mdev, pi->size); if (!err) err = err2; @@ -2206,7 +2206,7 @@ static int receive_Data(struct drbd_tconn *tconn, struct packet_info *pi) spin_lock(&tconn->epoch_lock); peer_req->epoch = tconn->current_epoch; - atomic_inc(&peer_req->epoch->epoch_size); + atomic_inc_unchecked(&peer_req->epoch->epoch_size); atomic_inc(&peer_req->epoch->active); spin_unlock(&tconn->epoch_lock); @@ -4347,7 +4347,7 @@ struct data_cmd { int expect_payload; size_t pkt_size; int (*fn)(struct drbd_tconn *, struct packet_info *); -}; +} __do_const; static struct data_cmd drbd_cmd_handler[] = { [P_DATA] = { 1, sizeof(struct p_data), receive_Data }, @@ -4467,7 +4467,7 @@ static void conn_disconnect(struct drbd_tconn *tconn) if (!list_empty(&tconn->current_epoch->list)) conn_err(tconn, "ASSERTION FAILED: tconn->current_epoch->list not empty\n"); /* ok, no more ee's on the fly, it is safe to reset the epoch_size */ - atomic_set(&tconn->current_epoch->epoch_size, 0); + atomic_set_unchecked(&tconn->current_epoch->epoch_size, 0); tconn->send.seen_any_write_yet = false; conn_info(tconn, "Connection closed\n"); @@ -5223,7 +5223,7 @@ static int tconn_finish_peer_reqs(struct drbd_tconn *tconn) struct asender_cmd { size_t pkt_size; int (*fn)(struct drbd_tconn *tconn, struct packet_info *); -}; +} __do_const; static struct asender_cmd asender_tbl[] = { [P_PING] = { 0, got_Ping }, diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d92d50f..a7e9d97 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -232,7 +232,7 @@ static int __do_lo_send_write(struct file *file, file_start_write(file); set_fs(get_ds()); - bw = file->f_op->write(file, buf, len, &pos); + bw = file->f_op->write(file, (const char __force_user *)buf, len, &pos); set_fs(old_fs); file_end_write(file); if (likely(bw == len)) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index f5d0ea1..c62380a 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -84,7 +84,7 @@ #define MAX_SPEED 0xffff #define ZONE(sector, pd) (((sector) + (pd)->offset) & \ - ~(sector_t)((pd)->settings.size - 1)) + ~(sector_t)((pd)->settings.size - 1UL)) static DEFINE_MUTEX(pktcdvd_mutex); static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 8a3aff7..d7538c2 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -416,7 +416,6 @@ int register_cdrom(struct cdrom_device_info *cdi) ENSURE(reset, CDC_RESET); ENSURE(generic_packet, CDC_GENERIC_PACKET); cdi->mc_flags = 0; - cdo->n_minors = 0; cdi->options = CDO_USE_FFLAGS; if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY)) @@ -436,8 +435,11 @@ int register_cdrom(struct cdrom_device_info *cdi) else cdi->cdda_method = CDDA_OLD; - if (!cdo->generic_packet) - cdo->generic_packet = cdrom_dummy_generic_packet; + if (!cdo->generic_packet) { + pax_open_kernel(); + *(void **)&cdo->generic_packet = cdrom_dummy_generic_packet; + pax_close_kernel(); + } cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); mutex_lock(&cdrom_mutex); @@ -458,7 +460,6 @@ void unregister_cdrom(struct cdrom_device_info *cdi) if (cdi->exit) cdi->exit(cdi); - cdi->ops->n_minors--; cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); } @@ -2107,7 +2108,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, */ nr = nframes; do { - cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL); + cgc.buffer = kzalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL); if (cgc.buffer) break; @@ -3429,7 +3430,7 @@ static int cdrom_print_info(const char *header, int val, char *info, struct cdrom_device_info *cdi; int ret; - ret = scnprintf(info + *pos, max_size - *pos, header); + ret = scnprintf(info + *pos, max_size - *pos, "%s", header); if (!ret) return 1; diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 4afcb65..a68a32d 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -491,7 +491,6 @@ static struct cdrom_device_ops gdrom_ops = { .audio_ioctl = gdrom_audio_ioctl, .capability = CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R, - .n_minors = 1, }; static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 3bb6fa3..34013fb 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -8,7 +8,8 @@ source "drivers/tty/Kconfig" config DEVKMEM bool "/dev/kmem virtual device support" - default y + default n + depends on !GRKERNSEC_KMEM help Say Y here if you want to support the /dev/kmem device. The /dev/kmem device is rarely used, but can be used for certain @@ -582,6 +583,7 @@ config DEVPORT bool depends on !M68K depends on ISA || PCI + depends on !GRKERNSEC_KMEM default y source "drivers/s390/char/Kconfig" diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c index a48e05b..6bac831 100644 --- a/drivers/char/agp/compat_ioctl.c +++ b/drivers/char/agp/compat_ioctl.c @@ -108,7 +108,7 @@ static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user return -ENOMEM; } - if (copy_from_user(usegment, (void __user *) ureserve.seg_list, + if (copy_from_user(usegment, (void __force_user *) ureserve.seg_list, sizeof(*usegment) * ureserve.seg_count)) { kfree(usegment); kfree(ksegment); diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 2e04433..771f2cc 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -817,7 +817,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) if (copy_from_user(&reserve, arg, sizeof(struct agp_region))) return -EFAULT; - if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) + if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv)) return -EFAULT; client = agp_find_client_by_pid(reserve.pid); @@ -847,7 +847,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) if (segment == NULL) return -ENOMEM; - if (copy_from_user(segment, (void __user *) reserve.seg_list, + if (copy_from_user(segment, (void __force_user *) reserve.seg_list, sizeof(struct agp_segment) * reserve.seg_count)) { kfree(segment); return -EFAULT; diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 4f94375..413694e 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -273,6 +273,7 @@ static int gen_rtc_ioctl(struct file *file, switch (cmd) { case RTC_PLL_GET: + memset(&pll, 0, sizeof(pll)); if (get_rtc_pll(&pll)) return -EINVAL; else diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index d784650..e8bfd69 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -559,7 +559,7 @@ static inline unsigned long hpet_time_div(struct hpets *hpets, } static int -hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, +hpet_ioctl_common(struct hpet_dev *devp, unsigned int cmd, unsigned long arg, struct hpet_info *info) { struct hpet_timer __iomem *timer; diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 86fe45c..c0ea948 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -314,7 +314,7 @@ PFX "RNG, try using the 'no_fwh_detect' option.\n"; if (no_fwh_detect) return -ENODEV; - printk(warning); + printk("%s", warning); return -EBUSY; } diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 4445fa1..7c6de37 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -420,7 +420,7 @@ struct ipmi_smi { struct proc_dir_entry *proc_dir; char proc_dir_name[10]; - atomic_t stats[IPMI_NUM_STATS]; + atomic_unchecked_t stats[IPMI_NUM_STATS]; /* * run_to_completion duplicate of smb_info, smi_info @@ -453,9 +453,9 @@ static DEFINE_MUTEX(smi_watchers_mutex); #define ipmi_inc_stat(intf, stat) \ - atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat]) + atomic_inc_unchecked(&(intf)->stats[IPMI_STAT_ ## stat]) #define ipmi_get_stat(intf, stat) \ - ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) + ((unsigned int) atomic_read_unchecked(&(intf)->stats[IPMI_STAT_ ## stat])) static int is_lan_addr(struct ipmi_addr *addr) { @@ -2883,7 +2883,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, INIT_LIST_HEAD(&intf->cmd_rcvrs); init_waitqueue_head(&intf->waitq); for (i = 0; i < IPMI_NUM_STATS; i++) - atomic_set(&intf->stats[i], 0); + atomic_set_unchecked(&intf->stats[i], 0); intf->proc_dir = NULL; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index af4b23f..79806fc 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -275,7 +275,7 @@ struct smi_info { unsigned char slave_addr; /* Counters and things for the proc filesystem. */ - atomic_t stats[SI_NUM_STATS]; + atomic_unchecked_t stats[SI_NUM_STATS]; struct task_struct *thread; @@ -284,9 +284,9 @@ struct smi_info { }; #define smi_inc_stat(smi, stat) \ - atomic_inc(&(smi)->stats[SI_STAT_ ## stat]) + atomic_inc_unchecked(&(smi)->stats[SI_STAT_ ## stat]) #define smi_get_stat(smi, stat) \ - ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat])) + ((unsigned int) atomic_read_unchecked(&(smi)->stats[SI_STAT_ ## stat])) #define SI_MAX_PARMS 4 @@ -3258,7 +3258,7 @@ static int try_smi_init(struct smi_info *new_smi) atomic_set(&new_smi->req_events, 0); new_smi->run_to_completion = 0; for (i = 0; i < SI_NUM_STATS; i++) - atomic_set(&new_smi->stats[i], 0); + atomic_set_unchecked(&new_smi->stats[i], 0); new_smi->interrupt_disabled = 1; atomic_set(&new_smi->stop_operation, 0); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 1ccbe94..6ad651a 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,10 @@ #define DEVPORT_MINOR 4 +#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC) +extern const struct file_operations grsec_fops; +#endif + static inline unsigned long size_inside_page(unsigned long start, unsigned long size) { @@ -69,9 +74,13 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) while (cursor < to) { if (!devmem_is_allowed(pfn)) { +#ifdef CONFIG_GRKERNSEC_KMEM + gr_handle_mem_readwrite(from, to); +#else printk(KERN_INFO "Program %s tried to access /dev/mem between %Lx->%Lx.\n", current->comm, from, to); +#endif return 0; } cursor += PAGE_SIZE; @@ -79,6 +88,11 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) } return 1; } +#elif defined(CONFIG_GRKERNSEC_KMEM) +static inline int range_is_allowed(unsigned long pfn, unsigned long size) +{ + return 0; +} #else static inline int range_is_allowed(unsigned long pfn, unsigned long size) { @@ -121,6 +135,7 @@ static ssize_t read_mem(struct file *file, char __user *buf, while (count > 0) { unsigned long remaining; + char *temp; sz = size_inside_page(p, count); @@ -136,7 +151,23 @@ static ssize_t read_mem(struct file *file, char __user *buf, if (!ptr) return -EFAULT; - remaining = copy_to_user(buf, ptr, sz); +#ifdef CONFIG_PAX_USERCOPY + temp = kmalloc(sz, GFP_KERNEL|GFP_USERCOPY); + if (!temp) { + unxlate_dev_mem_ptr(p, ptr); + return -ENOMEM; + } + memcpy(temp, ptr, sz); +#else + temp = ptr; +#endif + + remaining = copy_to_user(buf, temp, sz); + +#ifdef CONFIG_PAX_USERCOPY + kfree(temp); +#endif + unxlate_dev_mem_ptr(p, ptr); if (remaining) return -EFAULT; @@ -379,7 +410,7 @@ static ssize_t read_oldmem(struct file *file, char __user *buf, else csize = count; - rc = copy_oldmem_page(pfn, buf, csize, offset, 1); + rc = copy_oldmem_page(pfn, (char __force_kernel *)buf, csize, offset, 1); if (rc < 0) return rc; buf += csize; @@ -399,9 +430,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - ssize_t low_count, read, sz; + ssize_t low_count, read, sz, err = 0; char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ - int err = 0; read = 0; if (p < (unsigned long) high_memory) { @@ -423,6 +453,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, } #endif while (low_count > 0) { + char *temp; + sz = size_inside_page(p, low_count); /* @@ -432,7 +464,22 @@ static ssize_t read_kmem(struct file *file, char __user *buf, */ kbuf = xlate_dev_kmem_ptr((char *)p); - if (copy_to_user(buf, kbuf, sz)) +#ifdef CONFIG_PAX_USERCOPY + temp = kmalloc(sz, GFP_KERNEL|GFP_USERCOPY); + if (!temp) + return -ENOMEM; + memcpy(temp, kbuf, sz); +#else + temp = kbuf; +#endif + + err = copy_to_user(buf, temp, sz); + +#ifdef CONFIG_PAX_USERCOPY + kfree(temp); +#endif + + if (err) return -EFAULT; buf += sz; p += sz; @@ -869,6 +916,9 @@ static const struct memdev { #ifdef CONFIG_CRASH_DUMP [12] = { "oldmem", 0, &oldmem_fops, NULL }, #endif +#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC) + [13] = { "grsec",S_IRUSR | S_IWUGO, &grsec_fops, NULL }, +#endif }; static int memory_open(struct inode *inode, struct file *filp) @@ -940,7 +990,7 @@ static int __init chr_dev_init(void) continue; device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), - NULL, devlist[minor].name); + NULL, "%s", devlist[minor].name); } return tty_init(); diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index c689697..04e6d6a 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c @@ -479,6 +479,7 @@ int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_QueryAbilities entry pBDData %p\n", pBDData); + memset(pAbilities, 0, sizeof(*pAbilities)); /* fill out standard constant fields */ pAbilities->instr_per_sec = pBDData->rDspSettings.uIps; pAbilities->data_size = pBDData->rDspSettings.uDStoreSize; diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 9df78e2..01ba9ae 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -247,7 +247,7 @@ static ssize_t nvram_read(struct file *file, char __user *buf, spin_unlock_irq(&rtc_lock); - if (copy_to_user(buf, contents, tmp - contents)) + if (tmp - contents > sizeof(contents) || copy_to_user(buf, contents, tmp - contents)) return -EFAULT; *ppos = i; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 5c5cc00..ac9edb7 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2345,9 +2345,9 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", - __FILE__, __LINE__, info->device_name, port->count); + __FILE__, __LINE__, info->device_name, atomic_read(&port->count)); - WARN_ON(!port->count); + WARN_ON(!atomic_read(&port->count)); if (tty_port_close_start(port, tty, filp) == 0) goto cleanup; @@ -2365,7 +2365,7 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp) cleanup: if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__, __LINE__, - tty->driver->name, port->count); + tty->driver->name, atomic_read(&port->count)); } /* Wait until the transmitter is empty. @@ -2507,7 +2507,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", - __FILE__, __LINE__, tty->driver->name, port->count); + __FILE__, __LINE__, tty->driver->name, atomic_read(&port->count)); /* If port is closing, signal caller to try again */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){ @@ -2527,11 +2527,11 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) goto cleanup; } spin_lock(&port->lock); - port->count++; + atomic_inc(&port->count); spin_unlock(&port->lock); spin_unlock_irqrestore(&info->netlock, flags); - if (port->count == 1) { + if (atomic_read(&port->count) == 1) { /* 1st open on this device, init hardware */ retval = startup(info, tty); if (retval < 0) @@ -3920,7 +3920,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, unsigned short new_crctype; /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; switch (encoding) @@ -4024,7 +4024,7 @@ static int hdlcdev_open(struct net_device *dev) /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { + if (atomic_read(&info->port.count) != 0 || info->netcount != 0) { printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; @@ -4114,7 +4114,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) printk("%s:hdlcdev_ioctl(%s)\n", __FILE__, dev->name); /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; if (cmd != SIOCWANDEV) diff --git a/drivers/char/random.c b/drivers/char/random.c index 35487e8..dac8bd1 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -272,8 +272,13 @@ /* * Configuration information */ +#ifdef CONFIG_GRKERNSEC_RANDNET +#define INPUT_POOL_WORDS 512 +#define OUTPUT_POOL_WORDS 128 +#else #define INPUT_POOL_WORDS 128 #define OUTPUT_POOL_WORDS 32 +#endif #define SEC_XFER_SIZE 512 #define EXTRACT_SIZE 10 @@ -313,10 +318,17 @@ static struct poolinfo { int poolwords; int tap1, tap2, tap3, tap4, tap5; } poolinfo_table[] = { +#ifdef CONFIG_GRKERNSEC_RANDNET + /* x^512 + x^411 + x^308 + x^208 +x^104 + x + 1 -- 225 */ + { 512, 411, 308, 208, 104, 1 }, + /* x^128 + x^103 + x^76 + x^51 + x^25 + x + 1 -- 105 */ + { 128, 103, 76, 51, 25, 1 }, +#else /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */ { 128, 103, 76, 51, 25, 1 }, /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */ { 32, 26, 20, 14, 7, 1 }, +#endif #if 0 /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */ { 2048, 1638, 1231, 819, 411, 1 }, @@ -524,8 +536,8 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in, input_rotate += i ? 7 : 14; } - ACCESS_ONCE(r->input_rotate) = input_rotate; - ACCESS_ONCE(r->add_ptr) = i; + ACCESS_ONCE_RW(r->input_rotate) = input_rotate; + ACCESS_ONCE_RW(r->add_ptr) = i; smp_wmb(); if (out) @@ -1032,7 +1044,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, extract_buf(r, tmp); i = min_t(int, nbytes, EXTRACT_SIZE); - if (copy_to_user(buf, tmp, i)) { + if (i > sizeof(tmp) || copy_to_user(buf, tmp, i)) { ret = -EFAULT; break; } @@ -1368,7 +1380,7 @@ EXPORT_SYMBOL(generate_random_uuid); #include static int min_read_thresh = 8, min_write_thresh; -static int max_read_thresh = INPUT_POOL_WORDS * 32; +static int max_read_thresh = OUTPUT_POOL_WORDS * 32; static int max_write_thresh = INPUT_POOL_WORDS * 32; static char sysctl_bootid[16]; @@ -1384,7 +1396,7 @@ static char sysctl_bootid[16]; static int proc_do_uuid(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - ctl_table fake_table; + ctl_table_no_const fake_table; unsigned char buf[64], tmp_uuid[16], *uuid; uuid = table->data; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index bf2349db..5456d53 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -54,6 +54,7 @@ #include #include +#include #include @@ -490,7 +491,7 @@ static struct sonypi_device { spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; struct fasync_struct *fifo_async; - int open_count; + local_t open_count; int model; struct input_dev *input_jog_dev; struct input_dev *input_key_dev; @@ -897,7 +898,7 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on) static int sonypi_misc_release(struct inode *inode, struct file *file) { mutex_lock(&sonypi_device.lock); - sonypi_device.open_count--; + local_dec(&sonypi_device.open_count); mutex_unlock(&sonypi_device.lock); return 0; } @@ -906,9 +907,9 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) { mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ - if (!sonypi_device.open_count) + if (!local_read(&sonypi_device.open_count)) kfifo_reset(&sonypi_device.fifo); - sonypi_device.open_count++; + local_inc(&sonypi_device.open_count); mutex_unlock(&sonypi_device.lock); return 0; diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c index 64420b3..5c40b56 100644 --- a/drivers/char/tpm/tpm_acpi.c +++ b/drivers/char/tpm/tpm_acpi.c @@ -98,11 +98,12 @@ int read_log(struct tpm_bios_log *log) virt = acpi_os_map_memory(start, len); if (!virt) { kfree(log->bios_event_log); + log->bios_event_log = NULL; printk("%s: ERROR - Unable to map memory\n", __func__); return -EIO; } - memcpy_fromio(log->bios_event_log, virt, len); + memcpy_fromio(log->bios_event_log, (const char __force_kernel *)virt, len); acpi_os_unmap_memory(virt, len); return 0; diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c index 84ddc55..1d32f1e 100644 --- a/drivers/char/tpm/tpm_eventlog.c +++ b/drivers/char/tpm/tpm_eventlog.c @@ -95,7 +95,7 @@ static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) event = addr; if ((event->event_type == 0 && event->event_size == 0) || - ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit)) + (event->event_size >= limit - addr - sizeof(struct tcpa_event))) return NULL; return addr; @@ -120,7 +120,7 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v, return NULL; if ((event->event_type == 0 && event->event_size == 0) || - ((v + sizeof(struct tcpa_event) + event->event_size) >= limit)) + (event->event_size >= limit - v - sizeof(struct tcpa_event))) return NULL; (*pos)++; @@ -213,7 +213,8 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) int i; for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) - seq_putc(m, data[i]); + if (!seq_putc(m, data[i])) + return -EFAULT; return 0; } diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index fc45567..fa2a590 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -682,7 +682,7 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, if (to_user) { ssize_t ret; - ret = copy_to_user(out_buf, buf->buf + buf->offset, out_count); + ret = copy_to_user((char __force_user *)out_buf, buf->buf + buf->offset, out_count); if (ret) return -EFAULT; } else { @@ -785,7 +785,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, if (!port_has_data(port) && !port->host_connected) return 0; - return fill_readbuf(port, ubuf, count, true); + return fill_readbuf(port, (char __force_kernel *)ubuf, count, true); } static int wait_port_writable(struct port *port, bool nonblock) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index a33f46f..a720eed 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -122,7 +122,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk *clk; struct clk_init_data init; struct clk_composite *composite; - struct clk_ops *clk_composite_ops; + clk_ops_no_const *clk_composite_ops; composite = kzalloc(sizeof(*composite), GFP_KERNEL); if (!composite) { diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index bd11315..7f87098 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Clock Manager offsets */ #define CLKMGR_CTRL 0x0 @@ -135,8 +136,10 @@ static __init struct clk *socfpga_clk_init(struct device_node *node, if (strcmp(clk_name, "main_pll") || strcmp(clk_name, "periph_pll") || strcmp(clk_name, "sdram_pll")) { socfpga_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; - clk_pll_ops.enable = clk_gate_ops.enable; - clk_pll_ops.disable = clk_gate_ops.disable; + pax_open_kernel(); + *(void **)&clk_pll_ops.enable = clk_gate_ops.enable; + *(void **)&clk_pll_ops.disable = clk_gate_ops.disable; + pax_close_kernel(); } clk = clk_register(NULL, &socfpga_clk->hw.hw); diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index a2b2541..bc1e7ff 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -264,7 +264,7 @@ static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block arch_timer_cpu_nb __cpuinitdata = { +static struct notifier_block arch_timer_cpu_nb = { .notifier_call = arch_timer_cpu_notify, }; diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 350f493..489479e 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -199,7 +199,7 @@ static struct irqaction kona_timer_irq = { .handler = kona_timer_interrupt, }; -static void __init kona_timer_init(void) +static void __init kona_timer_init(struct device_node *np) { kona_timers_init(); kona_timer_clockevents_init(); diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index ade7513..069445f 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c @@ -169,7 +169,7 @@ static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata arch_timer_cpu_nb = { +static struct notifier_block arch_timer_cpu_nb = { .notifier_call = arch_timer_cpu_notify, }; diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index edc089e..bc7c0bc 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -172,7 +172,7 @@ static ssize_t show_global_boost(struct kobject *kobj, return sprintf(buf, "%u\n", boost_enabled); } -static struct global_attr global_boost = __ATTR(boost, 0644, +static global_attr_no_const global_boost = __ATTR(boost, 0644, show_global_boost, store_global_boost); @@ -705,8 +705,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu); per_cpu(acfreq_data, cpu) = data; - if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) - acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; + if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { + pax_open_kernel(); + *(u8 *)&acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_close_kernel(); + } result = acpi_processor_register_performance(data->acpi_data, cpu); if (result) @@ -832,7 +835,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); break; case ACPI_ADR_SPACE_FIXED_HARDWARE: - acpi_cpufreq_driver.get = get_cur_freq_on_cpu; + pax_open_kernel(); + *(void **)&acpi_cpufreq_driver.get = get_cur_freq_on_cpu; + pax_close_kernel(); policy->cur = get_cur_freq_on_cpu(cpu); break; default: @@ -843,8 +848,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) acpi_processor_notify_smm(THIS_MODULE); /* Check for APERF/MPERF support in hardware */ - if (boot_cpu_has(X86_FEATURE_APERFMPERF)) - acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; + if (boot_cpu_has(X86_FEATURE_APERFMPERF)) { + pax_open_kernel(); + *(void **)&acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; + pax_close_kernel(); + } pr_debug("CPU%u - ACPI performance management activated.\n", cpu); for (i = 0; i < perf->state_count; i++) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6485547..477033e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1854,7 +1854,7 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __refdata cpufreq_cpu_notifier = { +static struct notifier_block cpufreq_cpu_notifier = { .notifier_call = cpufreq_cpu_callback, }; @@ -1886,8 +1886,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) pr_debug("trying to register driver %s\n", driver_data->name); - if (driver_data->setpolicy) - driver_data->flags |= CPUFREQ_CONST_LOOPS; + if (driver_data->setpolicy) { + pax_open_kernel(); + *(u8 *)&driver_data->flags |= CPUFREQ_CONST_LOOPS; + pax_close_kernel(); + } write_lock_irqsave(&cpufreq_driver_lock, flags); if (cpufreq_driver) { diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index a86ff72..aad2b03 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -235,7 +235,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, struct dbs_data *dbs_data; struct od_cpu_dbs_info_s *od_dbs_info = NULL; struct cs_cpu_dbs_info_s *cs_dbs_info = NULL; - struct od_ops *od_ops = NULL; + const struct od_ops *od_ops = NULL; struct od_dbs_tuners *od_tuners = NULL; struct cs_dbs_tuners *cs_tuners = NULL; struct cpu_dbs_common_info *cpu_cdbs; @@ -298,7 +298,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, if ((cdata->governor == GOV_CONSERVATIVE) && (!policy->governor->initialized)) { - struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; + const struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; cpufreq_register_notifier(cs_ops->notifier_block, CPUFREQ_TRANSITION_NOTIFIER); @@ -315,7 +315,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, if ((dbs_data->cdata->governor == GOV_CONSERVATIVE) && (policy->governor->initialized == 1)) { - struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; + const struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; cpufreq_unregister_notifier(cs_ops->notifier_block, CPUFREQ_TRANSITION_NOTIFIER); diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 0d9e6be..461fd3b 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -204,7 +204,7 @@ struct common_dbs_data { void (*exit)(struct dbs_data *dbs_data); /* Governor specific ops, see below */ - void *gov_ops; + const void *gov_ops; }; /* Governer Per policy data */ diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index c087347..dad6268 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -615,14 +615,18 @@ void od_register_powersave_bias_handler(unsigned int (*f) (struct cpufreq_policy *, unsigned int, unsigned int), unsigned int powersave_bias) { - od_ops.powersave_bias_target = f; + pax_open_kernel(); + *(void **)&od_ops.powersave_bias_target = f; + pax_close_kernel(); od_set_powersave_bias(powersave_bias); } EXPORT_SYMBOL_GPL(od_register_powersave_bias_handler); void od_unregister_powersave_bias_handler(void) { - od_ops.powersave_bias_target = generic_powersave_bias_target; + pax_open_kernel(); + *(void **)&od_ops.powersave_bias_target = generic_powersave_bias_target; + pax_close_kernel(); od_set_powersave_bias(0); } EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler); diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index bfd6273..e39dd63 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -365,7 +365,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, } /* priority=1 so this will get called before cpufreq_remove_dev */ -static struct notifier_block cpufreq_stat_cpu_notifier __refdata = { +static struct notifier_block cpufreq_stat_cpu_notifier = { .notifier_call = cpufreq_stat_cpu_callback, .priority = 1, }; diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 421ef37..e708530c 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -160,10 +160,14 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) case 0x0F: /* Core Duo */ case 0x16: /* Celeron Core */ case 0x1C: /* Atom */ - p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_open_kernel(); + *(u8 *)&p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_close_kernel(); return speedstep_get_frequency(SPEEDSTEP_CPU_PCORE); case 0x0D: /* Pentium M (Dothan) */ - p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_open_kernel(); + *(u8 *)&p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_close_kernel(); /* fall through */ case 0x09: /* Pentium M (Banias) */ return speedstep_get_frequency(SPEEDSTEP_CPU_PM); @@ -175,7 +179,9 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) /* on P-4s, the TSC runs with constant frequency independent whether * throttling is active or not. */ - p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_open_kernel(); + *(u8 *)&p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_close_kernel(); if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4M) { printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. " diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index c71ee14..7c2e183 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -18,14 +18,12 @@ #include #include -static struct cpufreq_driver *cpufreq_us3_driver; - struct us3_freq_percpu_info { struct cpufreq_frequency_table table[4]; }; /* Indexed by cpu number. */ -static struct us3_freq_percpu_info *us3_freq_table; +static struct us3_freq_percpu_info us3_freq_table[NR_CPUS]; /* UltraSPARC-III has three dividers: 1, 2, and 32. These are controlled * in the Safari config register. @@ -186,12 +184,25 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) static int us3_freq_cpu_exit(struct cpufreq_policy *policy) { - if (cpufreq_us3_driver) - us3_set_cpu_divider_index(policy, 0); + us3_set_cpu_divider_index(policy->cpu, 0); return 0; } +static int __init us3_freq_init(void); +static void __exit us3_freq_exit(void); + +static struct cpufreq_driver cpufreq_us3_driver = { + .init = us3_freq_cpu_init, + .verify = us3_freq_verify, + .target = us3_freq_target, + .get = us3_freq_get, + .exit = us3_freq_cpu_exit, + .owner = THIS_MODULE, + .name = "UltraSPARC-III", + +}; + static int __init us3_freq_init(void) { unsigned long manuf, impl, ver; @@ -208,57 +219,15 @@ static int __init us3_freq_init(void) (impl == CHEETAH_IMPL || impl == CHEETAH_PLUS_IMPL || impl == JAGUAR_IMPL || - impl == PANTHER_IMPL)) { - struct cpufreq_driver *driver; - - ret = -ENOMEM; - driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); - if (!driver) - goto err_out; - - us3_freq_table = kzalloc( - (NR_CPUS * sizeof(struct us3_freq_percpu_info)), - GFP_KERNEL); - if (!us3_freq_table) - goto err_out; - - driver->init = us3_freq_cpu_init; - driver->verify = us3_freq_verify; - driver->target = us3_freq_target; - driver->get = us3_freq_get; - driver->exit = us3_freq_cpu_exit; - driver->owner = THIS_MODULE, - strcpy(driver->name, "UltraSPARC-III"); - - cpufreq_us3_driver = driver; - ret = cpufreq_register_driver(driver); - if (ret) - goto err_out; - - return 0; - -err_out: - if (driver) { - kfree(driver); - cpufreq_us3_driver = NULL; - } - kfree(us3_freq_table); - us3_freq_table = NULL; - return ret; - } + impl == PANTHER_IMPL)) + return cpufreq_register_driver(&cpufreq_us3_driver); return -ENODEV; } static void __exit us3_freq_exit(void) { - if (cpufreq_us3_driver) { - cpufreq_unregister_driver(cpufreq_us3_driver); - kfree(cpufreq_us3_driver); - cpufreq_us3_driver = NULL; - kfree(us3_freq_table); - us3_freq_table = NULL; - } + cpufreq_unregister_driver(&cpufreq_us3_driver); } MODULE_AUTHOR("David S. Miller "); diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 618e6f4..e89d915 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -353,8 +353,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) !cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; - if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) - centrino_driver.flags |= CPUFREQ_CONST_LOOPS; + if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) { + pax_open_kernel(); + *(u8 *)¢rino_driver.flags |= CPUFREQ_CONST_LOOPS; + pax_close_kernel(); + } if (policy->cpu != 0) return -ENODEV; diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index c3a93fe..e808f24 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -254,7 +254,7 @@ static int poll_idle(struct cpuidle_device *dev, static void poll_idle_init(struct cpuidle_driver *drv) { - struct cpuidle_state *state = &drv->states[0]; + cpuidle_state_no_const *state = &drv->states[0]; snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); diff --git a/drivers/cpuidle/governor.c b/drivers/cpuidle/governor.c index ea2f8e7..70ac501 100644 --- a/drivers/cpuidle/governor.c +++ b/drivers/cpuidle/governor.c @@ -87,7 +87,7 @@ int cpuidle_register_governor(struct cpuidle_governor *gov) mutex_lock(&cpuidle_lock); if (__cpuidle_find_governor(gov->name) == NULL) { ret = 0; - list_add_tail(&gov->governor_list, &cpuidle_governors); + pax_list_add_tail((struct list_head *)&gov->governor_list, &cpuidle_governors); if (!cpuidle_curr_governor || cpuidle_curr_governor->rating < gov->rating) cpuidle_switch_governor(gov); @@ -135,7 +135,7 @@ void cpuidle_unregister_governor(struct cpuidle_governor *gov) new_gov = cpuidle_replace_governor(gov->rating); cpuidle_switch_governor(new_gov); } - list_del(&gov->governor_list); + pax_list_del((struct list_head *)&gov->governor_list); mutex_unlock(&cpuidle_lock); } diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 428754a..8bdf9cc 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -131,7 +131,7 @@ static struct attribute *cpuidle_switch_attrs[] = { NULL }; -static struct attribute_group cpuidle_attr_group = { +static attribute_group_no_const cpuidle_attr_group = { .attrs = cpuidle_default_attrs, .name = "cpuidle", }; diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index ebf130e..e32d8a9 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -51,7 +51,7 @@ module_param_string(hifn_pll_ref, hifn_pll_ref, sizeof(hifn_pll_ref), 0444); MODULE_PARM_DESC(hifn_pll_ref, "PLL reference clock (pci[freq] or ext[freq], default ext)"); -static atomic_t hifn_dev_number; +static atomic_unchecked_t hifn_dev_number; #define ACRYPTO_OP_DECRYPT 0 #define ACRYPTO_OP_ENCRYPT 1 @@ -2577,7 +2577,7 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_out_disable_pci_device; snprintf(name, sizeof(name), "hifn%d", - atomic_inc_return(&hifn_dev_number)-1); + atomic_inc_return_unchecked(&hifn_dev_number)-1); err = pci_request_regions(pdev, name); if (err) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 3b36797..db0b0c0 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -477,7 +477,7 @@ struct devfreq *devfreq_add_device(struct device *dev, GFP_KERNEL); devfreq->last_stat_updated = jiffies; - dev_set_name(&devfreq->dev, dev_name(dev)); + dev_set_name(&devfreq->dev, "%s", dev_name(dev)); err = device_register(&devfreq->dev); if (err) { put_device(&devfreq->dev); @@ -588,7 +588,7 @@ int devfreq_add_governor(struct devfreq_governor *governor) goto err_out; } - list_add(&governor->node, &devfreq_governor_list); + pax_list_add((struct list_head *)&governor->node, &devfreq_governor_list); list_for_each_entry(devfreq, &devfreq_list, node) { int ret = 0; @@ -676,7 +676,7 @@ int devfreq_remove_governor(struct devfreq_governor *governor) } } - list_del(&governor->node); + pax_list_del((struct list_head *)&governor->node); err_out: mutex_unlock(&devfreq_list_lock); diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c index b70709b..1d8d02a 100644 --- a/drivers/dma/sh/shdma.c +++ b/drivers/dma/sh/shdma.c @@ -476,7 +476,7 @@ static int sh_dmae_nmi_handler(struct notifier_block *self, return ret; } -static struct notifier_block sh_dmae_nmi_notifier __read_mostly = { +static struct notifier_block sh_dmae_nmi_notifier = { .notifier_call = sh_dmae_nmi_handler, /* Run before NMI debug handler and KGDB */ diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 211021d..201d47f 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -474,9 +474,9 @@ void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev, */ int edac_device_alloc_index(void) { - static atomic_t device_indexes = ATOMIC_INIT(0); + static atomic_unchecked_t device_indexes = ATOMIC_INIT(0); - return atomic_inc_return(&device_indexes) - 1; + return atomic_inc_return_unchecked(&device_indexes) - 1; } EXPORT_SYMBOL_GPL(edac_device_alloc_index); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index c4d700a..0b57abd 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -148,7 +148,7 @@ static const char * const edac_caps[] = { struct dev_ch_attribute { struct device_attribute attr; int channel; -}; +} __do_const; #define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \ struct dev_ch_attribute dev_attr_legacy_##_name = \ @@ -1005,14 +1005,16 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) } if (mci->set_sdram_scrub_rate || mci->get_sdram_scrub_rate) { + pax_open_kernel(); if (mci->get_sdram_scrub_rate) { - dev_attr_sdram_scrub_rate.attr.mode |= S_IRUGO; - dev_attr_sdram_scrub_rate.show = &mci_sdram_scrub_rate_show; + *(umode_t *)&dev_attr_sdram_scrub_rate.attr.mode |= S_IRUGO; + *(void **)&dev_attr_sdram_scrub_rate.show = &mci_sdram_scrub_rate_show; } if (mci->set_sdram_scrub_rate) { - dev_attr_sdram_scrub_rate.attr.mode |= S_IWUSR; - dev_attr_sdram_scrub_rate.store = &mci_sdram_scrub_rate_store; + *(umode_t *)&dev_attr_sdram_scrub_rate.attr.mode |= S_IWUSR; + *(void **)&dev_attr_sdram_scrub_rate.store = &mci_sdram_scrub_rate_store; } + pax_close_kernel(); err = device_create_file(&mci->dev, &dev_attr_sdram_scrub_rate); if (err) { diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index dd370f9..0281629 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -29,7 +29,7 @@ static DEFINE_MUTEX(edac_pci_ctls_mutex); static LIST_HEAD(edac_pci_list); -static atomic_t pci_indexes = ATOMIC_INIT(0); +static atomic_unchecked_t pci_indexes = ATOMIC_INIT(0); /* * edac_pci_alloc_ctl_info @@ -315,7 +315,7 @@ EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period); */ int edac_pci_alloc_index(void) { - return atomic_inc_return(&pci_indexes) - 1; + return atomic_inc_return_unchecked(&pci_indexes) - 1; } EXPORT_SYMBOL_GPL(edac_pci_alloc_index); diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index e8658e4..22746d6 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -26,8 +26,8 @@ static int edac_pci_log_pe = 1; /* log PCI parity errors */ static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */ static int edac_pci_poll_msec = 1000; /* one second workq period */ -static atomic_t pci_parity_count = ATOMIC_INIT(0); -static atomic_t pci_nonparity_count = ATOMIC_INIT(0); +static atomic_unchecked_t pci_parity_count = ATOMIC_INIT(0); +static atomic_unchecked_t pci_nonparity_count = ATOMIC_INIT(0); static struct kobject *edac_pci_top_main_kobj; static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0); @@ -235,7 +235,7 @@ struct edac_pci_dev_attribute { void *value; ssize_t(*show) (void *, char *); ssize_t(*store) (void *, const char *, size_t); -}; +} __do_const; /* Set of show/store abstract level functions for PCI Parity object */ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr, @@ -579,7 +579,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) edac_printk(KERN_CRIT, EDAC_PCI, "Signaled System Error on %s\n", pci_name(dev)); - atomic_inc(&pci_nonparity_count); + atomic_inc_unchecked(&pci_nonparity_count); } if (status & (PCI_STATUS_PARITY)) { @@ -587,7 +587,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) "Master Data Parity Error on %s\n", pci_name(dev)); - atomic_inc(&pci_parity_count); + atomic_inc_unchecked(&pci_parity_count); } if (status & (PCI_STATUS_DETECTED_PARITY)) { @@ -595,7 +595,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) "Detected Parity Error on %s\n", pci_name(dev)); - atomic_inc(&pci_parity_count); + atomic_inc_unchecked(&pci_parity_count); } } @@ -618,7 +618,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " "Signaled System Error on %s\n", pci_name(dev)); - atomic_inc(&pci_nonparity_count); + atomic_inc_unchecked(&pci_nonparity_count); } if (status & (PCI_STATUS_PARITY)) { @@ -626,7 +626,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) "Master Data Parity Error on " "%s\n", pci_name(dev)); - atomic_inc(&pci_parity_count); + atomic_inc_unchecked(&pci_parity_count); } if (status & (PCI_STATUS_DETECTED_PARITY)) { @@ -634,7 +634,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) "Detected Parity Error on %s\n", pci_name(dev)); - atomic_inc(&pci_parity_count); + atomic_inc_unchecked(&pci_parity_count); } } } @@ -672,7 +672,7 @@ void edac_pci_do_parity_check(void) if (!check_pci_errors) return; - before_count = atomic_read(&pci_parity_count); + before_count = atomic_read_unchecked(&pci_parity_count); /* scan all PCI devices looking for a Parity Error on devices and * bridges. @@ -684,7 +684,7 @@ void edac_pci_do_parity_check(void) /* Only if operator has selected panic on PCI Error */ if (edac_pci_get_panic_on_pe()) { /* If the count is different 'after' from 'before' */ - if (before_count != atomic_read(&pci_parity_count)) + if (before_count != atomic_read_unchecked(&pci_parity_count)) panic("EDAC: PCI Parity Error"); } } diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 51b7e3a..aa8a3e8 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h @@ -77,7 +77,7 @@ struct amd_decoder_ops { bool (*mc0_mce)(u16, u8); bool (*mc1_mce)(u16, u8); bool (*mc2_mce)(u16, u8); -}; +} __no_const; void amd_report_gart_errors(bool); void amd_register_ecc_decoder(void (*f)(int, struct mce *)); diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 57ea7f4..af06b76 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -528,9 +528,9 @@ void fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, struct device *device) { - static atomic_t index = ATOMIC_INIT(-1); + static atomic_unchecked_t index = ATOMIC_INIT(-1); - card->index = atomic_inc_return(&index); + card->index = atomic_inc_return_unchecked(&index); card->driver = driver; card->device = device; card->current_tlabel = 0; @@ -680,7 +680,7 @@ EXPORT_SYMBOL_GPL(fw_card_release); void fw_core_remove_card(struct fw_card *card) { - struct fw_card_driver dummy_driver = dummy_driver_template; + fw_card_driver_no_const dummy_driver = dummy_driver_template; card->driver->update_phy_reg(card, 4, PHY_LINK_ACTIVE | PHY_CONTENDER, 0); diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 664a6ff..af13580 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -232,7 +232,7 @@ EXPORT_SYMBOL(fw_device_enable_phys_dma); struct config_rom_attribute { struct device_attribute attr; u32 key; -}; +} __do_const; static ssize_t show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 28a94c7..58da63a 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -38,6 +38,7 @@ #include #include #include +#include #include diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 515a42c..5ecf3ba 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -111,6 +111,7 @@ struct fw_card_driver { int (*stop_iso)(struct fw_iso_context *ctx); }; +typedef struct fw_card_driver __no_const fw_card_driver_no_const; void fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, struct device *device); diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 94a58a0..f5eba42 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -16,7 +16,7 @@ struct dmi_device_attribute{ struct device_attribute dev_attr; int field; -}; +} __do_const; #define to_dmi_dev_attr(_dev_attr) \ container_of(_dev_attr, struct dmi_device_attribute, dev_attr) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b95159b..841ae55 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -497,11 +497,6 @@ void __init dmi_scan_machine(void) } } else { - /* - * no iounmap() for that ioremap(); it would be a no-op, but - * it's so early in setup that sucker gets confused into doing - * what it shouldn't if we actually call it. - */ p = dmi_ioremap(0xF0000, 0x10000); if (p == NULL) goto error; @@ -786,7 +781,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *), if (buf == NULL) return -1; - dmi_table(buf, dmi_len, dmi_num, decode, private_data); + dmi_table((char __force_kernel *)buf, dmi_len, dmi_num, decode, private_data); iounmap(buf); return 0; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 5145fa3..0d3babd 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -65,14 +65,16 @@ static struct attribute_group efi_subsys_attr_group = { }; static struct efivars generic_efivars; -static struct efivar_operations generic_ops; +static efivar_operations_no_const generic_ops __read_only; static int generic_ops_register(void) { - generic_ops.get_variable = efi.get_variable; - generic_ops.set_variable = efi.set_variable; - generic_ops.get_next_variable = efi.get_next_variable; - generic_ops.query_variable_store = efi_query_variable_store; + pax_open_kernel(); + *(void **)&generic_ops.get_variable = efi.get_variable; + *(void **)&generic_ops.set_variable = efi.set_variable; + *(void **)&generic_ops.get_next_variable = efi.get_next_variable; + *(void **)&generic_ops.query_variable_store = efi_query_variable_store; + pax_close_kernel(); return efivars_register(&generic_efivars, &generic_ops, efi_kobj); } diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 8bd1bb6..c48b0c6 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -452,7 +452,7 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) static int create_efivars_bin_attributes(void) { - struct bin_attribute *attr; + bin_attribute_no_const *attr; int error; /* new_var */ diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c index 2a90ba6..07f3733 100644 --- a/drivers/firmware/google/memconsole.c +++ b/drivers/firmware/google/memconsole.c @@ -147,7 +147,9 @@ static int __init memconsole_init(void) if (!found_memconsole()) return -ENODEV; - memconsole_bin_attr.size = memconsole_length; + pax_open_kernel(); + *(size_t *)&memconsole_bin_attr.size = memconsole_length; + pax_close_kernel(); ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr); diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index e16d932..f0206ef 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -69,7 +69,7 @@ struct ichx_desc { /* Some chipsets have quirks, let these use their own request/get */ int (*request)(struct gpio_chip *chip, unsigned offset); int (*get)(struct gpio_chip *chip, unsigned offset); -}; +} __do_const; static struct { spinlock_t lock; diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c index 9902732..64b62dd 100644 --- a/drivers/gpio/gpio-vr41xx.c +++ b/drivers/gpio/gpio-vr41xx.c @@ -204,7 +204,7 @@ static int giu_get_irq(unsigned int irq) printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", maskl, pendl, maskh, pendh); - atomic_inc(&irq_err_count); + atomic_inc_unchecked(&irq_err_count); return -EINVAL; } diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ed1334e..ee0dd42 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -321,7 +321,7 @@ static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, struct drm_crtc *tmp; int crtc_mask = 1; - WARN(!crtc, "checking null crtc?\n"); + BUG_ON(!crtc); dev = crtc->dev; diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 9cc247f..36aa285 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -306,7 +306,7 @@ module_exit(drm_core_exit); /** * Copy and IOCTL return string to user space */ -static int drm_copy_field(char *buf, size_t *buf_len, const char *value) +static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) { int len; @@ -376,7 +376,7 @@ long drm_ioctl(struct file *filp, struct drm_file *file_priv = filp->private_data; struct drm_device *dev; const struct drm_ioctl_desc *ioctl = NULL; - drm_ioctl_t *func; + drm_ioctl_no_const_t func; unsigned int nr = DRM_IOCTL_NR(cmd); int retcode = -EINVAL; char stack_kdata[128]; @@ -389,7 +389,7 @@ long drm_ioctl(struct file *filp, return -ENODEV; atomic_inc(&dev->ioctl_count); - atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); + atomic_inc_unchecked(&dev->counts[_DRM_STAT_IOCTLS]); ++file_priv->ioctl_count; if ((nr >= DRM_CORE_IOCTL_COUNT) && diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 429e07d..e681a2c 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -71,7 +71,7 @@ static int drm_setup(struct drm_device * dev) } for (i = 0; i < ARRAY_SIZE(dev->counts); i++) - atomic_set(&dev->counts[i], 0); + atomic_set_unchecked(&dev->counts[i], 0); dev->sigdata.lock = NULL; @@ -135,7 +135,7 @@ int drm_open(struct inode *inode, struct file *filp) if (drm_device_is_unplugged(dev)) return -ENODEV; - if (!dev->open_count++) + if (local_inc_return(&dev->open_count) == 1) need_setup = 1; mutex_lock(&dev->struct_mutex); old_imapping = inode->i_mapping; @@ -151,7 +151,7 @@ int drm_open(struct inode *inode, struct file *filp) retcode = drm_open_helper(inode, filp, dev); if (retcode) goto err_undo; - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); + atomic_inc_unchecked(&dev->counts[_DRM_STAT_OPENS]); if (need_setup) { retcode = drm_setup(dev); if (retcode) @@ -166,7 +166,7 @@ err_undo: iput(container_of(dev->dev_mapping, struct inode, i_data)); dev->dev_mapping = old_mapping; mutex_unlock(&dev->struct_mutex); - dev->open_count--; + local_dec(&dev->open_count); return retcode; } EXPORT_SYMBOL(drm_open); @@ -441,7 +441,7 @@ int drm_release(struct inode *inode, struct file *filp) mutex_lock(&drm_global_mutex); - DRM_DEBUG("open_count = %d\n", dev->open_count); + DRM_DEBUG("open_count = %ld\n", local_read(&dev->open_count)); if (dev->driver->preclose) dev->driver->preclose(dev, file_priv); @@ -450,10 +450,10 @@ int drm_release(struct inode *inode, struct file *filp) * Begin inline drm_release */ - DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", + DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %ld\n", task_pid_nr(current), (long)old_encode_dev(file_priv->minor->device), - dev->open_count); + local_read(&dev->open_count)); /* Release any auth tokens that might point to this file_priv, (do that under the drm_global_mutex) */ @@ -550,8 +550,8 @@ int drm_release(struct inode *inode, struct file *filp) * End inline drm_release */ - atomic_inc(&dev->counts[_DRM_STAT_CLOSES]); - if (!--dev->open_count) { + atomic_inc_unchecked(&dev->counts[_DRM_STAT_CLOSES]); + if (local_dec_and_test(&dev->open_count)) { if (atomic_read(&dev->ioctl_count)) { DRM_ERROR("Device busy: %d\n", atomic_read(&dev->ioctl_count)); diff --git a/drivers/gpu/drm/drm_global.c b/drivers/gpu/drm/drm_global.c index f731116..629842c 100644 --- a/drivers/gpu/drm/drm_global.c +++ b/drivers/gpu/drm/drm_global.c @@ -36,7 +36,7 @@ struct drm_global_item { struct mutex mutex; void *object; - int refcount; + atomic_t refcount; }; static struct drm_global_item glob[DRM_GLOBAL_NUM]; @@ -49,7 +49,7 @@ void drm_global_init(void) struct drm_global_item *item = &glob[i]; mutex_init(&item->mutex); item->object = NULL; - item->refcount = 0; + atomic_set(&item->refcount, 0); } } @@ -59,7 +59,7 @@ void drm_global_release(void) for (i = 0; i < DRM_GLOBAL_NUM; ++i) { struct drm_global_item *item = &glob[i]; BUG_ON(item->object != NULL); - BUG_ON(item->refcount != 0); + BUG_ON(atomic_read(&item->refcount) != 0); } } @@ -70,7 +70,7 @@ int drm_global_item_ref(struct drm_global_reference *ref) void *object; mutex_lock(&item->mutex); - if (item->refcount == 0) { + if (atomic_read(&item->refcount) == 0) { item->object = kzalloc(ref->size, GFP_KERNEL); if (unlikely(item->object == NULL)) { ret = -ENOMEM; @@ -83,7 +83,7 @@ int drm_global_item_ref(struct drm_global_reference *ref) goto out_err; } - ++item->refcount; + atomic_inc(&item->refcount); ref->object = item->object; object = item->object; mutex_unlock(&item->mutex); @@ -100,9 +100,9 @@ void drm_global_item_unref(struct drm_global_reference *ref) struct drm_global_item *item = &glob[ref->global_type]; mutex_lock(&item->mutex); - BUG_ON(item->refcount == 0); + BUG_ON(atomic_read(&item->refcount) == 0); BUG_ON(ref->object != item->object); - if (--item->refcount == 0) { + if (atomic_dec_and_test(&item->refcount)) { ref->release(ref); item->object = NULL; } diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index d4b20ce..77a8d41 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -75,10 +75,14 @@ int drm_vm_info(struct seq_file *m, void *data) struct drm_local_map *map; struct drm_map_list *r_list; - /* Hardcoded from _DRM_FRAME_BUFFER, - _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and - _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ - const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; + static const char * const types[] = { + [_DRM_FRAME_BUFFER] = "FB", + [_DRM_REGISTERS] = "REG", + [_DRM_SHM] = "SHM", + [_DRM_AGP] = "AGP", + [_DRM_SCATTER_GATHER] = "SG", + [_DRM_CONSISTENT] = "PCI", + [_DRM_GEM] = "GEM" }; const char *type; int i; @@ -89,7 +93,7 @@ int drm_vm_info(struct seq_file *m, void *data) map = r_list->map; if (!map) continue; - if (map->type < 0 || map->type > 5) + if (map->type >= ARRAY_SIZE(types)) type = "??"; else type = types[map->type]; @@ -253,7 +257,11 @@ int drm_vma_info(struct seq_file *m, void *data) vma->vm_flags & VM_MAYSHARE ? 's' : 'p', vma->vm_flags & VM_LOCKED ? 'l' : '-', vma->vm_flags & VM_IO ? 'i' : '-', +#ifdef CONFIG_GRKERNSEC_HIDESYM + 0); +#else vma->vm_pgoff); +#endif #if defined(__i386__) pgprot = pgprot_val(vma->vm_page_prot); diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 2f4c434..dd12cd2 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -457,7 +457,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd, request = compat_alloc_user_space(nbytes); if (!access_ok(VERIFY_WRITE, request, nbytes)) return -EFAULT; - list = (struct drm_buf_desc *) (request + 1); + list = (struct drm_buf_desc __user *) (request + 1); if (__put_user(count, &request->count) || __put_user(list, &request->list)) @@ -518,7 +518,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd, request = compat_alloc_user_space(nbytes); if (!access_ok(VERIFY_WRITE, request, nbytes)) return -EFAULT; - list = (struct drm_buf_pub *) (request + 1); + list = (struct drm_buf_pub __user *) (request + 1); if (__put_user(count, &request->count) || __put_user(list, &request->list)) @@ -1016,7 +1016,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, return 0; } -drm_ioctl_compat_t *drm_compat_ioctls[] = { +drm_ioctl_compat_t drm_compat_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version, [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique, [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap, @@ -1062,7 +1062,6 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = { long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn; int ret; /* Assume that ioctls without an explicit compat routine will just @@ -1072,10 +1071,8 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr >= ARRAY_SIZE(drm_compat_ioctls)) return drm_ioctl(filp, cmd, arg); - fn = drm_compat_ioctls[nr]; - - if (fn != NULL) - ret = (*fn) (filp, cmd, arg); + if (drm_compat_ioctls[nr] != NULL) + ret = (*drm_compat_ioctls[nr]) (filp, cmd, arg); else ret = drm_ioctl(filp, cmd, arg); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index e77bd8b..1571b85 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -252,7 +252,7 @@ int drm_getstats(struct drm_device *dev, void *data, stats->data[i].value = (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0); else - stats->data[i].value = atomic_read(&dev->counts[i]); + stats->data[i].value = atomic_read_unchecked(&dev->counts[i]); stats->data[i].type = dev->types[i]; } diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index d752c96..fe08455 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -86,7 +86,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) if (drm_lock_take(&master->lock, lock->context)) { master->lock.file_priv = file_priv; master->lock.lock_time = jiffies; - atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); + atomic_inc_unchecked(&dev->counts[_DRM_STAT_LOCKS]); break; /* Got lock */ } @@ -157,7 +157,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; } - atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); + atomic_inc_unchecked(&dev->counts[_DRM_STAT_UNLOCKS]); if (drm_lock_free(&master->lock, lock->context)) { /* FIXME: Should really bail out here. */ diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 16f3ec5..b28f9ca 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -501,7 +501,7 @@ void drm_unplug_dev(struct drm_device *dev) drm_device_set_unplugged(dev); - if (dev->open_count == 0) { + if (local_read(&dev->open_count) == 0) { drm_put_dev(dev); } mutex_unlock(&drm_global_mutex); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 0229665..f61329c 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -499,7 +499,7 @@ EXPORT_SYMBOL(drm_sysfs_hotplug_event); int drm_sysfs_device_add(struct drm_minor *minor) { int err; - char *minor_str; + const char *minor_str; minor->kdev.parent = minor->dev->dev; diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 004ecdf..db1f6e0 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -945,8 +945,8 @@ static int i810_dma_vertex(struct drm_device *dev, void *data, dma->buflist[vertex->idx], vertex->discard, vertex->used); - atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]); - atomic_inc(&dev->counts[_DRM_STAT_DMA]); + atomic_add_unchecked(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]); + atomic_inc_unchecked(&dev->counts[_DRM_STAT_DMA]); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; @@ -1106,8 +1106,8 @@ static int i810_dma_mc(struct drm_device *dev, void *data, i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used, mc->last_render); - atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]); - atomic_inc(&dev->counts[_DRM_STAT_DMA]); + atomic_add_unchecked(mc->used, &dev->counts[_DRM_STAT_SECONDARY]); + atomic_inc_unchecked(&dev->counts[_DRM_STAT_DMA]); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index 6e0acad..93c8289 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h @@ -108,8 +108,8 @@ typedef struct drm_i810_private { int page_flipping; wait_queue_head_t irq_queue; - atomic_t irq_received; - atomic_t irq_emitted; + atomic_unchecked_t irq_received; + atomic_unchecked_t irq_emitted; int front_offset; } drm_i810_private_t; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e913d32..4d9b351 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -499,7 +499,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(GTIMR)); } seq_printf(m, "Interrupts received: %d\n", - atomic_read(&dev_priv->irq_received)); + atomic_read_unchecked(&dev_priv->irq_received)); for_each_ring(ring, dev_priv, i) { if (IS_GEN6(dev) || IS_GEN7(dev)) { seq_printf(m, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 17d9b0b..860e6d9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1259,7 +1259,7 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) bool can_switch; spin_lock(&dev->count_lock); - can_switch = (dev->open_count == 0); + can_switch = (local_read(&dev->open_count) == 0); spin_unlock(&dev->count_lock); return can_switch; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 47d8b68..52f5d8d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -916,7 +916,7 @@ typedef struct drm_i915_private { drm_dma_handle_t *status_page_dmah; struct resource mch_res; - atomic_t irq_received; + atomic_unchecked_t irq_received; /* protects the irq masks */ spinlock_t irq_lock; @@ -1813,7 +1813,7 @@ extern struct i2c_adapter *intel_gmbus_get_adapter( struct drm_i915_private *dev_priv, unsigned port); extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); -extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) +static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) { return container_of(adapter, struct intel_gmbus, adapter)->force_bit; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 117ce38..eefd237 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -727,9 +727,9 @@ i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) static int validate_exec_list(struct drm_i915_gem_exec_object2 *exec, - int count) + unsigned int count) { - int i; + unsigned int i; int relocs_total = 0; int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c index 3c59584..500f2e9 100644 --- a/drivers/gpu/drm/i915/i915_ioc32.c +++ b/drivers/gpu/drm/i915/i915_ioc32.c @@ -181,7 +181,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd, (unsigned long)request); } -static drm_ioctl_compat_t *i915_compat_ioctls[] = { +static drm_ioctl_compat_t i915_compat_ioctls[] = { [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer, [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer, [DRM_I915_GETPARAM] = compat_i915_getparam, @@ -202,18 +202,15 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = { long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn = NULL; int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls)) - fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls)) { + drm_ioctl_compat_t fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE]; ret = (*fn) (filp, cmd, arg); - else + } else ret = drm_ioctl(filp, cmd, arg); return ret; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e5e32869..1678f36 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -670,7 +670,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) int pipe; u32 pipe_stats[I915_MAX_PIPES]; - atomic_inc(&dev_priv->irq_received); + atomic_inc_unchecked(&dev_priv->irq_received); while (true) { iir = I915_READ(VLV_IIR); @@ -835,7 +835,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) irqreturn_t ret = IRQ_NONE; int i; - atomic_inc(&dev_priv->irq_received); + atomic_inc_unchecked(&dev_priv->irq_received); /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); @@ -925,7 +925,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier; - atomic_inc(&dev_priv->irq_received); + atomic_inc_unchecked(&dev_priv->irq_received); /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); @@ -2089,7 +2089,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - atomic_set(&dev_priv->irq_received, 0); + atomic_set_unchecked(&dev_priv->irq_received, 0); I915_WRITE(HWSTAM, 0xeffe); @@ -2124,7 +2124,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; - atomic_set(&dev_priv->irq_received, 0); + atomic_set_unchecked(&dev_priv->irq_received, 0); /* VLV magic */ I915_WRITE(VLV_IMR, 0); @@ -2411,7 +2411,7 @@ static void i8xx_irq_preinstall(struct drm_device * dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; - atomic_set(&dev_priv->irq_received, 0); + atomic_set_unchecked(&dev_priv->irq_received, 0); for_each_pipe(pipe) I915_WRITE(PIPESTAT(pipe), 0); @@ -2490,7 +2490,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; - atomic_inc(&dev_priv->irq_received); + atomic_inc_unchecked(&dev_priv->irq_received); iir = I915_READ16(IIR); if (iir == 0) @@ -2565,7 +2565,7 @@ static void i915_irq_preinstall(struct drm_device * dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; - atomic_set(&dev_priv->irq_received, 0); + atomic_set_unchecked(&dev_priv->irq_received, 0); if (I915_HAS_HOTPLUG(dev)) { I915_WRITE(PORT_HOTPLUG_EN, 0); @@ -2664,7 +2664,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; int pipe, ret = IRQ_NONE; - atomic_inc(&dev_priv->irq_received); + atomic_inc_unchecked(&dev_priv->irq_received); iir = I915_READ(IIR); do { @@ -2791,7 +2791,7 @@ static void i965_irq_preinstall(struct drm_device * dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; - atomic_set(&dev_priv->irq_received, 0); + atomic_set_unchecked(&dev_priv->irq_received, 0); I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); @@ -2898,7 +2898,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; - atomic_inc(&dev_priv->irq_received); + atomic_inc_unchecked(&dev_priv->irq_received); iir = I915_READ(IIR); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index eea5982..eeef407 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8935,13 +8935,13 @@ struct intel_quirk { int subsystem_vendor; int subsystem_device; void (*hook)(struct drm_device *dev); -}; +} __do_const; /* For systems that don't have a meaningful PCI subdevice/subvendor ID */ struct intel_dmi_quirk { void (*hook)(struct drm_device *dev); const struct dmi_system_id (*dmi_id_list)[]; -}; +} __do_const; static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) { @@ -8949,18 +8949,20 @@ static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) return 1; } -static const struct intel_dmi_quirk intel_dmi_quirks[] = { +static const struct dmi_system_id intel_dmi_quirks_table[] = { { - .dmi_id_list = &(const struct dmi_system_id[]) { - { - .callback = intel_dmi_reverse_brightness, - .ident = "NCR Corporation", - .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, ""), - }, - }, - { } /* terminating entry */ + .callback = intel_dmi_reverse_brightness, + .ident = "NCR Corporation", + .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, ""), }, + }, + { } /* terminating entry */ +}; + +static const struct intel_dmi_quirk intel_dmi_quirks[] = { + { + .dmi_id_list = &intel_dmi_quirks_table, .hook = quirk_invert_brightness, }, }; diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index 54558a0..2d97005 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -120,9 +120,9 @@ typedef struct drm_mga_private { u32 clear_cmd; u32 maccess; - atomic_t vbl_received; /**< Number of vblanks received. */ + atomic_unchecked_t vbl_received; /**< Number of vblanks received. */ wait_queue_head_t fence_queue; - atomic_t last_fence_retired; + atomic_unchecked_t last_fence_retired; u32 next_fence_to_post; unsigned int fb_cpp; diff --git a/drivers/gpu/drm/mga/mga_ioc32.c b/drivers/gpu/drm/mga/mga_ioc32.c index 709e90d..89a1c0d 100644 --- a/drivers/gpu/drm/mga/mga_ioc32.c +++ b/drivers/gpu/drm/mga/mga_ioc32.c @@ -189,7 +189,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, return 0; } -drm_ioctl_compat_t *mga_compat_ioctls[] = { +drm_ioctl_compat_t mga_compat_ioctls[] = { [DRM_MGA_INIT] = compat_mga_init, [DRM_MGA_GETPARAM] = compat_mga_getparam, [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap, @@ -207,18 +207,15 @@ drm_ioctl_compat_t *mga_compat_ioctls[] = { long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn = NULL; int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) - fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) { + drm_ioctl_compat_t fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE]; ret = (*fn) (filp, cmd, arg); - else + } else ret = drm_ioctl(filp, cmd, arg); return ret; diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c index 598c281..60d590e 100644 --- a/drivers/gpu/drm/mga/mga_irq.c +++ b/drivers/gpu/drm/mga/mga_irq.c @@ -43,7 +43,7 @@ u32 mga_get_vblank_counter(struct drm_device *dev, int crtc) if (crtc != 0) return 0; - return atomic_read(&dev_priv->vbl_received); + return atomic_read_unchecked(&dev_priv->vbl_received); } @@ -59,7 +59,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) /* VBLANK interrupt */ if (status & MGA_VLINEPEN) { MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); - atomic_inc(&dev_priv->vbl_received); + atomic_inc_unchecked(&dev_priv->vbl_received); drm_handle_vblank(dev, 0); handled = 1; } @@ -78,7 +78,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) if ((prim_start & ~0x03) != (prim_end & ~0x03)) MGA_WRITE(MGA_PRIMEND, prim_end); - atomic_inc(&dev_priv->last_fence_retired); + atomic_inc_unchecked(&dev_priv->last_fence_retired); DRM_WAKEUP(&dev_priv->fence_queue); handled = 1; } @@ -129,7 +129,7 @@ int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence) * using fences. */ DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ, - (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) + (((cur_fence = atomic_read_unchecked(&dev_priv->last_fence_retired)) - *sequence) <= (1 << 23))); *sequence = cur_fence; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 6aa2137..fe8dc55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -965,7 +965,7 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_table { const char id; int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); -}; +} __no_const; #define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry }) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index f2b30f8..d0f9a95 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -92,7 +92,7 @@ struct nouveau_drm { struct drm_global_reference mem_global_ref; struct ttm_bo_global_ref bo_global_ref; struct ttm_bo_device bdev; - atomic_t validate_sequence; + atomic_unchecked_t validate_sequence; int (*move)(struct nouveau_channel *, struct ttm_buffer_object *, struct ttm_mem_reg *, struct ttm_mem_reg *); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index b4b4d0c..b7edc15 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -322,7 +322,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, int ret, i; struct nouveau_bo *res_bo = NULL; - sequence = atomic_add_return(1, &drm->ttm.validate_sequence); + sequence = atomic_add_return_unchecked(1, &drm->ttm.validate_sequence); retry: if (++trycnt > 100000) { NV_ERROR(cli, "%s failed and gave up.\n", __func__); @@ -359,7 +359,7 @@ retry: if (ret) { validate_fini(op, NULL); if (unlikely(ret == -EAGAIN)) { - sequence = atomic_add_return(1, &drm->ttm.validate_sequence); + sequence = atomic_add_return_unchecked(1, &drm->ttm.validate_sequence); ret = ttm_bo_reserve_slowpath(&nvbo->bo, true, sequence); if (!ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_ioc32.c b/drivers/gpu/drm/nouveau/nouveau_ioc32.c index 08214bc..9208577 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ioc32.c +++ b/drivers/gpu/drm/nouveau/nouveau_ioc32.c @@ -50,7 +50,7 @@ long nouveau_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn = NULL; + drm_ioctl_compat_t fn = NULL; int ret; if (nr < DRM_COMMAND_BASE) diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 25d3495..d81aaf6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -62,7 +62,7 @@ nouveau_switcheroo_can_switch(struct pci_dev *pdev) bool can_switch; spin_lock(&dev->count_lock); - can_switch = (dev->open_count == 0); + can_switch = (local_read(&dev->open_count) == 0); spin_unlock(&dev->count_lock); return can_switch; } diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 489cb8c..0b8d0d3 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -103,7 +103,7 @@ static void qxl_ttm_global_fini(struct qxl_device *qdev) } } -static struct vm_operations_struct qxl_ttm_vm_ops; +static vm_operations_struct_no_const qxl_ttm_vm_ops __read_only; static const struct vm_operations_struct *ttm_vm_ops; static int qxl_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -147,8 +147,10 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma) return r; if (unlikely(ttm_vm_ops == NULL)) { ttm_vm_ops = vma->vm_ops; + pax_open_kernel(); qxl_ttm_vm_ops = *ttm_vm_ops; qxl_ttm_vm_ops.fault = &qxl_ttm_fault; + pax_close_kernel(); } vma->vm_ops = &qxl_ttm_vm_ops; return 0; @@ -556,25 +558,23 @@ static int qxl_mm_dump_table(struct seq_file *m, void *data) static int qxl_ttm_debugfs_init(struct qxl_device *qdev) { #if defined(CONFIG_DEBUG_FS) - static struct drm_info_list qxl_mem_types_list[QXL_DEBUGFS_MEM_TYPES]; - static char qxl_mem_types_names[QXL_DEBUGFS_MEM_TYPES][32]; - unsigned i; - - for (i = 0; i < QXL_DEBUGFS_MEM_TYPES; i++) { - if (i == 0) - sprintf(qxl_mem_types_names[i], "qxl_mem_mm"); - else - sprintf(qxl_mem_types_names[i], "qxl_surf_mm"); - qxl_mem_types_list[i].name = qxl_mem_types_names[i]; - qxl_mem_types_list[i].show = &qxl_mm_dump_table; - qxl_mem_types_list[i].driver_features = 0; - if (i == 0) - qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_VRAM].priv; - else - qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_PRIV0].priv; + static struct drm_info_list qxl_mem_types_list[QXL_DEBUGFS_MEM_TYPES] = { + { + .name = "qxl_mem_mm", + .show = &qxl_mm_dump_table, + }, + { + .name = "qxl_surf_mm", + .show = &qxl_mm_dump_table, + } + }; - } - return qxl_debugfs_add_files(qdev, qxl_mem_types_list, i); + pax_open_kernel(); + *(void **)&qxl_mem_types_list[0].data = qdev->mman.bdev.man[TTM_PL_VRAM].priv; + *(void **)&qxl_mem_types_list[1].data = qdev->mman.bdev.man[TTM_PL_PRIV0].priv; + pax_close_kernel(); + + return qxl_debugfs_add_files(qdev, qxl_mem_types_list, QXL_DEBUGFS_MEM_TYPES); #else return 0; #endif diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c index d4660cf..70dbe65 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c @@ -377,7 +377,7 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init) /* GH: Simple idle check. */ - atomic_set(&dev_priv->idle_count, 0); + atomic_set_unchecked(&dev_priv->idle_count, 0); /* We don't support anything other than bus-mastering ring mode, * but the ring can be in either AGP or PCI space for the ring diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h index 930c71b..499aded 100644 --- a/drivers/gpu/drm/r128/r128_drv.h +++ b/drivers/gpu/drm/r128/r128_drv.h @@ -90,14 +90,14 @@ typedef struct drm_r128_private { int is_pci; unsigned long cce_buffers_offset; - atomic_t idle_count; + atomic_unchecked_t idle_count; int page_flipping; int current_page; u32 crtc_offset; u32 crtc_offset_cntl; - atomic_t vbl_received; + atomic_unchecked_t vbl_received; u32 color_fmt; unsigned int front_offset; diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c index a954c54..9cc595c 100644 --- a/drivers/gpu/drm/r128/r128_ioc32.c +++ b/drivers/gpu/drm/r128/r128_ioc32.c @@ -177,7 +177,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); } -drm_ioctl_compat_t *r128_compat_ioctls[] = { +drm_ioctl_compat_t r128_compat_ioctls[] = { [DRM_R128_INIT] = compat_r128_init, [DRM_R128_DEPTH] = compat_r128_depth, [DRM_R128_STIPPLE] = compat_r128_stipple, @@ -196,18 +196,15 @@ drm_ioctl_compat_t *r128_compat_ioctls[] = { long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn = NULL; int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls)) - fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls)) { + drm_ioctl_compat_t fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE]; ret = (*fn) (filp, cmd, arg); - else + } else ret = drm_ioctl(filp, cmd, arg); return ret; diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c index 2ea4f09..d391371 100644 --- a/drivers/gpu/drm/r128/r128_irq.c +++ b/drivers/gpu/drm/r128/r128_irq.c @@ -41,7 +41,7 @@ u32 r128_get_vblank_counter(struct drm_device *dev, int crtc) if (crtc != 0) return 0; - return atomic_read(&dev_priv->vbl_received); + return atomic_read_unchecked(&dev_priv->vbl_received); } irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) @@ -55,7 +55,7 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) /* VBLANK interrupt */ if (status & R128_CRTC_VBLANK_INT) { R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); - atomic_inc(&dev_priv->vbl_received); + atomic_inc_unchecked(&dev_priv->vbl_received); drm_handle_vblank(dev, 0); return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c index 19bb7e6..de7e2a2 100644 --- a/drivers/gpu/drm/r128/r128_state.c +++ b/drivers/gpu/drm/r128/r128_state.c @@ -320,10 +320,10 @@ static void r128_clear_box(drm_r128_private_t *dev_priv, static void r128_cce_performance_boxes(drm_r128_private_t *dev_priv) { - if (atomic_read(&dev_priv->idle_count) == 0) + if (atomic_read_unchecked(&dev_priv->idle_count) == 0) r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); else - atomic_set(&dev_priv->idle_count, 0); + atomic_set_unchecked(&dev_priv->idle_count, 0); } #endif diff --git a/drivers/gpu/drm/radeon/mkregtable.c b/drivers/gpu/drm/radeon/mkregtable.c index 5a82b6b..9e69c73 100644 --- a/drivers/gpu/drm/radeon/mkregtable.c +++ b/drivers/gpu/drm/radeon/mkregtable.c @@ -637,14 +637,14 @@ static int parser_auth(struct table *t, const char *filename) regex_t mask_rex; regmatch_t match[4]; char buf[1024]; - size_t end; + long end; int len; int done = 0; int r; unsigned o; struct offset *offset; char last_reg_s[10]; - int last_reg; + unsigned long last_reg; if (regcomp (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) { diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index b0dc0b6..a9bfe9c 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1014,7 +1014,7 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) bool can_switch; spin_lock(&dev->count_lock); - can_switch = (dev->open_count == 0); + can_switch = (local_read(&dev->open_count) == 0); spin_unlock(&dev->count_lock); return can_switch; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index b369d42..8dd04eb 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -258,7 +258,7 @@ typedef struct drm_radeon_private { /* SW interrupt */ wait_queue_head_t swi_queue; - atomic_t swi_emitted; + atomic_unchecked_t swi_emitted; int vblank_crtc; uint32_t irq_enable_reg; uint32_t r500_disp_irq_reg; diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c index c180df8..5fd8186 100644 --- a/drivers/gpu/drm/radeon/radeon_ioc32.c +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c @@ -358,7 +358,7 @@ static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, request = compat_alloc_user_space(sizeof(*request)); if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || __put_user(req32.param, &request->param) - || __put_user((void __user *)(unsigned long)req32.value, + || __put_user((unsigned long)req32.value, &request->value)) return -EFAULT; @@ -368,7 +368,7 @@ static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, #define compat_radeon_cp_setparam NULL #endif /* X86_64 || IA64 */ -static drm_ioctl_compat_t *radeon_compat_ioctls[] = { +static drm_ioctl_compat_t radeon_compat_ioctls[] = { [DRM_RADEON_CP_INIT] = compat_radeon_cp_init, [DRM_RADEON_CLEAR] = compat_radeon_cp_clear, [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple, @@ -393,18 +393,15 @@ static drm_ioctl_compat_t *radeon_compat_ioctls[] = { long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn = NULL; int ret; if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) - fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) + if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) { + drm_ioctl_compat_t fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; ret = (*fn) (filp, cmd, arg); - else + } else ret = drm_ioctl(filp, cmd, arg); return ret; diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index 8d68e97..9dcfed8 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -226,8 +226,8 @@ static int radeon_emit_irq(struct drm_device * dev) unsigned int ret; RING_LOCALS; - atomic_inc(&dev_priv->swi_emitted); - ret = atomic_read(&dev_priv->swi_emitted); + atomic_inc_unchecked(&dev_priv->swi_emitted); + ret = atomic_read_unchecked(&dev_priv->swi_emitted); BEGIN_RING(4); OUT_RING_REG(RADEON_LAST_SWI_REG, ret); @@ -353,7 +353,7 @@ int radeon_driver_irq_postinstall(struct drm_device *dev) drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - atomic_set(&dev_priv->swi_emitted, 0); + atomic_set_unchecked(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); dev->max_vblank_count = 0x001fffff; diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 4d20910..6726b6d 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -2168,7 +2168,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file * if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, + if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS || DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, sarea_priv->nbox * sizeof(depth_boxes[0]))) return -EFAULT; @@ -3031,7 +3031,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_getparam_t *param = data; - int value; + int value = 0; DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 6c0ce89..57a2529 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -782,7 +782,7 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) man->size = size >> PAGE_SHIFT; } -static struct vm_operations_struct radeon_ttm_vm_ops; +static vm_operations_struct_no_const radeon_ttm_vm_ops __read_only; static const struct vm_operations_struct *ttm_vm_ops = NULL; static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -823,8 +823,10 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma) } if (unlikely(ttm_vm_ops == NULL)) { ttm_vm_ops = vma->vm_ops; + pax_open_kernel(); radeon_ttm_vm_ops = *ttm_vm_ops; radeon_ttm_vm_ops.fault = &radeon_ttm_fault; + pax_close_kernel(); } vma->vm_ops = &radeon_ttm_vm_ops; return 0; @@ -853,38 +855,33 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data) static int radeon_ttm_debugfs_init(struct radeon_device *rdev) { #if defined(CONFIG_DEBUG_FS) - static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2]; - static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32]; + static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2] = { + { + .name = "radeon_vram_mm", + .show = &radeon_mm_dump_table, + }, + { + .name = "radeon_gtt_mm", + .show = &radeon_mm_dump_table, + }, + { + .name = "ttm_page_pool", + .show = &ttm_page_alloc_debugfs, + }, + { + .name = "ttm_dma_page_pool", + .show = &ttm_dma_page_alloc_debugfs, + }, + }; unsigned i; - for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) { - if (i == 0) - sprintf(radeon_mem_types_names[i], "radeon_vram_mm"); - else - sprintf(radeon_mem_types_names[i], "radeon_gtt_mm"); - radeon_mem_types_list[i].name = radeon_mem_types_names[i]; - radeon_mem_types_list[i].show = &radeon_mm_dump_table; - radeon_mem_types_list[i].driver_features = 0; - if (i == 0) - radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv; - else - radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv; - - } - /* Add ttm page pool to debugfs */ - sprintf(radeon_mem_types_names[i], "ttm_page_pool"); - radeon_mem_types_list[i].name = radeon_mem_types_names[i]; - radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs; - radeon_mem_types_list[i].driver_features = 0; - radeon_mem_types_list[i++].data = NULL; + pax_open_kernel(); + *(void **)&radeon_mem_types_list[0].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv; + *(void **)&radeon_mem_types_list[1].data = rdev->mman.bdev.man[TTM_PL_TT].priv; + pax_close_kernel(); #ifdef CONFIG_SWIOTLB - if (swiotlb_nr_tbl()) { - sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool"); - radeon_mem_types_list[i].name = radeon_mem_types_names[i]; - radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs; - radeon_mem_types_list[i].driver_features = 0; - radeon_mem_types_list[i++].data = NULL; - } + if (swiotlb_nr_tbl()) + i++; #endif return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i); diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 55880d5..9e95342 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -327,9 +327,11 @@ static void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && rdev->pm.sideport_bandwidth.full) rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; - read_delay_latency.full = dfixed_const(370 * 800 * 1000); + read_delay_latency.full = dfixed_const(800 * 1000); read_delay_latency.full = dfixed_div(read_delay_latency, rdev->pm.igp_sideport_mclk); + a.full = dfixed_const(370); + read_delay_latency.full = dfixed_mul(read_delay_latency, a); } else { if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full && rdev->pm.k8_bandwidth.full) diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index dbc2def..0a9f710 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -264,7 +264,7 @@ static int ttm_mem_init_kernel_zone(struct ttm_mem_global *glob, zone->glob = glob; glob->zone_kernel = zone; ret = kobject_init_and_add( - &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name); + &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, "%s", zone->name); if (unlikely(ret != 0)) { kobject_put(&zone->kobj); return ret; @@ -347,7 +347,7 @@ static int ttm_mem_init_dma32_zone(struct ttm_mem_global *glob, zone->glob = glob; glob->zone_dma32 = zone; ret = kobject_init_and_add( - &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name); + &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, "%s", zone->name); if (unlikely(ret != 0)) { kobject_put(&zone->kobj); return ret; diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index bd2a3b4..122d9ad 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -394,9 +394,9 @@ static int ttm_pool_get_num_unused_pages(void) static int ttm_pool_mm_shrink(struct shrinker *shrink, struct shrink_control *sc) { - static atomic_t start_pool = ATOMIC_INIT(0); + static atomic_unchecked_t start_pool = ATOMIC_INIT(0); unsigned i; - unsigned pool_offset = atomic_add_return(1, &start_pool); + unsigned pool_offset = atomic_add_return_unchecked(1, &start_pool); struct ttm_page_pool *pool; int shrink_pages = sc->nr_to_scan; diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index dc0c065..58a0782 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -367,7 +367,6 @@ static int udl_fb_release(struct fb_info *info, int user) fb_deferred_io_cleanup(info); kfree(info->fbdefio); info->fbdefio = NULL; - info->fbops->fb_mmap = udl_fb_mmap; } pr_warn("released /dev/fb%d user=%d count=%d\n", diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 893a650..6190d3b 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -51,7 +51,7 @@ typedef struct drm_via_ring_buffer { typedef uint32_t maskarray_t[5]; typedef struct drm_via_irq { - atomic_t irq_received; + atomic_unchecked_t irq_received; uint32_t pending_mask; uint32_t enable_mask; wait_queue_head_t irq_queue; @@ -75,7 +75,7 @@ typedef struct drm_via_private { struct timeval last_vblank; int last_vblank_valid; unsigned usec_per_vblank; - atomic_t vbl_received; + atomic_unchecked_t vbl_received; drm_via_state_t hc_state; char pci_buf[VIA_PCI_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index ac98964..5dbf512 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -101,7 +101,7 @@ u32 via_get_vblank_counter(struct drm_device *dev, int crtc) if (crtc != 0) return 0; - return atomic_read(&dev_priv->vbl_received); + return atomic_read_unchecked(&dev_priv->vbl_received); } irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) @@ -116,8 +116,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) status = VIA_READ(VIA_REG_INTERRUPT); if (status & VIA_IRQ_VBLANK_PENDING) { - atomic_inc(&dev_priv->vbl_received); - if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { + atomic_inc_unchecked(&dev_priv->vbl_received); + if (!(atomic_read_unchecked(&dev_priv->vbl_received) & 0x0F)) { do_gettimeofday(&cur_vblank); if (dev_priv->last_vblank_valid) { dev_priv->usec_per_vblank = @@ -127,7 +127,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) dev_priv->last_vblank = cur_vblank; dev_priv->last_vblank_valid = 1; } - if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { + if (!(atomic_read_unchecked(&dev_priv->vbl_received) & 0xFF)) { DRM_DEBUG("US per vblank is: %u\n", dev_priv->usec_per_vblank); } @@ -137,7 +137,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) for (i = 0; i < dev_priv->num_irqs; ++i) { if (status & cur_irq->pending_mask) { - atomic_inc(&cur_irq->irq_received); + atomic_inc_unchecked(&cur_irq->irq_received); DRM_WAKEUP(&cur_irq->irq_queue); handled = 1; if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) @@ -242,11 +242,11 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, ((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4])); - cur_irq_sequence = atomic_read(&cur_irq->irq_received); + cur_irq_sequence = atomic_read_unchecked(&cur_irq->irq_received); } else { DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, (((cur_irq_sequence = - atomic_read(&cur_irq->irq_received)) - + atomic_read_unchecked(&cur_irq->irq_received)) - *sequence) <= (1 << 23))); } *sequence = cur_irq_sequence; @@ -284,7 +284,7 @@ void via_driver_irq_preinstall(struct drm_device *dev) } for (i = 0; i < dev_priv->num_irqs; ++i) { - atomic_set(&cur_irq->irq_received, 0); + atomic_set_unchecked(&cur_irq->irq_received, 0); cur_irq->enable_mask = dev_priv->irq_masks[i][0]; cur_irq->pending_mask = dev_priv->irq_masks[i][1]; DRM_INIT_WAITQUEUE(&cur_irq->irq_queue); @@ -366,7 +366,7 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) { case VIA_IRQ_RELATIVE: irqwait->request.sequence += - atomic_read(&cur_irq->irq_received); + atomic_read_unchecked(&cur_irq->irq_received); irqwait->request.type &= ~_DRM_VBLANK_RELATIVE; case VIA_IRQ_ABSOLUTE: break; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 13aeda7..4a952d1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -290,7 +290,7 @@ struct vmw_private { * Fencing and IRQs. */ - atomic_t marker_seq; + atomic_unchecked_t marker_seq; wait_queue_head_t fence_queue; wait_queue_head_t fifo_queue; int fence_queue_waiters; /* Protected by hw_mutex */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 3eb1486..0a47ee9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -137,7 +137,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) (unsigned int) min, (unsigned int) fifo->capabilities); - atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno); + atomic_set_unchecked(&dev_priv->marker_seq, dev_priv->last_read_seqno); iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE); vmw_marker_queue_init(&fifo->marker_queue); return vmw_fifo_send_fence(dev_priv, &dummy); @@ -355,7 +355,7 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) if (reserveable) iowrite32(bytes, fifo_mem + SVGA_FIFO_RESERVED); - return fifo_mem + (next_cmd >> 2); + return (__le32 __force_kernel *)fifo_mem + (next_cmd >> 2); } else { need_bounce = true; } @@ -475,7 +475,7 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) fm = vmw_fifo_reserve(dev_priv, bytes); if (unlikely(fm == NULL)) { - *seqno = atomic_read(&dev_priv->marker_seq); + *seqno = atomic_read_unchecked(&dev_priv->marker_seq); ret = -ENOMEM; (void)vmw_fallback_wait(dev_priv, false, true, *seqno, false, 3*HZ); @@ -483,7 +483,7 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) } do { - *seqno = atomic_add_return(1, &dev_priv->marker_seq); + *seqno = atomic_add_return_unchecked(1, &dev_priv->marker_seq); } while (*seqno == 0); if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index c509d40..3b640c3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -138,7 +138,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, int ret; num_clips = arg->num_clips; - clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr; + clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr; if (unlikely(num_clips == 0)) return 0; @@ -222,7 +222,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, int ret; num_clips = arg->num_clips; - clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr; + clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr; if (unlikely(num_clips == 0)) return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 4640adb..e1384ed 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -107,7 +107,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv, * emitted. Then the fence is stale and signaled. */ - ret = ((atomic_read(&dev_priv->marker_seq) - seqno) + ret = ((atomic_read_unchecked(&dev_priv->marker_seq) - seqno) > VMW_FENCE_WRAP); return ret; @@ -138,7 +138,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, if (fifo_idle) down_read(&fifo_state->rwsem); - signal_seq = atomic_read(&dev_priv->marker_seq); + signal_seq = atomic_read_unchecked(&dev_priv->marker_seq); ret = 0; for (;;) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c b/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c index 8a8725c2..afed796 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c @@ -151,7 +151,7 @@ int vmw_wait_lag(struct vmw_private *dev_priv, while (!vmw_lag_lt(queue, us)) { spin_lock(&queue->lock); if (list_empty(&queue->head)) - seqno = atomic_read(&dev_priv->marker_seq); + seqno = atomic_read_unchecked(&dev_priv->marker_seq); else { marker = list_first_entry(&queue->head, struct vmw_marker, head); diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c index 8c04943..4370ed9 100644 --- a/drivers/gpu/host1x/drm/dc.c +++ b/drivers/gpu/host1x/drm/dc.c @@ -999,7 +999,7 @@ static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor) } for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) - dc->debugfs_files[i].data = dc; + *(void **)&dc->debugfs_files[i].data = dc; err = drm_debugfs_create_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ed626e0..5340852 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -759,6 +759,56 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) } EXPORT_SYMBOL_GPL(hid_parse_report); +static const char * const hid_report_names[] = { + "HID_INPUT_REPORT", + "HID_OUTPUT_REPORT", + "HID_FEATURE_REPORT", +}; +/** + * hid_validate_report - validate existing device report + * + * @device: hid device + * @type: which report type to examine + * @id: which report ID to examine (0 for first) + * @fields: expected number of fields + * @report_counts: expected number of values per field + * + * Validate the report details after parsing. + */ +struct hid_report *hid_validate_report(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int fields, + unsigned int report_counts) +{ + struct hid_report *report; + unsigned int i; + + if (type > HID_FEATURE_REPORT) { + hid_err(hid, "invalid HID report %u\n", type); + return NULL; + } + + report = hid->report_enum[type].report_id_hash[id]; + if (!report) { + hid_err(hid, "missing %s %u\n", hid_report_names[type], id); + return NULL; + } + if (report->maxfield < fields) { + hid_err(hid, "not enough fields in %s %u\n", + hid_report_names[type], id); + return NULL; + } + for (i = 0; i < fields; i++) { + if (report->field[i]->report_count < report_counts) { + hid_err(hid, "not enough values in %s %u fields\n", + hid_report_names[type], id); + return NULL; + } + } + return report; +} +EXPORT_SYMBOL_GPL(hid_validate_report); + /** * hid_open_report - open a driver-specific device report * @@ -2284,7 +2334,7 @@ EXPORT_SYMBOL_GPL(hid_ignore); int hid_add_device(struct hid_device *hdev) { - static atomic_t id = ATOMIC_INIT(0); + static atomic_unchecked_t id = ATOMIC_INIT(0); int ret; if (WARN_ON(hdev->status & HID_STAT_ADDED)) @@ -2318,7 +2368,7 @@ int hid_add_device(struct hid_device *hdev) /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, - hdev->vendor, hdev->product, atomic_inc_return(&id)); + hdev->vendor, hdev->product, atomic_inc_return_unchecked(&id)); hid_debug_register(hdev, dev_name(&hdev->dev)); ret = device_add(&hdev->dev); diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 07837f5..b697ada 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -341,6 +341,11 @@ static int tpkbd_probe_tp(struct hid_device *hdev) char *name_mute, *name_micmute; int ret; + /* Validate required reports. */ + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 4, 4, 1) || + !hid_validate_report(hdev, HID_OUTPUT_REPORT, 3, 1, 2)) + return -ENODEV; + if (sysfs_create_group(&hdev->dev.kobj, &tpkbd_attr_group_pointer)) { hid_warn(hdev, "Could not create sysfs group\n"); diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index b3cd150..9805197 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; int error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); + /* Check that the report looks ok */ + report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7); + if (!report) return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 1) { - hid_err(hid, "output report is empty\n"); - return -ENODEV; - } - if (report->field[0]->report_count < 7) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); if (!lg2ff) diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index e52f181..53ac79b 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, int x, y; /* - * Maxusage should always be 63 (maximum fields) - * likely a better way to ensure this data is clean + * Available values in the field should always be 63, but we only use up to + * 35. Instead, clear the entire area, however big it is. */ - memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); + memset(report->field[0]->value, 0, + sizeof(__s32) * report->field[0]->report_count); switch (effect->type) { case FF_CONSTANT: @@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = { int lg3ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; const signed short *ff_bits = ff3_joystick_ac; int error; int i; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); - return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } + if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 35)) + return -ENODEV; /* Assume single fixed device G940 */ for (i = 0; ff_bits[i] >= 0; i++) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 0ddae2a..8b89f0f 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde int lg4ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; struct usb_device_descriptor *udesc; int error, i, j; __u16 bcdDevice, rev_maj, rev_min; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); + if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } /* Check what wheel has been connected */ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index d7ea8c8..a84fb40 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) int lgff_init(struct hid_device* hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; const signed short *ff_bits = ff_joystick; int error; int i; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } + if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(devices); i++) { if (dev->id.vendor == devices[i].idVendor && diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 5207591a..6c9197f 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -421,7 +421,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, struct hid_report *report; struct hid_report_enum *output_report_enum; u8 *data = (u8 *)(&dj_report->device_index); - int i; + unsigned int i, length; output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; @@ -431,7 +431,9 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, return -ENODEV; } - for (i = 0; i < report->field[0]->report_count; i++) + length = min_t(size_t, sizeof(*dj_report) - 1, + report->field[0]->report_count); + for (i = 0; i < length; i++) report->field[0]->value[i] = data[i]; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); @@ -738,6 +740,12 @@ static int logi_dj_probe(struct hid_device *hdev, goto hid_parse_fail; } + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, + 1, 3)) { + retval = -ENODEV; + goto hid_parse_fail; + } + /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index d39a5ce..4892dfc 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -330,9 +330,18 @@ static void mt_feature_mapping(struct hid_device *hdev, break; } } + /* Ignore if value index is out of bounds. */ + if (td->inputmode_index < 0 || + td->inputmode_index >= field->report_count) { + dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); + td->inputmode = -1; + } break; case HID_DG_CONTACTMAX: + /* Ignore if value count is out of bounds. */ + if (field->report_count < 1) + break; td->maxcontact_report_id = field->report->id; td->maxcontacts = field->value[0]; if (!td->maxcontacts && @@ -743,15 +752,21 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) unsigned count; int r, n; + if (report->maxfield == 0) + return; + /* * Includes multi-packet support where subsequent * packets are sent with zero contactcount. */ - if (td->cc_index >= 0) { - struct hid_field *field = report->field[td->cc_index]; - int value = field->value[td->cc_value_index]; - if (value) - td->num_expected = value; + if (td->cc_index >= 0 && td->cc_index < report->maxfield) { + field = report->field[td->cc_index]; + if (td->cc_value_index >= 0 && + td->cc_value_index < field->report_count) { + int value = field->value[td->cc_value_index]; + if (value) + td->num_expected = value; + } } for (r = 0; r < report->maxfield; r++) { diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index d164911..ef42e86 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev, goto err_free; } + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 0, 1, 16)) { + ret = -ENODEV; + goto err_free; + } + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { hid_err(hdev, "hw start failed\n"); diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c index 90124ff..3761764 100644 --- a/drivers/hid/hid-wiimote-debug.c +++ b/drivers/hid/hid-wiimote-debug.c @@ -66,7 +66,7 @@ static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, else if (size == 0) return -EIO; - if (copy_to_user(u, buf, size)) + if (size > sizeof(buf) || copy_to_user(u, buf, size)) return -EFAULT; *off += size; diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index 6ec28a3..b124991 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -68,22 +68,12 @@ static int zpff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; int error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); + report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 4, 1); + if (!report) return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 4) { - hid_err(hid, "not enough fields in report\n"); - return -ENODEV; - } zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); if (!zpff) diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index fc307e0..2b255e8 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -47,7 +47,7 @@ struct uhid_device { struct mutex report_lock; wait_queue_head_t report_wait; atomic_t report_done; - atomic_t report_id; + atomic_unchecked_t report_id; struct uhid_event report_buf; }; @@ -187,7 +187,7 @@ static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum, spin_lock_irqsave(&uhid->qlock, flags); ev->type = UHID_FEATURE; - ev->u.feature.id = atomic_inc_return(&uhid->report_id); + ev->u.feature.id = atomic_inc_return_unchecked(&uhid->report_id); ev->u.feature.rnum = rnum; ev->u.feature.rtype = report_type; @@ -471,7 +471,7 @@ static int uhid_dev_feature_answer(struct uhid_device *uhid, spin_lock_irqsave(&uhid->qlock, flags); /* id for old report; drop it silently */ - if (atomic_read(&uhid->report_id) != ev->u.feature_answer.id) + if (atomic_read_unchecked(&uhid->report_id) != ev->u.feature_answer.id) goto unlock; if (atomic_read(&uhid->report_done)) goto unlock; diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 0b122f8..b1d8160 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -394,8 +394,8 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, int ret = 0; int t; - next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle); - atomic_inc(&vmbus_connection.next_gpadl_handle); + next_gpadl_handle = atomic_read_unchecked(&vmbus_connection.next_gpadl_handle); + atomic_inc_unchecked(&vmbus_connection.next_gpadl_handle); ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount); if (ret) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index ae49237..380d4c9 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -112,7 +112,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) u64 output_address = (output) ? virt_to_phys(output) : 0; u32 output_address_hi = output_address >> 32; u32 output_address_lo = output_address & 0xFFFFFFFF; - void *hypercall_page = hv_context.hypercall_page; + void *hypercall_page = ktva_ktla(hv_context.hypercall_page); __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), "=a"(hv_status_lo) : "d" (control_hi), diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index deb5c25..ed2d4fd 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -464,7 +464,7 @@ MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add"); module_param(pressure_report_delay, uint, (S_IRUGO | S_IWUSR)); MODULE_PARM_DESC(pressure_report_delay, "Delay in secs in reporting pressure"); -static atomic_t trans_id = ATOMIC_INIT(0); +static atomic_unchecked_t trans_id = ATOMIC_INIT(0); static int dm_ring_size = (5 * PAGE_SIZE); @@ -825,7 +825,7 @@ static void hot_add_req(struct work_struct *dummy) memset(&resp, 0, sizeof(struct dm_hot_add_response)); resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE; resp.hdr.size = sizeof(struct dm_hot_add_response); - resp.hdr.trans_id = atomic_inc_return(&trans_id); + resp.hdr.trans_id = atomic_inc_return_unchecked(&trans_id); #ifdef CONFIG_MEMORY_HOTPLUG pg_start = dm->ha_wrk.ha_page_range.finfo.start_page; @@ -960,7 +960,7 @@ static void post_status(struct hv_dynmem_device *dm) memset(&status, 0, sizeof(struct dm_status)); status.hdr.type = DM_STATUS_REPORT; status.hdr.size = sizeof(struct dm_status); - status.hdr.trans_id = atomic_inc_return(&trans_id); + status.hdr.trans_id = atomic_inc_return_unchecked(&trans_id); /* * The host expects the guest to report free memory. @@ -980,7 +980,7 @@ static void post_status(struct hv_dynmem_device *dm) * send the status. This can happen if we were interrupted * after we picked our transaction ID. */ - if (status.hdr.trans_id != atomic_read(&trans_id)) + if (status.hdr.trans_id != atomic_read_unchecked(&trans_id)) return; vmbus_sendpacket(dm->dev->channel, &status, @@ -1081,7 +1081,7 @@ static void balloon_up(struct work_struct *dummy) bl_resp = (struct dm_balloon_response *)send_buffer; memset(send_buffer, 0, PAGE_SIZE); bl_resp->hdr.type = DM_BALLOON_RESPONSE; - bl_resp->hdr.trans_id = atomic_inc_return(&trans_id); + bl_resp->hdr.trans_id = atomic_inc_return_unchecked(&trans_id); bl_resp->hdr.size = sizeof(struct dm_balloon_response); bl_resp->more_pages = 1; @@ -1152,7 +1152,7 @@ static void balloon_down(struct hv_dynmem_device *dm, memset(&resp, 0, sizeof(struct dm_unballoon_response)); resp.hdr.type = DM_UNBALLOON_RESPONSE; - resp.hdr.trans_id = atomic_inc_return(&trans_id); + resp.hdr.trans_id = atomic_inc_return_unchecked(&trans_id); resp.hdr.size = sizeof(struct dm_unballoon_response); vmbus_sendpacket(dm_device.dev->channel, &resp, @@ -1215,7 +1215,7 @@ static void version_resp(struct hv_dynmem_device *dm, memset(&version_req, 0, sizeof(struct dm_version_request)); version_req.hdr.type = DM_VERSION_REQUEST; version_req.hdr.size = sizeof(struct dm_version_request); - version_req.hdr.trans_id = atomic_inc_return(&trans_id); + version_req.hdr.trans_id = atomic_inc_return_unchecked(&trans_id); version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN7; version_req.is_last_attempt = 1; @@ -1385,7 +1385,7 @@ static int balloon_probe(struct hv_device *dev, memset(&version_req, 0, sizeof(struct dm_version_request)); version_req.hdr.type = DM_VERSION_REQUEST; version_req.hdr.size = sizeof(struct dm_version_request); - version_req.hdr.trans_id = atomic_inc_return(&trans_id); + version_req.hdr.trans_id = atomic_inc_return_unchecked(&trans_id); version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN8; version_req.is_last_attempt = 0; @@ -1416,7 +1416,7 @@ static int balloon_probe(struct hv_device *dev, memset(&cap_msg, 0, sizeof(struct dm_capabilities)); cap_msg.hdr.type = DM_CAPABILITIES_REPORT; cap_msg.hdr.size = sizeof(struct dm_capabilities); - cap_msg.hdr.trans_id = atomic_inc_return(&trans_id); + cap_msg.hdr.trans_id = atomic_inc_return_unchecked(&trans_id); cap_msg.caps.cap_bits.balloon = 1; cap_msg.caps.cap_bits.hot_add = 1; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 12f2f9e..679603c 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -591,7 +591,7 @@ enum vmbus_connect_state { struct vmbus_connection { enum vmbus_connect_state conn_state; - atomic_t next_gpadl_handle; + atomic_unchecked_t next_gpadl_handle; /* * Represents channel interrupts. Each bit position represents a diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 4004e54..c2de226 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -668,10 +668,10 @@ int vmbus_device_register(struct hv_device *child_device_obj) { int ret = 0; - static atomic_t device_num = ATOMIC_INIT(0); + static atomic_unchecked_t device_num = ATOMIC_INIT(0); dev_set_name(&child_device_obj->device, "vmbus_0_%d", - atomic_inc_return(&device_num)); + atomic_inc_return_unchecked(&device_num)); child_device_obj->device.bus = &hv_bus; child_device_obj->device.parent = &hv_acpi_dev->dev; diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 6351aba..dc4aaf4 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -117,7 +117,7 @@ struct sensor_template { struct device_attribute *devattr, const char *buf, size_t count); int index; -}; +} __do_const; /* Averaging interval */ static int update_avg_interval(struct acpi_power_meter_resource *resource) @@ -629,7 +629,7 @@ static int register_attrs(struct acpi_power_meter_resource *resource, struct sensor_template *attrs) { struct device *dev = &resource->acpi_dev->dev; - struct sensor_device_attribute *sensors = + sensor_device_attribute_no_const *sensors = &resource->sensors[resource->num_sensors]; int res = 0; diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 62c2e32..8f2859a 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1084,7 +1084,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) { struct applesmc_node_group *grp; struct applesmc_dev_attr *node; - struct attribute *attr; + attribute_no_const *attr; int ret, i; for (grp = groups; grp->format; grp++) { diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index b25c643..a13460d 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -152,10 +152,10 @@ MODULE_DEVICE_TABLE(acpi, atk_ids); struct atk_sensor_data { struct list_head list; struct atk_data *data; - struct device_attribute label_attr; - struct device_attribute input_attr; - struct device_attribute limit1_attr; - struct device_attribute limit2_attr; + device_attribute_no_const label_attr; + device_attribute_no_const input_attr; + device_attribute_no_const limit1_attr; + device_attribute_no_const limit2_attr; char label_attr_name[ATTR_NAME_SIZE]; char input_attr_name[ATTR_NAME_SIZE]; char limit1_attr_name[ATTR_NAME_SIZE]; @@ -275,7 +275,7 @@ static ssize_t atk_name_show(struct device *dev, static struct device_attribute atk_name_attr = __ATTR(name, 0444, atk_name_show, NULL); -static void atk_init_attribute(struct device_attribute *attr, char *name, +static void atk_init_attribute(device_attribute_no_const *attr, char *name, sysfs_show_func show) { sysfs_attr_init(&attr->attr); diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 658ce3a..0d0c2f3 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -790,7 +790,7 @@ static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block coretemp_cpu_notifier __refdata = { +static struct notifier_block coretemp_cpu_notifier = { .notifier_call = coretemp_cpu_callback, }; diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 1429f6e..ee03d59 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -926,7 +926,7 @@ static int aem_register_sensors(struct aem_data *data, struct aem_rw_sensor_template *rw) { struct device *dev = &data->pdev->dev; - struct sensor_device_attribute *sensors = data->sensors; + sensor_device_attribute_no_const *sensors = data->sensors; int err; /* Set up read-only sensors */ diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c index 52b77af..aed1ddf 100644 --- a/drivers/hwmon/iio_hwmon.c +++ b/drivers/hwmon/iio_hwmon.c @@ -73,7 +73,7 @@ static int iio_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct iio_hwmon_state *st; - struct sensor_device_attribute *a; + sensor_device_attribute_no_const *a; int ret, i; int in_i = 1, temp_i = 1, curr_i = 1; enum iio_chan_type type; diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 9add6092..ee7ba3f 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -781,7 +781,7 @@ static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) return 0; } -static void pmbus_dev_attr_init(struct device_attribute *dev_attr, +static void pmbus_dev_attr_init(device_attribute_no_const *dev_attr, const char *name, umode_t mode, ssize_t (*show)(struct device *dev, @@ -798,7 +798,7 @@ static void pmbus_dev_attr_init(struct device_attribute *dev_attr, dev_attr->store = store; } -static void pmbus_attr_init(struct sensor_device_attribute *a, +static void pmbus_attr_init(sensor_device_attribute_no_const *a, const char *name, umode_t mode, ssize_t (*show)(struct device *dev, @@ -820,7 +820,7 @@ static int pmbus_add_boolean(struct pmbus_data *data, u16 reg, u8 mask) { struct pmbus_boolean *boolean; - struct sensor_device_attribute *a; + sensor_device_attribute_no_const *a; boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL); if (!boolean) @@ -845,7 +845,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, bool update, bool readonly) { struct pmbus_sensor *sensor; - struct device_attribute *a; + device_attribute_no_const *a; sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); if (!sensor) @@ -876,7 +876,7 @@ static int pmbus_add_label(struct pmbus_data *data, const char *lstring, int index) { struct pmbus_label *label; - struct device_attribute *a; + device_attribute_no_const *a; label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL); if (!label) diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 2507f90..1645765 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -169,7 +169,7 @@ struct sht15_data { int supply_uv; bool supply_uv_valid; struct work_struct update_supply_work; - atomic_t interrupt_handled; + atomic_unchecked_t interrupt_handled; }; /** @@ -542,13 +542,13 @@ static int sht15_measurement(struct sht15_data *data, ret = gpio_direction_input(data->pdata->gpio_data); if (ret) return ret; - atomic_set(&data->interrupt_handled, 0); + atomic_set_unchecked(&data->interrupt_handled, 0); enable_irq(gpio_to_irq(data->pdata->gpio_data)); if (gpio_get_value(data->pdata->gpio_data) == 0) { disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); /* Only relevant if the interrupt hasn't occurred. */ - if (!atomic_read(&data->interrupt_handled)) + if (!atomic_read_unchecked(&data->interrupt_handled)) schedule_work(&data->read_work); } ret = wait_event_timeout(data->wait_queue, @@ -820,7 +820,7 @@ static irqreturn_t sht15_interrupt_fired(int irq, void *d) /* First disable the interrupt */ disable_irq_nosync(irq); - atomic_inc(&data->interrupt_handled); + atomic_inc_unchecked(&data->interrupt_handled); /* Then schedule a reading work struct */ if (data->state != SHT15_READING_NOTHING) schedule_work(&data->read_work); @@ -842,11 +842,11 @@ static void sht15_bh_read_data(struct work_struct *work_s) * If not, then start the interrupt again - care here as could * have gone low in meantime so verify it hasn't! */ - atomic_set(&data->interrupt_handled, 0); + atomic_set_unchecked(&data->interrupt_handled, 0); enable_irq(gpio_to_irq(data->pdata->gpio_data)); /* If still not occurred or another handler was scheduled */ if (gpio_get_value(data->pdata->gpio_data) - || atomic_read(&data->interrupt_handled)) + || atomic_read_unchecked(&data->interrupt_handled)) return; } diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 76f157b..9c0db1b 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -296,7 +296,7 @@ static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block via_cputemp_cpu_notifier __refdata = { +static struct notifier_block via_cputemp_cpu_notifier = { .notifier_call = via_cputemp_cpu_callback, }; diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 07f01ac..d79ad3d 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -43,7 +43,7 @@ extern struct i2c_adapter amd756_smbus; static struct i2c_adapter *s4882_adapter; -static struct i2c_algorithm *s4882_algo; +static i2c_algorithm_no_const *s4882_algo; /* Wrapper access functions for multiplexed SMBus */ static DEFINE_MUTEX(amd756_lock); diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c index 2ca268d..c6acbdf 100644 --- a/drivers/i2c/busses/i2c-nforce2-s4985.c +++ b/drivers/i2c/busses/i2c-nforce2-s4985.c @@ -41,7 +41,7 @@ extern struct i2c_adapter *nforce2_smbus; static struct i2c_adapter *s4985_adapter; -static struct i2c_algorithm *s4985_algo; +static i2c_algorithm_no_const *s4985_algo; /* Wrapper access functions for multiplexed SMBus */ static DEFINE_MUTEX(nforce2_lock); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index c3ccdea..5b3dc1a 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -271,7 +271,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, break; } - data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; + data_ptrs[i] = (u8 __force_user *)rdwr_pa[i].buf; rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); if (IS_ERR(rdwr_pa[i].buf)) { res = PTR_ERR(rdwr_pa[i].buf); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 2ff6204..218c16e 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -768,7 +768,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) alignment = queue_dma_alignment(q) | q->dma_pad_mask; if ((unsigned long)buf & alignment || blk_rq_bytes(rq) & q->dma_pad_mask - || object_is_on_stack(buf)) + || object_starts_on_stack(buf)) drive->dma = 0; } } diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e145931..08bfc59 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -506,7 +506,7 @@ static ssize_t iio_write_channel_info(struct device *dev, } static -int __iio_device_attr_init(struct device_attribute *dev_attr, +int __iio_device_attr_init(device_attribute_no_const *dev_attr, const char *postfix, struct iio_chan_spec const *chan, ssize_t (*readfunc)(struct device *dev, diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 784b97c..c9ceadf 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -114,7 +114,7 @@ static char const counter_group_names[CM_COUNTER_GROUPS] struct cm_counter_group { struct kobject obj; - atomic_long_t counter[CM_ATTR_COUNT]; + atomic_long_unchecked_t counter[CM_ATTR_COUNT]; }; struct cm_counter_attribute { @@ -1395,7 +1395,7 @@ static void cm_dup_req_handler(struct cm_work *work, struct ib_mad_send_buf *msg = NULL; int ret; - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_REQ_COUNTER]); /* Quick state check to discard duplicate REQs. */ @@ -1779,7 +1779,7 @@ static void cm_dup_rep_handler(struct cm_work *work) if (!cm_id_priv) return; - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_REP_COUNTER]); ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg); if (ret) @@ -1946,7 +1946,7 @@ static int cm_rtu_handler(struct cm_work *work) if (cm_id_priv->id.state != IB_CM_REP_SENT && cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) { spin_unlock_irq(&cm_id_priv->lock); - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_RTU_COUNTER]); goto out; } @@ -2129,7 +2129,7 @@ static int cm_dreq_handler(struct cm_work *work) cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id, dreq_msg->local_comm_id); if (!cm_id_priv) { - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_DREQ_COUNTER]); cm_issue_drep(work->port, work->mad_recv_wc); return -EINVAL; @@ -2154,7 +2154,7 @@ static int cm_dreq_handler(struct cm_work *work) case IB_CM_MRA_REP_RCVD: break; case IB_CM_TIMEWAIT: - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_DREQ_COUNTER]); if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg)) goto unlock; @@ -2168,7 +2168,7 @@ static int cm_dreq_handler(struct cm_work *work) cm_free_msg(msg); goto deref; case IB_CM_DREQ_RCVD: - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_DREQ_COUNTER]); goto unlock; default: @@ -2535,7 +2535,7 @@ static int cm_mra_handler(struct cm_work *work) ib_modify_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg, timeout)) { if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD) - atomic_long_inc(&work->port-> + atomic_long_inc_unchecked(&work->port-> counter_group[CM_RECV_DUPLICATES]. counter[CM_MRA_COUNTER]); goto out; @@ -2544,7 +2544,7 @@ static int cm_mra_handler(struct cm_work *work) break; case IB_CM_MRA_REQ_RCVD: case IB_CM_MRA_REP_RCVD: - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_MRA_COUNTER]); /* fall through */ default: @@ -2706,7 +2706,7 @@ static int cm_lap_handler(struct cm_work *work) case IB_CM_LAP_IDLE: break; case IB_CM_MRA_LAP_SENT: - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_LAP_COUNTER]); if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg)) goto unlock; @@ -2722,7 +2722,7 @@ static int cm_lap_handler(struct cm_work *work) cm_free_msg(msg); goto deref; case IB_CM_LAP_RCVD: - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_LAP_COUNTER]); goto unlock; default: @@ -3006,7 +3006,7 @@ static int cm_sidr_req_handler(struct cm_work *work) cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv); if (cur_cm_id_priv) { spin_unlock_irq(&cm.lock); - atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. + atomic_long_inc_unchecked(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_SIDR_REQ_COUNTER]); goto out; /* Duplicate message. */ } @@ -3218,10 +3218,10 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent, if (!msg->context[0] && (attr_index != CM_REJ_COUNTER)) msg->retries = 1; - atomic_long_add(1 + msg->retries, + atomic_long_add_unchecked(1 + msg->retries, &port->counter_group[CM_XMIT].counter[attr_index]); if (msg->retries) - atomic_long_add(msg->retries, + atomic_long_add_unchecked(msg->retries, &port->counter_group[CM_XMIT_RETRIES]. counter[attr_index]); @@ -3431,7 +3431,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, } attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id); - atomic_long_inc(&port->counter_group[CM_RECV]. + atomic_long_inc_unchecked(&port->counter_group[CM_RECV]. counter[attr_id - CM_ATTR_ID_OFFSET]); work = kmalloc(sizeof *work + sizeof(struct ib_sa_path_rec) * paths, @@ -3636,7 +3636,7 @@ static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr, cm_attr = container_of(attr, struct cm_counter_attribute, attr); return sprintf(buf, "%ld\n", - atomic_long_read(&group->counter[cm_attr->index])); + atomic_long_read_unchecked(&group->counter[cm_attr->index])); } static const struct sysfs_ops cm_counter_ops = { diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index 9f5ad7c..588cd84 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c @@ -98,8 +98,8 @@ struct ib_fmr_pool { struct task_struct *thread; - atomic_t req_ser; - atomic_t flush_ser; + atomic_unchecked_t req_ser; + atomic_unchecked_t flush_ser; wait_queue_head_t force_wait; }; @@ -179,10 +179,10 @@ static int ib_fmr_cleanup_thread(void *pool_ptr) struct ib_fmr_pool *pool = pool_ptr; do { - if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) { + if (atomic_read_unchecked(&pool->flush_ser) - atomic_read_unchecked(&pool->req_ser) < 0) { ib_fmr_batch_release(pool); - atomic_inc(&pool->flush_ser); + atomic_inc_unchecked(&pool->flush_ser); wake_up_interruptible(&pool->force_wait); if (pool->flush_function) @@ -190,7 +190,7 @@ static int ib_fmr_cleanup_thread(void *pool_ptr) } set_current_state(TASK_INTERRUPTIBLE); - if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 && + if (atomic_read_unchecked(&pool->flush_ser) - atomic_read_unchecked(&pool->req_ser) >= 0 && !kthread_should_stop()) schedule(); __set_current_state(TASK_RUNNING); @@ -282,8 +282,8 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd, pool->dirty_watermark = params->dirty_watermark; pool->dirty_len = 0; spin_lock_init(&pool->pool_lock); - atomic_set(&pool->req_ser, 0); - atomic_set(&pool->flush_ser, 0); + atomic_set_unchecked(&pool->req_ser, 0); + atomic_set_unchecked(&pool->flush_ser, 0); init_waitqueue_head(&pool->force_wait); pool->thread = kthread_run(ib_fmr_cleanup_thread, @@ -411,11 +411,11 @@ int ib_flush_fmr_pool(struct ib_fmr_pool *pool) } spin_unlock_irq(&pool->pool_lock); - serial = atomic_inc_return(&pool->req_ser); + serial = atomic_inc_return_unchecked(&pool->req_ser); wake_up_process(pool->thread); if (wait_event_interruptible(pool->force_wait, - atomic_read(&pool->flush_ser) - serial >= 0)) + atomic_read_unchecked(&pool->flush_ser) - serial >= 0)) return -EINTR; return 0; @@ -525,7 +525,7 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr) } else { list_add_tail(&fmr->list, &pool->dirty_list); if (++pool->dirty_len >= pool->dirty_watermark) { - atomic_inc(&pool->req_ser); + atomic_inc_unchecked(&pool->req_ser); wake_up_process(pool->thread); } } diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 4cb8eb2..146bf60 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -249,7 +249,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, int err; struct fw_ri_tpte tpt; u32 stag_idx; - static atomic_t key; + static atomic_unchecked_t key; if (c4iw_fatal_error(rdev)) return -EIO; @@ -266,7 +266,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, if (rdev->stats.stag.cur > rdev->stats.stag.max) rdev->stats.stag.max = rdev->stats.stag.cur; mutex_unlock(&rdev->stats.lock); - *stag = (stag_idx << 8) | (atomic_inc_return(&key) & 0xff); + *stag = (stag_idx << 8) | (atomic_inc_return_unchecked(&key) & 0xff); } PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n", __func__, stag_state, type, pdid, stag_idx); diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 79b3dbc..96e5fcc 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -1868,7 +1868,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, struct ib_atomic_eth *ateth; struct ipath_ack_entry *e; u64 vaddr; - atomic64_t *maddr; + atomic64_unchecked_t *maddr; u64 sdata; u32 rkey; u8 next; @@ -1903,11 +1903,11 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, IB_ACCESS_REMOTE_ATOMIC))) goto nack_acc_unlck; /* Perform atomic OP and save result. */ - maddr = (atomic64_t *) qp->r_sge.sge.vaddr; + maddr = (atomic64_unchecked_t *) qp->r_sge.sge.vaddr; sdata = be64_to_cpu(ateth->swap_data); e = &qp->s_ack_queue[qp->r_head_ack_queue]; e->atomic_data = (opcode == OP(FETCH_ADD)) ? - (u64) atomic64_add_return(sdata, maddr) - sdata : + (u64) atomic64_add_return_unchecked(sdata, maddr) - sdata : (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, be64_to_cpu(ateth->compare_data), sdata); diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index 1f95bba..9530f87 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -266,7 +266,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) unsigned long flags; struct ib_wc wc; u64 sdata; - atomic64_t *maddr; + atomic64_unchecked_t *maddr; enum ib_wc_status send_status; /* @@ -382,11 +382,11 @@ again: IB_ACCESS_REMOTE_ATOMIC))) goto acc_err; /* Perform atomic OP and save result. */ - maddr = (atomic64_t *) qp->r_sge.sge.vaddr; + maddr = (atomic64_unchecked_t *) qp->r_sge.sge.vaddr; sdata = wqe->wr.wr.atomic.compare_add; *(u64 *) sqp->s_sge.sge.vaddr = (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) ? - (u64) atomic64_add_return(sdata, maddr) - sdata : + (u64) atomic64_add_return_unchecked(sdata, maddr) - sdata : (u64) cmpxchg((u64 *) qp->r_sge.sge.vaddr, sdata, wqe->wr.wr.atomic.swap); goto send_comp; diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 4d599ce..697b17f 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -98,7 +98,7 @@ __be64 mlx4_ib_gen_node_guid(void) __be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx) { - return cpu_to_be64(atomic_inc_return(&ctx->tid)) | + return cpu_to_be64(atomic_inc_return_unchecked(&ctx->tid)) | cpu_to_be64(0xff00000000000000LL); } diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index f61ec26..ebf72cf 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -398,7 +398,7 @@ struct mlx4_ib_demux_ctx { struct list_head mcg_mgid0_list; struct workqueue_struct *mcg_wq; struct mlx4_ib_demux_pv_ctx **tun; - atomic_t tid; + atomic_unchecked_t tid; int flushing; /* flushing the work queue */ }; diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 9d3e5c1..d9afe4a 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -772,7 +772,7 @@ static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base) mthca_dbg(dev, "Mapped doorbell page for posting FW commands\n"); } -int mthca_QUERY_FW(struct mthca_dev *dev) +int __intentional_overflow(-1) mthca_QUERY_FW(struct mthca_dev *dev) { struct mthca_mailbox *mailbox; u32 *outbox; diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index ed9a989..e0c5871 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -426,7 +426,7 @@ static inline u32 adjust_key(struct mthca_dev *dev, u32 key) return key; } -int mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, +int __intentional_overflow(-1) mthca_mr_alloc(struct mthca_dev *dev, u32 pd, int buffer_size_shift, u64 iova, u64 total_size, u32 access, struct mthca_mr *mr) { struct mthca_mailbox *mailbox; diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 4291410..d2ab1fb 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -98,7 +98,7 @@ MODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes"); LIST_HEAD(nes_adapter_list); static LIST_HEAD(nes_dev_list); -atomic_t qps_destroyed; +atomic_unchecked_t qps_destroyed; static unsigned int ee_flsh_adapter; static unsigned int sysfs_nonidx_addr; @@ -269,7 +269,7 @@ static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_r struct nes_qp *nesqp = cqp_request->cqp_callback_pointer; struct nes_adapter *nesadapter = nesdev->nesadapter; - atomic_inc(&qps_destroyed); + atomic_inc_unchecked(&qps_destroyed); /* Free the control structures */ diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 33cc589..3bd6538 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -177,17 +177,17 @@ extern unsigned int nes_debug_level; extern unsigned int wqm_quanta; extern struct list_head nes_adapter_list; -extern atomic_t cm_connects; -extern atomic_t cm_accepts; -extern atomic_t cm_disconnects; -extern atomic_t cm_closes; -extern atomic_t cm_connecteds; -extern atomic_t cm_connect_reqs; -extern atomic_t cm_rejects; -extern atomic_t mod_qp_timouts; -extern atomic_t qps_created; -extern atomic_t qps_destroyed; -extern atomic_t sw_qps_destroyed; +extern atomic_unchecked_t cm_connects; +extern atomic_unchecked_t cm_accepts; +extern atomic_unchecked_t cm_disconnects; +extern atomic_unchecked_t cm_closes; +extern atomic_unchecked_t cm_connecteds; +extern atomic_unchecked_t cm_connect_reqs; +extern atomic_unchecked_t cm_rejects; +extern atomic_unchecked_t mod_qp_timouts; +extern atomic_unchecked_t qps_created; +extern atomic_unchecked_t qps_destroyed; +extern atomic_unchecked_t sw_qps_destroyed; extern u32 mh_detected; extern u32 mh_pauses_sent; extern u32 cm_packets_sent; @@ -196,16 +196,16 @@ extern u32 cm_packets_created; extern u32 cm_packets_received; extern u32 cm_packets_dropped; extern u32 cm_packets_retrans; -extern atomic_t cm_listens_created; -extern atomic_t cm_listens_destroyed; +extern atomic_unchecked_t cm_listens_created; +extern atomic_unchecked_t cm_listens_destroyed; extern u32 cm_backlog_drops; -extern atomic_t cm_loopbacks; -extern atomic_t cm_nodes_created; -extern atomic_t cm_nodes_destroyed; -extern atomic_t cm_accel_dropped_pkts; -extern atomic_t cm_resets_recvd; -extern atomic_t pau_qps_created; -extern atomic_t pau_qps_destroyed; +extern atomic_unchecked_t cm_loopbacks; +extern atomic_unchecked_t cm_nodes_created; +extern atomic_unchecked_t cm_nodes_destroyed; +extern atomic_unchecked_t cm_accel_dropped_pkts; +extern atomic_unchecked_t cm_resets_recvd; +extern atomic_unchecked_t pau_qps_created; +extern atomic_unchecked_t pau_qps_destroyed; extern u32 int_mod_timer_init; extern u32 int_mod_cq_depth_256; diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 24b9f1a..00fd004 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -68,14 +68,14 @@ u32 cm_packets_dropped; u32 cm_packets_retrans; u32 cm_packets_created; u32 cm_packets_received; -atomic_t cm_listens_created; -atomic_t cm_listens_destroyed; +atomic_unchecked_t cm_listens_created; +atomic_unchecked_t cm_listens_destroyed; u32 cm_backlog_drops; -atomic_t cm_loopbacks; -atomic_t cm_nodes_created; -atomic_t cm_nodes_destroyed; -atomic_t cm_accel_dropped_pkts; -atomic_t cm_resets_recvd; +atomic_unchecked_t cm_loopbacks; +atomic_unchecked_t cm_nodes_created; +atomic_unchecked_t cm_nodes_destroyed; +atomic_unchecked_t cm_accel_dropped_pkts; +atomic_unchecked_t cm_resets_recvd; static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *); static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *); @@ -148,13 +148,13 @@ static struct nes_cm_ops nes_cm_api = { static struct nes_cm_core *g_cm_core; -atomic_t cm_connects; -atomic_t cm_accepts; -atomic_t cm_disconnects; -atomic_t cm_closes; -atomic_t cm_connecteds; -atomic_t cm_connect_reqs; -atomic_t cm_rejects; +atomic_unchecked_t cm_connects; +atomic_unchecked_t cm_accepts; +atomic_unchecked_t cm_disconnects; +atomic_unchecked_t cm_closes; +atomic_unchecked_t cm_connecteds; +atomic_unchecked_t cm_connect_reqs; +atomic_unchecked_t cm_rejects; int nes_add_ref_cm_node(struct nes_cm_node *cm_node) { @@ -1272,7 +1272,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, kfree(listener); listener = NULL; ret = 0; - atomic_inc(&cm_listens_destroyed); + atomic_inc_unchecked(&cm_listens_destroyed); } else { spin_unlock_irqrestore(&cm_core->listen_list_lock, flags); } @@ -1466,7 +1466,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, cm_node->rem_mac); add_hte_node(cm_core, cm_node); - atomic_inc(&cm_nodes_created); + atomic_inc_unchecked(&cm_nodes_created); return cm_node; } @@ -1524,7 +1524,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core, } atomic_dec(&cm_core->node_cnt); - atomic_inc(&cm_nodes_destroyed); + atomic_inc_unchecked(&cm_nodes_destroyed); nesqp = cm_node->nesqp; if (nesqp) { nesqp->cm_node = NULL; @@ -1588,7 +1588,7 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, static void drop_packet(struct sk_buff *skb) { - atomic_inc(&cm_accel_dropped_pkts); + atomic_inc_unchecked(&cm_accel_dropped_pkts); dev_kfree_skb_any(skb); } @@ -1651,7 +1651,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, { int reset = 0; /* whether to send reset in case of err.. */ - atomic_inc(&cm_resets_recvd); + atomic_inc_unchecked(&cm_resets_recvd); nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u." " refcnt=%d\n", cm_node, cm_node->state, atomic_read(&cm_node->ref_count)); @@ -2292,7 +2292,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core, rem_ref_cm_node(cm_node->cm_core, cm_node); return NULL; } - atomic_inc(&cm_loopbacks); + atomic_inc_unchecked(&cm_loopbacks); loopbackremotenode->loopbackpartner = cm_node; loopbackremotenode->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE; @@ -2567,7 +2567,7 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp); else { rem_ref_cm_node(cm_core, cm_node); - atomic_inc(&cm_accel_dropped_pkts); + atomic_inc_unchecked(&cm_accel_dropped_pkts); dev_kfree_skb_any(skb); } break; @@ -2875,7 +2875,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) if ((cm_id) && (cm_id->event_handler)) { if (issue_disconn) { - atomic_inc(&cm_disconnects); + atomic_inc_unchecked(&cm_disconnects); cm_event.event = IW_CM_EVENT_DISCONNECT; cm_event.status = disconn_status; cm_event.local_addr = cm_id->local_addr; @@ -2897,7 +2897,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) } if (issue_close) { - atomic_inc(&cm_closes); + atomic_inc_unchecked(&cm_closes); nes_disconnect(nesqp, 1); cm_id->provider_data = nesqp; @@ -3033,7 +3033,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu listener = %p\n", nesqp->hwqp.qp_id, cm_node, jiffies, cm_node->listener); - atomic_inc(&cm_accepts); + atomic_inc_unchecked(&cm_accepts); nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", netdev_refcnt_read(nesvnic->netdev)); @@ -3228,7 +3228,7 @@ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) struct nes_cm_core *cm_core; u8 *start_buff; - atomic_inc(&cm_rejects); + atomic_inc_unchecked(&cm_rejects); cm_node = (struct nes_cm_node *)cm_id->provider_data; loopback = cm_node->loopbackpartner; cm_core = cm_node->cm_core; @@ -3288,7 +3288,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ntohl(cm_id->local_addr.sin_addr.s_addr), ntohs(cm_id->local_addr.sin_port)); - atomic_inc(&cm_connects); + atomic_inc_unchecked(&cm_connects); nesqp->active_conn = 1; /* cache the cm_id in the qp */ @@ -3398,7 +3398,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog) g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node); return err; } - atomic_inc(&cm_listens_created); + atomic_inc_unchecked(&cm_listens_created); } cm_id->add_ref(cm_id); @@ -3499,7 +3499,7 @@ static void cm_event_connected(struct nes_cm_event *event) if (nesqp->destroyed) return; - atomic_inc(&cm_connecteds); + atomic_inc_unchecked(&cm_connecteds); nes_debug(NES_DBG_CM, "QP%u attempting to connect to 0x%08X:0x%04X on" " local port 0x%04X. jiffies = %lu.\n", nesqp->hwqp.qp_id, @@ -3679,7 +3679,7 @@ static void cm_event_reset(struct nes_cm_event *event) cm_id->add_ref(cm_id); ret = cm_id->event_handler(cm_id, &cm_event); - atomic_inc(&cm_closes); + atomic_inc_unchecked(&cm_closes); cm_event.event = IW_CM_EVENT_CLOSE; cm_event.status = 0; cm_event.provider_data = cm_id->provider_data; @@ -3715,7 +3715,7 @@ static void cm_event_mpa_req(struct nes_cm_event *event) return; cm_id = cm_node->cm_id; - atomic_inc(&cm_connect_reqs); + atomic_inc_unchecked(&cm_connect_reqs); nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", cm_node, cm_id, jiffies); @@ -3755,7 +3755,7 @@ static void cm_event_mpa_reject(struct nes_cm_event *event) return; cm_id = cm_node->cm_id; - atomic_inc(&cm_connect_reqs); + atomic_inc_unchecked(&cm_connect_reqs); nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n", cm_node, cm_id, jiffies); diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c index 4166452..fc952c3 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.c +++ b/drivers/infiniband/hw/nes/nes_mgt.c @@ -40,8 +40,8 @@ #include "nes.h" #include "nes_mgt.h" -atomic_t pau_qps_created; -atomic_t pau_qps_destroyed; +atomic_unchecked_t pau_qps_created; +atomic_unchecked_t pau_qps_destroyed; static void nes_replenish_mgt_rq(struct nes_vnic_mgt *mgtvnic) { @@ -621,7 +621,7 @@ void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp) { struct sk_buff *skb; unsigned long flags; - atomic_inc(&pau_qps_destroyed); + atomic_inc_unchecked(&pau_qps_destroyed); /* Free packets that have not yet been forwarded */ /* Lock is acquired by skb_dequeue when removing the skb */ @@ -810,7 +810,7 @@ static void nes_mgt_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq * cq->cq_vbase[head].cqe_words[NES_NIC_CQE_HASH_RCVNXT]); skb_queue_head_init(&nesqp->pau_list); spin_lock_init(&nesqp->pau_lock); - atomic_inc(&pau_qps_created); + atomic_inc_unchecked(&pau_qps_created); nes_change_quad_hash(nesdev, mgtvnic->nesvnic, nesqp); } diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 49eb511..a774366 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1273,39 +1273,39 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev, target_stat_values[++index] = mh_detected; target_stat_values[++index] = mh_pauses_sent; target_stat_values[++index] = nesvnic->endnode_ipv4_tcp_retransmits; - target_stat_values[++index] = atomic_read(&cm_connects); - target_stat_values[++index] = atomic_read(&cm_accepts); - target_stat_values[++index] = atomic_read(&cm_disconnects); - target_stat_values[++index] = atomic_read(&cm_connecteds); - target_stat_values[++index] = atomic_read(&cm_connect_reqs); - target_stat_values[++index] = atomic_read(&cm_rejects); - target_stat_values[++index] = atomic_read(&mod_qp_timouts); - target_stat_values[++index] = atomic_read(&qps_created); - target_stat_values[++index] = atomic_read(&sw_qps_destroyed); - target_stat_values[++index] = atomic_read(&qps_destroyed); - target_stat_values[++index] = atomic_read(&cm_closes); + target_stat_values[++index] = atomic_read_unchecked(&cm_connects); + target_stat_values[++index] = atomic_read_unchecked(&cm_accepts); + target_stat_values[++index] = atomic_read_unchecked(&cm_disconnects); + target_stat_values[++index] = atomic_read_unchecked(&cm_connecteds); + target_stat_values[++index] = atomic_read_unchecked(&cm_connect_reqs); + target_stat_values[++index] = atomic_read_unchecked(&cm_rejects); + target_stat_values[++index] = atomic_read_unchecked(&mod_qp_timouts); + target_stat_values[++index] = atomic_read_unchecked(&qps_created); + target_stat_values[++index] = atomic_read_unchecked(&sw_qps_destroyed); + target_stat_values[++index] = atomic_read_unchecked(&qps_destroyed); + target_stat_values[++index] = atomic_read_unchecked(&cm_closes); target_stat_values[++index] = cm_packets_sent; target_stat_values[++index] = cm_packets_bounced; target_stat_values[++index] = cm_packets_created; target_stat_values[++index] = cm_packets_received; target_stat_values[++index] = cm_packets_dropped; target_stat_values[++index] = cm_packets_retrans; - target_stat_values[++index] = atomic_read(&cm_listens_created); - target_stat_values[++index] = atomic_read(&cm_listens_destroyed); + target_stat_values[++index] = atomic_read_unchecked(&cm_listens_created); + target_stat_values[++index] = atomic_read_unchecked(&cm_listens_destroyed); target_stat_values[++index] = cm_backlog_drops; - target_stat_values[++index] = atomic_read(&cm_loopbacks); - target_stat_values[++index] = atomic_read(&cm_nodes_created); - target_stat_values[++index] = atomic_read(&cm_nodes_destroyed); - target_stat_values[++index] = atomic_read(&cm_accel_dropped_pkts); - target_stat_values[++index] = atomic_read(&cm_resets_recvd); + target_stat_values[++index] = atomic_read_unchecked(&cm_loopbacks); + target_stat_values[++index] = atomic_read_unchecked(&cm_nodes_created); + target_stat_values[++index] = atomic_read_unchecked(&cm_nodes_destroyed); + target_stat_values[++index] = atomic_read_unchecked(&cm_accel_dropped_pkts); + target_stat_values[++index] = atomic_read_unchecked(&cm_resets_recvd); target_stat_values[++index] = nesadapter->free_4kpbl; target_stat_values[++index] = nesadapter->free_256pbl; target_stat_values[++index] = int_mod_timer_init; target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated; target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed; target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc; - target_stat_values[++index] = atomic_read(&pau_qps_created); - target_stat_values[++index] = atomic_read(&pau_qps_destroyed); + target_stat_values[++index] = atomic_read_unchecked(&pau_qps_created); + target_stat_values[++index] = atomic_read_unchecked(&pau_qps_destroyed); } /** diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 8f67fe2..8960859 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -46,9 +46,9 @@ #include -atomic_t mod_qp_timouts; -atomic_t qps_created; -atomic_t sw_qps_destroyed; +atomic_unchecked_t mod_qp_timouts; +atomic_unchecked_t qps_created; +atomic_unchecked_t sw_qps_destroyed; static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev); @@ -1134,7 +1134,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, if (init_attr->create_flags) return ERR_PTR(-EINVAL); - atomic_inc(&qps_created); + atomic_inc_unchecked(&qps_created); switch (init_attr->qp_type) { case IB_QPT_RC: if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) { @@ -1465,7 +1465,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp) struct iw_cm_event cm_event; int ret = 0; - atomic_inc(&sw_qps_destroyed); + atomic_inc_unchecked(&sw_qps_destroyed); nesqp->destroyed = 1; /* Blow away the connection if it exists. */ diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 4d11575..3e890e5 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -51,6 +51,7 @@ #include #include #include +#include #include "qib_common.h" #include "qib_verbs.h" diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index da739d9..da1c7f4 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -487,14 +487,14 @@ EXPORT_SYMBOL(gameport_set_phys); */ static void gameport_init_port(struct gameport *gameport) { - static atomic_t gameport_no = ATOMIC_INIT(0); + static atomic_unchecked_t gameport_no = ATOMIC_INIT(0); __module_get(THIS_MODULE); mutex_init(&gameport->drv_mutex); device_initialize(&gameport->dev); dev_set_name(&gameport->dev, "gameport%lu", - (unsigned long)atomic_inc_return(&gameport_no) - 1); + (unsigned long)atomic_inc_return_unchecked(&gameport_no) - 1); gameport->dev.bus = &gameport_bus; gameport->dev.release = gameport_release_port; if (gameport->parent) diff --git a/drivers/input/input.c b/drivers/input/input.c index c044699..174d71a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -2019,7 +2019,7 @@ static void devm_input_device_unregister(struct device *dev, void *res) */ int input_register_device(struct input_dev *dev) { - static atomic_t input_no = ATOMIC_INIT(0); + static atomic_unchecked_t input_no = ATOMIC_INIT(0); struct input_devres *devres = NULL; struct input_handler *handler; unsigned int packet_size; @@ -2074,7 +2074,7 @@ int input_register_device(struct input_dev *dev) dev->setkeycode = input_default_setkeycode; dev_set_name(&dev->dev, "input%ld", - (unsigned long) atomic_inc_return(&input_no) - 1); + (unsigned long) atomic_inc_return_unchecked(&input_no) - 1); error = device_add(&dev->dev); if (error) diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 04c69af..5f92d00 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index fa061d4..4a6957c 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -735,7 +735,7 @@ static void xpad_led_set(struct led_classdev *led_cdev, static int xpad_led_probe(struct usb_xpad *xpad) { - static atomic_t led_seq = ATOMIC_INIT(0); + static atomic_unchecked_t led_seq = ATOMIC_INIT(0); long led_no; struct xpad_led *led; struct led_classdev *led_cdev; @@ -748,7 +748,7 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (!led) return -ENOMEM; - led_no = (long)atomic_inc_return(&led_seq) - 1; + led_no = (long)atomic_inc_return_unchecked(&led_seq) - 1; snprintf(led->name, sizeof(led->name), "xpad%ld", led_no); led->xpad = xpad; diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index e204f26..8459f15 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1621,7 +1621,7 @@ static int ims_pcu_identify_type(struct ims_pcu *pcu, u8 *device_id) static int ims_pcu_init_application_mode(struct ims_pcu *pcu) { - static atomic_t device_no = ATOMIC_INIT(0); + static atomic_unchecked_t device_no = ATOMIC_INIT(0); const struct ims_pcu_device_info *info; u8 device_id; @@ -1653,7 +1653,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) } /* Device appears to be operable, complete initialization */ - pcu->device_no = atomic_inc_return(&device_no) - 1; + pcu->device_no = atomic_inc_return_unchecked(&device_no) - 1; error = ims_pcu_setup_backlight(pcu); if (error) diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 2f0b39d..7370f13 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -116,7 +116,7 @@ struct psmouse_attribute { ssize_t (*set)(struct psmouse *psmouse, void *data, const char *buf, size_t count); bool protect; -}; +} __do_const; #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr, diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 4c842c3..590b0bf 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -738,7 +738,7 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, spin_unlock_irq(&client->packet_lock); - if (copy_to_user(buffer, data, count)) + if (count > sizeof(data) || copy_to_user(buffer, data, count)) return -EFAULT; return count; diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 25fc597..558bf3b3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -496,7 +496,7 @@ static void serio_release_port(struct device *dev) */ static void serio_init_port(struct serio *serio) { - static atomic_t serio_no = ATOMIC_INIT(0); + static atomic_unchecked_t serio_no = ATOMIC_INIT(0); __module_get(THIS_MODULE); @@ -507,7 +507,7 @@ static void serio_init_port(struct serio *serio) mutex_init(&serio->drv_mutex); device_initialize(&serio->dev); dev_set_name(&serio->dev, "serio%ld", - (long)atomic_inc_return(&serio_no) - 1); + (long)atomic_inc_return_unchecked(&serio_no) - 1); serio->dev.bus = &serio_bus; serio->dev.release = serio_release_port; serio->dev.groups = serio_device_attr_groups; diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 59df2e7..8f1cafb 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -293,7 +293,7 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data, static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) { - static atomic_t serio_raw_no = ATOMIC_INIT(0); + static atomic_unchecked_t serio_raw_no = ATOMIC_INIT(0); struct serio_raw *serio_raw; int err; @@ -304,7 +304,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) } snprintf(serio_raw->name, sizeof(serio_raw->name), - "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1); + "serio_raw%ld", (long)atomic_inc_return_unchecked(&serio_raw_no) - 1); kref_init(&serio_raw->kref); INIT_LIST_HEAD(&serio_raw->client_list); init_waitqueue_head(&serio_raw->wait); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d8f98b1..f62a640 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -583,7 +583,7 @@ static struct notifier_block iommu_bus_nb = { static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) { bus_register_notifier(bus, &iommu_bus_nb); - bus_for_each_dev(bus, NULL, ops, add_iommu_group); + bus_for_each_dev(bus, NULL, (void *)ops, add_iommu_group); } /** diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index dcfea4e..f4226b2 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -354,7 +354,7 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) void panic_if_irq_remap(const char *msg) { if (irq_remapping_enabled) - panic(msg); + panic("%s", msg); } static void ir_ack_apic_edge(struct irq_data *data) @@ -375,10 +375,12 @@ static void ir_print_prefix(struct irq_data *data, struct seq_file *p) void irq_remap_modify_chip_defaults(struct irq_chip *chip) { - chip->irq_print_chip = ir_print_prefix; - chip->irq_ack = ir_ack_apic_edge; - chip->irq_eoi = ir_ack_apic_level; - chip->irq_set_affinity = x86_io_apic_ops.set_affinity; + pax_open_kernel(); + *(void **)&chip->irq_print_chip = ir_print_prefix; + *(void **)&chip->irq_ack = ir_ack_apic_edge; + *(void **)&chip->irq_eoi = ir_ack_apic_level; + *(void **)&chip->irq_set_affinity = x86_io_apic_ops.set_affinity; + pax_close_kernel(); } bool setup_remapped_irq(int irq, struct irq_cfg *cfg, struct irq_chip *chip) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 19ceaa6..3625818 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -84,7 +84,7 @@ static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly; * Supported arch specific GIC irq extension. * Default make them NULL. */ -struct irq_chip gic_arch_extn = { +irq_chip_no_const gic_arch_extn = { .irq_eoi = NULL, .irq_mask = NULL, .irq_unmask = NULL, @@ -333,7 +333,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_exit(chip, desc); } -static struct irq_chip gic_chip = { +static irq_chip_no_const gic_chip __read_only = { .name = "GIC", .irq_mask = gic_mask_irq, .irq_unmask = gic_unmask_irq, diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index ac6f72b..81150f2 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -81,8 +81,8 @@ struct capiminor { struct capi20_appl *ap; u32 ncci; - atomic_t datahandle; - atomic_t msgid; + atomic_unchecked_t datahandle; + atomic_unchecked_t msgid; struct tty_port port; int ttyinstop; @@ -391,7 +391,7 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) capimsg_setu16(s, 2, mp->ap->applid); capimsg_setu8 (s, 4, CAPI_DATA_B3); capimsg_setu8 (s, 5, CAPI_RESP); - capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid)); + capimsg_setu16(s, 6, atomic_inc_return_unchecked(&mp->msgid)); capimsg_setu32(s, 8, mp->ncci); capimsg_setu16(s, 12, datahandle); } @@ -512,14 +512,14 @@ static void handle_minor_send(struct capiminor *mp) mp->outbytes -= len; spin_unlock_bh(&mp->outlock); - datahandle = atomic_inc_return(&mp->datahandle); + datahandle = atomic_inc_return_unchecked(&mp->datahandle); skb_push(skb, CAPI_DATA_B3_REQ_LEN); memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN); capimsg_setu16(skb->data, 2, mp->ap->applid); capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); capimsg_setu8 (skb->data, 5, CAPI_REQ); - capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid)); + capimsg_setu16(skb->data, 6, atomic_inc_return_unchecked(&mp->msgid)); capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */ capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */ capimsg_setu16(skb->data, 16, len); /* Data length */ diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 600c79b..3752bab 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -130,9 +130,9 @@ static int if_open(struct tty_struct *tty, struct file *filp) } tty->driver_data = cs; - ++cs->port.count; + atomic_inc(&cs->port.count); - if (cs->port.count == 1) { + if (atomic_read(&cs->port.count) == 1) { tty_port_tty_set(&cs->port, tty); cs->port.low_latency = 1; } @@ -156,9 +156,9 @@ static void if_close(struct tty_struct *tty, struct file *filp) if (!cs->connected) gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else if (!cs->port.count) + else if (!atomic_read(&cs->port.count)) dev_warn(cs->dev, "%s: device not opened\n", __func__); - else if (!--cs->port.count) + else if (!atomic_dec_return(&cs->port.count)) tty_port_tty_set(&cs->port, NULL); mutex_unlock(&cs->mutex); diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index d0a41cb..f0cdb8c 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -547,7 +547,7 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); memcpy(cs->hw.usb->bchars, buf, 6); return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, - 0, 0, &buf, 6, 2000); + 0, 0, buf, 6, 2000); } static void gigaset_freebcshw(struct bc_state *bcs) diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index 4d9b195..455075c 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -176,7 +176,7 @@ int b1_load_t4file(avmcard *card, capiloaddatapart *t4file) } if (left) { if (t4file->user) { - if (copy_from_user(buf, dp, left)) + if (left > sizeof buf || copy_from_user(buf, dp, left)) return -EFAULT; } else { memcpy(buf, dp, left); @@ -224,7 +224,7 @@ int b1_load_config(avmcard *card, capiloaddatapart *config) } if (left) { if (config->user) { - if (copy_from_user(buf, dp, left)) + if (left > sizeof buf || copy_from_user(buf, dp, left)) return -EFAULT; } else { memcpy(buf, dp, left); diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 9bb12ba..d4262f7 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1651,6 +1651,8 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) } else return -EINVAL; case IIOCDBGVAR: + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; if (arg) { if (copy_to_user(argp, &dev, sizeof(ulong))) return -EFAULT; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 3c5f249..5fac4d0 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1508,9 +1508,9 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, - port->count); + atomic_read(&port->count)); #endif - port->count++; + atomic_inc(&port->count); port->tty = tty; /* * Start up serial port @@ -1554,7 +1554,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - if ((tty->count == 1) && (port->count != 1)) { + if ((tty->count == 1) && (atomic_read(&port->count) != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always @@ -1563,15 +1563,15 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) * serial port won't be shutdown. */ printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, " - "info->count is %d\n", port->count); - port->count = 1; + "info->count is %d\n", atomic_read(&port->count)); + atomic_set(&port->count, 1); } - if (--port->count < 0) { + if (atomic_dec_return(&port->count) < 0) { printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n", - info->line, port->count); - port->count = 0; + info->line, atomic_read(&port->count)); + atomic_set(&port->count, 0); } - if (port->count) { + if (atomic_read(&port->count)) { #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); #endif @@ -1625,7 +1625,7 @@ isdn_tty_hangup(struct tty_struct *tty) if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup")) return; isdn_tty_shutdown(info); - port->count = 0; + atomic_set(&port->count, 0); port->flags &= ~ASYNC_NORMAL_ACTIVE; port->tty = NULL; wake_up_interruptible(&port->open_wait); @@ -1970,7 +1970,7 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup) for (i = 0; i < ISDN_MAX_CHANNELS; i++) { modem_info *info = &dev->mdm.info[i]; - if (info->port.count == 0) + if (atomic_read(&info->port.count) == 0) continue; if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index e74df7c..03a03ba 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1045,7 +1045,7 @@ icn_writecmd(const u_char *buf, int len, int user, icn_card *card) if (count > len) count = len; if (user) { - if (copy_from_user(msg, buf, count)) + if (count > sizeof msg || copy_from_user(msg, buf, count)) return -EFAULT; } else memcpy(msg, buf, count); diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 22b720e..77025f5 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -288,8 +288,10 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) u8 *data; int len; - if (skb->len < sizeof(int)) + if (skb->len < sizeof(int)) { printk(KERN_ERR "%s: PH_CONTROL message too short\n", __func__); + return -EINVAL; + } cont = *((int *)skb->data); len = skb->len - sizeof(int); data = skb->data + sizeof(int); diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c index 6a8405d..0bd1c7e 100644 --- a/drivers/leds/leds-clevo-mail.c +++ b/drivers/leds/leds-clevo-mail.c @@ -40,7 +40,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id) * detected as working, but in reality it is not) as low as * possible. */ -static struct dmi_system_id __initdata clevo_mail_led_dmi_table[] = { +static const struct dmi_system_id __initconst clevo_mail_led_dmi_table[] = { { .callback = clevo_mail_led_dmi_callback, .ident = "Clevo D410J", diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index 64e204e..c6bf189 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c @@ -91,7 +91,7 @@ MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection"); * detected as working, but in reality it is not) as low as * possible. */ -static struct dmi_system_id __initdata nas_led_whitelist[] = { +static const struct dmi_system_id __initconst nas_led_whitelist[] = { { .callback = ss4200_led_dmi_callback, .ident = "Intel SS4200-E", diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index 0bf1e4e..b4bf44e 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c @@ -97,9 +97,17 @@ static __init int map_switcher(void) * The end address needs +1 because __get_vm_area allocates an * extra guard page, so we need space for that. */ + +#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) + switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE, + VM_ALLOC | VM_KERNEXEC, switcher_addr, switcher_addr + + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE); +#else switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE, VM_ALLOC, switcher_addr, switcher_addr + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE); +#endif + if (!switcher_vma) { err = -ENOMEM; printk("lguest: could not map switcher pages high\n"); @@ -124,7 +132,7 @@ static __init int map_switcher(void) * Now the Switcher is mapped at the right address, we can't fail! * Copy in the compiled-in Switcher code (from x86/switcher_32.S). */ - memcpy(switcher_vma->addr, start_switcher_text, + memcpy(switcher_vma->addr, ktla_ktva(start_switcher_text), end_switcher_text - start_switcher_text); printk(KERN_INFO "lguest: mapped switcher at %p\n", diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 5b9ac32..2ef4f26 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -559,7 +559,7 @@ void pin_page(struct lg_cpu *cpu, unsigned long vaddr) /*:*/ #ifdef CONFIG_X86_PAE -static void release_pmd(pmd_t *spmd) +static void __intentional_overflow(-1) release_pmd(pmd_t *spmd) { /* If the entry's not present, there's nothing to release. */ if (pmd_flags(*spmd) & _PAGE_PRESENT) { diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index f0a3347..f6608b2 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -59,7 +59,7 @@ static struct { /* Offset from where switcher.S was compiled to where we've copied it */ static unsigned long switcher_offset(void) { - return switcher_addr - (unsigned long)start_switcher_text; + return switcher_addr - (unsigned long)ktla_ktva(start_switcher_text); } /* This cpu's struct lguest_pages (after the Switcher text page) */ @@ -99,7 +99,13 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) * These copies are pretty cheap, so we do them unconditionally: */ /* Save the current Host top-level page directory. */ + +#ifdef CONFIG_PAX_PER_CPU_PGD + pages->state.host_cr3 = read_cr3(); +#else pages->state.host_cr3 = __pa(current->mm->pgd); +#endif + /* * Set up the Guest's page tables to see this CPU's pages (and no * other CPU's pages). @@ -475,7 +481,7 @@ void __init lguest_arch_host_init(void) * compiled-in switcher code and the high-mapped copy we just made. */ for (i = 0; i < IDT_ENTRIES; i++) - default_idt_entries[i] += switcher_offset(); + default_idt_entries[i] = ktla_ktva(default_idt_entries[i]) + switcher_offset(); /* * Set up the Switcher's per-cpu areas. @@ -558,7 +564,7 @@ void __init lguest_arch_host_init(void) * it will be undisturbed when we switch. To change %cs and jump we * need this structure to feed to Intel's "lcall" instruction. */ - lguest_entry.offset = (long)switch_to_guest + switcher_offset(); + lguest_entry.offset = (long)ktla_ktva(switch_to_guest) + switcher_offset(); lguest_entry.segment = LGUEST_CS; /* diff --git a/drivers/lguest/x86/switcher_32.S b/drivers/lguest/x86/switcher_32.S index 40634b0..4f5855e 100644 --- a/drivers/lguest/x86/switcher_32.S +++ b/drivers/lguest/x86/switcher_32.S @@ -87,6 +87,7 @@ #include #include #include +#include // We mark the start of the code to copy // It's placed in .text tho it's never run here @@ -149,6 +150,13 @@ ENTRY(switch_to_guest) // Changes type when we load it: damn Intel! // For after we switch over our page tables // That entry will be read-only: we'd crash. + +#ifdef CONFIG_PAX_KERNEXEC + mov %cr0, %edx + xor $X86_CR0_WP, %edx + mov %edx, %cr0 +#endif + movl $(GDT_ENTRY_TSS*8), %edx ltr %dx @@ -157,9 +165,15 @@ ENTRY(switch_to_guest) // Let's clear it again for our return. // The GDT descriptor of the Host // Points to the table after two "size" bytes - movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx + movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %eax // Clear "used" from type field (byte 5, bit 2) - andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx) + andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%eax) + +#ifdef CONFIG_PAX_KERNEXEC + mov %cr0, %eax + xor $X86_CR0_WP, %eax + mov %eax, %cr0 +#endif // Once our page table's switched, the Guest is live! // The Host fades as we run this final step. @@ -295,13 +309,12 @@ deliver_to_host: // I consulted gcc, and it gave // These instructions, which I gladly credit: leal (%edx,%ebx,8), %eax - movzwl (%eax),%edx - movl 4(%eax), %eax - xorw %ax, %ax - orl %eax, %edx + movl 4(%eax), %edx + movw (%eax), %dx // Now the address of the handler's in %edx // We call it now: its "iret" drops us home. - jmp *%edx + ljmp $__KERNEL_CS, $1f +1: jmp *%edx // Every interrupt can come to us here // But we must truly tell each apart. diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h index 0003992..854bbce 100644 --- a/drivers/md/bcache/closure.h +++ b/drivers/md/bcache/closure.h @@ -622,7 +622,7 @@ static inline void closure_wake_up(struct closure_waitlist *list) static inline void set_closure_fn(struct closure *cl, closure_fn *fn, struct workqueue_struct *wq) { - BUG_ON(object_is_on_stack(cl)); + BUG_ON(object_starts_on_stack(cl)); closure_set_ip(cl); cl->fn = fn; cl->wq = wq; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index b4713ce..b30139b 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1603,7 +1603,7 @@ err_unlock_gc: err: closure_sync(&op.cl); /* XXX: test this, it's broken */ - bch_cache_set_error(c, err); + bch_cache_set_error(c, "%s", err); } static bool can_attach_cache(struct cache *ca, struct cache_set *c) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 5a2c754..0fa55db 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1779,7 +1779,7 @@ void bitmap_status(struct seq_file *seq, struct bitmap *bitmap) chunk_kb ? "KB" : "B"); if (bitmap->storage.file) { seq_printf(seq, ", file: "); - seq_path(seq, &bitmap->storage.file->f_path, " \t\n"); + seq_path(seq, &bitmap->storage.file->f_path, " \t\n\\"); } seq_printf(seq, "\n"); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 81a79b7..87a0f73 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1697,7 +1697,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) cmd == DM_LIST_VERSIONS_CMD) return 0; - if ((cmd == DM_DEV_CREATE_CMD)) { + if (cmd == DM_DEV_CREATE_CMD) { if (!*param->name) { DMWARN("name not supplied when creating device"); return -EINVAL; diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 699b5be..eac0a15 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -40,7 +40,7 @@ enum dm_raid1_error { struct mirror { struct mirror_set *ms; - atomic_t error_count; + atomic_unchecked_t error_count; unsigned long error_type; struct dm_dev *dev; sector_t offset; @@ -186,7 +186,7 @@ static struct mirror *get_valid_mirror(struct mirror_set *ms) struct mirror *m; for (m = ms->mirror; m < ms->mirror + ms->nr_mirrors; m++) - if (!atomic_read(&m->error_count)) + if (!atomic_read_unchecked(&m->error_count)) return m; return NULL; @@ -218,7 +218,7 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type) * simple way to tell if a device has encountered * errors. */ - atomic_inc(&m->error_count); + atomic_inc_unchecked(&m->error_count); if (test_and_set_bit(error_type, &m->error_type)) return; @@ -409,7 +409,7 @@ static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector) struct mirror *m = get_default_mirror(ms); do { - if (likely(!atomic_read(&m->error_count))) + if (likely(!atomic_read_unchecked(&m->error_count))) return m; if (m-- == ms->mirror) @@ -423,7 +423,7 @@ static int default_ok(struct mirror *m) { struct mirror *default_mirror = get_default_mirror(m->ms); - return !atomic_read(&default_mirror->error_count); + return !atomic_read_unchecked(&default_mirror->error_count); } static int mirror_available(struct mirror_set *ms, struct bio *bio) @@ -560,7 +560,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads) */ if (likely(region_in_sync(ms, region, 1))) m = choose_mirror(ms, bio->bi_sector); - else if (m && atomic_read(&m->error_count)) + else if (m && atomic_read_unchecked(&m->error_count)) m = NULL; if (likely(m)) @@ -927,7 +927,7 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, } ms->mirror[mirror].ms = ms; - atomic_set(&(ms->mirror[mirror].error_count), 0); + atomic_set_unchecked(&(ms->mirror[mirror].error_count), 0); ms->mirror[mirror].error_type = 0; ms->mirror[mirror].offset = offset; @@ -1340,7 +1340,7 @@ static void mirror_resume(struct dm_target *ti) */ static char device_status_char(struct mirror *m) { - if (!atomic_read(&(m->error_count))) + if (!atomic_read_unchecked(&(m->error_count))) return 'A'; return (test_bit(DM_RAID1_FLUSH_ERROR, &(m->error_type))) ? 'F' : diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index d907ca6..cfb8384 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -20,7 +20,7 @@ struct stripe { struct dm_dev *dev; sector_t physical_start; - atomic_t error_count; + atomic_unchecked_t error_count; }; struct stripe_c { @@ -185,7 +185,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) kfree(sc); return r; } - atomic_set(&(sc->stripe[i].error_count), 0); + atomic_set_unchecked(&(sc->stripe[i].error_count), 0); } ti->private = sc; @@ -326,7 +326,7 @@ static void stripe_status(struct dm_target *ti, status_type_t type, DMEMIT("%d ", sc->stripes); for (i = 0; i < sc->stripes; i++) { DMEMIT("%s ", sc->stripe[i].dev->name); - buffer[i] = atomic_read(&(sc->stripe[i].error_count)) ? + buffer[i] = atomic_read_unchecked(&(sc->stripe[i].error_count)) ? 'D' : 'A'; } buffer[i] = '\0'; @@ -371,8 +371,8 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error) */ for (i = 0; i < sc->stripes; i++) if (!strcmp(sc->stripe[i].dev->name, major_minor)) { - atomic_inc(&(sc->stripe[i].error_count)); - if (atomic_read(&(sc->stripe[i].error_count)) < + atomic_inc_unchecked(&(sc->stripe[i].error_count)); + if (atomic_read_unchecked(&(sc->stripe[i].error_count)) < DM_IO_ERROR_THRESHOLD) schedule_work(&sc->trigger_event); } diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 1ff252a..ee384c1 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -389,7 +389,7 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, if (!dev_size) return 0; - if ((start >= dev_size) || (start + len > dev_size)) { + if ((start >= dev_size) || (len > dev_size - start)) { DMWARN("%s: %s too small for target: " "start=%llu, len=%llu, dev_size=%llu", dm_device_name(ti->table->md), bdevname(bdev, b), diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 60bce43..9b997d0 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -397,7 +397,7 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd) { pmd->info.tm = pmd->tm; pmd->info.levels = 2; - pmd->info.value_type.context = pmd->data_sm; + pmd->info.value_type.context = (dm_space_map_no_const *)pmd->data_sm; pmd->info.value_type.size = sizeof(__le64); pmd->info.value_type.inc = data_block_inc; pmd->info.value_type.dec = data_block_dec; @@ -416,7 +416,7 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd) pmd->bl_info.tm = pmd->tm; pmd->bl_info.levels = 1; - pmd->bl_info.value_type.context = pmd->data_sm; + pmd->bl_info.value_type.context = (dm_space_map_no_const *)pmd->data_sm; pmd->bl_info.value_type.size = sizeof(__le64); pmd->bl_info.value_type.inc = data_block_inc; pmd->bl_info.value_type.dec = data_block_dec; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 33f2010..23fb84c 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -169,9 +169,9 @@ struct mapped_device { /* * Event handling. */ - atomic_t event_nr; + atomic_unchecked_t event_nr; wait_queue_head_t eventq; - atomic_t uevent_seq; + atomic_unchecked_t uevent_seq; struct list_head uevent_list; spinlock_t uevent_lock; /* Protect access to uevent_list */ @@ -1884,8 +1884,8 @@ static struct mapped_device *alloc_dev(int minor) rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); - atomic_set(&md->event_nr, 0); - atomic_set(&md->uevent_seq, 0); + atomic_set_unchecked(&md->event_nr, 0); + atomic_set_unchecked(&md->uevent_seq, 0); INIT_LIST_HEAD(&md->uevent_list); spin_lock_init(&md->uevent_lock); @@ -2033,7 +2033,7 @@ static void event_callback(void *context) dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj); - atomic_inc(&md->event_nr); + atomic_inc_unchecked(&md->event_nr); wake_up(&md->eventq); } @@ -2690,18 +2690,18 @@ int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, uint32_t dm_next_uevent_seq(struct mapped_device *md) { - return atomic_add_return(1, &md->uevent_seq); + return atomic_add_return_unchecked(1, &md->uevent_seq); } uint32_t dm_get_event_nr(struct mapped_device *md) { - return atomic_read(&md->event_nr); + return atomic_read_unchecked(&md->event_nr); } int dm_wait_event(struct mapped_device *md, int event_nr) { return wait_event_interruptible(md->eventq, - (event_nr != atomic_read(&md->event_nr))); + (event_nr != atomic_read_unchecked(&md->event_nr))); } void dm_uevent_add(struct mapped_device *md, struct list_head *elist) diff --git a/drivers/md/md.c b/drivers/md/md.c index 51f0345..c77810e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -234,10 +234,10 @@ EXPORT_SYMBOL_GPL(md_trim_bio); * start build, activate spare */ static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters); -static atomic_t md_event_count; +static atomic_unchecked_t md_event_count; void md_new_event(struct mddev *mddev) { - atomic_inc(&md_event_count); + atomic_inc_unchecked(&md_event_count); wake_up(&md_event_waiters); } EXPORT_SYMBOL_GPL(md_new_event); @@ -247,7 +247,7 @@ EXPORT_SYMBOL_GPL(md_new_event); */ static void md_new_event_inintr(struct mddev *mddev) { - atomic_inc(&md_event_count); + atomic_inc_unchecked(&md_event_count); wake_up(&md_event_waiters); } @@ -1501,7 +1501,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE) && (le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET)) rdev->new_data_offset += (s32)le32_to_cpu(sb->new_offset); - atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); + atomic_set_unchecked(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256; bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; @@ -1745,7 +1745,7 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev) else sb->resync_offset = cpu_to_le64(0); - sb->cnt_corrected_read = cpu_to_le32(atomic_read(&rdev->corrected_errors)); + sb->cnt_corrected_read = cpu_to_le32(atomic_read_unchecked(&rdev->corrected_errors)); sb->raid_disks = cpu_to_le32(mddev->raid_disks); sb->size = cpu_to_le64(mddev->dev_sectors); @@ -2750,7 +2750,7 @@ __ATTR(state, S_IRUGO|S_IWUSR, state_show, state_store); static ssize_t errors_show(struct md_rdev *rdev, char *page) { - return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors)); + return sprintf(page, "%d\n", atomic_read_unchecked(&rdev->corrected_errors)); } static ssize_t @@ -2759,7 +2759,7 @@ errors_store(struct md_rdev *rdev, const char *buf, size_t len) char *e; unsigned long n = simple_strtoul(buf, &e, 10); if (*buf && (*e == 0 || *e == '\n')) { - atomic_set(&rdev->corrected_errors, n); + atomic_set_unchecked(&rdev->corrected_errors, n); return len; } return -EINVAL; @@ -3207,8 +3207,8 @@ int md_rdev_init(struct md_rdev *rdev) rdev->sb_loaded = 0; rdev->bb_page = NULL; atomic_set(&rdev->nr_pending, 0); - atomic_set(&rdev->read_errors, 0); - atomic_set(&rdev->corrected_errors, 0); + atomic_set_unchecked(&rdev->read_errors, 0); + atomic_set_unchecked(&rdev->corrected_errors, 0); INIT_LIST_HEAD(&rdev->same_set); init_waitqueue_head(&rdev->blocked_wait); @@ -7009,7 +7009,7 @@ static int md_seq_show(struct seq_file *seq, void *v) spin_unlock(&pers_lock); seq_printf(seq, "\n"); - seq->poll_event = atomic_read(&md_event_count); + seq->poll_event = atomic_read_unchecked(&md_event_count); return 0; } if (v == (void*)2) { @@ -7112,7 +7112,7 @@ static int md_seq_open(struct inode *inode, struct file *file) return error; seq = file->private_data; - seq->poll_event = atomic_read(&md_event_count); + seq->poll_event = atomic_read_unchecked(&md_event_count); return error; } @@ -7126,7 +7126,7 @@ static unsigned int mdstat_poll(struct file *filp, poll_table *wait) /* always allow read */ mask = POLLIN | POLLRDNORM; - if (seq->poll_event != atomic_read(&md_event_count)) + if (seq->poll_event != atomic_read_unchecked(&md_event_count)) mask |= POLLERR | POLLPRI; return mask; } @@ -7170,7 +7170,7 @@ static int is_mddev_idle(struct mddev *mddev, int init) struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; curr_events = (int)part_stat_read(&disk->part0, sectors[0]) + (int)part_stat_read(&disk->part0, sectors[1]) - - atomic_read(&disk->sync_io); + atomic_read_unchecked(&disk->sync_io); /* sync IO will cause sync_io to increase before the disk_stats * as sync_io is counted when a request starts, and * disk_stats is counted when it completes. diff --git a/drivers/md/md.h b/drivers/md/md.h index 653f992b6..6af6c40 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -94,13 +94,13 @@ struct md_rdev { * only maintained for arrays that * support hot removal */ - atomic_t read_errors; /* number of consecutive read errors that + atomic_unchecked_t read_errors; /* number of consecutive read errors that * we have tried to ignore. */ struct timespec last_read_error; /* monotonic time since our * last read error */ - atomic_t corrected_errors; /* number of corrected read errors, + atomic_unchecked_t corrected_errors; /* number of corrected read errors, * for reporting to userspace and storing * in superblock. */ @@ -434,7 +434,7 @@ static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev) static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors) { - atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io); + atomic_add_unchecked(nr_sectors, &bdev->bd_contains->bd_disk->sync_io); } struct md_personality diff --git a/drivers/md/persistent-data/dm-space-map.h b/drivers/md/persistent-data/dm-space-map.h index 3e6d115..ffecdeb 100644 --- a/drivers/md/persistent-data/dm-space-map.h +++ b/drivers/md/persistent-data/dm-space-map.h @@ -71,6 +71,7 @@ struct dm_space_map { dm_sm_threshold_fn fn, void *context); }; +typedef struct dm_space_map __no_const dm_space_map_no_const; /*----------------------------------------------------------------*/ diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 6f48244..7d29145 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1822,7 +1822,7 @@ static int fix_sync_read_error(struct r1bio *r1_bio) if (r1_sync_page_io(rdev, sect, s, bio->bi_io_vec[idx].bv_page, READ) != 0) - atomic_add(s, &rdev->corrected_errors); + atomic_add_unchecked(s, &rdev->corrected_errors); } sectors -= s; sect += s; @@ -2049,7 +2049,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk, test_bit(In_sync, &rdev->flags)) { if (r1_sync_page_io(rdev, sect, s, conf->tmppage, READ)) { - atomic_add(s, &rdev->corrected_errors); + atomic_add_unchecked(s, &rdev->corrected_errors); printk(KERN_INFO "md/raid1:%s: read error corrected " "(%d sectors at %llu on %s)\n", diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 081bb33..3c4b287 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1940,7 +1940,7 @@ static void end_sync_read(struct bio *bio, int error) /* The write handler will notice the lack of * R10BIO_Uptodate and record any errors etc */ - atomic_add(r10_bio->sectors, + atomic_add_unchecked(r10_bio->sectors, &conf->mirrors[d].rdev->corrected_errors); /* for reconstruct, we always reschedule after a read. @@ -2298,7 +2298,7 @@ static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev) { struct timespec cur_time_mon; unsigned long hours_since_last; - unsigned int read_errors = atomic_read(&rdev->read_errors); + unsigned int read_errors = atomic_read_unchecked(&rdev->read_errors); ktime_get_ts(&cur_time_mon); @@ -2320,9 +2320,9 @@ static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev) * overflowing the shift of read_errors by hours_since_last. */ if (hours_since_last >= 8 * sizeof(read_errors)) - atomic_set(&rdev->read_errors, 0); + atomic_set_unchecked(&rdev->read_errors, 0); else - atomic_set(&rdev->read_errors, read_errors >> hours_since_last); + atomic_set_unchecked(&rdev->read_errors, read_errors >> hours_since_last); } static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector, @@ -2376,8 +2376,8 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10 return; check_decay_read_errors(mddev, rdev); - atomic_inc(&rdev->read_errors); - if (atomic_read(&rdev->read_errors) > max_read_errors) { + atomic_inc_unchecked(&rdev->read_errors); + if (atomic_read_unchecked(&rdev->read_errors) > max_read_errors) { char b[BDEVNAME_SIZE]; bdevname(rdev->bdev, b); @@ -2385,7 +2385,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10 "md/raid10:%s: %s: Raid device exceeded " "read_error threshold [cur %d:max %d]\n", mdname(mddev), b, - atomic_read(&rdev->read_errors), max_read_errors); + atomic_read_unchecked(&rdev->read_errors), max_read_errors); printk(KERN_NOTICE "md/raid10:%s: %s: Failing raid device\n", mdname(mddev), b); @@ -2540,7 +2540,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10 sect + choose_data_offset(r10_bio, rdev)), bdevname(rdev->bdev, b)); - atomic_add(s, &rdev->corrected_errors); + atomic_add_unchecked(s, &rdev->corrected_errors); } rdev_dec_pending(rdev, mddev); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a35b846..e295c6d 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1764,21 +1764,21 @@ static void raid5_end_read_request(struct bio * bi, int error) mdname(conf->mddev), STRIPE_SECTORS, (unsigned long long)s, bdevname(rdev->bdev, b)); - atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); + atomic_add_unchecked(STRIPE_SECTORS, &rdev->corrected_errors); clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); } else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags)) clear_bit(R5_ReadNoMerge, &sh->dev[i].flags); - if (atomic_read(&rdev->read_errors)) - atomic_set(&rdev->read_errors, 0); + if (atomic_read_unchecked(&rdev->read_errors)) + atomic_set_unchecked(&rdev->read_errors, 0); } else { const char *bdn = bdevname(rdev->bdev, b); int retry = 0; int set_bad = 0; clear_bit(R5_UPTODATE, &sh->dev[i].flags); - atomic_inc(&rdev->read_errors); + atomic_inc_unchecked(&rdev->read_errors); if (test_bit(R5_ReadRepl, &sh->dev[i].flags)) printk_ratelimited( KERN_WARNING @@ -1806,7 +1806,7 @@ static void raid5_end_read_request(struct bio * bi, int error) mdname(conf->mddev), (unsigned long long)s, bdn); - } else if (atomic_read(&rdev->read_errors) + } else if (atomic_read_unchecked(&rdev->read_errors) > conf->max_nr_stripes) printk(KERN_WARNING "md/raid:%s: Too many read errors, failing device %s.\n", diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 401ef64..836e563 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -192,7 +192,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, const struct dvb_device *template, void *priv, int type) { struct dvb_device *dvbdev; - struct file_operations *dvbdevfops; + file_operations_no_const *dvbdevfops; struct device *clsdev; int minor; int id; diff --git a/drivers/media/dvb-frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h index 9b6c3bb..baeb5c7 100644 --- a/drivers/media/dvb-frontends/dib3000.h +++ b/drivers/media/dvb-frontends/dib3000.h @@ -39,7 +39,7 @@ struct dib_fe_xfer_ops int (*fifo_ctrl)(struct dvb_frontend *fe, int onoff); int (*pid_ctrl)(struct dvb_frontend *fe, int index, int pid, int onoff); int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl); -}; +} __no_const; #if IS_ENABLED(CONFIG_DVB_DIB3000MB) extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index c7a9be1..683f6f8 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -50,9 +50,9 @@ MODULE_VERSION(CX88_VERSION); /* ------------------------------------------------------------------ */ -static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +static int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +static int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +static int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; module_param_array(video_nr, int, NULL, 0444); module_param_array(vbi_nr, int, NULL, 0444); diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 07b8460..e6d7265 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -84,7 +84,7 @@ static struct pci_device_id ivtv_pci_tbl[] = { MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); /* ivtv instance counter */ -static atomic_t ivtv_instance = ATOMIC_INIT(0); +static atomic_unchecked_t ivtv_instance = ATOMIC_INIT(0); /* Parameter declarations */ static int cardtype[IVTV_MAX_CARDS]; diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index d338b19..aae4f9e 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -63,7 +63,6 @@ enum omap_vout_channels { OMAP_VIDEO2, }; -static struct videobuf_queue_ops video_vbq_ops; /* Variables configurable through module params*/ static u32 video1_numbuffers = 3; static u32 video2_numbuffers = 3; @@ -1015,6 +1014,12 @@ static int omap_vout_open(struct file *file) { struct videobuf_queue *q; struct omap_vout_device *vout = NULL; + static struct videobuf_queue_ops video_vbq_ops = { + .buf_setup = omap_vout_buffer_setup, + .buf_prepare = omap_vout_buffer_prepare, + .buf_release = omap_vout_buffer_release, + .buf_queue = omap_vout_buffer_queue, + }; vout = video_drvdata(file); v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Entering %s\n", __func__); @@ -1032,10 +1037,6 @@ static int omap_vout_open(struct file *file) vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; q = &vout->vbq; - video_vbq_ops.buf_setup = omap_vout_buffer_setup; - video_vbq_ops.buf_prepare = omap_vout_buffer_prepare; - video_vbq_ops.buf_release = omap_vout_buffer_release; - video_vbq_ops.buf_queue = omap_vout_buffer_queue; spin_lock_init(&vout->vbq_lock); videobuf_queue_dma_contig_init(q, &video_vbq_ops, q->dev, diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h index 04e6490..2df65bf 100644 --- a/drivers/media/platform/s5p-tv/mixer.h +++ b/drivers/media/platform/s5p-tv/mixer.h @@ -156,7 +156,7 @@ struct mxr_layer { /** layer index (unique identifier) */ int idx; /** callbacks for layer methods */ - struct mxr_layer_ops ops; + struct mxr_layer_ops *ops; /** format array */ const struct mxr_format **fmt_array; /** size of format array */ diff --git a/drivers/media/platform/s5p-tv/mixer_grp_layer.c b/drivers/media/platform/s5p-tv/mixer_grp_layer.c index b93a21f..2535195 100644 --- a/drivers/media/platform/s5p-tv/mixer_grp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_grp_layer.c @@ -235,7 +235,7 @@ struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx) { struct mxr_layer *layer; int ret; - struct mxr_layer_ops ops = { + static struct mxr_layer_ops ops = { .release = mxr_graph_layer_release, .buffer_set = mxr_graph_buffer_set, .stream_set = mxr_graph_stream_set, diff --git a/drivers/media/platform/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c index b713403..53cb5ad 100644 --- a/drivers/media/platform/s5p-tv/mixer_reg.c +++ b/drivers/media/platform/s5p-tv/mixer_reg.c @@ -276,7 +276,7 @@ static void mxr_irq_layer_handle(struct mxr_layer *layer) layer->update_buf = next; } - layer->ops.buffer_set(layer, layer->update_buf); + layer->ops->buffer_set(layer, layer->update_buf); if (done && done != layer->shadow_buf) vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE); diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index ef0efdf..8c78eb6 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -209,7 +209,7 @@ static void mxr_layer_default_geo(struct mxr_layer *layer) layer->geo.src.height = layer->geo.src.full_height; mxr_geometry_dump(mdev, &layer->geo); - layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0); + layer->ops->fix_geometry(layer, MXR_GEOMETRY_SINK, 0); mxr_geometry_dump(mdev, &layer->geo); } @@ -227,7 +227,7 @@ static void mxr_layer_update_output(struct mxr_layer *layer) layer->geo.dst.full_width = mbus_fmt.width; layer->geo.dst.full_height = mbus_fmt.height; layer->geo.dst.field = mbus_fmt.field; - layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0); + layer->ops->fix_geometry(layer, MXR_GEOMETRY_SINK, 0); mxr_geometry_dump(mdev, &layer->geo); } @@ -333,7 +333,7 @@ static int mxr_s_fmt(struct file *file, void *priv, /* set source size to highest accepted value */ geo->src.full_width = max(geo->dst.full_width, pix->width); geo->src.full_height = max(geo->dst.full_height, pix->height); - layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); + layer->ops->fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); mxr_geometry_dump(mdev, &layer->geo); /* set cropping to total visible screen */ geo->src.width = pix->width; @@ -341,12 +341,12 @@ static int mxr_s_fmt(struct file *file, void *priv, geo->src.x_offset = 0; geo->src.y_offset = 0; /* assure consistency of geometry */ - layer->ops.fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET); + layer->ops->fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET); mxr_geometry_dump(mdev, &layer->geo); /* set full size to lowest possible value */ geo->src.full_width = 0; geo->src.full_height = 0; - layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); + layer->ops->fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); mxr_geometry_dump(mdev, &layer->geo); /* returning results */ @@ -473,7 +473,7 @@ static int mxr_s_selection(struct file *file, void *fh, target->width = s->r.width; target->height = s->r.height; - layer->ops.fix_geometry(layer, stage, s->flags); + layer->ops->fix_geometry(layer, stage, s->flags); /* retrieve update selection rectangle */ res.left = target->x_offset; @@ -954,13 +954,13 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) mxr_output_get(mdev); mxr_layer_update_output(layer); - layer->ops.format_set(layer); + layer->ops->format_set(layer); /* enabling layer in hardware */ spin_lock_irqsave(&layer->enq_slock, flags); layer->state = MXR_LAYER_STREAMING; spin_unlock_irqrestore(&layer->enq_slock, flags); - layer->ops.stream_set(layer, MXR_ENABLE); + layer->ops->stream_set(layer, MXR_ENABLE); mxr_streamer_get(mdev); return 0; @@ -1030,7 +1030,7 @@ static int stop_streaming(struct vb2_queue *vq) spin_unlock_irqrestore(&layer->enq_slock, flags); /* disabling layer in hardware */ - layer->ops.stream_set(layer, MXR_DISABLE); + layer->ops->stream_set(layer, MXR_DISABLE); /* remove one streamer */ mxr_streamer_put(mdev); /* allow changes in output configuration */ @@ -1069,8 +1069,8 @@ void mxr_base_layer_unregister(struct mxr_layer *layer) void mxr_layer_release(struct mxr_layer *layer) { - if (layer->ops.release) - layer->ops.release(layer); + if (layer->ops->release) + layer->ops->release(layer); } void mxr_base_layer_release(struct mxr_layer *layer) @@ -1096,7 +1096,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev, layer->mdev = mdev; layer->idx = idx; - layer->ops = *ops; + layer->ops = ops; spin_lock_init(&layer->enq_slock); INIT_LIST_HEAD(&layer->enq_list); diff --git a/drivers/media/platform/s5p-tv/mixer_vp_layer.c b/drivers/media/platform/s5p-tv/mixer_vp_layer.c index 3d13a63..da31bf1 100644 --- a/drivers/media/platform/s5p-tv/mixer_vp_layer.c +++ b/drivers/media/platform/s5p-tv/mixer_vp_layer.c @@ -206,7 +206,7 @@ struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx) { struct mxr_layer *layer; int ret; - struct mxr_layer_ops ops = { + static struct mxr_layer_ops ops = { .release = mxr_vp_layer_release, .buffer_set = mxr_vp_buffer_set, .stream_set = mxr_vp_stream_set, diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 545c04c..a14bded 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -324,6 +324,8 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo unsigned char readbuf[RDS_BUFFER]; int i = 0; + if (count > RDS_BUFFER) + return -EFAULT; mutex_lock(&dev->lock); if (dev->rdsstat == 0) cadet_start_rds(dev); @@ -339,7 +341,7 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo while (i < count && dev->rdsin != dev->rdsout) readbuf[i++] = dev->rdsbuf[dev->rdsout++]; - if (i && copy_to_user(data, readbuf, i)) + if (i > sizeof(readbuf) || copy_to_user(data, readbuf, i)) i = -EFAULT; unlock: mutex_unlock(&dev->lock); diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index bd4d3a7..ffc0b9d 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -61,7 +61,7 @@ MODULE_PARM_DESC(radio_nr, "Radio device number"); /* TEA5757 pin mappings */ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; -static atomic_t maxiradio_instance = ATOMIC_INIT(0); +static atomic_unchecked_t maxiradio_instance = ATOMIC_INIT(0); #define PCI_VENDOR_ID_GUILLEMOT 0x5046 #define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 8fa18ab..caee70f 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -79,7 +79,7 @@ struct shark_device { u32 last_val; }; -static atomic_t shark_instance = ATOMIC_INIT(0); +static atomic_unchecked_t shark_instance = ATOMIC_INIT(0); static void shark_write_val(struct snd_tea575x *tea, u32 val) { diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index 9fb6697..f167415 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -74,7 +74,7 @@ struct shark_device { u8 *transfer_buffer; }; -static atomic_t shark_instance = ATOMIC_INIT(0); +static atomic_unchecked_t shark_instance = ATOMIC_INIT(0); static int shark_write_reg(struct radio_tea5777 *tea, u64 reg) { diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9dc8baf..796d52f 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1456,7 +1456,7 @@ static int si476x_radio_probe(struct platform_device *pdev) struct si476x_radio *radio; struct v4l2_ctrl *ctrl; - static atomic_t instance = ATOMIC_INIT(0); + static atomic_unchecked_t instance = ATOMIC_INIT(0); radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL); if (!radio) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 1cf382a..c22998c 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1030,7 +1030,7 @@ EXPORT_SYMBOL_GPL(rc_free_device); int rc_register_device(struct rc_dev *dev) { static bool raw_init = false; /* raw decoders loaded? */ - static atomic_t devno = ATOMIC_INIT(0); + static atomic_unchecked_t devno = ATOMIC_INIT(0); struct rc_map *rc_map; const char *path; int rc; @@ -1061,7 +1061,7 @@ int rc_register_device(struct rc_dev *dev) */ mutex_lock(&dev->lock); - dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); + dev->devno = (unsigned long)(atomic_inc_return_unchecked(&devno) - 1); dev_set_name(&dev->dev, "rc%ld", dev->devno); dev_set_drvdata(&dev->dev, dev); rc = device_add(&dev->dev); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 3940bb0..fb3952a 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -1068,7 +1068,7 @@ static struct dib0070_config dib7070p_dib0070_config = { struct dib0700_adapter_state { int (*set_param_save) (struct dvb_frontend *); -}; +} __no_const; static int dib7070_set_param_override(struct dvb_frontend *fe) { diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 6e237b6..dc25556 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -118,7 +118,7 @@ struct su3000_state { struct s6x0_state { int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v); -}; +} __no_const; /* debug */ static int dvb_usb_dw2102_debug; diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index f129551..ecf6514 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -326,7 +326,7 @@ struct v4l2_buffer32 { __u32 reserved; }; -static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, +static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { void __user *up_pln; @@ -355,7 +355,7 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, return 0; } -static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, +static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { if (copy_in_user(up32, up, 2 * sizeof(__u32)) || @@ -772,7 +772,7 @@ static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subde put_user(kp->start_block, &up->start_block) || put_user(kp->blocks, &up->blocks) || put_user(tmp, &up->edid) || - copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved))) + copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) return -EFAULT; return 0; } diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 8ed5da2..47fee46 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -74,9 +74,9 @@ int v4l2_device_put(struct v4l2_device *v4l2_dev) EXPORT_SYMBOL_GPL(v4l2_device_put); int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, - atomic_t *instance) + atomic_unchecked_t *instance) { - int num = atomic_inc_return(instance) - 1; + int num = atomic_inc_return_unchecked(instance) - 1; int len = strlen(basename); if (basename[len - 1] >= '0' && basename[len - 1] <= '9') diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 7658586..1079260 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1995,7 +1995,8 @@ struct v4l2_ioctl_info { struct file *file, void *fh, void *p); } u; void (*debug)(const void *arg, bool write_only); -}; +} __do_const; +typedef struct v4l2_ioctl_info __no_const v4l2_ioctl_info_no_const; /* This control needs a priority check */ #define INFO_FL_PRIO (1 << 0) @@ -2177,7 +2178,7 @@ static long __video_do_ioctl(struct file *file, struct video_device *vfd = video_devdata(file); const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; bool write_only = false; - struct v4l2_ioctl_info default_info; + v4l2_ioctl_info_no_const default_info; const struct v4l2_ioctl_info *info; void *fh = file->private_data; struct v4l2_fh *vfh = NULL; @@ -2251,7 +2252,7 @@ done: } static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, - void * __user *user_ptr, void ***kernel_ptr) + void __user **user_ptr, void ***kernel_ptr) { int ret = 0; @@ -2267,7 +2268,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, ret = -EINVAL; break; } - *user_ptr = (void __user *)buf->m.planes; + *user_ptr = (void __force_user *)buf->m.planes; *kernel_ptr = (void *)&buf->m.planes; *array_size = sizeof(struct v4l2_plane) * buf->length; ret = 1; @@ -2302,7 +2303,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, ret = -EINVAL; break; } - *user_ptr = (void __user *)ctrls->controls; + *user_ptr = (void __force_user *)ctrls->controls; *kernel_ptr = (void *)&ctrls->controls; *array_size = sizeof(struct v4l2_ext_control) * ctrls->count; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 767ff4d..c69d259 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6755,8 +6755,13 @@ static int mpt_iocinfo_proc_show(struct seq_file *m, void *v) seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); +#ifdef CONFIG_GRKERNSEC_HIDESYM + seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", NULL, NULL); +#else seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma); +#endif + /* * Rounding UP to nearest 4-kB boundary here... */ @@ -6769,7 +6774,11 @@ static int mpt_iocinfo_proc_show(struct seq_file *m, void *v) ioc->facts.GlobalCredits); seq_printf(m, " Frames @ 0x%p (Dma @ 0x%p)\n", +#ifdef CONFIG_GRKERNSEC_HIDESYM + NULL, NULL); +#else (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma); +#endif sz = (ioc->reply_sz * ioc->reply_depth) + 128; seq_printf(m, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index dd239bd..689c4f7 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -446,6 +446,23 @@ mptsas_is_end_device(struct mptsas_devinfo * attached) return 0; } +static inline void +mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy) +{ + if (phy_info->port_details) { + phy_info->port_details->rphy = rphy; + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n", + ioc->name, rphy)); + } + + if (rphy) { + dsaswideprintk(ioc, dev_printk(KERN_DEBUG, + &rphy->dev, MYIOC_s_FMT "add:", ioc->name)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n", + ioc->name, rphy, rphy->dev.release)); + } +} + /* no mutex */ static void mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details) @@ -484,23 +501,6 @@ mptsas_get_rphy(struct mptsas_phyinfo *phy_info) return NULL; } -static inline void -mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy) -{ - if (phy_info->port_details) { - phy_info->port_details->rphy = rphy; - dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n", - ioc->name, rphy)); - } - - if (rphy) { - dsaswideprintk(ioc, dev_printk(KERN_DEBUG, - &rphy->dev, MYIOC_s_FMT "add:", ioc->name)); - dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n", - ioc->name, rphy, rphy->dev.release)); - } -} - static inline struct sas_port * mptsas_get_port(struct mptsas_phyinfo *phy_info) { diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 727819c..ad74694 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1271,15 +1271,16 @@ mptscsih_info(struct Scsi_Host *SChost) h = shost_priv(SChost); - if (h) { - if (h->info_kbuf == NULL) - if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) - return h->info_kbuf; - h->info_kbuf[0] = '\0'; - - mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); - h->info_kbuf[size-1] = '\0'; - } + if (!h) + return NULL; + + if (h->info_kbuf == NULL) + if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) + return h->info_kbuf; + h->info_kbuf[0] = '\0'; + + mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); + h->info_kbuf[size-1] = '\0'; return h->info_kbuf; } diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index b7d87cd..9890039 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -255,12 +255,6 @@ static char *scsi_devices[] = { "Array Controller Device" }; -static char *chtostr(char *tmp, u8 *chars, int n) -{ - tmp[0] = 0; - return strncat(tmp, (char *)chars, n); -} - static int i2o_report_query_status(struct seq_file *seq, int block_status, char *group) { @@ -790,7 +784,6 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) } *result; i2o_exec_execute_ddm_table ddm_table; - char tmp[28 + 1]; result = kmalloc(sizeof(*result), GFP_KERNEL); if (!result) @@ -825,8 +818,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); seq_printf(seq, "%-#8x", ddm_table.module_id); - seq_printf(seq, "%-29s", - chtostr(tmp, ddm_table.module_name_version, 28)); + seq_printf(seq, "%-.28s", ddm_table.module_name_version); seq_printf(seq, "%9d ", ddm_table.data_size); seq_printf(seq, "%8d", ddm_table.code_size); @@ -893,7 +885,6 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) i2o_driver_result_table *result; i2o_driver_store_table *dst; - char tmp[28 + 1]; result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); if (result == NULL) @@ -928,9 +919,8 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) seq_printf(seq, "%-#7x", dst->i2o_vendor_id); seq_printf(seq, "%-#8x", dst->module_id); - seq_printf(seq, "%-29s", - chtostr(tmp, dst->module_name_version, 28)); - seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8)); + seq_printf(seq, "%-.28s", dst->module_name_version); + seq_printf(seq, "%-.8s", dst->date); seq_printf(seq, "%8d ", dst->module_size); seq_printf(seq, "%8d ", dst->mpb_size); seq_printf(seq, "0x%04x", dst->module_flags); @@ -1250,7 +1240,6 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) // == (allow) 512d bytes (max) static u16 *work16 = (u16 *) work32; int token; - char tmp[16 + 1]; token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); @@ -1262,14 +1251,10 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0])); seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); - seq_printf(seq, "Vendor info : %s\n", - chtostr(tmp, (u8 *) (work32 + 2), 16)); - seq_printf(seq, "Product info : %s\n", - chtostr(tmp, (u8 *) (work32 + 6), 16)); - seq_printf(seq, "Description : %s\n", - chtostr(tmp, (u8 *) (work32 + 10), 16)); - seq_printf(seq, "Product rev. : %s\n", - chtostr(tmp, (u8 *) (work32 + 14), 8)); + seq_printf(seq, "Vendor info : %.16s\n", (u8 *) (work32 + 2)); + seq_printf(seq, "Product info : %.16s\n", (u8 *) (work32 + 6)); + seq_printf(seq, "Description : %.16s\n", (u8 *) (work32 + 10)); + seq_printf(seq, "Product rev. : %.8s\n", (u8 *) (work32 + 14)); seq_printf(seq, "Serial number : "); print_serial_number(seq, (u8 *) (work32 + 16), @@ -1306,8 +1291,6 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) u8 pad[256]; // allow up to 256 byte (max) serial number } result; - char tmp[24 + 1]; - token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); if (token < 0) { @@ -1316,10 +1299,8 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) } seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); - seq_printf(seq, "Module name : %s\n", - chtostr(tmp, result.module_name, 24)); - seq_printf(seq, "Module revision : %s\n", - chtostr(tmp, result.module_rev, 8)); + seq_printf(seq, "Module name : %.24s\n", result.module_name); + seq_printf(seq, "Module revision : %.8s\n", result.module_rev); seq_printf(seq, "Serial number : "); print_serial_number(seq, result.serial_number, sizeof(result) - 36); @@ -1343,8 +1324,6 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) u8 instance_number[4]; } result; - char tmp[64 + 1]; - token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); if (token < 0) { @@ -1352,14 +1331,10 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) return 0; } - seq_printf(seq, "Device name : %s\n", - chtostr(tmp, result.device_name, 64)); - seq_printf(seq, "Service name : %s\n", - chtostr(tmp, result.service_name, 64)); - seq_printf(seq, "Physical name : %s\n", - chtostr(tmp, result.physical_location, 64)); - seq_printf(seq, "Instance number : %s\n", - chtostr(tmp, result.instance_number, 4)); + seq_printf(seq, "Device name : %.64s\n", result.device_name); + seq_printf(seq, "Service name : %.64s\n", result.service_name); + seq_printf(seq, "Physical name : %.64s\n", result.physical_location); + seq_printf(seq, "Instance number : %.4s\n", result.instance_number); return 0; } diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index a8c08f3..155fe3d 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -111,10 +111,10 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) spin_lock_irqsave(&c->context_list_lock, flags); - if (unlikely(atomic_inc_and_test(&c->context_list_counter))) - atomic_inc(&c->context_list_counter); + if (unlikely(atomic_inc_and_test_unchecked(&c->context_list_counter))) + atomic_inc_unchecked(&c->context_list_counter); - entry->context = atomic_read(&c->context_list_counter); + entry->context = atomic_read_unchecked(&c->context_list_counter); list_add(&entry->list, &c->context_list); @@ -1077,7 +1077,7 @@ struct i2o_controller *i2o_iop_alloc(void) #if BITS_PER_LONG == 64 spin_lock_init(&c->context_list_lock); - atomic_set(&c->context_list_counter, 0); + atomic_set_unchecked(&c->context_list_counter, 0); INIT_LIST_HEAD(&c->context_list); #endif diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 45ece11..8efa218 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index a5f9888..1c0ed56 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "twl-core.h" @@ -728,10 +729,12 @@ int twl4030_init_irq(struct device *dev, int irq_num) * Install an irq handler for each of the SIH modules; * clone dummy irq_chip since PIH can't *do* anything */ - twl4030_irq_chip = dummy_irq_chip; - twl4030_irq_chip.name = "twl4030"; + pax_open_kernel(); + memcpy((void *)&twl4030_irq_chip, &dummy_irq_chip, sizeof twl4030_irq_chip); + *(const char **)&twl4030_irq_chip.name = "twl4030"; - twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack; + *(void **)&twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack; + pax_close_kernel(); for (i = irq_base; i < irq_end; i++) { irq_set_chip_and_handler(i, &twl4030_irq_chip, diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index 277a8db..0e0b754 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c @@ -387,10 +387,12 @@ int twl6030_init_irq(struct device *dev, int irq_num) * install an irq handler for each of the modules; * clone dummy irq_chip since PIH can't *do* anything */ - twl6030_irq_chip = dummy_irq_chip; - twl6030_irq_chip.name = "twl6030"; - twl6030_irq_chip.irq_set_type = NULL; - twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; + pax_open_kernel(); + memcpy((void *)&twl6030_irq_chip, &dummy_irq_chip, sizeof twl6030_irq_chip); + *(const char **)&twl6030_irq_chip.name = "twl6030"; + *(void **)&twl6030_irq_chip.irq_set_type = NULL; + *(void **)&twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; + pax_close_kernel(); for (i = irq_base; i < irq_end; i++) { irq_set_chip_and_handler(i, &twl6030_irq_chip, diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index f32550a..e3e52a2 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -920,7 +920,9 @@ struct c2port_device *c2port_device_register(char *name, mutex_init(&c2dev->mutex); /* Create binary file */ - c2port_bin_attrs.size = ops->blocks_num * ops->block_size; + pax_open_kernel(); + *(size_t *)&c2port_bin_attrs.size = ops->blocks_num * ops->block_size; + pax_close_kernel(); ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); if (unlikely(ret)) goto error_device_create_bin_file; diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 36f5d52..32311c3 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -834,7 +834,7 @@ static void run_plant_and_detach_test(int is_early) char before[BREAK_INSTR_SIZE]; char after[BREAK_INSTR_SIZE]; - probe_kernel_read(before, (char *)kgdbts_break_test, + probe_kernel_read(before, ktla_ktva((char *)kgdbts_break_test), BREAK_INSTR_SIZE); init_simple_test(); ts.tst = plant_and_detach_test; @@ -842,7 +842,7 @@ static void run_plant_and_detach_test(int is_early) /* Activate test with initial breakpoint */ if (!is_early) kgdb_breakpoint(); - probe_kernel_read(after, (char *)kgdbts_break_test, + probe_kernel_read(after, ktla_ktva((char *)kgdbts_break_test), BREAK_INSTR_SIZE); if (memcmp(before, after, BREAK_INSTR_SIZE)) { printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n"); diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index 4cd4a3d..b48cbc7 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c @@ -498,7 +498,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *data) * the lid is closed. This leads to interrupts as soon as a little move * is done. */ - atomic_inc(&lis3->count); + atomic_inc_unchecked(&lis3->count); wake_up_interruptible(&lis3->misc_wait); kill_fasync(&lis3->async_queue, SIGIO, POLL_IN); @@ -584,7 +584,7 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file) if (lis3->pm_dev) pm_runtime_get_sync(lis3->pm_dev); - atomic_set(&lis3->count, 0); + atomic_set_unchecked(&lis3->count, 0); return 0; } @@ -616,7 +616,7 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, add_wait_queue(&lis3->misc_wait, &wait); while (true) { set_current_state(TASK_INTERRUPTIBLE); - data = atomic_xchg(&lis3->count, 0); + data = atomic_xchg_unchecked(&lis3->count, 0); if (data) break; @@ -657,7 +657,7 @@ static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) struct lis3lv02d, miscdev); poll_wait(file, &lis3->misc_wait, wait); - if (atomic_read(&lis3->count)) + if (atomic_read_unchecked(&lis3->count)) return POLLIN | POLLRDNORM; return 0; } diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h index c439c82..1f20f57 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.h +++ b/drivers/misc/lis3lv02d/lis3lv02d.h @@ -297,7 +297,7 @@ struct lis3lv02d { struct input_polled_dev *idev; /* input device */ struct platform_device *pdev; /* platform device */ struct regulator_bulk_data regulators[2]; - atomic_t count; /* interrupt count after last read */ + atomic_unchecked_t count; /* interrupt count after last read */ union axis_conversion ac; /* hw -> logical axis */ int mapped_btns[3]; diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c index 2f30bad..c4c13d0 100644 --- a/drivers/misc/sgi-gru/gruhandles.c +++ b/drivers/misc/sgi-gru/gruhandles.c @@ -44,8 +44,8 @@ static void update_mcs_stats(enum mcs_op op, unsigned long clks) unsigned long nsec; nsec = CLKS2NSEC(clks); - atomic_long_inc(&mcs_op_statistics[op].count); - atomic_long_add(nsec, &mcs_op_statistics[op].total); + atomic_long_inc_unchecked(&mcs_op_statistics[op].count); + atomic_long_add_unchecked(nsec, &mcs_op_statistics[op].total); if (mcs_op_statistics[op].max < nsec) mcs_op_statistics[op].max = nsec; } diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c index 797d796..ae8f01e 100644 --- a/drivers/misc/sgi-gru/gruprocfs.c +++ b/drivers/misc/sgi-gru/gruprocfs.c @@ -32,9 +32,9 @@ #define printstat(s, f) printstat_val(s, &gru_stats.f, #f) -static void printstat_val(struct seq_file *s, atomic_long_t *v, char *id) +static void printstat_val(struct seq_file *s, atomic_long_unchecked_t *v, char *id) { - unsigned long val = atomic_long_read(v); + unsigned long val = atomic_long_read_unchecked(v); seq_printf(s, "%16lu %s\n", val, id); } @@ -134,8 +134,8 @@ static int mcs_statistics_show(struct seq_file *s, void *p) seq_printf(s, "%-20s%12s%12s%12s\n", "#id", "count", "aver-clks", "max-clks"); for (op = 0; op < mcsop_last; op++) { - count = atomic_long_read(&mcs_op_statistics[op].count); - total = atomic_long_read(&mcs_op_statistics[op].total); + count = atomic_long_read_unchecked(&mcs_op_statistics[op].count); + total = atomic_long_read_unchecked(&mcs_op_statistics[op].total); max = mcs_op_statistics[op].max; seq_printf(s, "%-20s%12ld%12ld%12ld\n", id[op], count, count ? total / count : 0, max); diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index 5c3ce24..4915ccb 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h @@ -167,82 +167,82 @@ extern unsigned int gru_max_gids; * GRU statistics. */ struct gru_stats_s { - atomic_long_t vdata_alloc; - atomic_long_t vdata_free; - atomic_long_t gts_alloc; - atomic_long_t gts_free; - atomic_long_t gms_alloc; - atomic_long_t gms_free; - atomic_long_t gts_double_allocate; - atomic_long_t assign_context; - atomic_long_t assign_context_failed; - atomic_long_t free_context; - atomic_long_t load_user_context; - atomic_long_t load_kernel_context; - atomic_long_t lock_kernel_context; - atomic_long_t unlock_kernel_context; - atomic_long_t steal_user_context; - atomic_long_t steal_kernel_context; - atomic_long_t steal_context_failed; - atomic_long_t nopfn; - atomic_long_t asid_new; - atomic_long_t asid_next; - atomic_long_t asid_wrap; - atomic_long_t asid_reuse; - atomic_long_t intr; - atomic_long_t intr_cbr; - atomic_long_t intr_tfh; - atomic_long_t intr_spurious; - atomic_long_t intr_mm_lock_failed; - atomic_long_t call_os; - atomic_long_t call_os_wait_queue; - atomic_long_t user_flush_tlb; - atomic_long_t user_unload_context; - atomic_long_t user_exception; - atomic_long_t set_context_option; - atomic_long_t check_context_retarget_intr; - atomic_long_t check_context_unload; - atomic_long_t tlb_dropin; - atomic_long_t tlb_preload_page; - atomic_long_t tlb_dropin_fail_no_asid; - atomic_long_t tlb_dropin_fail_upm; - atomic_long_t tlb_dropin_fail_invalid; - atomic_long_t tlb_dropin_fail_range_active; - atomic_long_t tlb_dropin_fail_idle; - atomic_long_t tlb_dropin_fail_fmm; - atomic_long_t tlb_dropin_fail_no_exception; - atomic_long_t tfh_stale_on_fault; - atomic_long_t mmu_invalidate_range; - atomic_long_t mmu_invalidate_page; - atomic_long_t flush_tlb; - atomic_long_t flush_tlb_gru; - atomic_long_t flush_tlb_gru_tgh; - atomic_long_t flush_tlb_gru_zero_asid; - - atomic_long_t copy_gpa; - atomic_long_t read_gpa; - - atomic_long_t mesq_receive; - atomic_long_t mesq_receive_none; - atomic_long_t mesq_send; - atomic_long_t mesq_send_failed; - atomic_long_t mesq_noop; - atomic_long_t mesq_send_unexpected_error; - atomic_long_t mesq_send_lb_overflow; - atomic_long_t mesq_send_qlimit_reached; - atomic_long_t mesq_send_amo_nacked; - atomic_long_t mesq_send_put_nacked; - atomic_long_t mesq_page_overflow; - atomic_long_t mesq_qf_locked; - atomic_long_t mesq_qf_noop_not_full; - atomic_long_t mesq_qf_switch_head_failed; - atomic_long_t mesq_qf_unexpected_error; - atomic_long_t mesq_noop_unexpected_error; - atomic_long_t mesq_noop_lb_overflow; - atomic_long_t mesq_noop_qlimit_reached; - atomic_long_t mesq_noop_amo_nacked; - atomic_long_t mesq_noop_put_nacked; - atomic_long_t mesq_noop_page_overflow; + atomic_long_unchecked_t vdata_alloc; + atomic_long_unchecked_t vdata_free; + atomic_long_unchecked_t gts_alloc; + atomic_long_unchecked_t gts_free; + atomic_long_unchecked_t gms_alloc; + atomic_long_unchecked_t gms_free; + atomic_long_unchecked_t gts_double_allocate; + atomic_long_unchecked_t assign_context; + atomic_long_unchecked_t assign_context_failed; + atomic_long_unchecked_t free_context; + atomic_long_unchecked_t load_user_context; + atomic_long_unchecked_t load_kernel_context; + atomic_long_unchecked_t lock_kernel_context; + atomic_long_unchecked_t unlock_kernel_context; + atomic_long_unchecked_t steal_user_context; + atomic_long_unchecked_t steal_kernel_context; + atomic_long_unchecked_t steal_context_failed; + atomic_long_unchecked_t nopfn; + atomic_long_unchecked_t asid_new; + atomic_long_unchecked_t asid_next; + atomic_long_unchecked_t asid_wrap; + atomic_long_unchecked_t asid_reuse; + atomic_long_unchecked_t intr; + atomic_long_unchecked_t intr_cbr; + atomic_long_unchecked_t intr_tfh; + atomic_long_unchecked_t intr_spurious; + atomic_long_unchecked_t intr_mm_lock_failed; + atomic_long_unchecked_t call_os; + atomic_long_unchecked_t call_os_wait_queue; + atomic_long_unchecked_t user_flush_tlb; + atomic_long_unchecked_t user_unload_context; + atomic_long_unchecked_t user_exception; + atomic_long_unchecked_t set_context_option; + atomic_long_unchecked_t check_context_retarget_intr; + atomic_long_unchecked_t check_context_unload; + atomic_long_unchecked_t tlb_dropin; + atomic_long_unchecked_t tlb_preload_page; + atomic_long_unchecked_t tlb_dropin_fail_no_asid; + atomic_long_unchecked_t tlb_dropin_fail_upm; + atomic_long_unchecked_t tlb_dropin_fail_invalid; + atomic_long_unchecked_t tlb_dropin_fail_range_active; + atomic_long_unchecked_t tlb_dropin_fail_idle; + atomic_long_unchecked_t tlb_dropin_fail_fmm; + atomic_long_unchecked_t tlb_dropin_fail_no_exception; + atomic_long_unchecked_t tfh_stale_on_fault; + atomic_long_unchecked_t mmu_invalidate_range; + atomic_long_unchecked_t mmu_invalidate_page; + atomic_long_unchecked_t flush_tlb; + atomic_long_unchecked_t flush_tlb_gru; + atomic_long_unchecked_t flush_tlb_gru_tgh; + atomic_long_unchecked_t flush_tlb_gru_zero_asid; + + atomic_long_unchecked_t copy_gpa; + atomic_long_unchecked_t read_gpa; + + atomic_long_unchecked_t mesq_receive; + atomic_long_unchecked_t mesq_receive_none; + atomic_long_unchecked_t mesq_send; + atomic_long_unchecked_t mesq_send_failed; + atomic_long_unchecked_t mesq_noop; + atomic_long_unchecked_t mesq_send_unexpected_error; + atomic_long_unchecked_t mesq_send_lb_overflow; + atomic_long_unchecked_t mesq_send_qlimit_reached; + atomic_long_unchecked_t mesq_send_amo_nacked; + atomic_long_unchecked_t mesq_send_put_nacked; + atomic_long_unchecked_t mesq_page_overflow; + atomic_long_unchecked_t mesq_qf_locked; + atomic_long_unchecked_t mesq_qf_noop_not_full; + atomic_long_unchecked_t mesq_qf_switch_head_failed; + atomic_long_unchecked_t mesq_qf_unexpected_error; + atomic_long_unchecked_t mesq_noop_unexpected_error; + atomic_long_unchecked_t mesq_noop_lb_overflow; + atomic_long_unchecked_t mesq_noop_qlimit_reached; + atomic_long_unchecked_t mesq_noop_amo_nacked; + atomic_long_unchecked_t mesq_noop_put_nacked; + atomic_long_unchecked_t mesq_noop_page_overflow; }; @@ -251,8 +251,8 @@ enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync, tghop_invalidate, mcsop_last}; struct mcs_op_statistic { - atomic_long_t count; - atomic_long_t total; + atomic_long_unchecked_t count; + atomic_long_unchecked_t total; unsigned long max; }; @@ -275,7 +275,7 @@ extern struct mcs_op_statistic mcs_op_statistics[mcsop_last]; #define STAT(id) do { \ if (gru_options & OPT_STATS) \ - atomic_long_inc(&gru_stats.id); \ + atomic_long_inc_unchecked(&gru_stats.id); \ } while (0) #ifdef CONFIG_SGI_GRU_DEBUG diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index c862cd4..0d176fe 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -288,7 +288,7 @@ struct xpc_interface { xpc_notify_func, void *); void (*received) (short, int, void *); enum xp_retval (*partid_to_nasids) (short, void *); -}; +} __no_const; extern struct xpc_interface xpc_interface; diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index b94d5f7..7f494c5 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h @@ -835,6 +835,7 @@ struct xpc_arch_operations { void (*received_payload) (struct xpc_channel *, void *); void (*notify_senders_of_disconnect) (struct xpc_channel *); }; +typedef struct xpc_arch_operations __no_const xpc_arch_operations_no_const; /* struct xpc_partition act_state values (for XPC HB) */ @@ -876,7 +877,7 @@ extern struct xpc_registration xpc_registrations[]; /* found in xpc_main.c */ extern struct device *xpc_part; extern struct device *xpc_chan; -extern struct xpc_arch_operations xpc_arch_ops; +extern xpc_arch_operations_no_const xpc_arch_ops; extern int xpc_disengage_timelimit; extern int xpc_disengage_timedout; extern int xpc_activate_IRQ_rcvd; diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index d971817..33bdca5 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -166,7 +166,7 @@ static struct notifier_block xpc_die_notifier = { .notifier_call = xpc_system_die, }; -struct xpc_arch_operations xpc_arch_ops; +xpc_arch_operations_no_const xpc_arch_ops; /* * Timer function to enforce the timelimit on the partition disengage. @@ -1210,7 +1210,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) if (((die_args->trapnr == X86_TRAP_MF) || (die_args->trapnr == X86_TRAP_XF)) && - !user_mode_vm(die_args->regs)) + !user_mode(die_args->regs)) xpc_die_deactivate(); break; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 49f04bc..65660c2 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -247,7 +247,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, void *data_buf; int is_on_stack; - is_on_stack = object_is_on_stack(buf); + is_on_stack = object_starts_on_stack(buf); if (is_on_stack) { /* * dma onto stack is unsafe/nonportable, but callers to this diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 0b74189..818358f 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -202,5 +202,5 @@ struct dw_mci_drv_data { void (*prepare_command)(struct dw_mci *host, u32 *cmdr); void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); int (*parse_dt)(struct dw_mci *host); -}; +} __do_const; #endif /* _DW_MMC_H_ */ diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index c6f6246..60760a8 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -664,9 +664,11 @@ static int sdhci_s3c_probe(struct platform_device *pdev) * we can use overriding functions instead of default. */ if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { - sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; - sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; - sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; + pax_open_kernel(); + *(void **)&sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; + *(void **)&sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; + *(void **)&sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; + pax_close_kernel(); } /* It supports additional host capabilities if needed */ diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 0c8bb6b..6f35deb 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "denali.h" diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 51b9d6a..52af9a7 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index f9d5615..99dd95f 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -56,7 +56,7 @@ ssize_t sm_attr_show(struct device *dev, struct device_attribute *attr, #define SM_CIS_VENDOR_OFFSET 0x59 struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) { - struct attribute_group *attr_group; + attribute_group_no_const *attr_group; struct attribute **attributes; struct sm_sysfs_attribute *vendor_attribute; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 666cf3a..60693be 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4876,7 +4876,7 @@ static unsigned int bond_get_num_tx_queues(void) return tx_queues; } -static struct rtnl_link_ops bond_link_ops __read_mostly = { +static struct rtnl_link_ops bond_link_ops = { .kind = "bond", .priv_size = sizeof(struct bonding), .setup = bond_setup, @@ -5001,8 +5001,8 @@ static void __exit bonding_exit(void) bond_destroy_debugfs(); - rtnl_link_unregister(&bond_link_ops); unregister_pernet_subsys(&bond_net_ops); + rtnl_link_unregister(&bond_link_ops); #ifdef CONFIG_NET_POLL_CONTROLLER /* diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index e1d2643..7f4133b 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -872,9 +872,11 @@ static int ax_probe(struct platform_device *pdev) if (ax->plat->reg_offsets) ei_local->reg_offset = ax->plat->reg_offsets; else { + resource_size_t _mem_size = mem_size; + do_div(_mem_size, 0x18); ei_local->reg_offset = ax->reg_offsets; for (ret = 0; ret < 0x18; ret++) - ax->reg_offsets[ret] = (mem_size / 0x18) * ret; + ax->reg_offsets[ret] = _mem_size * ret; } if (!request_mem_region(mem->start, mem_size, pdev->name)) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 151675d..0139a9d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -1112,7 +1112,7 @@ static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp) static inline void bnx2x_init_bp_objs(struct bnx2x *bp) { /* RX_MODE controlling object */ - bnx2x_init_rx_mode_obj(bp, &bp->rx_mode_obj); + bnx2x_init_rx_mode_obj(bp); /* multicast configuration controlling object */ bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index ce1a916..10b52b0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -960,6 +960,9 @@ static int bnx2x_set_dump(struct net_device *dev, struct ethtool_dump *val) struct bnx2x *bp = netdev_priv(dev); /* Use the ethtool_dump "flag" field as the dump preset index */ + if (val->flag < 1 || val->flag > DUMP_MAX_PRESETS) + return -EINVAL; + bp->dump_preset_idx = val->flag; return 0; } @@ -986,8 +989,6 @@ static int bnx2x_get_dump_data(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); struct dump_header dump_hdr = {0}; - memset(p, 0, dump->len); - /* Disable parity attentions as long as following dump may * cause false alarms by reading never written registers. We * will re-enable parity attentions right after the dump. diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index b4c9dea..2a9927f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11497,6 +11497,8 @@ static int bnx2x_init_bp(struct bnx2x *bp) bp->min_msix_vec_cnt = 2; BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt); + bp->dump_preset_idx = 1; + return rc; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 32a9609..0b1c53a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -2387,15 +2387,14 @@ int bnx2x_config_rx_mode(struct bnx2x *bp, return rc; } -void bnx2x_init_rx_mode_obj(struct bnx2x *bp, - struct bnx2x_rx_mode_obj *o) +void bnx2x_init_rx_mode_obj(struct bnx2x *bp) { if (CHIP_IS_E1x(bp)) { - o->wait_comp = bnx2x_empty_rx_mode_wait; - o->config_rx_mode = bnx2x_set_rx_mode_e1x; + bp->rx_mode_obj.wait_comp = bnx2x_empty_rx_mode_wait; + bp->rx_mode_obj.config_rx_mode = bnx2x_set_rx_mode_e1x; } else { - o->wait_comp = bnx2x_wait_rx_mode_comp_e2; - o->config_rx_mode = bnx2x_set_rx_mode_e2; + bp->rx_mode_obj.wait_comp = bnx2x_wait_rx_mode_comp_e2; + bp->rx_mode_obj.config_rx_mode = bnx2x_set_rx_mode_e2; } } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index 43c00bc..dd1d03d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -1321,8 +1321,7 @@ int bnx2x_vlan_mac_move(struct bnx2x *bp, /********************* RX MODE ****************/ -void bnx2x_init_rx_mode_obj(struct bnx2x *bp, - struct bnx2x_rx_mode_obj *o); +void bnx2x_init_rx_mode_obj(struct bnx2x *bp); /** * bnx2x_config_rx_mode - Send and RX_MODE ramrod according to the provided parameters. diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index ff6e30e..87e8452 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -147,6 +147,7 @@ #define CHIPREV_ID_5750_A0 0x4000 #define CHIPREV_ID_5750_A1 0x4001 #define CHIPREV_ID_5750_A3 0x4003 +#define CHIPREV_ID_5750_C1 0x4201 #define CHIPREV_ID_5750_C2 0x4202 #define CHIPREV_ID_5752_A0_HW 0x5000 #define CHIPREV_ID_5752_A0 0x6000 diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 71497e8..b650951 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -3037,7 +3037,9 @@ static void t3_io_resume(struct pci_dev *pdev) CH_ALERT(adapter, "adapter recovering, PEX ERR 0x%x\n", t3_read_reg(adapter, A_PCIE_PEX_ERR)); + rtnl_lock(); t3_resume_ports(adapter); + rtnl_unlock(); } static const struct pci_error_handlers t3_err_handler = { diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h index 8cffcdf..aadf043 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h +++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h @@ -87,7 +87,7 @@ typedef void (*arp_failure_handler_func)(struct t3cdev * dev, */ struct l2t_skb_cb { arp_failure_handler_func arp_failure_handler; -}; +} __no_const; #define L2T_SKB_CB(skb) ((struct l2t_skb_cb *)(skb)->cb) diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 4c83003..2a2a5b9 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -5388,7 +5388,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) for (i=0; idev_addr[i]; } - if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; + if (ioc->len > sizeof tmp.addr || copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; case DE4X5_SET_HWADDR: /* Set the hardware address */ @@ -5428,7 +5428,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) spin_lock_irqsave(&lp->lock, flags); memcpy(&statbuf, &lp->pktStats, ioc->len); spin_unlock_irqrestore(&lp->lock, flags); - if (copy_to_user(ioc->data, &statbuf, ioc->len)) + if (ioc->len > sizeof statbuf || copy_to_user(ioc->data, &statbuf, ioc->len)) return -EFAULT; break; } diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 7371626..2d90469 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -469,7 +469,7 @@ static void accumulate_16bit_val(u32 *acc, u16 val) if (wrapped) newacc += 65536; - ACCESS_ONCE(*acc) = newacc; + ACCESS_ONCE_RW(*acc) = newacc; } void populate_erx_stats(struct be_adapter *adapter, diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 21b85fb..b49e5fc 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include "ftgmac100.h" diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index a6eda8d..935d273 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include "ftmac100.h" diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 331987d..3be1135 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -776,7 +776,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) } /* update the base incval used to calculate frequency adjustment */ - ACCESS_ONCE(adapter->base_incval) = incval; + ACCESS_ONCE_RW(adapter->base_incval) = incval; smp_mb(); /* need lock to prevent incorrect read while modifying cyclecounter */ diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c index fbe5363..266b4e3 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -3461,7 +3461,10 @@ __vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp, struct __vxge_hw_fifo *fifo; struct vxge_hw_fifo_config *config; u32 txdl_size, txdl_per_memblock; - struct vxge_hw_mempool_cbs fifo_mp_callback; + static struct vxge_hw_mempool_cbs fifo_mp_callback = { + .item_func_alloc = __vxge_hw_fifo_mempool_item_alloc, + }; + struct __vxge_hw_virtualpath *vpath; if ((vp == NULL) || (attr == NULL)) { @@ -3544,8 +3547,6 @@ __vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp, goto exit; } - fifo_mp_callback.item_func_alloc = __vxge_hw_fifo_mempool_item_alloc; - fifo->mempool = __vxge_hw_mempool_create(vpath->hldev, fifo->config->memblock_size, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 5e7fb1d..f8d1810 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -1948,7 +1948,9 @@ int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter) op_mode = QLC_83XX_DEFAULT_OPMODE; if (op_mode == QLC_83XX_DEFAULT_OPMODE) { - adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; + pax_open_kernel(); + *(void **)&adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; + pax_close_kernel(); ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; } else { return -EIO; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index b0c3de9..fc5857e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c @@ -200,15 +200,21 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) if (priv_level == QLCNIC_NON_PRIV_FUNC) { ahw->op_mode = QLCNIC_NON_PRIV_FUNC; ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; - nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic; + pax_open_kernel(); + *(void **)&nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic; + pax_close_kernel(); } else if (priv_level == QLCNIC_PRIV_FUNC) { ahw->op_mode = QLCNIC_PRIV_FUNC; ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry; - nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic; + pax_open_kernel(); + *(void **)&nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic; + pax_close_kernel(); } else if (priv_level == QLCNIC_MGMT_FUNC) { ahw->op_mode = QLCNIC_MGMT_FUNC; ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; - nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic; + pax_open_kernel(); + *(void **)&nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic; + pax_close_kernel(); } else { return -EIO; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 6acf82b..14b097e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -206,10 +206,10 @@ int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter) if (err) { dev_info(&adapter->pdev->dev, "Failed to set driver version in firmware\n"); - return -EIO; + err = -EIO; } - - return 0; + qlcnic_free_mbx_args(&cmd); + return err; } int diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index d3f8797..82a03d3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c @@ -262,7 +262,7 @@ void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr, mac_req = (struct qlcnic_mac_req *)&(req->words[0]); mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD; - memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN); + memcpy(mac_req->mac_addr, uaddr, ETH_ALEN); vlan_req = (struct qlcnic_vlan_req *)&req->words[1]; vlan_req->vlan_id = cpu_to_le16(vlan_id); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 393f961..d343034 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -753,22 +753,22 @@ struct rtl8169_private { struct mdio_ops { void (*write)(struct rtl8169_private *, int, int); int (*read)(struct rtl8169_private *, int); - } mdio_ops; + } __no_const mdio_ops; struct pll_power_ops { void (*down)(struct rtl8169_private *); void (*up)(struct rtl8169_private *); - } pll_power_ops; + } __no_const pll_power_ops; struct jumbo_ops { void (*enable)(struct rtl8169_private *); void (*disable)(struct rtl8169_private *); - } jumbo_ops; + } __no_const jumbo_ops; struct csi_ops { void (*write)(struct rtl8169_private *, int, int); u32 (*read)(struct rtl8169_private *, int); - } csi_ops; + } __no_const csi_ops; int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); int (*get_settings)(struct net_device *, struct ethtool_cmd *); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 9a95abf..36df7f9 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -535,7 +535,7 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings) (u32)((u64)ptp->start.dma_addr >> 32)); /* Clear flag that signals MC ready */ - ACCESS_ONCE(*start) = 0; + ACCESS_ONCE_RW(*start) = 0; efx_mcdi_rpc_start(efx, MC_CMD_PTP, synch_buf, MC_CMD_PTP_IN_SYNCHRONIZE_LEN); diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index 50617c5..b13724c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -140,8 +140,8 @@ void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode) writel(value, ioaddr + MMC_CNTRL); - pr_debug("stmmac: MMC ctrl register (offset 0x%x): 0x%08x\n", - MMC_CNTRL, value); +// pr_debug("stmmac: MMC ctrl register (offset 0x%x): 0x%08x\n", +// MMC_CNTRL, value); } /* To mask all all interrupts.*/ diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index e6fe0d8..2b7d752 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -101,7 +101,7 @@ struct rndis_device { enum rndis_device_state state; bool link_state; - atomic_t new_req_id; + atomic_unchecked_t new_req_id; spinlock_t request_lock; struct list_head req_list; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 0775f0a..d4fb316 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -104,7 +104,7 @@ static struct rndis_request *get_rndis_request(struct rndis_device *dev, * template */ set = &rndis_msg->msg.set_req; - set->req_id = atomic_inc_return(&dev->new_req_id); + set->req_id = atomic_inc_return_unchecked(&dev->new_req_id); /* Add to the request list */ spin_lock_irqsave(&dev->request_lock, flags); @@ -752,7 +752,7 @@ static void rndis_filter_halt_device(struct rndis_device *dev) /* Setup the rndis set */ halt = &request->request_msg.msg.halt_req; - halt->req_id = atomic_inc_return(&dev->new_req_id); + halt->req_id = atomic_inc_return_unchecked(&dev->new_req_id); /* Ignore return since this msg is optional. */ rndis_filter_send_request(dev, request); diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c index bf0d55e..82bcfbd 100644 --- a/drivers/net/ieee802154/fakehard.c +++ b/drivers/net/ieee802154/fakehard.c @@ -364,7 +364,7 @@ static int ieee802154fake_probe(struct platform_device *pdev) phy->transmit_power = 0xbf; dev->netdev_ops = &fake_ops; - dev->ml_priv = &fake_mlme; + dev->ml_priv = (void *)&fake_mlme; priv = netdev_priv(dev); priv->phy = phy; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 06eba6e..a06bf31 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -909,13 +909,15 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { int macvlan_link_register(struct rtnl_link_ops *ops) { /* common fields */ - ops->priv_size = sizeof(struct macvlan_dev); - ops->validate = macvlan_validate; - ops->maxtype = IFLA_MACVLAN_MAX; - ops->policy = macvlan_policy; - ops->changelink = macvlan_changelink; - ops->get_size = macvlan_get_size; - ops->fill_info = macvlan_fill_info; + pax_open_kernel(); + *(size_t *)&ops->priv_size = sizeof(struct macvlan_dev); + *(void **)&ops->validate = macvlan_validate; + *(int *)&ops->maxtype = IFLA_MACVLAN_MAX; + *(const void **)&ops->policy = macvlan_policy; + *(void **)&ops->changelink = macvlan_changelink; + *(void **)&ops->get_size = macvlan_get_size; + *(void **)&ops->fill_info = macvlan_fill_info; + pax_close_kernel(); return rtnl_link_register(ops); }; @@ -971,7 +973,7 @@ static int macvlan_device_event(struct notifier_block *unused, return NOTIFY_DONE; } -static struct notifier_block macvlan_notifier_block __read_mostly = { +static struct notifier_block macvlan_notifier_block = { .notifier_call = macvlan_device_event, }; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 523d6b2..5e16aa1 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -1110,7 +1110,7 @@ static int macvtap_device_event(struct notifier_block *unused, return NOTIFY_DONE; } -static struct notifier_block macvtap_notifier_block __read_mostly = { +static struct notifier_block macvtap_notifier_block = { .notifier_call = macvtap_device_event, }; diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index daec9b0..6428fcb 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus) struct mdiobb_ctrl *ctrl = bus->priv; module_put(ctrl->ops->owner); + mdiobus_unregister(bus); mdiobus_free(bus); } EXPORT_SYMBOL(free_mdio_bitbang); diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 72ff14b..11d442d 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -999,7 +999,6 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) void __user *addr = (void __user *) ifr->ifr_ifru.ifru_data; struct ppp_stats stats; struct ppp_comp_stats cstats; - char *vers; switch (cmd) { case SIOCGPPPSTATS: @@ -1021,8 +1020,7 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; case SIOCGPPPVER: - vers = PPP_VERSION; - if (copy_to_user(addr, vers, strlen(vers) + 1)) + if (copy_to_user(addr, PPP_VERSION, sizeof(PPP_VERSION))) break; err = 0; break; diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index 1252d9c..80e660b 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -488,7 +488,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) register struct tcphdr *thp; register struct iphdr *ip; register struct cstate *cs; - int len, hdrlen; + long len, hdrlen; unsigned char *cp = icp; /* We've got a compressed packet; read the change byte */ diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index b305105..8ead6df 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2682,7 +2682,7 @@ static int team_device_event(struct notifier_block *unused, return NOTIFY_DONE; } -static struct notifier_block team_notifier_block __read_mostly = { +static struct notifier_block team_notifier_block = { .notifier_call = team_device_event, }; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7b54f4f..1a453eb 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1871,7 +1871,7 @@ unlock: } static long __tun_chr_ioctl(struct file *file, unsigned int cmd, - unsigned long arg, int ifreq_len) + unsigned long arg, size_t ifreq_len) { struct tun_file *tfile = file->private_data; struct tun_struct *tun; @@ -1883,6 +1883,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, int vnet_hdr_sz; int ret; + if (ifreq_len > sizeof ifr) + return -EFAULT; + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) { if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index cba1d46..f703766 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -71,7 +71,7 @@ #include #include #include - +#include #define MOD_AUTHOR "Option Wireless" #define MOD_DESCRIPTION "USB High Speed Option driver" @@ -1180,7 +1180,7 @@ static void put_rxbuf_data_and_resubmit_ctrl_urb(struct hso_serial *serial) struct urb *urb; urb = serial->rx_urb[0]; - if (serial->port.count > 0) { + if (atomic_read(&serial->port.count) > 0) { count = put_rxbuf_data(urb, serial); if (count == -1) return; @@ -1216,7 +1216,7 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) DUMP1(urb->transfer_buffer, urb->actual_length); /* Anyone listening? */ - if (serial->port.count == 0) + if (atomic_read(&serial->port.count) == 0) return; if (status == 0) { @@ -1298,8 +1298,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) tty_port_tty_set(&serial->port, tty); /* check for port already opened, if not set the termios */ - serial->port.count++; - if (serial->port.count == 1) { + if (atomic_inc_return(&serial->port.count) == 1) { serial->rx_state = RX_IDLE; /* Force default termio settings */ _hso_serial_set_termios(tty, NULL); @@ -1311,7 +1310,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) result = hso_start_serial_device(serial->parent, GFP_KERNEL); if (result) { hso_stop_serial_device(serial->parent); - serial->port.count--; + atomic_dec(&serial->port.count); kref_put(&serial->parent->ref, hso_serial_ref_free); } } else { @@ -1348,10 +1347,10 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) /* reset the rts and dtr */ /* do the actual close */ - serial->port.count--; + atomic_dec(&serial->port.count); - if (serial->port.count <= 0) { - serial->port.count = 0; + if (atomic_read(&serial->port.count) <= 0) { + atomic_set(&serial->port.count, 0); tty_port_tty_set(&serial->port, NULL); if (!usb_gone) hso_stop_serial_device(serial->parent); @@ -1427,7 +1426,7 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) /* the actual setup */ spin_lock_irqsave(&serial->serial_lock, flags); - if (serial->port.count) + if (atomic_read(&serial->port.count)) _hso_serial_set_termios(tty, old); else tty->termios = *old; @@ -1886,7 +1885,7 @@ static void intr_callback(struct urb *urb) D1("Pending read interrupt on port %d\n", i); spin_lock(&serial->serial_lock); if (serial->rx_state == RX_IDLE && - serial->port.count > 0) { + atomic_read(&serial->port.count) > 0) { /* Setup and send a ctrl req read on * port i */ if (!serial->rx_urb_filled[0]) { @@ -3057,7 +3056,7 @@ static int hso_resume(struct usb_interface *iface) /* Start all serial ports */ for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) { if (serial_table[i] && (serial_table[i]->interface == iface)) { - if (dev2ser(serial_table[i])->port.count) { + if (atomic_read(&dev2ser(serial_table[i])->port.count)) { result = hso_start_serial_device(serial_table[i], GFP_NOIO); hso_kick_transmit(dev2ser(serial_table[i])); diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index a79e9d3..78cd4fa 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -52,7 +52,7 @@ static const char driver_name[] = "sierra_net"; /* atomic counter partially included in MAC address to make sure 2 devices * do not end up with the same MAC - concept breaks in case of > 255 ifaces */ -static atomic_t iface_counter = ATOMIC_INIT(0); +static atomic_unchecked_t iface_counter = ATOMIC_INIT(0); /* * SYNC Timer Delay definition used to set the expiry time @@ -698,7 +698,7 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->netdev_ops = &sierra_net_device_ops; /* change MAC addr to include, ifacenum, and to be unique */ - dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); + dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return_unchecked(&iface_counter); dev->net->dev_addr[ETH_ALEN-1] = ifacenum; /* we will have to manufacture ethernet headers, prepare template */ diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 054489f..aee050a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1579,7 +1579,7 @@ nla_put_failure: return -EMSGSIZE; } -static struct rtnl_link_ops vxlan_link_ops __read_mostly = { +static struct rtnl_link_ops vxlan_link_ops = { .kind = "vxlan", .maxtype = IFLA_VXLAN_MAX, .policy = vxlan_policy, diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 34c8a33..3261fdc 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -353,7 +353,7 @@ static int at76_dfu_get_state(struct usb_device *udev, u8 *state) } /* Convert timeout from the DFU status to jiffies */ -static inline unsigned long at76_get_timeout(struct dfu_status *s) +static inline unsigned long __intentional_overflow(-1) at76_get_timeout(struct dfu_status *s) { return msecs_to_jiffies((s->poll_timeout[2] << 16) | (s->poll_timeout[1] << 8) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 8d78253..bebbb68 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -184,8 +184,8 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ads->ds_txstatus6 = ads->ds_txstatus7 = 0; ads->ds_txstatus8 = ads->ds_txstatus9 = 0; - ACCESS_ONCE(ads->ds_link) = i->link; - ACCESS_ONCE(ads->ds_data) = i->buf_addr[0]; + ACCESS_ONCE_RW(ads->ds_link) = i->link; + ACCESS_ONCE_RW(ads->ds_data) = i->buf_addr[0]; ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore); ctl6 = SM(i->keytype, AR_EncrType); @@ -199,26 +199,26 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) if ((i->is_first || i->is_last) && i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) { - ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0) + ACCESS_ONCE_RW(ads->ds_ctl2) = set11nTries(i->rates, 0) | set11nTries(i->rates, 1) | set11nTries(i->rates, 2) | set11nTries(i->rates, 3) | (i->dur_update ? AR_DurUpdateEna : 0) | SM(0, AR_BurstDur); - ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0) + ACCESS_ONCE_RW(ads->ds_ctl3) = set11nRate(i->rates, 0) | set11nRate(i->rates, 1) | set11nRate(i->rates, 2) | set11nRate(i->rates, 3); } else { - ACCESS_ONCE(ads->ds_ctl2) = 0; - ACCESS_ONCE(ads->ds_ctl3) = 0; + ACCESS_ONCE_RW(ads->ds_ctl2) = 0; + ACCESS_ONCE_RW(ads->ds_ctl3) = 0; } if (!i->is_first) { - ACCESS_ONCE(ads->ds_ctl0) = 0; - ACCESS_ONCE(ads->ds_ctl1) = ctl1; - ACCESS_ONCE(ads->ds_ctl6) = ctl6; + ACCESS_ONCE_RW(ads->ds_ctl0) = 0; + ACCESS_ONCE_RW(ads->ds_ctl1) = ctl1; + ACCESS_ONCE_RW(ads->ds_ctl6) = ctl6; return; } @@ -243,7 +243,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) break; } - ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) + ACCESS_ONCE_RW(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(i->txpower, AR_XmitPower) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) @@ -253,19 +253,19 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); - ACCESS_ONCE(ads->ds_ctl1) = ctl1; - ACCESS_ONCE(ads->ds_ctl6) = ctl6; + ACCESS_ONCE_RW(ads->ds_ctl1) = ctl1; + ACCESS_ONCE_RW(ads->ds_ctl6) = ctl6; if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST) return; - ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0) + ACCESS_ONCE_RW(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0) | set11nPktDurRTSCTS(i->rates, 1); - ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2) + ACCESS_ONCE_RW(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2) | set11nPktDurRTSCTS(i->rates, 3); - ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0) + ACCESS_ONCE_RW(ads->ds_ctl7) = set11nRateFlags(i->rates, 0) | set11nRateFlags(i->rates, 1) | set11nRateFlags(i->rates, 2) | set11nRateFlags(i->rates, 3) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 301bf72..3f5654f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -39,47 +39,47 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) (i->qcu << AR_TxQcuNum_S) | desc_len; checksum += val; - ACCESS_ONCE(ads->info) = val; + ACCESS_ONCE_RW(ads->info) = val; checksum += i->link; - ACCESS_ONCE(ads->link) = i->link; + ACCESS_ONCE_RW(ads->link) = i->link; checksum += i->buf_addr[0]; - ACCESS_ONCE(ads->data0) = i->buf_addr[0]; + ACCESS_ONCE_RW(ads->data0) = i->buf_addr[0]; checksum += i->buf_addr[1]; - ACCESS_ONCE(ads->data1) = i->buf_addr[1]; + ACCESS_ONCE_RW(ads->data1) = i->buf_addr[1]; checksum += i->buf_addr[2]; - ACCESS_ONCE(ads->data2) = i->buf_addr[2]; + ACCESS_ONCE_RW(ads->data2) = i->buf_addr[2]; checksum += i->buf_addr[3]; - ACCESS_ONCE(ads->data3) = i->buf_addr[3]; + ACCESS_ONCE_RW(ads->data3) = i->buf_addr[3]; checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl3) = val; + ACCESS_ONCE_RW(ads->ctl3) = val; checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl5) = val; + ACCESS_ONCE_RW(ads->ctl5) = val; checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl7) = val; + ACCESS_ONCE_RW(ads->ctl7) = val; checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl9) = val; + ACCESS_ONCE_RW(ads->ctl9) = val; checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); - ACCESS_ONCE(ads->ctl10) = checksum; + ACCESS_ONCE_RW(ads->ctl10) = checksum; if (i->is_first || i->is_last) { - ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0) + ACCESS_ONCE_RW(ads->ctl13) = set11nTries(i->rates, 0) | set11nTries(i->rates, 1) | set11nTries(i->rates, 2) | set11nTries(i->rates, 3) | (i->dur_update ? AR_DurUpdateEna : 0) | SM(0, AR_BurstDur); - ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0) + ACCESS_ONCE_RW(ads->ctl14) = set11nRate(i->rates, 0) | set11nRate(i->rates, 1) | set11nRate(i->rates, 2) | set11nRate(i->rates, 3); } else { - ACCESS_ONCE(ads->ctl13) = 0; - ACCESS_ONCE(ads->ctl14) = 0; + ACCESS_ONCE_RW(ads->ctl13) = 0; + ACCESS_ONCE_RW(ads->ctl14) = 0; } ads->ctl20 = 0; @@ -89,17 +89,17 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ctl17 = SM(i->keytype, AR_EncrType); if (!i->is_first) { - ACCESS_ONCE(ads->ctl11) = 0; - ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore; - ACCESS_ONCE(ads->ctl15) = 0; - ACCESS_ONCE(ads->ctl16) = 0; - ACCESS_ONCE(ads->ctl17) = ctl17; - ACCESS_ONCE(ads->ctl18) = 0; - ACCESS_ONCE(ads->ctl19) = 0; + ACCESS_ONCE_RW(ads->ctl11) = 0; + ACCESS_ONCE_RW(ads->ctl12) = i->is_last ? 0 : AR_TxMore; + ACCESS_ONCE_RW(ads->ctl15) = 0; + ACCESS_ONCE_RW(ads->ctl16) = 0; + ACCESS_ONCE_RW(ads->ctl17) = ctl17; + ACCESS_ONCE_RW(ads->ctl18) = 0; + ACCESS_ONCE_RW(ads->ctl19) = 0; return; } - ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) + ACCESS_ONCE_RW(ads->ctl11) = (i->pkt_len & AR_FrameLen) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(i->txpower, AR_XmitPower) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) @@ -135,22 +135,22 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; ctl12 |= SM(val, AR_PAPRDChainMask); - ACCESS_ONCE(ads->ctl12) = ctl12; - ACCESS_ONCE(ads->ctl17) = ctl17; + ACCESS_ONCE_RW(ads->ctl12) = ctl12; + ACCESS_ONCE_RW(ads->ctl17) = ctl17; - ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0) + ACCESS_ONCE_RW(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0) | set11nPktDurRTSCTS(i->rates, 1); - ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2) + ACCESS_ONCE_RW(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2) | set11nPktDurRTSCTS(i->rates, 3); - ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0) + ACCESS_ONCE_RW(ads->ctl18) = set11nRateFlags(i->rates, 0) | set11nRateFlags(i->rates, 1) | set11nRateFlags(i->rates, 2) | set11nRateFlags(i->rates, 3) | SM(i->rtscts_rate, AR_RTSCTSRate); - ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; + ACCESS_ONCE_RW(ads->ctl19) = AR_Not_Sounding; } static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ae30343..a117806 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -652,7 +652,7 @@ struct ath_hw_private_ops { /* ANI */ void (*ani_cache_ini_regs)(struct ath_hw *ah); -}; +} __no_const; /** * struct ath_spec_scan - parameters for Atheros spectral scan @@ -721,7 +721,7 @@ struct ath_hw_ops { struct ath_spec_scan *param); void (*spectral_scan_trigger)(struct ath_hw *ah); void (*spectral_scan_wait)(struct ath_hw *ah); -}; +} __no_const; struct ath_nf_limits { s16 max; diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index b37a582..680835d 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3639,7 +3639,9 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ if (il3945_mod_params.disable_hw_scan) { D_INFO("Disabling hw_scan\n"); - il3945_mac_ops.hw_scan = NULL; + pax_open_kernel(); + *(void **)&il3945_mac_ops.hw_scan = NULL; + pax_close_kernel(); } D_INFO("*** LOAD DRIVER ***\n"); diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c index d532948..e0d8bb1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c @@ -203,7 +203,7 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[64]; - int buf_size; + size_t buf_size; u32 offset, len; memset(buf, 0, sizeof(buf)); @@ -473,7 +473,7 @@ static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file, struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; u32 reset_flag; memset(buf, 0, sizeof(buf)); @@ -554,7 +554,7 @@ static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int ht40; memset(buf, 0, sizeof(buf)); @@ -606,7 +606,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int value; memset(buf, 0, sizeof(buf)); @@ -698,10 +698,10 @@ DEBUGFS_READ_FILE_OPS(temperature); DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); DEBUGFS_READ_FILE_OPS(current_sleep_command); -static const char *fmt_value = " %-30s %10u\n"; -static const char *fmt_hex = " %-30s 0x%02X\n"; -static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; -static const char *fmt_header = +static const char fmt_value[] = " %-30s %10u\n"; +static const char fmt_hex[] = " %-30s 0x%02X\n"; +static const char fmt_table[] = " %-30s %10u %10u %10u %10u\n"; +static const char fmt_header[] = "%-32s current cumulative delta max\n"; static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) @@ -1871,7 +1871,7 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int clear; memset(buf, 0, sizeof(buf)); @@ -1916,7 +1916,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int trace; memset(buf, 0, sizeof(buf)); @@ -1987,7 +1987,7 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int missed; memset(buf, 0, sizeof(buf)); @@ -2028,7 +2028,7 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int plcp; memset(buf, 0, sizeof(buf)); @@ -2088,7 +2088,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int flush; memset(buf, 0, sizeof(buf)); @@ -2178,7 +2178,7 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int rts; if (!priv->cfg->ht_params) @@ -2220,7 +2220,7 @@ static ssize_t iwl_dbgfs_echo_test_write(struct file *file, { struct iwl_priv *priv = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; memset(buf, 0, sizeof(buf)); buf_size = min(count, sizeof(buf) - 1); @@ -2254,7 +2254,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, struct iwl_priv *priv = file->private_data; u32 event_log_flag; char buf[8]; - int buf_size; + size_t buf_size; /* check that the interface is up */ if (!iwl_is_ready(priv)) @@ -2308,7 +2308,7 @@ static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file, struct iwl_priv *priv = file->private_data; char buf[8]; u32 calib_disabled; - int buf_size; + size_t buf_size; memset(buf, 0, sizeof(buf)); buf_size = min(count, sizeof(buf) - 1); diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index a8afc7b..de058b2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -1189,7 +1189,7 @@ static void iwl_option_config(struct iwl_priv *priv) static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) { struct iwl_nvm_data *data = priv->nvm_data; - char *debug_msg; + static const char debug_msg[] = "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n"; if (data->sku_cap_11n_enable && !priv->cfg->ht_params) { @@ -1203,7 +1203,6 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) return -EINVAL; } - debug_msg = "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n"; IWL_DEBUG_INFO(priv, debug_msg, data->sku_cap_band_24GHz_enable ? "" : "NOT", "enabled", data->sku_cap_band_52GHz_enable ? "" : "NOT", "enabled", diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index aeb70e1..d7b5bb5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1329,7 +1329,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, struct isr_statistics *isr_stats = &trans_pcie->isr_stats; char buf[8]; - int buf_size; + size_t buf_size; u32 reset_flag; memset(buf, 0, sizeof(buf)); @@ -1350,7 +1350,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, { struct iwl_trans *trans = file->private_data; char buf[8]; - int buf_size; + size_t buf_size; int csr; memset(buf, 0, sizeof(buf)); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cb34c78..9fec0dc 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2195,25 +2195,19 @@ static int __init init_mac80211_hwsim(void) if (channels > 1) { hwsim_if_comb.num_different_channels = channels; - mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; - mac80211_hwsim_ops.cancel_hw_scan = - mac80211_hwsim_cancel_hw_scan; - mac80211_hwsim_ops.sw_scan_start = NULL; - mac80211_hwsim_ops.sw_scan_complete = NULL; - mac80211_hwsim_ops.remain_on_channel = - mac80211_hwsim_roc; - mac80211_hwsim_ops.cancel_remain_on_channel = - mac80211_hwsim_croc; - mac80211_hwsim_ops.add_chanctx = - mac80211_hwsim_add_chanctx; - mac80211_hwsim_ops.remove_chanctx = - mac80211_hwsim_remove_chanctx; - mac80211_hwsim_ops.change_chanctx = - mac80211_hwsim_change_chanctx; - mac80211_hwsim_ops.assign_vif_chanctx = - mac80211_hwsim_assign_vif_chanctx; - mac80211_hwsim_ops.unassign_vif_chanctx = - mac80211_hwsim_unassign_vif_chanctx; + pax_open_kernel(); + *(void **)&mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; + *(void **)&mac80211_hwsim_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan; + *(void **)&mac80211_hwsim_ops.sw_scan_start = NULL; + *(void **)&mac80211_hwsim_ops.sw_scan_complete = NULL; + *(void **)&mac80211_hwsim_ops.remain_on_channel = mac80211_hwsim_roc; + *(void **)&mac80211_hwsim_ops.cancel_remain_on_channel = mac80211_hwsim_croc; + *(void **)&mac80211_hwsim_ops.add_chanctx = mac80211_hwsim_add_chanctx; + *(void **)&mac80211_hwsim_ops.remove_chanctx = mac80211_hwsim_remove_chanctx; + *(void **)&mac80211_hwsim_ops.change_chanctx = mac80211_hwsim_change_chanctx; + *(void **)&mac80211_hwsim_ops.assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx; + *(void **)&mac80211_hwsim_ops.unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx; + pax_close_kernel(); } spin_lock_init(&hwsim_radio_lock); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 8169a85..7fa3b47 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1238,7 +1238,7 @@ static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold) netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold); - if (rts_threshold < 0 || rts_threshold > 2347) + if (rts_threshold > 2347) rts_threshold = 2347; tmp = cpu_to_le32(rts_threshold); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7510723..5ba37f5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -386,7 +386,7 @@ struct rt2x00_intf { * for hardware which doesn't support hardware * sequence counting. */ - atomic_t seqno; + atomic_unchecked_t seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index d955741..8730748 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -252,9 +252,9 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, * sequence counter given by mac80211. */ if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - seqno = atomic_add_return(0x10, &intf->seqno); + seqno = atomic_add_return_unchecked(0x10, &intf->seqno); else - seqno = atomic_read(&intf->seqno); + seqno = atomic_read_unchecked(&intf->seqno); hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(seqno); diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index e2b3d9c..67a5184 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -271,13 +271,17 @@ static int wl1251_sdio_probe(struct sdio_func *func, irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; - wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; + pax_open_kernel(); + *(void **)&wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; + *(void **)&wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; + pax_close_kernel(); wl1251_info("using dedicated interrupt line"); } else { - wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; - wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; + pax_open_kernel(); + *(void **)&wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; + *(void **)&wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; + pax_close_kernel(); wl1251_info("using SDIO interrupt"); } diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 1c627da..69f7d17 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -656,7 +656,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl) sizeof(wl->conf.mem)); /* read data preparation is only needed by wl127x */ - wl->ops->prepare_read = wl127x_prepare_read; + pax_open_kernel(); + *(void **)&wl->ops->prepare_read = wl127x_prepare_read; + pax_close_kernel(); wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, @@ -681,7 +683,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl) sizeof(wl->conf.mem)); /* read data preparation is only needed by wl127x */ - wl->ops->prepare_read = wl127x_prepare_read; + pax_open_kernel(); + *(void **)&wl->ops->prepare_read = wl127x_prepare_read; + pax_close_kernel(); wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER, WL127X_IFTYPE_SR_VER, WL127X_MAJOR_SR_VER, diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 9fa692d..b31fee0 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1687,8 +1687,10 @@ static int wl18xx_setup(struct wl1271 *wl) } if (!checksum_param) { - wl18xx_ops.set_rx_csum = NULL; - wl18xx_ops.init_vif = NULL; + pax_open_kernel(); + *(void **)&wl18xx_ops.set_rx_csum = NULL; + *(void **)&wl18xx_ops.init_vif = NULL; + pax_close_kernel(); } /* Enable 11a Band only if we have 5G antennas */ diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 7ef0b4a..ff65c28 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -386,7 +386,7 @@ static inline void handle_regs_int(struct urb *urb) { struct zd_usb *usb = urb->context; struct zd_usb_interrupt *intr = &usb->intr; - int len; + unsigned int len; u16 int_num; ZD_ASSERT(in_interrupt()); diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index d93b2b6..ae50401 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -332,7 +332,7 @@ static void add_data(struct op_entry *entry, struct mm_struct *mm) if (cookie == NO_COOKIE) offset = pc; if (cookie == INVALID_COOKIE) { - atomic_inc(&oprofile_stats.sample_lost_no_mapping); + atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mapping); offset = pc; } if (cookie != last_cookie) { @@ -376,14 +376,14 @@ add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel) /* add userspace sample */ if (!mm) { - atomic_inc(&oprofile_stats.sample_lost_no_mm); + atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mm); return 0; } cookie = lookup_dcookie(mm, s->eip, &offset); if (cookie == INVALID_COOKIE) { - atomic_inc(&oprofile_stats.sample_lost_no_mapping); + atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mapping); return 0; } @@ -552,7 +552,7 @@ void sync_buffer(int cpu) /* ignore backtraces if failed to add a sample */ if (state == sb_bt_start) { state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); + atomic_inc_unchecked(&oprofile_stats.bt_lost_no_mapping); } } release_mm(mm); diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index c0cc4e7..44d4e54 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -53,7 +53,7 @@ void add_event_entry(unsigned long value) } if (buffer_pos == buffer_size) { - atomic_inc(&oprofile_stats.event_lost_overflow); + atomic_inc_unchecked(&oprofile_stats.event_lost_overflow); return; } diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index ed2c3ec..deda85a 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -110,7 +110,7 @@ static void switch_worker(struct work_struct *work) if (oprofile_ops.switch_events()) return; - atomic_inc(&oprofile_stats.multiplex_counter); + atomic_inc_unchecked(&oprofile_stats.multiplex_counter); start_switch_worker(); } diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index 84a208d..d61b0a1 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c @@ -27,7 +27,7 @@ unsigned long oprofile_time_slice; #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX -static ssize_t timeout_read(struct file *file, char __user *buf, +static ssize_t __intentional_overflow(-1) timeout_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { return oprofilefs_ulong_to_user(jiffies_to_msecs(oprofile_time_slice), diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index 917d28e..d62d981 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -30,11 +30,11 @@ void oprofile_reset_stats(void) cpu_buf->sample_invalid_eip = 0; } - atomic_set(&oprofile_stats.sample_lost_no_mm, 0); - atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); - atomic_set(&oprofile_stats.event_lost_overflow, 0); - atomic_set(&oprofile_stats.bt_lost_no_mapping, 0); - atomic_set(&oprofile_stats.multiplex_counter, 0); + atomic_set_unchecked(&oprofile_stats.sample_lost_no_mm, 0); + atomic_set_unchecked(&oprofile_stats.sample_lost_no_mapping, 0); + atomic_set_unchecked(&oprofile_stats.event_lost_overflow, 0); + atomic_set_unchecked(&oprofile_stats.bt_lost_no_mapping, 0); + atomic_set_unchecked(&oprofile_stats.multiplex_counter, 0); } diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h index 38b6fc0..b5cbfce 100644 --- a/drivers/oprofile/oprofile_stats.h +++ b/drivers/oprofile/oprofile_stats.h @@ -13,11 +13,11 @@ #include struct oprofile_stat_struct { - atomic_t sample_lost_no_mm; - atomic_t sample_lost_no_mapping; - atomic_t bt_lost_no_mapping; - atomic_t event_lost_overflow; - atomic_t multiplex_counter; + atomic_unchecked_t sample_lost_no_mm; + atomic_unchecked_t sample_lost_no_mapping; + atomic_unchecked_t bt_lost_no_mapping; + atomic_unchecked_t event_lost_overflow; + atomic_unchecked_t multiplex_counter; }; extern struct oprofile_stat_struct oprofile_stats; diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index 7c12d9c..558bf3bb 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -190,7 +190,7 @@ static const struct file_operations atomic_ro_fops = { int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root, - char const *name, atomic_t *val) + char const *name, atomic_unchecked_t *val) { return __oprofilefs_create_file(sb, root, name, &atomic_ro_fops, 0444, val); diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 93404f7..4a313d8 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -93,7 +93,7 @@ static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __refdata oprofile_cpu_notifier = { +static struct notifier_block oprofile_cpu_notifier = { .notifier_call = oprofile_cpu_notify, }; diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index 92ed045..62d39bd7 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -64,7 +64,7 @@ static int do_active_device(ctl_table *table, int write, *ppos += len; - return copy_to_user(result, buffer, len) ? -EFAULT : 0; + return (len > sizeof buffer || copy_to_user(result, buffer, len)) ? -EFAULT : 0; } #ifdef CONFIG_PARPORT_1284 @@ -106,7 +106,7 @@ static int do_autoprobe(ctl_table *table, int write, *ppos += len; - return copy_to_user (result, buffer, len) ? -EFAULT : 0; + return (len > sizeof buffer || copy_to_user (result, buffer, len)) ? -EFAULT : 0; } #endif /* IEEE1284.3 support. */ diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index c35e8ad..fc33beb 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -464,7 +464,9 @@ static int __init ibm_acpiphp_init(void) goto init_cleanup; } - ibm_apci_table_attr.size = ibm_get_table_from_acpi(NULL); + pax_open_kernel(); + *(size_t *)&ibm_apci_table_attr.size = ibm_get_table_from_acpi(NULL); + pax_close_kernel(); retval = sysfs_create_bin_file(sysdir, &ibm_apci_table_attr); return retval; diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index a6a71c4..c91097b 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c @@ -73,7 +73,6 @@ static u16 port; static unsigned int enum_bit; static u8 enum_mask; -static struct cpci_hp_controller_ops generic_hpc_ops; static struct cpci_hp_controller generic_hpc; static int __init validate_parameters(void) @@ -139,6 +138,10 @@ static int query_enum(void) return ((value & enum_mask) == enum_mask); } +static struct cpci_hp_controller_ops generic_hpc_ops = { + .query_enum = query_enum, +}; + static int __init cpcihp_generic_init(void) { int status; @@ -165,7 +168,6 @@ static int __init cpcihp_generic_init(void) pci_dev_put(dev); memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller)); - generic_hpc_ops.query_enum = query_enum; generic_hpc.ops = &generic_hpc_ops; status = cpci_hp_register_controller(&generic_hpc); diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index 449b4bb..257e2e8 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -59,7 +59,6 @@ /* local variables */ static bool debug; static bool poll; -static struct cpci_hp_controller_ops zt5550_hpc_ops; static struct cpci_hp_controller zt5550_hpc; /* Primary cPCI bus bridge device */ @@ -205,6 +204,10 @@ static int zt5550_hc_disable_irq(void) return 0; } +static struct cpci_hp_controller_ops zt5550_hpc_ops = { + .query_enum = zt5550_hc_query_enum, +}; + static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { int status; @@ -216,16 +219,17 @@ static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id dbg("returned from zt5550_hc_config"); memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller)); - zt5550_hpc_ops.query_enum = zt5550_hc_query_enum; zt5550_hpc.ops = &zt5550_hpc_ops; if(!poll) { zt5550_hpc.irq = hc_dev->irq; zt5550_hpc.irq_flags = IRQF_SHARED; zt5550_hpc.dev_id = hc_dev; - zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq; - zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq; - zt5550_hpc_ops.check_irq = zt5550_hc_check_irq; + pax_open_kernel(); + *(void **)&zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq; + *(void **)&zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq; + *(void **)&zt5550_hpc_ops.check_irq = zt5550_hc_check_irq; + pax_open_kernel(); } else { info("using ENUM# polling mode"); } diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c index 76ba8a1..20ca857 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.c +++ b/drivers/pci/hotplug/cpqphp_nvram.c @@ -428,9 +428,13 @@ static u32 store_HRT (void __iomem *rom_start) void compaq_nvram_init (void __iomem *rom_start) { + +#ifndef CONFIG_PAX_KERNEXEC if (rom_start) { compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR); } +#endif + dbg("int15 entry = %p\n", compaq_int15_entry_point); /* initialize our int15 lock */ diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index ec20f74..c1d961e 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -441,8 +441,10 @@ int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, return -EINVAL; } - slot->ops->owner = owner; - slot->ops->mod_name = mod_name; + pax_open_kernel(); + *(struct module **)&slot->ops->owner = owner; + *(const char **)&slot->ops->mod_name = mod_name; + pax_close_kernel(); mutex_lock(&pci_hp_mutex); /* diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 7d72c5e..edce02c 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -91,7 +91,7 @@ static int init_slot(struct controller *ctrl) struct slot *slot = ctrl->slot; struct hotplug_slot *hotplug = NULL; struct hotplug_slot_info *info = NULL; - struct hotplug_slot_ops *ops = NULL; + hotplug_slot_ops_no_const *ops = NULL; char name[SLOT_NAME_SIZE]; int retval = -ENOMEM; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 5127f3f..b225573 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -773,14 +773,12 @@ static void pcie_shutdown_notification(struct controller *ctrl) static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; - char name[32]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; - snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); - slot->wq = alloc_workqueue(name, 0, 0); + slot->wq = alloc_workqueue("pciehp-%u", 0, 0, PSN(ctrl)); if (!slot->wq) goto abort; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 5b4a9d9..cd5ac1f 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1071,7 +1071,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) { /* allocate attribute structure, piggyback attribute name */ int name_len = write_combine ? 13 : 10; - struct bin_attribute *res_attr; + bin_attribute_no_const *res_attr; int retval; res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC); @@ -1256,7 +1256,7 @@ static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_stor static int pci_create_capabilities_sysfs(struct pci_dev *dev) { int retval; - struct bin_attribute *attr; + bin_attribute_no_const *attr; /* If the device has VPD, try to expose it in sysfs. */ if (dev->vpd) { @@ -1303,7 +1303,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) { int retval; int rom_size = 0; - struct bin_attribute *attr; + bin_attribute_no_const *attr; if (!sysfs_initialized) return -EACCES; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d1182c4..2a138ec 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -92,7 +92,7 @@ struct pci_vpd_ops { struct pci_vpd { unsigned int len; const struct pci_vpd_ops *ops; - struct bin_attribute *attr; /* descriptor for sysfs VPD entry */ + bin_attribute_no_const *attr; /* descriptor for sysfs VPD entry */ }; int pci_vpd_pci22_init(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index d320df6..ca9a8f6 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -27,9 +27,9 @@ #define MODULE_PARAM_PREFIX "pcie_aspm." /* Note: those are not register definitions */ -#define ASPM_STATE_L0S_UP (1) /* Upstream direction L0s state */ -#define ASPM_STATE_L0S_DW (2) /* Downstream direction L0s state */ -#define ASPM_STATE_L1 (4) /* L1 state */ +#define ASPM_STATE_L0S_UP (1U) /* Upstream direction L0s state */ +#define ASPM_STATE_L0S_DW (2U) /* Downstream direction L0s state */ +#define ASPM_STATE_L1 (4U) /* L1 state */ #define ASPM_STATE_L0S (ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW) #define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ea37072..10e58e5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -173,7 +173,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct pci_bus_region region; bool bar_too_big = false, bar_disabled = false; - mask = type ? PCI_ROM_ADDRESS_MASK : ~0; + mask = type ? (u32)PCI_ROM_ADDRESS_MASK : ~0; /* No printks while decoding is disabled! */ if (!dev->mmio_always_on) { diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 0812608..b04018c 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -453,7 +453,16 @@ static const struct file_operations proc_bus_pci_dev_operations = { static int __init pci_proc_init(void) { struct pci_dev *dev = NULL; + +#ifdef CONFIG_GRKERNSEC_PROC_ADD +#ifdef CONFIG_GRKERNSEC_PROC_USER + proc_bus_pci_dir = proc_mkdir_mode("bus/pci", S_IRUSR | S_IXUSR, NULL); +#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) + proc_bus_pci_dir = proc_mkdir_mode("bus/pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL); +#endif +#else proc_bus_pci_dir = proc_mkdir("bus/pci", NULL); +#endif proc_create("devices", 0, proc_bus_pci_dir, &proc_bus_pci_dev_operations); proc_initialized = 1; diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 3e5b4497..dcdfb70 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c @@ -301,7 +301,7 @@ static int __init setup_tsl2563_als(const struct dmi_system_id *id) return 0; } -static struct dmi_system_id __initdata chromeos_laptop_dmi_table[] = { +static struct dmi_system_id __initconst chromeos_laptop_dmi_table[] = { { .ident = "Samsung Series 5 550 - Touchpad", .matches = { diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 6b22938..bc9700e 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -1000,12 +1000,14 @@ static int __init load_scm_model_init(struct platform_device *sdev) if (!quirks->ec_read_only) { /* allow userland write sysfs file */ - dev_attr_bluetooth.store = store_bluetooth; - dev_attr_wlan.store = store_wlan; - dev_attr_threeg.store = store_threeg; - dev_attr_bluetooth.attr.mode |= S_IWUSR; - dev_attr_wlan.attr.mode |= S_IWUSR; - dev_attr_threeg.attr.mode |= S_IWUSR; + pax_open_kernel(); + *(void **)&dev_attr_bluetooth.store = store_bluetooth; + *(void **)&dev_attr_wlan.store = store_wlan; + *(void **)&dev_attr_threeg.store = store_threeg; + *(umode_t *)&dev_attr_bluetooth.attr.mode |= S_IWUSR; + *(umode_t *)&dev_attr_wlan.attr.mode |= S_IWUSR; + *(umode_t *)&dev_attr_threeg.attr.mode |= S_IWUSR; + pax_close_kernel(); } /* disable hardware control by fn key */ diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 2ac045f..39c443d 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2483,7 +2483,7 @@ static void sony_nc_gfx_switch_cleanup(struct platform_device *pd) } /* High speed charging function */ -static struct device_attribute *hsc_handle; +static device_attribute_no_const *hsc_handle; static ssize_t sony_nc_highspeed_charging_store(struct device *dev, struct device_attribute *attr, diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 54d31c0..3f896d3 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -2093,7 +2093,7 @@ static int hotkey_mask_get(void) return 0; } -void static hotkey_mask_warn_incomplete_mask(void) +static void hotkey_mask_warn_incomplete_mask(void) { /* log only what the user can fix... */ const u32 wantedmask = hotkey_driver_mask & @@ -2324,11 +2324,6 @@ static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m) } } -static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, - struct tp_nvram_state *newn, - const u32 event_mask) -{ - #define TPACPI_COMPARE_KEY(__scancode, __member) \ do { \ if ((event_mask & (1 << __scancode)) && \ @@ -2342,36 +2337,42 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, tpacpi_hotkey_send_key(__scancode); \ } while (0) - void issue_volchange(const unsigned int oldvol, - const unsigned int newvol) - { - unsigned int i = oldvol; +static void issue_volchange(const unsigned int oldvol, + const unsigned int newvol, + const u32 event_mask) +{ + unsigned int i = oldvol; - while (i > newvol) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); - i--; - } - while (i < newvol) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); - i++; - } + while (i > newvol) { + TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); + i--; } + while (i < newvol) { + TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); + i++; + } +} - void issue_brightnesschange(const unsigned int oldbrt, - const unsigned int newbrt) - { - unsigned int i = oldbrt; +static void issue_brightnesschange(const unsigned int oldbrt, + const unsigned int newbrt, + const u32 event_mask) +{ + unsigned int i = oldbrt; - while (i > newbrt) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND); - i--; - } - while (i < newbrt) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME); - i++; - } + while (i > newbrt) { + TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND); + i--; + } + while (i < newbrt) { + TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME); + i++; } +} +static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, + struct tp_nvram_state *newn, + const u32 event_mask) +{ TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle); TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle); TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle); @@ -2405,7 +2406,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, oldn->volume_level != newn->volume_level) { /* recently muted, or repeated mute keypress, or * multiple presses ending in mute */ - issue_volchange(oldn->volume_level, newn->volume_level); + issue_volchange(oldn->volume_level, newn->volume_level, event_mask); TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); } } else { @@ -2415,7 +2416,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); } if (oldn->volume_level != newn->volume_level) { - issue_volchange(oldn->volume_level, newn->volume_level); + issue_volchange(oldn->volume_level, newn->volume_level, event_mask); } else if (oldn->volume_toggle != newn->volume_toggle) { /* repeated vol up/down keypress at end of scale ? */ if (newn->volume_level == 0) @@ -2428,7 +2429,8 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, /* handle brightness */ if (oldn->brightness_level != newn->brightness_level) { issue_brightnesschange(oldn->brightness_level, - newn->brightness_level); + newn->brightness_level, + event_mask); } else if (oldn->brightness_toggle != newn->brightness_toggle) { /* repeated key presses that didn't change state */ if (newn->brightness_level == 0) @@ -2437,10 +2439,10 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, && !tp_features.bright_unkfw) TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME); } +} #undef TPACPI_COMPARE_KEY #undef TPACPI_MAY_SEND_KEY -} /* * Polling driver diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index e4ac38a..b13344c 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -743,7 +743,7 @@ static int wmi_create_device(const struct guid_block *gblock, wblock->dev.class = &wmi_class; wmi_gtoa(gblock->guid, guid_string); - dev_set_name(&wblock->dev, guid_string); + dev_set_name(&wblock->dev, "%s", guid_string); dev_set_drvdata(&wblock->dev, wblock); diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index 769d265..a3a05ca 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c @@ -58,7 +58,7 @@ do { \ set_desc_limit(&gdt[(selname) >> 3], (size) - 1); \ } while(0) -static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, +static const struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4093, (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1); /* @@ -95,7 +95,10 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, cpu = get_cpu(); save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8]; + + pax_open_kernel(); get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc; + pax_close_kernel(); /* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave(&pnp_bios_lock, flags); @@ -133,7 +136,10 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, :"memory"); spin_unlock_irqrestore(&pnp_bios_lock, flags); + pax_open_kernel(); get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40; + pax_close_kernel(); + put_cpu(); /* If we get here and this is set then the PnP BIOS faulted on us. */ @@ -467,7 +473,7 @@ int pnp_bios_read_escd(char *data, u32 nvram_base) return status; } -void pnpbios_calls_init(union pnp_bios_install_struct *header) +void __init pnpbios_calls_init(union pnp_bios_install_struct *header) { int i; @@ -475,6 +481,8 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment = PNP_CS16; + pax_open_kernel(); + for_each_possible_cpu(i) { struct desc_struct *gdt = get_cpu_gdt_table(i); if (!gdt) @@ -486,4 +494,6 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_DS], (unsigned long)__va(header->fields.pm16dseg)); } + + pax_close_kernel(); } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 3e6db1c..1fbbdae 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -360,7 +360,7 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res) return 1; /* check if the resource is valid */ - if (*irq < 0 || *irq > 15) + if (*irq > 15) return 0; /* check if the resource is reserved */ @@ -424,7 +424,7 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) return 1; /* check if the resource is valid */ - if (*dma < 0 || *dma == 4 || *dma > 7) + if (*dma == 4 || *dma > 7) return 0; /* check if the resource is reserved */ diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 0c52e2a..3421ab7 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -37,7 +37,11 @@ static int polling; #if IS_ENABLED(CONFIG_USB_PHY) static struct usb_phy *transceiver; -static struct notifier_block otg_nb; +static int otg_handle_notification(struct notifier_block *nb, + unsigned long event, void *unused); +static struct notifier_block otg_nb = { + .notifier_call = otg_handle_notification +}; #endif static struct regulator *ac_draw; @@ -369,7 +373,6 @@ static int pda_power_probe(struct platform_device *pdev) #if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) { - otg_nb.notifier_call = otg_handle_notification; ret = usb_register_notifier(transceiver, &otg_nb); if (ret) { dev_err(dev, "failure to register otg notifier\n"); diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h index cc439fd..8fa30df 100644 --- a/drivers/power/power_supply.h +++ b/drivers/power/power_supply.h @@ -16,12 +16,12 @@ struct power_supply; #ifdef CONFIG_SYSFS -extern void power_supply_init_attrs(struct device_type *dev_type); +extern void power_supply_init_attrs(void); extern int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env); #else -static inline void power_supply_init_attrs(struct device_type *dev_type) {} +static inline void power_supply_init_attrs(void) {} #define power_supply_uevent NULL #endif /* CONFIG_SYSFS */ diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 1c517c3..ffa2f17 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -24,7 +24,10 @@ struct class *power_supply_class; EXPORT_SYMBOL_GPL(power_supply_class); -static struct device_type power_supply_dev_type; +extern const struct attribute_group *power_supply_attr_groups[]; +static struct device_type power_supply_dev_type = { + .groups = power_supply_attr_groups, +}; static bool __power_supply_is_supplied_by(struct power_supply *supplier, struct power_supply *supply) @@ -554,7 +557,7 @@ static int __init power_supply_class_init(void) return PTR_ERR(power_supply_class); power_supply_class->dev_uevent = power_supply_uevent; - power_supply_init_attrs(&power_supply_dev_type); + power_supply_init_attrs(); return 0; } diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 29178f7..c65f324 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -230,17 +230,15 @@ static struct attribute_group power_supply_attr_group = { .is_visible = power_supply_attr_is_visible, }; -static const struct attribute_group *power_supply_attr_groups[] = { +const struct attribute_group *power_supply_attr_groups[] = { &power_supply_attr_group, NULL, }; -void power_supply_init_attrs(struct device_type *dev_type) +void power_supply_init_attrs(void) { int i; - dev_type->groups = power_supply_attr_groups; - for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) __power_supply_attrs[i] = &power_supply_attrs[i].attr; } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 815d6df..811633a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3529,7 +3529,7 @@ regulator_register(const struct regulator_desc *regulator_desc, { const struct regulation_constraints *constraints = NULL; const struct regulator_init_data *init_data; - static atomic_t regulator_no = ATOMIC_INIT(0); + static atomic_unchecked_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; struct device *dev; int ret, i; @@ -3599,7 +3599,7 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->dev.of_node = config->of_node; rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", - atomic_inc_return(®ulator_no) - 1); + atomic_inc_return_unchecked(®ulator_no) - 1); ret = device_register(&rdev->dev); if (ret != 0) { put_device(&rdev->dev); diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index d428ef9..fdc0357 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -333,8 +333,10 @@ static int max8660_probe(struct i2c_client *client, max8660->shadow_regs[MAX8660_OVER1] = 5; } else { /* Otherwise devices can be toggled via software */ - max8660_dcdc_ops.enable = max8660_dcdc_enable; - max8660_dcdc_ops.disable = max8660_dcdc_disable; + pax_open_kernel(); + *(void **)&max8660_dcdc_ops.enable = max8660_dcdc_enable; + *(void **)&max8660_dcdc_ops.disable = max8660_dcdc_disable; + pax_close_kernel(); } /* diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index adb1414..c13e0ce 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -401,9 +401,11 @@ static int max8973_probe(struct i2c_client *client, if (!pdata->enable_ext_control) { max->desc.enable_reg = MAX8973_VOUT; max->desc.enable_mask = MAX8973_VOUT_ENABLE; - max8973_dcdc_ops.enable = regulator_enable_regmap; - max8973_dcdc_ops.disable = regulator_disable_regmap; - max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap; + pax_open_kernel(); + *(void **)&max8973_dcdc_ops.enable = regulator_enable_regmap; + *(void **)&max8973_dcdc_ops.disable = regulator_disable_regmap; + *(void **)&max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap; + pax_close_kernel(); } max->enable_external_control = pdata->enable_ext_control; diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index b716283..3cc4349 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -582,10 +582,12 @@ static int mc13892_regulator_probe(struct platform_device *pdev) } mc13xxx_unlock(mc13892); - mc13892_regulators[MC13892_VCAM].desc.ops->set_mode + pax_open_kernel(); + *(void **)&mc13892_regulators[MC13892_VCAM].desc.ops->set_mode = mc13892_vcam_set_mode; - mc13892_regulators[MC13892_VCAM].desc.ops->get_mode + *(void **)&mc13892_regulators[MC13892_VCAM].desc.ops->get_mode = mc13892_vcam_get_mode; + pax_close_kernel(); mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, ARRAY_SIZE(mc13892_regulators)); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f1cb706..4c7832a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -724,7 +724,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) hpet_rtc_timer_init(); /* export at least the first block of NVRAM */ - nvram.size = address_space - NVRAM_OFFSET; + pax_open_kernel(); + *(size_t *)&nvram.size = address_space - NVRAM_OFFSET; + pax_close_kernel(); retval = sysfs_create_bin_file(&dev->kobj, &nvram); if (retval < 0) { dev_dbg(dev, "can't create nvram file? %d\n", retval); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index d049393..bb20be0 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "rtc-core.h" static dev_t rtc_devt; @@ -347,6 +348,8 @@ static long rtc_dev_ioctl(struct file *file, if (copy_from_user(&tm, uarg, sizeof(tm))) return -EFAULT; + gr_log_timechange(); + return rtc_set_time(rtc, &tm); case RTC_PIE_ON: diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index b53992a..776df84 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -107,7 +107,7 @@ struct ds1307 { u8 offset; /* register's offset */ u8 regs[11]; u16 nvram_offset; - struct bin_attribute *nvram; + bin_attribute_no_const *nvram; enum ds_type type; unsigned long flags; #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 130f29a..6179d03 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -482,7 +482,9 @@ static int m48t59_rtc_probe(struct platform_device *pdev) goto out; } - m48t59_nvram_attr.size = pdata->offset; + pax_open_kernel(); + *(size_t *)&m48t59_nvram_attr.size = pdata->offset; + pax_close_kernel(); ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); if (ret) { diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index e693af6..2e525b6 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -36,7 +36,7 @@ struct bfa_iotag_s { struct bfa_itn_s { bfa_isr_func_t isr; -}; +} __no_const; void bfa_itn_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void (*isr)(struct bfa_s *bfa, struct bfi_msg_s *m)); diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 23a90e7..9cf04ee 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -258,7 +258,7 @@ struct bfa_ioc_cbfn_s { bfa_ioc_disable_cbfn_t disable_cbfn; bfa_ioc_hbfail_cbfn_t hbfail_cbfn; bfa_ioc_reset_cbfn_t reset_cbfn; -}; +} __no_const; /* * IOC event notification mechanism. @@ -346,7 +346,7 @@ struct bfa_ioc_hwif_s { void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc); bfa_boolean_t (*ioc_lpu_read_stat) (struct bfa_ioc_s *ioc); -}; +} __no_const; /* * Queue element to wait for room in request queue. FIFO order is diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c index 8c05ae01..b2cf224 100644 --- a/drivers/scsi/fcoe/fcoe_sysfs.c +++ b/drivers/scsi/fcoe/fcoe_sysfs.c @@ -33,8 +33,8 @@ */ #include "libfcoe.h" -static atomic_t ctlr_num; -static atomic_t fcf_num; +static atomic_unchecked_t ctlr_num; +static atomic_unchecked_t fcf_num; /* * fcoe_fcf_dev_loss_tmo: the default number of seconds that fcoe sysfs @@ -681,7 +681,7 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent, if (!ctlr) goto out; - ctlr->id = atomic_inc_return(&ctlr_num) - 1; + ctlr->id = atomic_inc_return_unchecked(&ctlr_num) - 1; ctlr->f = f; ctlr->mode = FIP_CONN_TYPE_FABRIC; INIT_LIST_HEAD(&ctlr->fcfs); @@ -898,7 +898,7 @@ struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr, fcf->dev.parent = &ctlr->dev; fcf->dev.bus = &fcoe_bus_type; fcf->dev.type = &fcoe_fcf_device_type; - fcf->id = atomic_inc_return(&fcf_num) - 1; + fcf->id = atomic_inc_return_unchecked(&fcf_num) - 1; fcf->state = FCOE_FCF_STATE_UNKNOWN; fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo; @@ -934,8 +934,8 @@ int __init fcoe_sysfs_setup(void) { int error; - atomic_set(&ctlr_num, 0); - atomic_set(&fcf_num, 0); + atomic_set_unchecked(&ctlr_num, 0); + atomic_set_unchecked(&fcf_num, 0); error = bus_register(&fcoe_bus_type); if (error) diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index df0c3c7..b00e1d0 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -42,7 +42,7 @@ #include "scsi_logging.h" -static atomic_t scsi_host_next_hn = ATOMIC_INIT(0); /* host_no for next new host */ +static atomic_unchecked_t scsi_host_next_hn = ATOMIC_INIT(0); /* host_no for next new host */ static void scsi_host_cls_release(struct device *dev) @@ -361,7 +361,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) * subtract one because we increment first then return, but we need to * know what the next host number was before increment */ - shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1; + shost->host_no = atomic_inc_return_unchecked(&scsi_host_next_hn) - 1; shost->dma_channel = 0xff; /* These three are default values which can be overridden */ diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 7f4f790..b75b92a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -554,7 +554,7 @@ static inline u32 next_command(struct ctlr_info *h, u8 q) unsigned long flags; if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant))) - return h->access.command_completed(h, q); + return h->access->command_completed(h, q); if ((rq->head[rq->current_entry] & 1) == rq->wraparound) { a = rq->head[rq->current_entry]; @@ -3422,7 +3422,7 @@ static void start_io(struct ctlr_info *h) while (!list_empty(&h->reqQ)) { c = list_entry(h->reqQ.next, struct CommandList, list); /* can't do anything if fifo is full */ - if ((h->access.fifo_full(h))) { + if ((h->access->fifo_full(h))) { dev_warn(&h->pdev->dev, "fifo full\n"); break; } @@ -3444,7 +3444,7 @@ static void start_io(struct ctlr_info *h) /* Tell the controller execute command */ spin_unlock_irqrestore(&h->lock, flags); - h->access.submit_command(h, c); + h->access->submit_command(h, c); spin_lock_irqsave(&h->lock, flags); } spin_unlock_irqrestore(&h->lock, flags); @@ -3452,17 +3452,17 @@ static void start_io(struct ctlr_info *h) static inline unsigned long get_next_completion(struct ctlr_info *h, u8 q) { - return h->access.command_completed(h, q); + return h->access->command_completed(h, q); } static inline bool interrupt_pending(struct ctlr_info *h) { - return h->access.intr_pending(h); + return h->access->intr_pending(h); } static inline long interrupt_not_for_us(struct ctlr_info *h) { - return (h->access.intr_pending(h) == 0) || + return (h->access->intr_pending(h) == 0) || (h->interrupts_enabled == 0); } @@ -4364,7 +4364,7 @@ static int hpsa_pci_init(struct ctlr_info *h) if (prod_index < 0) return -ENODEV; h->product_name = products[prod_index].product_name; - h->access = *(products[prod_index].access); + h->access = products[prod_index].access; pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); @@ -4646,7 +4646,7 @@ static void controller_lockup_detected(struct ctlr_info *h) assert_spin_locked(&lockup_detector_lock); remove_ctlr_from_lockup_detector_list(h); - h->access.set_intr_mask(h, HPSA_INTR_OFF); + h->access->set_intr_mask(h, HPSA_INTR_OFF); spin_lock_irqsave(&h->lock, flags); h->lockup_detected = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); spin_unlock_irqrestore(&h->lock, flags); @@ -4823,7 +4823,7 @@ reinit_after_soft_reset: } /* make sure the board interrupts are off */ - h->access.set_intr_mask(h, HPSA_INTR_OFF); + h->access->set_intr_mask(h, HPSA_INTR_OFF); if (hpsa_request_irq(h, do_hpsa_intr_msi, do_hpsa_intr_intx)) goto clean2; @@ -4857,7 +4857,7 @@ reinit_after_soft_reset: * fake ones to scoop up any residual completions. */ spin_lock_irqsave(&h->lock, flags); - h->access.set_intr_mask(h, HPSA_INTR_OFF); + h->access->set_intr_mask(h, HPSA_INTR_OFF); spin_unlock_irqrestore(&h->lock, flags); free_irqs(h); rc = hpsa_request_irq(h, hpsa_msix_discard_completions, @@ -4876,9 +4876,9 @@ reinit_after_soft_reset: dev_info(&h->pdev->dev, "Board READY.\n"); dev_info(&h->pdev->dev, "Waiting for stale completions to drain.\n"); - h->access.set_intr_mask(h, HPSA_INTR_ON); + h->access->set_intr_mask(h, HPSA_INTR_ON); msleep(10000); - h->access.set_intr_mask(h, HPSA_INTR_OFF); + h->access->set_intr_mask(h, HPSA_INTR_OFF); rc = controller_reset_failed(h->cfgtable); if (rc) @@ -4899,7 +4899,7 @@ reinit_after_soft_reset: } /* Turn the interrupts on so we can service requests */ - h->access.set_intr_mask(h, HPSA_INTR_ON); + h->access->set_intr_mask(h, HPSA_INTR_ON); hpsa_hba_inquiry(h); hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ @@ -4954,7 +4954,7 @@ static void hpsa_shutdown(struct pci_dev *pdev) * To write all data in the battery backed cache to disks */ hpsa_flush_cache(h); - h->access.set_intr_mask(h, HPSA_INTR_OFF); + h->access->set_intr_mask(h, HPSA_INTR_OFF); hpsa_free_irqs_and_disable_msix(h); } @@ -5122,7 +5122,7 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 use_short_tags) return; } /* Change the access methods to the performant access methods */ - h->access = SA5_performant_access; + h->access = &SA5_performant_access; h->transMethod = CFGTBL_Trans_Performant; } diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 9816479..c5d4e97 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -79,7 +79,7 @@ struct ctlr_info { unsigned int msix_vector; unsigned int msi_vector; int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ - struct access_method access; + struct access_method *access; /* queue and queue Info */ struct list_head reqQ; diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8b928c6..9c76300 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -100,12 +100,12 @@ struct fc_exch_mgr { u16 pool_max_index; struct { - atomic_t no_free_exch; - atomic_t no_free_exch_xid; - atomic_t xid_not_found; - atomic_t xid_busy; - atomic_t seq_not_found; - atomic_t non_bls_resp; + atomic_unchecked_t no_free_exch; + atomic_unchecked_t no_free_exch_xid; + atomic_unchecked_t xid_not_found; + atomic_unchecked_t xid_busy; + atomic_unchecked_t seq_not_found; + atomic_unchecked_t non_bls_resp; } stats; }; @@ -736,7 +736,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, /* allocate memory for exchange */ ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC); if (!ep) { - atomic_inc(&mp->stats.no_free_exch); + atomic_inc_unchecked(&mp->stats.no_free_exch); goto out; } memset(ep, 0, sizeof(*ep)); @@ -797,7 +797,7 @@ out: return ep; err: spin_unlock_bh(&pool->lock); - atomic_inc(&mp->stats.no_free_exch_xid); + atomic_inc_unchecked(&mp->stats.no_free_exch_xid); mempool_free(ep, mp->ep_pool); return NULL; } @@ -940,7 +940,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, xid = ntohs(fh->fh_ox_id); /* we originated exch */ ep = fc_exch_find(mp, xid); if (!ep) { - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); reject = FC_RJT_OX_ID; goto out; } @@ -970,7 +970,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, ep = fc_exch_find(mp, xid); if ((f_ctl & FC_FC_FIRST_SEQ) && fc_sof_is_init(fr_sof(fp))) { if (ep) { - atomic_inc(&mp->stats.xid_busy); + atomic_inc_unchecked(&mp->stats.xid_busy); reject = FC_RJT_RX_ID; goto rel; } @@ -981,7 +981,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, } xid = ep->xid; /* get our XID */ } else if (!ep) { - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); reject = FC_RJT_RX_ID; /* XID not found */ goto out; } @@ -998,7 +998,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, } else { sp = &ep->seq; if (sp->id != fh->fh_seq_id) { - atomic_inc(&mp->stats.seq_not_found); + atomic_inc_unchecked(&mp->stats.seq_not_found); if (f_ctl & FC_FC_END_SEQ) { /* * Update sequence_id based on incoming last @@ -1448,22 +1448,22 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) ep = fc_exch_find(mp, ntohs(fh->fh_ox_id)); if (!ep) { - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); goto out; } if (ep->esb_stat & ESB_ST_COMPLETE) { - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); goto rel; } if (ep->rxid == FC_XID_UNKNOWN) ep->rxid = ntohs(fh->fh_rx_id); if (ep->sid != 0 && ep->sid != ntoh24(fh->fh_d_id)) { - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); goto rel; } if (ep->did != ntoh24(fh->fh_s_id) && ep->did != FC_FID_FLOGI) { - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); goto rel; } sof = fr_sof(fp); @@ -1472,7 +1472,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) sp->ssb_stat |= SSB_ST_RESP; sp->id = fh->fh_seq_id; } else if (sp->id != fh->fh_seq_id) { - atomic_inc(&mp->stats.seq_not_found); + atomic_inc_unchecked(&mp->stats.seq_not_found); goto rel; } @@ -1536,9 +1536,9 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) sp = fc_seq_lookup_orig(mp, fp); /* doesn't hold sequence */ if (!sp) - atomic_inc(&mp->stats.xid_not_found); + atomic_inc_unchecked(&mp->stats.xid_not_found); else - atomic_inc(&mp->stats.non_bls_resp); + atomic_inc_unchecked(&mp->stats.non_bls_resp); fc_frame_free(fp); } @@ -2185,13 +2185,13 @@ void fc_exch_update_stats(struct fc_lport *lport) list_for_each_entry(ema, &lport->ema_list, ema_list) { mp = ema->mp; - st->fc_no_free_exch += atomic_read(&mp->stats.no_free_exch); + st->fc_no_free_exch += atomic_read_unchecked(&mp->stats.no_free_exch); st->fc_no_free_exch_xid += - atomic_read(&mp->stats.no_free_exch_xid); - st->fc_xid_not_found += atomic_read(&mp->stats.xid_not_found); - st->fc_xid_busy += atomic_read(&mp->stats.xid_busy); - st->fc_seq_not_found += atomic_read(&mp->stats.seq_not_found); - st->fc_non_bls_resp += atomic_read(&mp->stats.non_bls_resp); + atomic_read_unchecked(&mp->stats.no_free_exch_xid); + st->fc_xid_not_found += atomic_read_unchecked(&mp->stats.xid_not_found); + st->fc_xid_busy += atomic_read_unchecked(&mp->stats.xid_busy); + st->fc_seq_not_found += atomic_read_unchecked(&mp->stats.seq_not_found); + st->fc_non_bls_resp += atomic_read_unchecked(&mp->stats.non_bls_resp); } } EXPORT_SYMBOL(fc_exch_update_stats); diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 161c98e..6d563b3 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -554,7 +554,7 @@ static struct ata_port_operations sas_sata_ops = { .postreset = ata_std_postreset, .error_handler = ata_std_error_handler, .post_internal_cmd = sas_ata_post_internal, - .qc_defer = ata_std_qc_defer, + .qc_defer = ata_std_qc_defer, .qc_prep = ata_noop_qc_prep, .qc_issue = sas_ata_qc_issue, .qc_fill_rtf = sas_ata_qc_fill_rtf, diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index bcc56ca..6f4174a 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -431,7 +431,7 @@ struct lpfc_vport { struct dentry *debug_nodelist; struct dentry *vport_debugfs_root; struct lpfc_debugfs_trc *disc_trc; - atomic_t disc_trc_cnt; + atomic_unchecked_t disc_trc_cnt; #endif uint8_t stat_data_enabled; uint8_t stat_data_blocked; @@ -865,8 +865,8 @@ struct lpfc_hba { struct timer_list fabric_block_timer; unsigned long bit_flags; #define FABRIC_COMANDS_BLOCKED 0 - atomic_t num_rsrc_err; - atomic_t num_cmd_success; + atomic_unchecked_t num_rsrc_err; + atomic_unchecked_t num_cmd_success; unsigned long last_rsrc_error_time; unsigned long last_ramp_down_time; unsigned long last_ramp_up_time; @@ -902,7 +902,7 @@ struct lpfc_hba { struct dentry *debug_slow_ring_trc; struct lpfc_debugfs_trc *slow_ring_trc; - atomic_t slow_ring_trc_cnt; + atomic_unchecked_t slow_ring_trc_cnt; /* iDiag debugfs sub-directory */ struct dentry *idiag_root; struct dentry *idiag_pci_cfg; diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index f525ecb..32549a4 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -106,7 +106,7 @@ MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, #include -static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); +static atomic_unchecked_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); static unsigned long lpfc_debugfs_start_time = 0L; /* iDiag */ @@ -147,7 +147,7 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) lpfc_debugfs_enable = 0; len = 0; - index = (atomic_read(&vport->disc_trc_cnt) + 1) & + index = (atomic_read_unchecked(&vport->disc_trc_cnt) + 1) & (lpfc_debugfs_max_disc_trc - 1); for (i = index; i < lpfc_debugfs_max_disc_trc; i++) { dtp = vport->disc_trc + i; @@ -213,7 +213,7 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) lpfc_debugfs_enable = 0; len = 0; - index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) & + index = (atomic_read_unchecked(&phba->slow_ring_trc_cnt) + 1) & (lpfc_debugfs_max_slow_ring_trc - 1); for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) { dtp = phba->slow_ring_trc + i; @@ -646,14 +646,14 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, !vport || !vport->disc_trc) return; - index = atomic_inc_return(&vport->disc_trc_cnt) & + index = atomic_inc_return_unchecked(&vport->disc_trc_cnt) & (lpfc_debugfs_max_disc_trc - 1); dtp = vport->disc_trc + index; dtp->fmt = fmt; dtp->data1 = data1; dtp->data2 = data2; dtp->data3 = data3; - dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt); + dtp->seq_cnt = atomic_inc_return_unchecked(&lpfc_debugfs_seq_trc_cnt); dtp->jif = jiffies; #endif return; @@ -684,14 +684,14 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt, !phba || !phba->slow_ring_trc) return; - index = atomic_inc_return(&phba->slow_ring_trc_cnt) & + index = atomic_inc_return_unchecked(&phba->slow_ring_trc_cnt) & (lpfc_debugfs_max_slow_ring_trc - 1); dtp = phba->slow_ring_trc + index; dtp->fmt = fmt; dtp->data1 = data1; dtp->data2 = data2; dtp->data3 = data3; - dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt); + dtp->seq_cnt = atomic_inc_return_unchecked(&lpfc_debugfs_seq_trc_cnt); dtp->jif = jiffies; #endif return; @@ -4182,7 +4182,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) "slow_ring buffer\n"); goto debug_failed; } - atomic_set(&phba->slow_ring_trc_cnt, 0); + atomic_set_unchecked(&phba->slow_ring_trc_cnt, 0); memset(phba->slow_ring_trc, 0, (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_slow_ring_trc)); @@ -4228,7 +4228,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) "buffer\n"); goto debug_failed; } - atomic_set(&vport->disc_trc_cnt, 0); + atomic_set_unchecked(&vport->disc_trc_cnt, 0); snprintf(name, sizeof(name), "discovery_trace"); vport->debug_disc_trc = diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index cb465b2..2e7b25f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -10950,8 +10950,10 @@ lpfc_init(void) "misc_register returned with status %d", error); if (lpfc_enable_npiv) { - lpfc_transport_functions.vport_create = lpfc_vport_create; - lpfc_transport_functions.vport_delete = lpfc_vport_delete; + pax_open_kernel(); + *(void **)&lpfc_transport_functions.vport_create = lpfc_vport_create; + *(void **)&lpfc_transport_functions.vport_delete = lpfc_vport_delete; + pax_close_kernel(); } lpfc_transport_template = fc_attach_transport(&lpfc_transport_functions); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 8523b278e..ce1d812 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -331,7 +331,7 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba) uint32_t evt_posted; spin_lock_irqsave(&phba->hbalock, flags); - atomic_inc(&phba->num_rsrc_err); + atomic_inc_unchecked(&phba->num_rsrc_err); phba->last_rsrc_error_time = jiffies; if ((phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL) > jiffies) { @@ -372,7 +372,7 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport, unsigned long flags; struct lpfc_hba *phba = vport->phba; uint32_t evt_posted; - atomic_inc(&phba->num_cmd_success); + atomic_inc_unchecked(&phba->num_cmd_success); if (vport->cfg_lun_queue_depth <= queue_depth) return; @@ -416,8 +416,8 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) unsigned long num_rsrc_err, num_cmd_success; int i; - num_rsrc_err = atomic_read(&phba->num_rsrc_err); - num_cmd_success = atomic_read(&phba->num_cmd_success); + num_rsrc_err = atomic_read_unchecked(&phba->num_rsrc_err); + num_cmd_success = atomic_read_unchecked(&phba->num_cmd_success); /* * The error and success command counters are global per @@ -445,8 +445,8 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) } } lpfc_destroy_vport_work_array(phba, vports); - atomic_set(&phba->num_rsrc_err, 0); - atomic_set(&phba->num_cmd_success, 0); + atomic_set_unchecked(&phba->num_rsrc_err, 0); + atomic_set_unchecked(&phba->num_cmd_success, 0); } /** @@ -480,8 +480,8 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) } } lpfc_destroy_vport_work_array(phba, vports); - atomic_set(&phba->num_rsrc_err, 0); - atomic_set(&phba->num_cmd_success, 0); + atomic_set_unchecked(&phba->num_rsrc_err, 0); + atomic_set_unchecked(&phba->num_cmd_success, 0); } /** diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 8e1b737..50ff510 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -200,8 +200,8 @@ static int pmcraid_slave_alloc(struct scsi_device *scsi_dev) res->scsi_dev = scsi_dev; scsi_dev->hostdata = res; res->change_detected = 0; - atomic_set(&res->read_failures, 0); - atomic_set(&res->write_failures, 0); + atomic_set_unchecked(&res->read_failures, 0); + atomic_set_unchecked(&res->write_failures, 0); rc = 0; } spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags); @@ -2676,9 +2676,9 @@ static int pmcraid_error_handler(struct pmcraid_cmd *cmd) /* If this was a SCSI read/write command keep count of errors */ if (SCSI_CMD_TYPE(scsi_cmd->cmnd[0]) == SCSI_READ_CMD) - atomic_inc(&res->read_failures); + atomic_inc_unchecked(&res->read_failures); else if (SCSI_CMD_TYPE(scsi_cmd->cmnd[0]) == SCSI_WRITE_CMD) - atomic_inc(&res->write_failures); + atomic_inc_unchecked(&res->write_failures); if (!RES_IS_GSCSI(res->cfg_entry) && masked_ioasc != PMCRAID_IOASC_HW_DEVICE_BUS_STATUS_ERROR) { @@ -3534,7 +3534,7 @@ static int pmcraid_queuecommand_lck( * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses * hrrq_id assigned here in queuecommand */ - ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % + ioarcb->hrrq_id = atomic_add_return_unchecked(1, &(pinstance->last_message_id)) % pinstance->num_hrrq; cmd->cmd_done = pmcraid_io_done; @@ -3846,7 +3846,7 @@ static long pmcraid_ioctl_passthrough( * block of scsi_cmd which is re-used (e.g. cancel/abort), which uses * hrrq_id assigned here in queuecommand */ - ioarcb->hrrq_id = atomic_add_return(1, &(pinstance->last_message_id)) % + ioarcb->hrrq_id = atomic_add_return_unchecked(1, &(pinstance->last_message_id)) % pinstance->num_hrrq; if (request_size) { @@ -4483,7 +4483,7 @@ static void pmcraid_worker_function(struct work_struct *workp) pinstance = container_of(workp, struct pmcraid_instance, worker_q); /* add resources only after host is added into system */ - if (!atomic_read(&pinstance->expose_resources)) + if (!atomic_read_unchecked(&pinstance->expose_resources)) return; fw_version = be16_to_cpu(pinstance->inq_data->fw_version); @@ -5310,8 +5310,8 @@ static int pmcraid_init_instance(struct pci_dev *pdev, struct Scsi_Host *host, init_waitqueue_head(&pinstance->reset_wait_q); atomic_set(&pinstance->outstanding_cmds, 0); - atomic_set(&pinstance->last_message_id, 0); - atomic_set(&pinstance->expose_resources, 0); + atomic_set_unchecked(&pinstance->last_message_id, 0); + atomic_set_unchecked(&pinstance->expose_resources, 0); INIT_LIST_HEAD(&pinstance->free_res_q); INIT_LIST_HEAD(&pinstance->used_res_q); @@ -6024,7 +6024,7 @@ static int pmcraid_probe(struct pci_dev *pdev, /* Schedule worker thread to handle CCN and take care of adding and * removing devices to OS */ - atomic_set(&pinstance->expose_resources, 1); + atomic_set_unchecked(&pinstance->expose_resources, 1); schedule_work(&pinstance->worker_q); return rc; diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h index e1d150f..6c6df44 100644 --- a/drivers/scsi/pmcraid.h +++ b/drivers/scsi/pmcraid.h @@ -748,7 +748,7 @@ struct pmcraid_instance { struct pmcraid_isr_param hrrq_vector[PMCRAID_NUM_MSIX_VECTORS]; /* Message id as filled in last fired IOARCB, used to identify HRRQ */ - atomic_t last_message_id; + atomic_unchecked_t last_message_id; /* configuration table */ struct pmcraid_config_table *cfg_table; @@ -777,7 +777,7 @@ struct pmcraid_instance { atomic_t outstanding_cmds; /* should add/delete resources to mid-layer now ?*/ - atomic_t expose_resources; + atomic_unchecked_t expose_resources; @@ -813,8 +813,8 @@ struct pmcraid_resource_entry { struct pmcraid_config_table_entry_ext cfg_entry_ext; }; struct scsi_device *scsi_dev; /* Link scsi_device structure */ - atomic_t read_failures; /* count of failed READ commands */ - atomic_t write_failures; /* count of failed WRITE commands */ + atomic_unchecked_t read_failures; /* count of failed READ commands */ + atomic_unchecked_t write_failures; /* count of failed WRITE commands */ /* To indicate add/delete/modify during CCN */ u8 change_detected; diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index bf60c63..74d4dce 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2001,7 +2001,7 @@ qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) return 0; } -struct fc_function_template qla2xxx_transport_functions = { +fc_function_template_no_const qla2xxx_transport_functions = { .show_host_node_name = 1, .show_host_port_name = 1, @@ -2048,7 +2048,7 @@ struct fc_function_template qla2xxx_transport_functions = { .bsg_timeout = qla24xx_bsg_timeout, }; -struct fc_function_template qla2xxx_transport_vport_functions = { +fc_function_template_no_const qla2xxx_transport_vport_functions = { .show_host_node_name = 1, .show_host_port_name = 1, diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 026bfde..90c4018 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -528,8 +528,8 @@ extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *); struct device_attribute; extern struct device_attribute *qla2x00_host_attrs[]; struct fc_function_template; -extern struct fc_function_template qla2xxx_transport_functions; -extern struct fc_function_template qla2xxx_transport_vport_functions; +extern fc_function_template_no_const qla2xxx_transport_functions; +extern fc_function_template_no_const qla2xxx_transport_vport_functions; extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); extern void qla2x00_init_host_attr(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ad72c1d..afc9a98 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1571,8 +1571,10 @@ qla2x00_config_dma_addressing(struct qla_hw_data *ha) !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) { /* Ok, a 64bit DMA mask is applicable. */ ha->flags.enable_64bit_addressing = 1; - ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64; - ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64; + pax_open_kernel(); + *(void **)&ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64; + *(void **)&ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64; + pax_close_kernel(); return; } } diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index ddf16a8..80f4dd0 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -291,7 +291,7 @@ struct ddb_entry { * (4000 only) */ atomic_t relogin_timer; /* Max Time to wait for * relogin to complete */ - atomic_t relogin_retry_count; /* Num of times relogin has been + atomic_unchecked_t relogin_retry_count; /* Num of times relogin has been * retried */ uint32_t default_time2wait; /* Default Min time between * relogins (+aens) */ diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 4d231c1..2892c37 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2971,12 +2971,12 @@ static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) */ if (!iscsi_is_session_online(cls_sess)) { /* Reset retry relogin timer */ - atomic_inc(&ddb_entry->relogin_retry_count); + atomic_inc_unchecked(&ddb_entry->relogin_retry_count); DEBUG2(ql4_printk(KERN_INFO, ha, "%s: index[%d] relogin timed out-retrying" " relogin (%d), retry (%d)\n", __func__, ddb_entry->fw_ddb_index, - atomic_read(&ddb_entry->relogin_retry_count), + atomic_read_unchecked(&ddb_entry->relogin_retry_count), ddb_entry->default_time2wait + 4)); set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); atomic_set(&ddb_entry->retry_relogin_timer, @@ -5081,7 +5081,7 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); atomic_set(&ddb_entry->relogin_timer, 0); - atomic_set(&ddb_entry->relogin_retry_count, 0); + atomic_set_unchecked(&ddb_entry->relogin_retry_count, 0); def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout); ddb_entry->default_relogin_timeout = (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ? diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index eaa808e..95f8841 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -661,7 +661,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) unsigned long timeout; int rtn = 0; - atomic_inc(&cmd->device->iorequest_cnt); + atomic_inc_unchecked(&cmd->device->iorequest_cnt); /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 86d5220..f22c51a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1458,7 +1458,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) shost = sdev->host; scsi_init_cmd_errh(cmd); cmd->result = DID_NO_CONNECT << 16; - atomic_inc(&cmd->device->iorequest_cnt); + atomic_inc_unchecked(&cmd->device->iorequest_cnt); /* * SCSI request completion path will do scsi_device_unbusy(), @@ -1484,9 +1484,9 @@ static void scsi_softirq_done(struct request *rq) INIT_LIST_HEAD(&cmd->eh_entry); - atomic_inc(&cmd->device->iodone_cnt); + atomic_inc_unchecked(&cmd->device->iodone_cnt); if (cmd->result) - atomic_inc(&cmd->device->ioerr_cnt); + atomic_inc_unchecked(&cmd->device->ioerr_cnt); disposition = scsi_decide_disposition(cmd); if (disposition != SUCCESS && diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 931a7d9..0c2a754 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -658,7 +658,7 @@ show_iostat_##field(struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ struct scsi_device *sdev = to_scsi_device(dev); \ - unsigned long long count = atomic_read(&sdev->field); \ + unsigned long long count = atomic_read_unchecked(&sdev->field); \ return snprintf(buf, 20, "0x%llx\n", count); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL) diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 84a1fdf..693b0d6 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -362,7 +362,7 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, int err; dprintk("%lx %u\n", uaddr, len); - err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL); + err = blk_rq_map_user(q, rq, NULL, (void __user *)uaddr, len, GFP_KERNEL); if (err) { /* * TODO: need to fixup sg_tablesize, max_segment_size, diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index e106c27..11a380e 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -497,7 +497,7 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_class, * Netlink Infrastructure */ -static atomic_t fc_event_seq; +static atomic_unchecked_t fc_event_seq; /** * fc_get_event_number - Obtain the next sequential FC event number @@ -510,7 +510,7 @@ static atomic_t fc_event_seq; u32 fc_get_event_number(void) { - return atomic_add_return(1, &fc_event_seq); + return atomic_add_return_unchecked(1, &fc_event_seq); } EXPORT_SYMBOL(fc_get_event_number); @@ -654,7 +654,7 @@ static __init int fc_transport_init(void) { int error; - atomic_set(&fc_event_seq, 0); + atomic_set_unchecked(&fc_event_seq, 0); error = transport_class_register(&fc_host_class); if (error) @@ -844,7 +844,7 @@ static int fc_str_to_dev_loss(const char *buf, unsigned long *val) char *cp; *val = simple_strtoul(buf, &cp, 0); - if ((*cp && (*cp != '\n')) || (*val < 0)) + if (*cp && (*cp != '\n')) return -EINVAL; /* * Check for overflow; dev_loss_tmo is u32 diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 133926b..903000d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -80,7 +80,7 @@ struct iscsi_internal { struct transport_container session_cont; }; -static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ +static atomic_unchecked_t iscsi_session_nr; /* sysfs session id for next new session */ static struct workqueue_struct *iscsi_eh_timer_workq; static DEFINE_IDA(iscsi_sess_ida); @@ -1738,7 +1738,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) int err; ihost = shost->shost_data; - session->sid = atomic_add_return(1, &iscsi_session_nr); + session->sid = atomic_add_return_unchecked(1, &iscsi_session_nr); if (target_id == ISCSI_MAX_TARGET) { id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL); @@ -3944,7 +3944,7 @@ static __init int iscsi_transport_init(void) printk(KERN_INFO "Loading iSCSI transport class v%s.\n", ISCSI_TRANSPORT_VERSION); - atomic_set(&iscsi_session_nr, 0); + atomic_set_unchecked(&iscsi_session_nr, 0); err = class_register(&iscsi_transport_class); if (err) diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index f379c7f..e8fc69c 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -33,7 +33,7 @@ #include "scsi_transport_srp_internal.h" struct srp_host_attrs { - atomic_t next_port_id; + atomic_unchecked_t next_port_id; }; #define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) @@ -61,7 +61,7 @@ static int srp_host_setup(struct transport_container *tc, struct device *dev, struct Scsi_Host *shost = dev_to_shost(dev); struct srp_host_attrs *srp_host = to_srp_host_attrs(shost); - atomic_set(&srp_host->next_port_id, 0); + atomic_set_unchecked(&srp_host->next_port_id, 0); return 0; } @@ -210,7 +210,7 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost, memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id)); rport->roles = ids->roles; - id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id); + id = atomic_inc_return_unchecked(&to_srp_host_attrs(shost)->next_port_id); dev_set_name(&rport->dev, "port-%d:%d", shost->host_no, id); transport_setup_device(&rport->dev); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c398634..47ccb41 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2923,7 +2923,7 @@ static int sd_probe(struct device *dev) sdkp->disk = gd; sdkp->index = index; atomic_set(&sdkp->openers, 0); - atomic_set(&sdkp->device->ioerr_cnt, 0); + atomic_set_unchecked(&sdkp->device->ioerr_cnt, 0); if (!sdp->request_queue->rq_timeout) { if (sdp->type != TYPE_MOD) @@ -2936,7 +2936,7 @@ static int sd_probe(struct device *dev) device_initialize(&sdkp->dev); sdkp->dev.parent = dev; sdkp->dev.class = &sd_disk_class; - dev_set_name(&sdkp->dev, dev_name(dev)); + dev_set_name(&sdkp->dev, "%s", dev_name(dev)); if (device_add(&sdkp->dev)) goto out_free_index; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index df5e961..df6b97f 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1102,7 +1102,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) sdp->disk->disk_name, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), NULL, - (char *)arg); + (char __user *)arg); case BLKTRACESTART: return blk_trace_startstop(sdp->device->request_queue, 1); case BLKTRACESTOP: diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 32b7bb1..2f1c4bd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1631,7 +1631,7 @@ int spi_bus_unlock(struct spi_master *master) EXPORT_SYMBOL_GPL(spi_bus_unlock); /* portable code must never pass more than 32 bytes */ -#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES) +#define SPI_BUFSIZ max(32UL,SMP_CACHE_BYTES) static u8 *buf; diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c index ec9e2ae..cd15d67 100644 --- a/drivers/staging/android/timed_output.c +++ b/drivers/staging/android/timed_output.c @@ -25,7 +25,7 @@ #include "timed_output.h" static struct class *timed_output_class; -static atomic_t device_count; +static atomic_unchecked_t device_count; static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -59,7 +59,7 @@ static int create_timed_output_class(void) timed_output_class = class_create(THIS_MODULE, "timed_output"); if (IS_ERR(timed_output_class)) return PTR_ERR(timed_output_class); - atomic_set(&device_count, 0); + atomic_set_unchecked(&device_count, 0); } return 0; @@ -76,7 +76,7 @@ int timed_output_dev_register(struct timed_output_dev *tdev) if (ret < 0) return ret; - tdev->index = atomic_inc_return(&device_count); + tdev->index = atomic_inc_return_unchecked(&device_count); tdev->dev = device_create(timed_output_class, NULL, MKDEV(0, tdev->index), NULL, tdev->name); if (IS_ERR(tdev->dev)) diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/staging/media/solo6x10/solo6x10-core.c index 3675020..e80d92c 100644 --- a/drivers/staging/media/solo6x10/solo6x10-core.c +++ b/drivers/staging/media/solo6x10/solo6x10-core.c @@ -434,7 +434,7 @@ static void solo_device_release(struct device *dev) static int solo_sysfs_init(struct solo_dev *solo_dev) { - struct bin_attribute *sdram_attr = &solo_dev->sdram_attr; + bin_attribute_no_const *sdram_attr = &solo_dev->sdram_attr; struct device *dev = &solo_dev->dev; const char *driver; int i; diff --git a/drivers/staging/media/solo6x10/solo6x10-p2m.c b/drivers/staging/media/solo6x10/solo6x10-p2m.c index 3335941..2b26186 100644 --- a/drivers/staging/media/solo6x10/solo6x10-p2m.c +++ b/drivers/staging/media/solo6x10/solo6x10-p2m.c @@ -77,7 +77,7 @@ int solo_p2m_dma_desc(struct solo_dev *solo_dev, /* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */ if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) { - p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M; + p2m_id = atomic_inc_return_unchecked(&solo_dev->p2m_count) % SOLO_NR_P2M; if (p2m_id < 0) p2m_id = -p2m_id; } diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h index 6f91d2e..3f011d2 100644 --- a/drivers/staging/media/solo6x10/solo6x10.h +++ b/drivers/staging/media/solo6x10/solo6x10.h @@ -238,7 +238,7 @@ struct solo_dev { /* P2M DMA Engine */ struct solo_p2m_dev p2m_dev[SOLO_NR_P2M]; - atomic_t p2m_count; + atomic_unchecked_t p2m_count; int p2m_jiffies; unsigned int p2m_timeouts; diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 34afc16..ffe44dd 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -421,11 +421,11 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) /* Increment RX stats for virtual ports */ if (work->ipprt >= CVMX_PIP_NUM_INPUT_PORTS) { #ifdef CONFIG_64BIT - atomic64_add(1, (atomic64_t *)&priv->stats.rx_packets); - atomic64_add(skb->len, (atomic64_t *)&priv->stats.rx_bytes); + atomic64_add_unchecked(1, (atomic64_unchecked_t *)&priv->stats.rx_packets); + atomic64_add_unchecked(skb->len, (atomic64_unchecked_t *)&priv->stats.rx_bytes); #else - atomic_add(1, (atomic_t *)&priv->stats.rx_packets); - atomic_add(skb->len, (atomic_t *)&priv->stats.rx_bytes); + atomic_add_unchecked(1, (atomic_unchecked_t *)&priv->stats.rx_packets); + atomic_add_unchecked(skb->len, (atomic_unchecked_t *)&priv->stats.rx_bytes); #endif } netif_receive_skb(skb); @@ -437,9 +437,9 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) dev->name); */ #ifdef CONFIG_64BIT - atomic64_add(1, (atomic64_t *)&priv->stats.rx_dropped); + atomic64_unchecked_add(1, (atomic64_unchecked_t *)&priv->stats.rx_dropped); #else - atomic_add(1, (atomic_t *)&priv->stats.rx_dropped); + atomic_add_unchecked(1, (atomic_unchecked_t *)&priv->stats.rx_dropped); #endif dev_kfree_skb_irq(skb); } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index c3a90e7..023619a 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -252,11 +252,11 @@ static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) * since the RX tasklet also increments it. */ #ifdef CONFIG_64BIT - atomic64_add(rx_status.dropped_packets, - (atomic64_t *)&priv->stats.rx_dropped); + atomic64_add_unchecked(rx_status.dropped_packets, + (atomic64_unchecked_t *)&priv->stats.rx_dropped); #else - atomic_add(rx_status.dropped_packets, - (atomic_t *)&priv->stats.rx_dropped); + atomic_add_unchecked(rx_status.dropped_packets, + (atomic_unchecked_t *)&priv->stats.rx_dropped); #endif } diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h index dc23395..cf7e9b1 100644 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ b/drivers/staging/rtl8712/rtl871x_io.h @@ -108,7 +108,7 @@ struct _io_ops { u8 *pmem); u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); -}; +} __no_const; struct io_req { struct list_head list; diff --git a/drivers/staging/sbe-2t3e3/netdev.c b/drivers/staging/sbe-2t3e3/netdev.c index 1f5088b..0e59820 100644 --- a/drivers/staging/sbe-2t3e3/netdev.c +++ b/drivers/staging/sbe-2t3e3/netdev.c @@ -51,7 +51,7 @@ static int t3e3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) t3e3_if_config(sc, cmd_2t3e3, (char *)¶m, &resp, &rlen); if (rlen) - if (copy_to_user(data, &resp, rlen)) + if (rlen > sizeof resp || copy_to_user(data, &resp, rlen)) return -EFAULT; return 0; diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index a863a98..d272795 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h @@ -83,7 +83,7 @@ struct vhci_hcd { unsigned resuming:1; unsigned long re_timeout; - atomic_t seqnum; + atomic_unchecked_t seqnum; /* * NOTE: diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index d7974cb..d78076b 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -441,7 +441,7 @@ static void vhci_tx_urb(struct urb *urb) spin_lock(&vdev->priv_lock); - priv->seqnum = atomic_inc_return(&the_controller->seqnum); + priv->seqnum = atomic_inc_return_unchecked(&the_controller->seqnum); if (priv->seqnum == 0xffff) dev_info(&urb->dev->dev, "seqnum max\n"); @@ -687,7 +687,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) return -ENOMEM; } - unlink->seqnum = atomic_inc_return(&the_controller->seqnum); + unlink->seqnum = atomic_inc_return_unchecked(&the_controller->seqnum); if (unlink->seqnum == 0xffff) pr_info("seqnum max\n"); @@ -891,7 +891,7 @@ static int vhci_start(struct usb_hcd *hcd) vdev->rhport = rhport; } - atomic_set(&vhci->seqnum, 0); + atomic_set_unchecked(&vhci->seqnum, 0); spin_lock_init(&vhci->lock); hcd->power_budget = 0; /* no limit */ diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index d07fcb5..358e1e1 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -80,7 +80,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, if (!urb) { pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum); pr_info("max seqnum %d\n", - atomic_read(&the_controller->seqnum)); + atomic_read_unchecked(&the_controller->seqnum)); usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return; } diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c index 8417c2f..ef5ebd6 100644 --- a/drivers/staging/vt6655/hostap.c +++ b/drivers/staging/vt6655/hostap.c @@ -69,14 +69,13 @@ static int msglevel = MSG_LEVEL_INFO; * */ +static net_device_ops_no_const apdev_netdev_ops; + static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked) { PSDevice apdev_priv; struct net_device *dev = pDevice->dev; int ret; - const struct net_device_ops apdev_netdev_ops = { - .ndo_start_xmit = pDevice->tx_80211, - }; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name); @@ -88,6 +87,8 @@ static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked) *apdev_priv = *pDevice; memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN); + /* only half broken now */ + apdev_netdev_ops.ndo_start_xmit = pDevice->tx_80211; pDevice->apdev->netdev_ops = &apdev_netdev_ops; pDevice->apdev->type = ARPHRD_IEEE80211; diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c index c699a30..b90a5fd 100644 --- a/drivers/staging/vt6656/hostap.c +++ b/drivers/staging/vt6656/hostap.c @@ -60,14 +60,13 @@ static int msglevel =MSG_LEVEL_INFO; * */ +static net_device_ops_no_const apdev_netdev_ops; + static int hostap_enable_hostapd(struct vnt_private *pDevice, int rtnl_locked) { struct vnt_private *apdev_priv; struct net_device *dev = pDevice->dev; int ret; - const struct net_device_ops apdev_netdev_ops = { - .ndo_start_xmit = pDevice->tx_80211, - }; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name); @@ -79,6 +78,8 @@ static int hostap_enable_hostapd(struct vnt_private *pDevice, int rtnl_locked) *apdev_priv = *pDevice; memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN); + /* only half broken now */ + apdev_netdev_ops.ndo_start_xmit = pDevice->tx_80211; pDevice->apdev->netdev_ops = &apdev_netdev_ops; pDevice->apdev->type = ARPHRD_IEEE80211; diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h index d128ce2..fc1f9a1 100644 --- a/drivers/staging/zcache/tmem.h +++ b/drivers/staging/zcache/tmem.h @@ -225,7 +225,7 @@ struct tmem_pamops { bool (*is_remote)(void *); int (*replace_in_obj)(void *, struct tmem_obj *); #endif -}; +} __no_const; extern void tmem_register_pamops(struct tmem_pamops *m); /* memory allocation methods provided by the host implementation */ @@ -234,7 +234,7 @@ struct tmem_hostops { void (*obj_free)(struct tmem_obj *, struct tmem_pool *); struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *); void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *); -}; +} __no_const; extern void tmem_register_hostops(struct tmem_hostops *m); /* core tmem accessor functions */ diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index d3536f5..a0c2ce9 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c @@ -62,7 +62,7 @@ static const u32 sbp_unit_directory_template[] = { #define SESSION_MAINTENANCE_INTERVAL HZ -static atomic_t login_id = ATOMIC_INIT(0); +static atomic_unchecked_t login_id = ATOMIC_INIT(0); static void session_maintenance_work(struct work_struct *); static int sbp_run_transaction(struct fw_card *, int, int, int, int, @@ -444,7 +444,7 @@ static void sbp_management_request_login( login->lun = se_lun; login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo); login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)); - login->login_id = atomic_inc_return(&login_id); + login->login_id = atomic_inc_return_unchecked(&login_id); login->tgt_agt = sbp_target_agent_register(login); if (IS_ERR(login->tgt_agt)) { diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4630481..c26782a 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1400,7 +1400,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) spin_lock_init(&dev->se_port_lock); spin_lock_init(&dev->se_tmr_lock); spin_lock_init(&dev->qf_cmd_lock); - atomic_set(&dev->dev_ordered_id, 0); + atomic_set_unchecked(&dev->dev_ordered_id, 0); INIT_LIST_HEAD(&dev->t10_wwn.t10_vpd_list); spin_lock_init(&dev->t10_wwn.t10_vpd_lock); INIT_LIST_HEAD(&dev->t10_pr.registration_list); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 21e3158..43c6004 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1080,7 +1080,7 @@ transport_check_alloc_task_attr(struct se_cmd *cmd) * Used to determine when ORDERED commands should go from * Dormant to Active status. */ - cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id); + cmd->se_ordered_id = atomic_inc_return_unchecked(&dev->dev_ordered_id); smp_mb__after_atomic_inc(); pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n", cmd->se_ordered_id, cmd->sam_task_attr, diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index 33f83fe..d80f8e1 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1570,10 +1570,10 @@ static int cy_open(struct tty_struct *tty, struct file *filp) printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, info->port.count); #endif - info->port.count++; + atomic_inc(&info->port.count); #ifdef CY_DEBUG_COUNT printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", - current->pid, info->port.count); + current->pid, atomic_read(&info->port.count)); #endif /* @@ -3972,7 +3972,7 @@ static int cyclades_proc_show(struct seq_file *m, void *v) for (j = 0; j < cy_card[i].nports; j++) { info = &cy_card[i].ports[j]; - if (info->port.count) { + if (atomic_read(&info->port.count)) { /* XXX is the ldisc num worth this? */ struct tty_struct *tty; struct tty_ldisc *ld; diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index eb255e8..f637a57 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -338,7 +338,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) spin_lock_irqsave(&hp->port.lock, flags); /* Check and then increment for fast path open. */ - if (hp->port.count++ > 0) { + if (atomic_inc_return(&hp->port.count) > 1) { spin_unlock_irqrestore(&hp->port.lock, flags); hvc_kick(); return 0; @@ -388,7 +388,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) spin_lock_irqsave(&hp->port.lock, flags); - if (--hp->port.count == 0) { + if (atomic_dec_return(&hp->port.count) == 0) { spin_unlock_irqrestore(&hp->port.lock, flags); /* We are done with the tty pointer now. */ tty_port_tty_set(&hp->port, NULL); @@ -406,9 +406,9 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) */ tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT); } else { - if (hp->port.count < 0) + if (atomic_read(&hp->port.count) < 0) printk(KERN_ERR "hvc_close %X: oops, count is %d\n", - hp->vtermno, hp->port.count); + hp->vtermno, atomic_read(&hp->port.count)); spin_unlock_irqrestore(&hp->port.lock, flags); } } @@ -438,12 +438,12 @@ static void hvc_hangup(struct tty_struct *tty) * open->hangup case this can be called after the final close so prevent * that from happening for now. */ - if (hp->port.count <= 0) { + if (atomic_read(&hp->port.count) <= 0) { spin_unlock_irqrestore(&hp->port.lock, flags); return; } - hp->port.count = 0; + atomic_set(&hp->port.count, 0); spin_unlock_irqrestore(&hp->port.lock, flags); tty_port_tty_set(&hp->port, NULL); @@ -491,7 +491,7 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count return -EPIPE; /* FIXME what's this (unprotected) check for? */ - if (hp->port.count <= 0) + if (atomic_read(&hp->port.count) <= 0) return -EIO; spin_lock_irqsave(&hp->lock, flags); diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 81e939e..95ead10 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -83,6 +83,7 @@ #include #include #include +#include /* * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00). @@ -416,7 +417,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribut spin_lock_irqsave(&hvcsd->lock, flags); - if (hvcsd->port.count > 0) { + if (atomic_read(&hvcsd->port.count) > 0) { spin_unlock_irqrestore(&hvcsd->lock, flags); printk(KERN_INFO "HVCS: vterm state unchanged. " "The hvcs device node is still in use.\n"); @@ -1127,7 +1128,7 @@ static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty) } } - hvcsd->port.count = 0; + atomic_set(&hvcsd->port.count, 0); hvcsd->port.tty = tty; tty->driver_data = hvcsd; @@ -1180,7 +1181,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) unsigned long flags; spin_lock_irqsave(&hvcsd->lock, flags); - hvcsd->port.count++; + atomic_inc(&hvcsd->port.count); hvcsd->todo_mask |= HVCS_SCHED_READ; spin_unlock_irqrestore(&hvcsd->lock, flags); @@ -1216,7 +1217,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) hvcsd = tty->driver_data; spin_lock_irqsave(&hvcsd->lock, flags); - if (--hvcsd->port.count == 0) { + if (atomic_dec_and_test(&hvcsd->port.count)) { vio_disable_interrupts(hvcsd->vdev); @@ -1241,10 +1242,10 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) free_irq(irq, hvcsd); return; - } else if (hvcsd->port.count < 0) { + } else if (atomic_read(&hvcsd->port.count) < 0) { printk(KERN_ERR "HVCS: vty-server@%X open_count: %d" " is missmanaged.\n", - hvcsd->vdev->unit_address, hvcsd->port.count); + hvcsd->vdev->unit_address, atomic_read(&hvcsd->port.count)); } spin_unlock_irqrestore(&hvcsd->lock, flags); @@ -1266,7 +1267,7 @@ static void hvcs_hangup(struct tty_struct * tty) spin_lock_irqsave(&hvcsd->lock, flags); /* Preserve this so that we know how many kref refs to put */ - temp_open_count = hvcsd->port.count; + temp_open_count = atomic_read(&hvcsd->port.count); /* * Don't kref put inside the spinlock because the destruction @@ -1281,7 +1282,7 @@ static void hvcs_hangup(struct tty_struct * tty) tty->driver_data = NULL; hvcsd->port.tty = NULL; - hvcsd->port.count = 0; + atomic_set(&hvcsd->port.count, 0); /* This will drop any buffered data on the floor which is OK in a hangup * scenario. */ @@ -1352,7 +1353,7 @@ static int hvcs_write(struct tty_struct *tty, * the middle of a write operation? This is a crummy place to do this * but we want to keep it all in the spinlock. */ - if (hvcsd->port.count <= 0) { + if (atomic_read(&hvcsd->port.count) <= 0) { spin_unlock_irqrestore(&hvcsd->lock, flags); return -ENODEV; } @@ -1426,7 +1427,7 @@ static int hvcs_write_room(struct tty_struct *tty) { struct hvcs_struct *hvcsd = tty->driver_data; - if (!hvcsd || hvcsd->port.count <= 0) + if (!hvcsd || atomic_read(&hvcsd->port.count) <= 0) return 0; return HVCS_BUFF_LEN - hvcsd->chars_in_buffer; diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 4190199..48f2920 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -85,7 +85,7 @@ struct hvsi_struct { int n_outbuf; uint32_t vtermno; uint32_t virq; - atomic_t seqno; /* HVSI packet sequence number */ + atomic_unchecked_t seqno; /* HVSI packet sequence number */ uint16_t mctrl; uint8_t state; /* HVSI protocol state */ uint8_t flags; @@ -295,7 +295,7 @@ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno) packet.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER; packet.hdr.len = sizeof(struct hvsi_query_response); - packet.hdr.seqno = atomic_inc_return(&hp->seqno); + packet.hdr.seqno = atomic_inc_return_unchecked(&hp->seqno); packet.verb = VSV_SEND_VERSION_NUMBER; packet.u.version = HVSI_VERSION; packet.query_seqno = query_seqno+1; @@ -555,7 +555,7 @@ static int hvsi_query(struct hvsi_struct *hp, uint16_t verb) packet.hdr.type = VS_QUERY_PACKET_HEADER; packet.hdr.len = sizeof(struct hvsi_query); - packet.hdr.seqno = atomic_inc_return(&hp->seqno); + packet.hdr.seqno = atomic_inc_return_unchecked(&hp->seqno); packet.verb = verb; pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len); @@ -597,7 +597,7 @@ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl) int wrote; packet.hdr.type = VS_CONTROL_PACKET_HEADER, - packet.hdr.seqno = atomic_inc_return(&hp->seqno); + packet.hdr.seqno = atomic_inc_return_unchecked(&hp->seqno); packet.hdr.len = sizeof(struct hvsi_control); packet.verb = VSV_SET_MODEM_CTL; packet.mask = HVSI_TSDTR; @@ -680,7 +680,7 @@ static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count) BUG_ON(count > HVSI_MAX_OUTGOING_DATA); packet.hdr.type = VS_DATA_PACKET_HEADER; - packet.hdr.seqno = atomic_inc_return(&hp->seqno); + packet.hdr.seqno = atomic_inc_return_unchecked(&hp->seqno); packet.hdr.len = count + sizeof(struct hvsi_header); memcpy(&packet.data, buf, count); @@ -697,7 +697,7 @@ static void hvsi_close_protocol(struct hvsi_struct *hp) struct hvsi_control packet __ALIGNED__; packet.hdr.type = VS_CONTROL_PACKET_HEADER; - packet.hdr.seqno = atomic_inc_return(&hp->seqno); + packet.hdr.seqno = atomic_inc_return_unchecked(&hp->seqno); packet.hdr.len = 6; packet.verb = VSV_CLOSE_PROTOCOL; diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c index ac27671..0f627ee 100644 --- a/drivers/tty/hvc/hvsi_lib.c +++ b/drivers/tty/hvc/hvsi_lib.c @@ -9,7 +9,7 @@ static int hvsi_send_packet(struct hvsi_priv *pv, struct hvsi_header *packet) { - packet->seqno = atomic_inc_return(&pv->seqno); + packet->seqno = atomic_inc_return_unchecked(&pv->seqno); /* Assumes that always succeeds, works in practice */ return pv->put_chars(pv->termno, (char *)packet, packet->len); @@ -21,7 +21,7 @@ static void hvsi_start_handshake(struct hvsi_priv *pv) /* Reset state */ pv->established = 0; - atomic_set(&pv->seqno, 0); + atomic_set_unchecked(&pv->seqno, 0); pr_devel("HVSI@%x: Handshaking started\n", pv->termno); @@ -265,7 +265,7 @@ int hvsilib_read_mctrl(struct hvsi_priv *pv) pv->mctrl_update = 0; q.hdr.type = VS_QUERY_PACKET_HEADER; q.hdr.len = sizeof(struct hvsi_query); - q.hdr.seqno = atomic_inc_return(&pv->seqno); + q.hdr.seqno = atomic_inc_return_unchecked(&pv->seqno); q.verb = VSV_SEND_MODEM_CTL_STATUS; rc = hvsi_send_packet(pv, &q.hdr); if (rc <= 0) { diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c index 8fd72ff..34a0bed 100644 --- a/drivers/tty/ipwireless/tty.c +++ b/drivers/tty/ipwireless/tty.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "tty.h" #include "network.h" @@ -99,10 +100,10 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp) mutex_unlock(&tty->ipw_tty_mutex); return -ENODEV; } - if (tty->port.count == 0) + if (atomic_read(&tty->port.count) == 0) tty->tx_bytes_queued = 0; - tty->port.count++; + atomic_inc(&tty->port.count); tty->port.tty = linux_tty; linux_tty->driver_data = tty; @@ -118,9 +119,7 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp) static void do_ipw_close(struct ipw_tty *tty) { - tty->port.count--; - - if (tty->port.count == 0) { + if (atomic_dec_return(&tty->port.count) == 0) { struct tty_struct *linux_tty = tty->port.tty; if (linux_tty != NULL) { @@ -141,7 +140,7 @@ static void ipw_hangup(struct tty_struct *linux_tty) return; mutex_lock(&tty->ipw_tty_mutex); - if (tty->port.count == 0) { + if (atomic_read(&tty->port.count) == 0) { mutex_unlock(&tty->ipw_tty_mutex); return; } @@ -164,7 +163,7 @@ void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, mutex_lock(&tty->ipw_tty_mutex); - if (!tty->port.count) { + if (!atomic_read(&tty->port.count)) { mutex_unlock(&tty->ipw_tty_mutex); return; } @@ -206,7 +205,7 @@ static int ipw_write(struct tty_struct *linux_tty, return -ENODEV; mutex_lock(&tty->ipw_tty_mutex); - if (!tty->port.count) { + if (!atomic_read(&tty->port.count)) { mutex_unlock(&tty->ipw_tty_mutex); return -EINVAL; } @@ -246,7 +245,7 @@ static int ipw_write_room(struct tty_struct *linux_tty) if (!tty) return -ENODEV; - if (!tty->port.count) + if (!atomic_read(&tty->port.count)) return -EINVAL; room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; @@ -288,7 +287,7 @@ static int ipw_chars_in_buffer(struct tty_struct *linux_tty) if (!tty) return 0; - if (!tty->port.count) + if (!atomic_read(&tty->port.count)) return 0; return tty->tx_bytes_queued; @@ -369,7 +368,7 @@ static int ipw_tiocmget(struct tty_struct *linux_tty) if (!tty) return -ENODEV; - if (!tty->port.count) + if (!atomic_read(&tty->port.count)) return -EINVAL; return get_control_lines(tty); @@ -385,7 +384,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, if (!tty) return -ENODEV; - if (!tty->port.count) + if (!atomic_read(&tty->port.count)) return -EINVAL; return set_control_lines(tty, set, clear); @@ -399,7 +398,7 @@ static int ipw_ioctl(struct tty_struct *linux_tty, if (!tty) return -ENODEV; - if (!tty->port.count) + if (!atomic_read(&tty->port.count)) return -EINVAL; /* FIXME: Exactly how is the tty object locked here .. */ @@ -555,7 +554,7 @@ void ipwireless_tty_free(struct ipw_tty *tty) * are gone */ mutex_lock(&ttyj->ipw_tty_mutex); } - while (ttyj->port.count) + while (atomic_read(&ttyj->port.count)) do_ipw_close(ttyj); ipwireless_disassociate_network_ttys(network, ttyj->channel_idx); diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 1deaca4..c8582d4 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1189,7 +1189,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) } ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; - ch->port.count++; + atomic_inc(&ch->port.count); tty->driver_data = ch; tty_port_tty_set(&ch->port, tty); mutex_lock(&ch->port.mutex); diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 6422390..49003ac 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1632,7 +1632,7 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) spin_lock_init(&dlci->lock); mutex_init(&dlci->mutex); dlci->fifo = &dlci->_fifo; - if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) { + if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL)) { kfree(dlci); return NULL; } @@ -2932,7 +2932,7 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) struct gsm_dlci *dlci = tty->driver_data; struct tty_port *port = &dlci->port; - port->count++; + atomic_inc(&port->count); dlci_get(dlci); dlci_get(dlci->gsm->dlci[0]); mux_get(dlci->gsm); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 6c7fe90..9241dab 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2203,6 +2203,7 @@ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { *ops = tty_ldisc_N_TTY; ops->owner = NULL; - ops->refcount = ops->flags = 0; + atomic_set(&ops->refcount, 0); + ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index abfd990..5ab5da9 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -796,8 +796,10 @@ static void __init unix98_pty_init(void) panic("Couldn't register Unix98 pts driver"); /* Now create the /dev/ptmx special device */ + pax_open_kernel(); tty_default_fops(&ptmx_fops); - ptmx_fops.open = ptmx_open; + *(void **)&ptmx_fops.open = ptmx_open; + pax_close_kernel(); cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 354564e..fe50d9a 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -914,7 +914,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) tty->driver_data = info; tty_port_tty_set(port, tty); - if (port->count++ == 0) { + if (atomic_inc_return(&port->count) == 1) { atomic_inc(&rp_num_ports_open); #ifdef ROCKET_DEBUG_OPEN @@ -923,7 +923,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) #endif } #ifdef ROCKET_DEBUG_OPEN - printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count); + printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, atomic-read(&info->port.count)); #endif /* @@ -1515,7 +1515,7 @@ static void rp_hangup(struct tty_struct *tty) spin_unlock_irqrestore(&info->port.lock, flags); return; } - if (info->port.count) + if (atomic_read(&info->port.count)) atomic_dec(&rp_num_ports_open); clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); spin_unlock_irqrestore(&info->port.lock, flags); diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c index e2520ab..034e20b 100644 --- a/drivers/tty/serial/ioc4_serial.c +++ b/drivers/tty/serial/ioc4_serial.c @@ -437,7 +437,7 @@ struct ioc4_soft { } is_intr_info[MAX_IOC4_INTR_ENTS]; /* Number of entries active in the above array */ - atomic_t is_num_intrs; + atomic_unchecked_t is_num_intrs; } is_intr_type[IOC4_NUM_INTR_TYPES]; /* is_ir_lock must be held while @@ -974,7 +974,7 @@ intr_connect(struct ioc4_soft *soft, int type, BUG_ON(!((type == IOC4_SIO_INTR_TYPE) || (type == IOC4_OTHER_INTR_TYPE))); - i = atomic_inc_return(&soft-> is_intr_type[type].is_num_intrs) - 1; + i = atomic_inc_return_unchecked(&soft-> is_intr_type[type].is_num_intrs) - 1; BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0))); /* Save off the lower level interrupt handler */ @@ -1001,7 +1001,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg) soft = arg; for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) { - num_intrs = (int)atomic_read( + num_intrs = (int)atomic_read_unchecked( &soft->is_intr_type[intr_type].is_num_intrs); this_mir = this_ir = pending_intrs(soft, intr_type); diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 1002054..dd644a8 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -24,8 +24,9 @@ #define MAX_CONFIG_LEN 40 static struct kgdb_io kgdboc_io_ops; +static struct kgdb_io kgdboc_io_ops_console; -/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */ +/* -1 = init not run yet, 0 = unconfigured, 1/2 = configured. */ static int configured = -1; static char config[MAX_CONFIG_LEN]; @@ -151,6 +152,8 @@ static void cleanup_kgdboc(void) kgdboc_unregister_kbd(); if (configured == 1) kgdb_unregister_io_module(&kgdboc_io_ops); + else if (configured == 2) + kgdb_unregister_io_module(&kgdboc_io_ops_console); } static int configure_kgdboc(void) @@ -160,13 +163,13 @@ static int configure_kgdboc(void) int err; char *cptr = config; struct console *cons; + int is_console = 0; err = kgdboc_option_setup(config); if (err || !strlen(config) || isspace(config[0])) goto noconfig; err = -ENODEV; - kgdboc_io_ops.is_console = 0; kgdb_tty_driver = NULL; kgdboc_use_kms = 0; @@ -187,7 +190,7 @@ static int configure_kgdboc(void) int idx; if (cons->device && cons->device(cons, &idx) == p && idx == tty_line) { - kgdboc_io_ops.is_console = 1; + is_console = 1; break; } cons = cons->next; @@ -197,7 +200,13 @@ static int configure_kgdboc(void) kgdb_tty_line = tty_line; do_register: - err = kgdb_register_io_module(&kgdboc_io_ops); + if (is_console) { + err = kgdb_register_io_module(&kgdboc_io_ops_console); + configured = 2; + } else { + err = kgdb_register_io_module(&kgdboc_io_ops); + configured = 1; + } if (err) goto noconfig; @@ -205,8 +214,6 @@ do_register: if (err) goto nmi_con_failed; - configured = 1; - return 0; nmi_con_failed: @@ -223,7 +230,7 @@ noconfig: static int __init init_kgdboc(void) { /* Already configured? */ - if (configured == 1) + if (configured >= 1) return 0; return configure_kgdboc(); @@ -272,7 +279,7 @@ static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) if (config[len - 1] == '\n') config[len - 1] = '\0'; - if (configured == 1) + if (configured >= 1) cleanup_kgdboc(); /* Go and configure with the new params. */ @@ -312,6 +319,15 @@ static struct kgdb_io kgdboc_io_ops = { .post_exception = kgdboc_post_exp_handler, }; +static struct kgdb_io kgdboc_io_ops_console = { + .name = "kgdboc", + .read_char = kgdboc_get_char, + .write_char = kgdboc_put_char, + .pre_exception = kgdboc_pre_exp_handler, + .post_exception = kgdboc_post_exp_handler, + .is_console = 1 +}; + #ifdef CONFIG_KGDB_SERIAL_CONSOLE /* This is only available if kgdboc is a built in for early debugging */ static int __init kgdboc_early_init(char *opt) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index b11e997..6d25a3b 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -857,7 +857,7 @@ static struct uart_driver msm_uart_driver = { .cons = MSM_CONSOLE, }; -static atomic_t msm_uart_next_id = ATOMIC_INIT(0); +static atomic_unchecked_t msm_uart_next_id = ATOMIC_INIT(0); static int __init msm_serial_probe(struct platform_device *pdev) { @@ -867,7 +867,7 @@ static int __init msm_serial_probe(struct platform_device *pdev) int irq; if (pdev->id == -1) - pdev->id = atomic_inc_return(&msm_uart_next_id) - 1; + pdev->id = atomic_inc_return_unchecked(&msm_uart_next_id) - 1; if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) return -ENXIO; diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 0c8a9fa..234a95f 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -453,11 +453,16 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) } } +static int s3c64xx_serial_startup(struct uart_port *port); static int s3c24xx_serial_startup(struct uart_port *port) { struct s3c24xx_uart_port *ourport = to_ourport(port); int ret; + /* Startup sequence is different for s3c64xx and higher SoC's */ + if (s3c24xx_serial_has_interrupt_mask(port)) + return s3c64xx_serial_startup(port); + dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n", port->mapbase, port->membase); @@ -1124,10 +1129,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, /* setup info for port */ port->dev = &platdev->dev; - /* Startup sequence is different for s3c64xx and higher SoC's */ - if (s3c24xx_serial_has_interrupt_mask(port)) - s3c24xx_serial_ops.startup = s3c64xx_serial_startup; - port->uartclk = 1; if (cfg->uart_flags & UPF_CONS_FLOW) { diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index f87dbfd..42ad4b1 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1454,7 +1454,7 @@ static void uart_hangup(struct tty_struct *tty) uart_flush_buffer(tty); uart_shutdown(tty, state); spin_lock_irqsave(&port->lock, flags); - port->count = 0; + atomic_set(&port->count, 0); clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); spin_unlock_irqrestore(&port->lock, flags); tty_port_tty_set(port, NULL); @@ -1550,7 +1550,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) goto end; } - port->count++; + atomic_inc(&port->count); if (!state->uart_port || state->uart_port->flags & UPF_DEAD) { retval = -ENXIO; goto err_dec_count; @@ -1578,7 +1578,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * Make sure the device is in D0 state. */ - if (port->count == 1) + if (atomic_read(&port->count) == 1) uart_change_pm(state, UART_PM_STATE_ON); /* @@ -1596,7 +1596,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) end: return retval; err_dec_count: - port->count--; + atomic_inc(&port->count); mutex_unlock(&port->mutex); goto end; } diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 8eaf1ab..85c030d 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -3090,7 +3090,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_close(%s) entry, count=%d\n", - __FILE__,__LINE__, info->device_name, info->port.count); + __FILE__,__LINE__, info->device_name, atomic_read(&info->port.count)); if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; @@ -3108,7 +3108,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) cleanup: if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__, - tty->driver->name, info->port.count); + tty->driver->name, atomic_read(&info->port.count)); } /* end of mgsl_close() */ @@ -3207,8 +3207,8 @@ static void mgsl_hangup(struct tty_struct *tty) mgsl_flush_buffer(tty); shutdown(info); - - info->port.count = 0; + + atomic_set(&info->port.count, 0); info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; @@ -3297,12 +3297,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):block_til_ready before block on %s count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); + __FILE__,__LINE__, tty->driver->name, atomic_read(&port->count)); spin_lock_irqsave(&info->irq_spinlock, flags); if (!tty_hung_up_p(filp)) { extra_count = true; - port->count--; + atomic_dec(&port->count); } spin_unlock_irqrestore(&info->irq_spinlock, flags); port->blocked_open++; @@ -3331,7 +3331,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):block_til_ready blocking on %s count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); + __FILE__,__LINE__, tty->driver->name, atomic_read(&port->count)); tty_unlock(tty); schedule(); @@ -3343,12 +3343,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, /* FIXME: Racy on hangup during close wait */ if (extra_count) - port->count++; + atomic_inc(&port->count); port->blocked_open--; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):block_til_ready after blocking on %s count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); + __FILE__,__LINE__, tty->driver->name, atomic_read(&port->count)); if (!retval) port->flags |= ASYNC_NORMAL_ACTIVE; @@ -3400,7 +3400,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_open(%s), old ref count = %d\n", - __FILE__,__LINE__,tty->driver->name, info->port.count); + __FILE__,__LINE__,tty->driver->name, atomic_read(&info->port.count)); /* If port is closing, signal caller to try again */ if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ @@ -3419,10 +3419,10 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) spin_unlock_irqrestore(&info->netlock, flags); goto cleanup; } - info->port.count++; + atomic_inc(&info->port.count); spin_unlock_irqrestore(&info->netlock, flags); - if (info->port.count == 1) { + if (atomic_read(&info->port.count) == 1) { /* 1st open on this device, init hardware */ retval = startup(info); if (retval < 0) @@ -3446,8 +3446,8 @@ cleanup: if (retval) { if (tty->count == 1) info->port.tty = NULL; /* tty layer will release tty struct */ - if(info->port.count) - info->port.count--; + if (atomic_read(&info->port.count)) + atomic_dec(&info->port.count); } return retval; @@ -7665,7 +7665,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, unsigned short new_crctype; /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; switch (encoding) @@ -7760,7 +7760,7 @@ static int hdlcdev_open(struct net_device *dev) /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { + if (atomic_read(&info->port.count) != 0 || info->netcount != 0) { printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; @@ -7846,7 +7846,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; if (cmd != SIOCWANDEV) diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 1abf946..1ee34fc 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -670,7 +670,7 @@ static int open(struct tty_struct *tty, struct file *filp) tty->driver_data = info; info->port.tty = tty; - DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count)); + DBGINFO(("%s open, old ref count = %d\n", info->device_name, atomic_read(&info->port.count))); /* If port is closing, signal caller to try again */ if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ @@ -691,10 +691,10 @@ static int open(struct tty_struct *tty, struct file *filp) mutex_unlock(&info->port.mutex); goto cleanup; } - info->port.count++; + atomic_inc(&info->port.count); spin_unlock_irqrestore(&info->netlock, flags); - if (info->port.count == 1) { + if (atomic_read(&info->port.count) == 1) { /* 1st open on this device, init hardware */ retval = startup(info); if (retval < 0) { @@ -715,8 +715,8 @@ cleanup: if (retval) { if (tty->count == 1) info->port.tty = NULL; /* tty layer will release tty struct */ - if(info->port.count) - info->port.count--; + if(atomic_read(&info->port.count)) + atomic_dec(&info->port.count); } DBGINFO(("%s open rc=%d\n", info->device_name, retval)); @@ -729,7 +729,7 @@ static void close(struct tty_struct *tty, struct file *filp) if (sanity_check(info, tty->name, "close")) return; - DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); + DBGINFO(("%s close entry, count=%d\n", info->device_name, atomic_read(&info->port.count))); if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; @@ -746,7 +746,7 @@ static void close(struct tty_struct *tty, struct file *filp) tty_port_close_end(&info->port, tty); info->port.tty = NULL; cleanup: - DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); + DBGINFO(("%s close exit, count=%d\n", tty->driver->name, atomic_read(&info->port.count))); } static void hangup(struct tty_struct *tty) @@ -764,7 +764,7 @@ static void hangup(struct tty_struct *tty) shutdown(info); spin_lock_irqsave(&info->port.lock, flags); - info->port.count = 0; + atomic_set(&info->port.count, 0); info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; spin_unlock_irqrestore(&info->port.lock, flags); @@ -1449,7 +1449,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, unsigned short new_crctype; /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; DBGINFO(("%s hdlcdev_attach\n", info->device_name)); @@ -1544,7 +1544,7 @@ static int hdlcdev_open(struct net_device *dev) /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { + if (atomic_read(&info->port.count) != 0 || info->netcount != 0) { DBGINFO(("%s hdlc_open busy\n", dev->name)); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; @@ -1629,7 +1629,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) DBGINFO(("%s hdlcdev_ioctl\n", dev->name)); /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; if (cmd != SIOCWANDEV) @@ -2413,7 +2413,7 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) if (port == NULL) continue; spin_lock(&port->lock); - if ((port->port.count || port->netcount) && + if ((atomic_read(&port->port.count) || port->netcount) && port->pending_bh && !port->bh_running && !port->bh_requested) { DBGISR(("%s bh queued\n", port->device_name)); @@ -3302,7 +3302,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) { extra_count = true; - port->count--; + atomic_dec(&port->count); } spin_unlock_irqrestore(&info->lock, flags); port->blocked_open++; @@ -3339,7 +3339,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, remove_wait_queue(&port->open_wait, &wait); if (extra_count) - port->count++; + atomic_inc(&port->count); port->blocked_open--; if (!retval) diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index ff17138..e38b41e 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -750,7 +750,7 @@ static int open(struct tty_struct *tty, struct file *filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s open(), old ref count = %d\n", - __FILE__,__LINE__,tty->driver->name, info->port.count); + __FILE__,__LINE__,tty->driver->name, atomic_read(&info->port.count)); /* If port is closing, signal caller to try again */ if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){ @@ -769,10 +769,10 @@ static int open(struct tty_struct *tty, struct file *filp) spin_unlock_irqrestore(&info->netlock, flags); goto cleanup; } - info->port.count++; + atomic_inc(&info->port.count); spin_unlock_irqrestore(&info->netlock, flags); - if (info->port.count == 1) { + if (atomic_read(&info->port.count) == 1) { /* 1st open on this device, init hardware */ retval = startup(info); if (retval < 0) @@ -796,8 +796,8 @@ cleanup: if (retval) { if (tty->count == 1) info->port.tty = NULL; /* tty layer will release tty struct */ - if(info->port.count) - info->port.count--; + if(atomic_read(&info->port.count)) + atomic_dec(&info->port.count); } return retval; @@ -815,7 +815,7 @@ static void close(struct tty_struct *tty, struct file *filp) if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s close() entry, count=%d\n", - __FILE__,__LINE__, info->device_name, info->port.count); + __FILE__,__LINE__, info->device_name, atomic_read(&info->port.count)); if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; @@ -834,7 +834,7 @@ static void close(struct tty_struct *tty, struct file *filp) cleanup: if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__, - tty->driver->name, info->port.count); + tty->driver->name, atomic_read(&info->port.count)); } /* Called by tty_hangup() when a hangup is signaled. @@ -857,7 +857,7 @@ static void hangup(struct tty_struct *tty) shutdown(info); spin_lock_irqsave(&info->port.lock, flags); - info->port.count = 0; + atomic_set(&info->port.count, 0); info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; spin_unlock_irqrestore(&info->port.lock, flags); @@ -1565,7 +1565,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, unsigned short new_crctype; /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; switch (encoding) @@ -1660,7 +1660,7 @@ static int hdlcdev_open(struct net_device *dev) /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); - if (info->port.count != 0 || info->netcount != 0) { + if (atomic_read(&info->port.count) != 0 || info->netcount != 0) { printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; @@ -1746,7 +1746,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); /* return error if TTY interface open */ - if (info->port.count) + if (atomic_read(&info->port.count)) return -EBUSY; if (cmd != SIOCWANDEV) @@ -2620,7 +2620,7 @@ static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id) * do not request bottom half processing if the * device is not open in a normal mode. */ - if ( port && (port->port.count || port->netcount) && + if ( port && (atomic_read(&port->port.count) || port->netcount) && port->pending_bh && !port->bh_running && !port->bh_requested ) { if ( debug_level >= DEBUG_LEVEL_ISR ) @@ -3318,12 +3318,12 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready() before block, count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); + __FILE__,__LINE__, tty->driver->name, atomic_read(&port->count)); spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) { extra_count = true; - port->count--; + atomic_dec(&port->count); } spin_unlock_irqrestore(&info->lock, flags); port->blocked_open++; @@ -3352,7 +3352,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready() count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); + __FILE__,__LINE__, tty->driver->name, atomic_read(&port->count)); tty_unlock(tty); schedule(); @@ -3363,12 +3363,12 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, remove_wait_queue(&port->open_wait, &wait); if (extra_count) - port->count++; + atomic_inc(&port->count); port->blocked_open--; if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):%s block_til_ready() after, count=%d\n", - __FILE__,__LINE__, tty->driver->name, port->count ); + __FILE__,__LINE__, tty->driver->name, atomic_read(&port->count)); if (!retval) port->flags |= ASYNC_NORMAL_ACTIVE; diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b51c154..17d55d1 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -1022,7 +1022,7 @@ EXPORT_SYMBOL(unregister_sysrq_key); static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - if (count) { + if (count && capable(CAP_SYS_ADMIN)) { char c; if (get_user(c, buf)) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 59d26ef5..3135b94 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3467,7 +3467,7 @@ EXPORT_SYMBOL_GPL(get_current_tty); void tty_default_fops(struct file_operations *fops) { - *fops = tty_fops; + memcpy((void *)fops, &tty_fops, sizeof(tty_fops)); } /* diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 1afe192..73d2c20 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -66,7 +66,7 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) raw_spin_lock_irqsave(&tty_ldisc_lock, flags); tty_ldiscs[disc] = new_ldisc; new_ldisc->num = disc; - new_ldisc->refcount = 0; + atomic_set(&new_ldisc->refcount, 0); raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); return ret; @@ -94,7 +94,7 @@ int tty_unregister_ldisc(int disc) return -EINVAL; raw_spin_lock_irqsave(&tty_ldisc_lock, flags); - if (tty_ldiscs[disc]->refcount) + if (atomic_read(&tty_ldiscs[disc]->refcount)) ret = -EBUSY; else tty_ldiscs[disc] = NULL; @@ -115,7 +115,7 @@ static struct tty_ldisc_ops *get_ldops(int disc) if (ldops) { ret = ERR_PTR(-EAGAIN); if (try_module_get(ldops->owner)) { - ldops->refcount++; + atomic_inc(&ldops->refcount); ret = ldops; } } @@ -128,7 +128,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops) unsigned long flags; raw_spin_lock_irqsave(&tty_ldisc_lock, flags); - ldops->refcount--; + atomic_dec(&ldops->refcount); module_put(ldops->owner); raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); } @@ -196,7 +196,7 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld) /* unreleased reader reference(s) will cause this WARN */ WARN_ON(!atomic_dec_and_test(&ld->users)); - ld->ops->refcount--; + atomic_dec(&ld->ops->refcount); module_put(ld->ops->owner); kfree(ld); raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index f597e88..b7f68ed 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -232,7 +232,7 @@ void tty_port_hangup(struct tty_port *port) unsigned long flags; spin_lock_irqsave(&port->lock, flags); - port->count = 0; + atomic_set(&port->count, 0); port->flags &= ~ASYNC_NORMAL_ACTIVE; tty = port->tty; if (tty) @@ -390,7 +390,7 @@ int tty_port_block_til_ready(struct tty_port *port, /* The port lock protects the port counts */ spin_lock_irqsave(&port->lock, flags); if (!tty_hung_up_p(filp)) - port->count--; + atomic_dec(&port->count); port->blocked_open++; spin_unlock_irqrestore(&port->lock, flags); @@ -432,7 +432,7 @@ int tty_port_block_til_ready(struct tty_port *port, we must not mess that up further */ spin_lock_irqsave(&port->lock, flags); if (!tty_hung_up_p(filp)) - port->count++; + atomic_inc(&port->count); port->blocked_open--; if (retval == 0) port->flags |= ASYNC_NORMAL_ACTIVE; @@ -466,19 +466,19 @@ int tty_port_close_start(struct tty_port *port, return 0; } - if (tty->count == 1 && port->count != 1) { + if (tty->count == 1 && atomic_read(&port->count) != 1) { printk(KERN_WARNING "tty_port_close_start: tty->count = 1 port count = %d.\n", - port->count); - port->count = 1; + atomic_read(&port->count)); + atomic_set(&port->count, 1); } - if (--port->count < 0) { + if (atomic_dec_return(&port->count) < 0) { printk(KERN_WARNING "tty_port_close_start: count = %d\n", - port->count); - port->count = 0; + atomic_read(&port->count)); + atomic_set(&port->count, 0); } - if (port->count) { + if (atomic_read(&port->count)) { spin_unlock_irqrestore(&port->lock, flags); if (port->ops->drop) port->ops->drop(port); @@ -564,7 +564,7 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty, { spin_lock_irq(&port->lock); if (!tty_hung_up_p(filp)) - ++port->count; + atomic_inc(&port->count); spin_unlock_irq(&port->lock); tty_port_tty_set(port, tty); diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index a9af1b9a..1e08e7f 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -647,6 +647,16 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) kbd->kbdmode == VC_OFF) && value != KVAL(K_SAK)) return; /* SAK is allowed even in raw mode */ + +#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP) + { + void *func = fn_handler[value]; + if (func == fn_show_state || func == fn_show_ptregs || + func == fn_show_mem) + return; + } +#endif + fn_handler[value](vc); } @@ -1795,9 +1805,6 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) return -EFAULT; - if (!capable(CAP_SYS_TTY_CONFIG)) - perm = 0; - switch (cmd) { case KDGKBENT: /* Ensure another thread doesn't free it under us */ @@ -1812,6 +1819,9 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, spin_unlock_irqrestore(&kbd_event_lock, flags); return put_user(val, &user_kbe->kb_value); case KDSKBENT: + if (!capable(CAP_SYS_TTY_CONFIG)) + perm = 0; + if (!perm) return -EPERM; if (!i && v == K_NOSUCHMAP) { @@ -1902,9 +1912,6 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) int i, j, k; int ret; - if (!capable(CAP_SYS_TTY_CONFIG)) - perm = 0; - kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); if (!kbs) { ret = -ENOMEM; @@ -1938,6 +1945,9 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) kfree(kbs); return ((p && *p) ? -EOVERFLOW : 0); case KDSKBSENT: + if (!capable(CAP_SYS_TTY_CONFIG)) + perm = 0; + if (!perm) { ret = -EPERM; goto reterr; diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index b645c47..a55c182 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -25,6 +25,7 @@ #include #include #include +#include #define UIO_MAX_DEVICES (1U << MINORBITS) @@ -32,10 +33,10 @@ struct uio_device { struct module *owner; struct device *dev; int minor; - atomic_t event; + atomic_unchecked_t event; struct fasync_struct *async_queue; wait_queue_head_t wait; - int vma_count; + local_t vma_count; struct uio_info *info; struct kobject *map_dir; struct kobject *portio_dir; @@ -242,7 +243,7 @@ static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf) { struct uio_device *idev = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event)); + return sprintf(buf, "%u\n", (unsigned int)atomic_read_unchecked(&idev->event)); } static struct device_attribute uio_class_attributes[] = { @@ -398,7 +399,7 @@ void uio_event_notify(struct uio_info *info) { struct uio_device *idev = info->uio_dev; - atomic_inc(&idev->event); + atomic_inc_unchecked(&idev->event); wake_up_interruptible(&idev->wait); kill_fasync(&idev->async_queue, SIGIO, POLL_IN); } @@ -451,7 +452,7 @@ static int uio_open(struct inode *inode, struct file *filep) } listener->dev = idev; - listener->event_count = atomic_read(&idev->event); + listener->event_count = atomic_read_unchecked(&idev->event); filep->private_data = listener; if (idev->info->open) { @@ -502,7 +503,7 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait) return -EIO; poll_wait(filep, &idev->wait, wait); - if (listener->event_count != atomic_read(&idev->event)) + if (listener->event_count != atomic_read_unchecked(&idev->event)) return POLLIN | POLLRDNORM; return 0; } @@ -527,7 +528,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf, do { set_current_state(TASK_INTERRUPTIBLE); - event_count = atomic_read(&idev->event); + event_count = atomic_read_unchecked(&idev->event); if (event_count != listener->event_count) { if (copy_to_user(buf, &event_count, count)) retval = -EFAULT; @@ -596,13 +597,13 @@ static int uio_find_mem_index(struct vm_area_struct *vma) static void uio_vma_open(struct vm_area_struct *vma) { struct uio_device *idev = vma->vm_private_data; - idev->vma_count++; + local_inc(&idev->vma_count); } static void uio_vma_close(struct vm_area_struct *vma) { struct uio_device *idev = vma->vm_private_data; - idev->vma_count--; + local_dec(&idev->vma_count); } static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -809,7 +810,7 @@ int __uio_register_device(struct module *owner, idev->owner = owner; idev->info = info; init_waitqueue_head(&idev->wait); - atomic_set(&idev->event, 0); + atomic_set_unchecked(&idev->event, 0); ret = uio_get_minor(idev); if (ret) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 8a7eb77..c00402f 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -473,7 +473,7 @@ static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev, ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp); if (ret < 2) return -EINVAL; - if (index < 0 || index > 0x7f) + if (index > 0x7f) return -EINVAL; pos += tmp; diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index d3527dd..26effa2 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -333,7 +333,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char if (printk_ratelimit()) atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); return; } @@ -361,7 +361,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char if (length > ATM_MAX_AAL5_PDU) { atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n", __func__, length, vcc); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); goto out; } @@ -370,14 +370,14 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char if (sarb->len < pdu_length) { atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n", __func__, pdu_length, sarb->len, vcc); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); goto out; } if (crc32_be(~0, skb_tail_pointer(sarb) - pdu_length, pdu_length) != 0xc704dd7b) { atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n", __func__, vcc); - atomic_inc(&vcc->stats->rx_err); + atomic_inc_unchecked(&vcc->stats->rx_err); goto out; } @@ -389,7 +389,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char if (printk_ratelimit()) atm_err(instance, "%s: no memory for skb (length: %u)!\n", __func__, length); - atomic_inc(&vcc->stats->rx_drop); + atomic_inc_unchecked(&vcc->stats->rx_drop); goto out; } @@ -417,7 +417,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char vcc->push(vcc, skb); - atomic_inc(&vcc->stats->rx); + atomic_inc_unchecked(&vcc->stats->rx); out: skb_trim(sarb, 0); } @@ -623,7 +623,7 @@ static void usbatm_tx_process(unsigned long data) struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; usbatm_pop(vcc, skb); - atomic_inc(&vcc->stats->tx); + atomic_inc_unchecked(&vcc->stats->tx); skb = skb_dequeue(&instance->sndqueue); } @@ -779,11 +779,11 @@ static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *pag if (!left--) return sprintf(page, "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", - atomic_read(&atm_dev->stats.aal5.tx), - atomic_read(&atm_dev->stats.aal5.tx_err), - atomic_read(&atm_dev->stats.aal5.rx), - atomic_read(&atm_dev->stats.aal5.rx_err), - atomic_read(&atm_dev->stats.aal5.rx_drop)); + atomic_read_unchecked(&atm_dev->stats.aal5.tx), + atomic_read_unchecked(&atm_dev->stats.aal5.tx_err), + atomic_read_unchecked(&atm_dev->stats.aal5.rx), + atomic_read_unchecked(&atm_dev->stats.aal5.rx_err), + atomic_read_unchecked(&atm_dev->stats.aal5.rx_drop)); if (!left--) { if (instance->disconnected) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 2a3bbdf..91d72cf 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -126,7 +126,7 @@ static const char format_endpt[] = * time it gets called. */ static struct device_connect_event { - atomic_t count; + atomic_unchecked_t count; wait_queue_head_t wait; } device_event = { .count = ATOMIC_INIT(1), @@ -164,7 +164,7 @@ static const struct class_info clas_info[] = { void usbfs_conn_disc_event(void) { - atomic_add(2, &device_event.count); + atomic_add_unchecked(2, &device_event.count); wake_up(&device_event.wait); } @@ -652,7 +652,7 @@ static unsigned int usb_device_poll(struct file *file, poll_wait(file, &device_event.wait, wait); - event_count = atomic_read(&device_event.count); + event_count = atomic_read_unchecked(&device_event.count); if (file->f_version != event_count) { file->f_version = event_count; return POLLIN | POLLRDNORM; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d53547d..6a22d02 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1526,7 +1526,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) */ usb_get_urb(urb); atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); + atomic_inc_unchecked(&urb->dev->urbnum); usbmon_urb_submit(&hcd->self, urb); /* NOTE requirements on root-hub callers (usbfs and the hub @@ -1553,7 +1553,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) urb->hcpriv = NULL; INIT_LIST_HEAD(&urb->urb_list); atomic_dec(&urb->use_count); - atomic_dec(&urb->dev->urbnum); + atomic_dec_unchecked(&urb->dev->urbnum); if (atomic_read(&urb->reject)) wake_up(&usb_kill_urb_queue); usb_put_urb(urb); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6cf2ae0..f701610 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -4419,6 +4420,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, goto done; return; } + + if (gr_handle_new_usb()) + goto done; + if (hub_is_superspeed(hub->hdev)) unit_load = 150; else diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 444d30e..f15c850 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -129,7 +129,7 @@ static int usb_internal_control_msg(struct usb_device *usb_dev, * method can wait for it to complete. Since you don't have a handle on the * URB used, you can't cancel the request. */ -int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, +int __intentional_overflow(-1) usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index aa38db4..0a08682 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -239,7 +239,7 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) struct usb_device *udev; udev = to_usb_device(dev); - return sprintf(buf, "%d\n", atomic_read(&udev->urbnum)); + return sprintf(buf, "%d\n", atomic_read_unchecked(&udev->urbnum)); } static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b10da72..43aa0b2 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -389,7 +389,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, set_dev_node(&dev->dev, dev_to_node(bus->controller)); dev->state = USB_STATE_ATTACHED; dev->lpm_disable_count = 1; - atomic_set(&dev->urbnum, 0); + atomic_set_unchecked(&dev->urbnum, 0); INIT_LIST_HEAD(&dev->ep0.urb_list); dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 14d28d6..5f511ac 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -550,8 +550,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, if (!usb_endpoint_xfer_isoc(desc)) return 0; - memset(&trb_link, 0, sizeof(trb_link)); - /* Link TRB for ISOC. The HWO bit is never reset */ trb_st_hw = &dep->trb_pool[0]; diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 5e29dde..eca992f 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -98,7 +98,8 @@ static inline u32 dbgp_len_update(u32 x, u32 len) #ifdef CONFIG_KGDB static struct kgdb_io kgdbdbgp_io_ops; -#define dbgp_kgdb_mode (dbg_io_ops == &kgdbdbgp_io_ops) +static struct kgdb_io kgdbdbgp_io_ops_console; +#define dbgp_kgdb_mode (dbg_io_ops == &kgdbdbgp_io_ops || dbg_io_ops == &kgdbdbgp_io_ops_console) #else #define dbgp_kgdb_mode (0) #endif @@ -1047,6 +1048,13 @@ static struct kgdb_io kgdbdbgp_io_ops = { .write_char = kgdbdbgp_write_char, }; +static struct kgdb_io kgdbdbgp_io_ops_console = { + .name = "kgdbdbgp", + .read_char = kgdbdbgp_read_char, + .write_char = kgdbdbgp_write_char, + .is_console = 1 +}; + static int kgdbdbgp_wait_time; static int __init kgdbdbgp_parse_config(char *str) @@ -1062,8 +1070,10 @@ static int __init kgdbdbgp_parse_config(char *str) ptr++; kgdbdbgp_wait_time = simple_strtoul(ptr, &ptr, 10); } - kgdb_register_io_module(&kgdbdbgp_io_ops); - kgdbdbgp_io_ops.is_console = early_dbgp_console.index != -1; + if (early_dbgp_console.index != -1) + kgdb_register_io_module(&kgdbdbgp_io_ops_console); + else + kgdb_register_io_module(&kgdbdbgp_io_ops); return 0; } diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index b369292..9f3ba40 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -733,9 +733,9 @@ static int gs_open(struct tty_struct *tty, struct file *file) spin_lock_irq(&port->port_lock); /* already open? Great. */ - if (port->port.count) { + if (atomic_read(&port->port.count)) { status = 0; - port->port.count++; + atomic_inc(&port->port.count); /* currently opening/closing? wait ... */ } else if (port->openclose) { @@ -794,7 +794,7 @@ static int gs_open(struct tty_struct *tty, struct file *file) tty->driver_data = port; port->port.tty = tty; - port->port.count = 1; + atomic_set(&port->port.count, 1); port->openclose = false; /* if connected, start the I/O stream */ @@ -836,11 +836,11 @@ static void gs_close(struct tty_struct *tty, struct file *file) spin_lock_irq(&port->port_lock); - if (port->port.count != 1) { - if (port->port.count == 0) + if (atomic_read(&port->port.count) != 1) { + if (atomic_read(&port->port.count) == 0) WARN_ON(1); else - --port->port.count; + atomic_dec(&port->port.count); goto exit; } @@ -850,7 +850,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) * and sleep if necessary */ port->openclose = true; - port->port.count = 0; + atomic_set(&port->port.count, 0); gser = port->port_usb; if (gser && gser->disconnect) @@ -1066,7 +1066,7 @@ static int gs_closed(struct gs_port *port) int cond; spin_lock_irq(&port->port_lock); - cond = (port->port.count == 0) && !port->openclose; + cond = (atomic_read(&port->port.count) == 0) && !port->openclose; spin_unlock_irq(&port->port_lock); return cond; } @@ -1209,7 +1209,7 @@ int gserial_connect(struct gserial *gser, u8 port_num) /* if it's already open, start I/O ... and notify the serial * protocol about open/close status (connect/disconnect). */ - if (port->port.count) { + if (atomic_read(&port->port.count)) { pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); gs_start_io(port); if (gser->connect) @@ -1256,7 +1256,7 @@ void gserial_disconnect(struct gserial *gser) port->port_usb = NULL; gser->ioport = NULL; - if (port->port.count > 0 || port->openclose) { + if (atomic_read(&port->port.count) > 0 || port->openclose) { wake_up_interruptible(&port->drain_wait); if (port->port.tty) tty_hangup(port->port.tty); @@ -1272,7 +1272,7 @@ void gserial_disconnect(struct gserial *gser) /* finally, free any unused/unusable I/O buffers */ spin_lock_irqsave(&port->port_lock, flags); - if (port->port.count == 0 && !port->openclose) + if (atomic_read(&port->port.count) == 0 && !port->openclose) gs_buf_free(&port->port_write_buf); gs_free_requests(gser->out, &port->read_pool, NULL); gs_free_requests(gser->out, &port->read_queue, NULL); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index ba6a5d6..f88f7f3 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -83,7 +83,7 @@ struct appledisplay { spinlock_t lock; }; -static atomic_t count_displays = ATOMIC_INIT(0); +static atomic_unchecked_t count_displays = ATOMIC_INIT(0); static struct workqueue_struct *wq; static void appledisplay_complete(struct urb *urb) @@ -281,7 +281,7 @@ static int appledisplay_probe(struct usb_interface *iface, /* Register backlight device */ snprintf(bl_name, sizeof(bl_name), "appledisplay%d", - atomic_inc_return(&count_displays) - 1); + atomic_inc_return_unchecked(&count_displays) - 1); memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 5f3bcd3..bfca43f 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -124,7 +124,7 @@ static int usb_console_setup(struct console *co, char *options) info->port = port; - ++port->port.count; + atomic_inc(&port->port.count); if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { if (serial->type->set_termios) { /* @@ -174,7 +174,7 @@ static int usb_console_setup(struct console *co, char *options) } /* Now that any required fake tty operations are completed restore * the tty port count */ - --port->port.count; + atomic_dec(&port->port.count); /* The console is special in terms of closing the device so * indicate this port is now acting as a system console. */ port->port.console = 1; @@ -187,7 +187,7 @@ static int usb_console_setup(struct console *co, char *options) free_tty: kfree(tty); reset_open_count: - port->port.count = 0; + atomic_set(&port->port.count, 0); usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 75f70f0..d467e1a 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -63,7 +63,7 @@ struct us_unusual_dev { __u8 useProtocol; __u8 useTransport; int (*initFunction)(struct us_data *); -}; +} __do_const; /* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */ diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h index d6bea3e..60b250e 100644 --- a/drivers/usb/wusbcore/wa-hc.h +++ b/drivers/usb/wusbcore/wa-hc.h @@ -192,7 +192,7 @@ struct wahc { struct list_head xfer_delayed_list; spinlock_t xfer_list_lock; struct work_struct xfer_work; - atomic_t xfer_id_count; + atomic_unchecked_t xfer_id_count; }; @@ -246,7 +246,7 @@ static inline void wa_init(struct wahc *wa) INIT_LIST_HEAD(&wa->xfer_delayed_list); spin_lock_init(&wa->xfer_list_lock); INIT_WORK(&wa->xfer_work, wa_urb_enqueue_run); - atomic_set(&wa->xfer_id_count, 1); + atomic_set_unchecked(&wa->xfer_id_count, 1); } /** diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 028fc83..65bb105 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -296,7 +296,7 @@ out: */ static void wa_xfer_id_init(struct wa_xfer *xfer) { - xfer->id = atomic_add_return(1, &xfer->wa->xfer_id_count); + xfer->id = atomic_add_return_unchecked(1, &xfer->wa->xfer_id_count); } /* diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 6d78736..65be90e 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -486,7 +486,7 @@ static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev) return 0; /* TODO Prevent device auto probing */ - WARN("Device %s added to live group %d!\n", dev_name(dev), + WARN(1, "Device %s added to live group %d!\n", dev_name(dev), iommu_group_id(group->iommu_group)); return 0; @@ -506,7 +506,7 @@ static int vfio_group_nb_del_dev(struct vfio_group *group, struct device *dev) if (likely(!device)) return 0; - WARN("Device %s removed from live group %d!\n", dev_name(dev), + WARN(1, "Device %s removed from live group %d!\n", dev_name(dev), iommu_group_id(group->iommu_group)); vfio_device_put(device); diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 5174eba..86e764a 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -800,7 +800,7 @@ static inline int getu16_kern(u16 *val, const u16 *p) static inline int putu16_kern(u16 *p, u16 val) { - ACCESS_ONCE(*p) = val; + ACCESS_ONCE_RW(*p) = val; return 0; } diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 8c55011..eed4ae1a 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -149,7 +149,7 @@ enum { }; /* Must match above enum */ -static char * const r128_family[] = { +static const char * const r128_family[] = { "AGP", "PCI", "PRO AGP", diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 4f27fdc..d3537e6 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -1325,10 +1325,14 @@ static int atyfb_set_par(struct fb_info *info) par->accel_flags = var->accel_flags; /* hack */ if (var->accel_flags) { - info->fbops->fb_sync = atyfb_sync; + pax_open_kernel(); + *(void **)&info->fbops->fb_sync = atyfb_sync; + pax_close_kernel(); info->flags &= ~FBINFO_HWACCEL_DISABLED; } else { - info->fbops->fb_sync = NULL; + pax_open_kernel(); + *(void **)&info->fbops->fb_sync = NULL; + pax_close_kernel(); info->flags |= FBINFO_HWACCEL_DISABLED; } diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index 95ec042..e6affdd 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c @@ -7,6 +7,7 @@ #include #include +#include #ifdef __sparc__ #include @@ -208,7 +209,9 @@ int aty_init_cursor(struct fb_info *info) info->sprite.buf_align = 16; /* and 64 lines tall. */ info->sprite.flags = FB_PIXMAP_IO; - info->fbops->fb_cursor = atyfb_cursor; + pax_open_kernel(); + *(void **)&info->fbops->fb_cursor = atyfb_cursor; + pax_close_kernel(); return 0; } diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index c74e7aa..e3c2790 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -304,7 +304,7 @@ struct backlight_device *backlight_device_register(const char *name, new_bd->dev.class = backlight_class; new_bd->dev.parent = parent; new_bd->dev.release = bl_device_release; - dev_set_name(&new_bd->dev, name); + dev_set_name(&new_bd->dev, "%s", name); dev_set_drvdata(&new_bd->dev, devdata); /* Set default properties */ diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index bca6ccc..252107e 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c @@ -78,7 +78,7 @@ static struct kb3886bl_machinfo *bl_machinfo; static unsigned long kb3886bl_flags; #define KB3886BL_SUSPENDED 0x01 -static struct dmi_system_id __initdata kb3886bl_device_table[] = { +static const struct dmi_system_id __initconst kb3886bl_device_table[] = { { .ident = "Sahara Touch-iT", .matches = { diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 34fb6bd..3649fd9 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -219,7 +219,7 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, new_ld->dev.class = lcd_class; new_ld->dev.parent = parent; new_ld->dev.release = lcd_device_release; - dev_set_name(&new_ld->dev, name); + dev_set_name(&new_ld->dev, "%s", name); dev_set_drvdata(&new_ld->dev, devdata); rc = device_register(&new_ld->dev); diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 900aa4e..6d49418 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -206,7 +206,9 @@ void fb_deferred_io_init(struct fb_info *info) BUG_ON(!fbdefio); mutex_init(&fbdefio->lock); - info->fbops->fb_mmap = fb_deferred_io_mmap; + pax_open_kernel(); + *(void **)&info->fbops->fb_mmap = fb_deferred_io_mmap; + pax_close_kernel(); INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work); INIT_LIST_HEAD(&fbdefio->pagelist); if (fbdefio->delay == 0) /* set a default of 1 s */ @@ -237,7 +239,7 @@ void fb_deferred_io_cleanup(struct fb_info *info) page->mapping = NULL; } - info->fbops->fb_mmap = NULL; + *(void **)&info->fbops->fb_mmap = NULL; mutex_destroy(&fbdefio->lock); } EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup); diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index 5c3960d..15cf8fc 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -285,8 +285,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) rc = -ENODEV; goto out; } - if (cmap->start < 0 || (!info->fbops->fb_setcolreg && - !info->fbops->fb_setcmap)) { + if (!info->fbops->fb_setcolreg && !info->fbops->fb_setcmap) { rc = -EINVAL; goto out1; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 098bfc6..796841d 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -428,7 +428,7 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, image->dx += image->width + 8; } } else if (rotate == FB_ROTATE_UD) { - for (x = 0; x < num && image->dx >= 0; x++) { + for (x = 0; x < num && (__s32)image->dx >= 0; x++) { info->fbops->fb_imageblit(info, image); image->dx -= image->width + 8; } @@ -440,7 +440,7 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, image->dy += image->height + 8; } } else if (rotate == FB_ROTATE_CCW) { - for (x = 0; x < num && image->dy >= 0; x++) { + for (x = 0; x < num && (__s32)image->dy >= 0; x++) { info->fbops->fb_imageblit(info, image); image->dy -= image->height + 8; } @@ -1166,7 +1166,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, return -EFAULT; if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) return -EINVAL; - if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) + if (con2fb.framebuffer >= FB_MAX) return -EINVAL; if (!registered_fb[con2fb.framebuffer]) request_module("fb%d", con2fb.framebuffer); diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c index d4d2c5f..ebbd113 100644 --- a/drivers/video/hyperv_fb.c +++ b/drivers/video/hyperv_fb.c @@ -233,7 +233,7 @@ static uint screen_fb_size; static inline int synthvid_send(struct hv_device *hdev, struct synthvid_msg *msg) { - static atomic64_t request_id = ATOMIC64_INIT(0); + static atomic64_unchecked_t request_id = ATOMIC64_INIT(0); int ret; msg->pipe_hdr.type = PIPE_MSG_DATA; @@ -241,7 +241,7 @@ static inline int synthvid_send(struct hv_device *hdev, ret = vmbus_sendpacket(hdev->channel, msg, msg->vid_hdr.size + sizeof(struct pipe_msg_hdr), - atomic64_inc_return(&request_id), + atomic64_inc_return_unchecked(&request_id), VM_PKT_DATA_INBAND, 0); if (ret) diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c index 7672d2e..b56437f 100644 --- a/drivers/video/i810/i810_accel.c +++ b/drivers/video/i810/i810_accel.c @@ -73,6 +73,7 @@ static inline int wait_for_space(struct fb_info *info, u32 space) } } printk("ringbuffer lockup!!!\n"); + printk("head:%u tail:%u iring.size:%u space:%u\n", head, tail, par->iring.size, space); i810_report_error(mmio); par->dev_flags |= LOCKUP; info->pixmap.scan_align = 1; diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm index 3c14e43..eafa544 100644 --- a/drivers/video/logo/logo_linux_clut224.ppm +++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,1123 @@ P3 -# Standard 224-color Linux logo 80 80 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 10 10 10 10 10 10 - 10 10 10 6 6 6 6 6 6 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 22 22 22 26 26 26 30 30 30 34 34 34 - 30 30 30 30 30 30 26 26 26 18 18 18 - 14 14 14 10 10 10 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 26 26 26 42 42 42 - 54 54 54 66 66 66 78 78 78 78 78 78 - 78 78 78 74 74 74 66 66 66 54 54 54 - 42 42 42 26 26 26 18 18 18 10 10 10 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 22 22 22 42 42 42 66 66 66 86 86 86 - 66 66 66 38 38 38 38 38 38 22 22 22 - 26 26 26 34 34 34 54 54 54 66 66 66 - 86 86 86 70 70 70 46 46 46 26 26 26 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 50 50 50 82 82 82 58 58 58 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 54 54 54 86 86 86 66 66 66 - 38 38 38 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 78 78 78 34 34 34 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 70 70 70 - 78 78 78 46 46 46 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 42 42 42 82 82 82 - 26 26 26 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 46 46 46 34 34 34 6 6 6 2 2 6 - 42 42 42 78 78 78 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 30 30 30 66 66 66 58 58 58 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 86 86 86 101 101 101 46 46 46 10 10 10 - 2 2 6 58 58 58 70 70 70 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 86 86 86 10 10 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 30 30 30 - 94 94 94 94 94 94 58 58 58 26 26 26 - 2 2 6 6 6 6 78 78 78 54 54 54 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 62 62 62 62 62 62 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 54 54 54 38 38 38 18 18 18 10 10 10 - 2 2 6 2 2 6 34 34 34 82 82 82 - 38 38 38 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 10 10 10 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 54 54 54 - 66 66 66 26 26 26 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 82 82 82 2 2 6 2 2 6 - 2 2 6 6 6 6 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 6 6 6 - 14 14 14 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 18 18 18 - 82 82 82 34 34 34 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 6 6 6 6 6 6 22 22 22 34 34 34 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 34 34 34 - 10 10 10 50 50 50 22 22 22 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 86 86 86 42 42 42 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 38 38 38 116 116 116 94 94 94 22 22 22 - 22 22 22 2 2 6 2 2 6 2 2 6 - 14 14 14 86 86 86 138 138 138 162 162 162 -154 154 154 38 38 38 26 26 26 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 14 14 14 -134 134 134 198 198 198 195 195 195 116 116 116 - 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 -214 214 214 134 134 134 14 14 14 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 50 50 50 18 18 18 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 - 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 174 174 174 123 123 123 -221 221 221 234 234 234 74 74 74 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 -123 123 123 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 - 90 90 90 238 238 238 158 158 158 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 149 149 149 -128 128 128 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 - 46 46 46 190 190 190 198 198 198 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 94 94 94 14 14 14 101 101 101 -128 128 128 2 2 6 18 18 18 116 116 116 -118 98 46 121 92 8 121 92 8 98 78 10 -162 162 162 106 106 106 2 2 6 2 2 6 - 2 2 6 195 195 195 195 195 195 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 1 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 54 38 6 154 114 10 -226 170 11 236 186 11 225 175 15 184 144 12 -215 174 15 175 146 61 37 26 9 2 2 6 - 70 70 70 246 246 246 138 138 138 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 66 66 66 26 26 26 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 188 164 115 192 133 9 225 175 15 -239 182 13 234 190 10 232 195 16 232 200 30 -245 207 45 241 208 19 232 195 16 184 144 12 -218 194 134 211 206 186 42 42 42 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 74 74 74 30 30 30 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 86 86 86 14 14 14 2 2 6 -121 87 25 192 133 9 219 162 10 239 182 13 -236 186 11 232 195 16 241 208 19 244 214 54 -246 218 60 246 218 38 246 215 20 241 208 19 -241 208 19 226 184 13 121 87 25 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 82 82 82 34 34 34 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 82 82 82 30 30 30 61 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 -234 190 10 238 202 15 241 208 19 246 218 74 -246 218 38 246 215 20 246 215 20 246 215 20 -226 184 13 215 174 15 184 144 12 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 26 26 26 94 94 94 42 42 42 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 236 186 11 -232 195 16 241 208 19 244 214 54 245 215 43 -246 215 20 246 215 20 241 208 19 198 155 10 -200 144 11 216 158 10 156 118 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 90 90 90 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 210 162 10 239 182 13 238 190 10 -238 202 15 241 208 19 246 215 20 246 215 20 -241 208 19 203 166 17 185 133 11 210 150 10 -216 158 10 210 150 10 102 78 10 2 2 6 - 6 6 6 54 54 54 14 14 14 2 2 6 - 2 2 6 62 62 62 74 74 74 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 78 78 78 50 50 50 6 6 6 - 94 70 30 139 102 15 190 146 13 226 184 13 -232 200 30 232 195 16 215 174 15 190 146 13 -168 122 10 192 133 9 210 150 10 213 154 11 -202 150 34 182 157 106 101 98 89 2 2 6 - 2 2 6 78 78 78 116 116 116 58 58 58 - 2 2 6 22 22 22 90 90 90 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 50 50 50 6 6 6 -128 128 128 174 154 114 156 107 11 168 122 10 -198 155 10 184 144 12 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 188 164 115 -195 195 195 198 198 198 174 174 174 14 14 14 - 2 2 6 22 22 22 116 116 116 116 116 116 - 22 22 22 2 2 6 74 74 74 70 70 70 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 101 101 101 26 26 26 10 10 10 -138 138 138 190 190 190 174 154 114 156 107 11 -197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 190 142 34 190 178 144 187 187 187 -202 202 202 221 221 221 214 214 214 66 66 66 - 2 2 6 2 2 6 50 50 50 62 62 62 - 6 6 6 2 2 6 10 10 10 90 90 90 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 34 34 34 - 74 74 74 74 74 74 2 2 6 6 6 6 -144 144 144 198 198 198 190 190 190 178 166 146 -154 121 60 156 107 11 156 107 11 168 124 44 -174 154 114 187 187 187 190 190 190 210 210 210 -246 246 246 253 253 253 253 253 253 182 182 182 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 62 62 62 - 74 74 74 34 34 34 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 22 22 22 54 54 54 - 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 -190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 - 82 82 82 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 86 86 86 54 54 54 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 46 46 46 90 90 90 - 46 46 46 18 18 18 6 6 6 182 182 182 -253 253 253 246 246 246 206 206 206 190 190 190 -190 190 190 190 190 190 190 190 190 190 190 190 -206 206 206 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 86 86 86 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 38 38 38 74 74 74 66 66 66 - 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 -190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 78 78 78 70 70 70 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 66 66 66 78 78 78 6 6 6 - 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 178 178 178 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 18 18 18 90 90 90 62 62 62 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 58 58 58 90 90 90 18 18 18 2 2 6 - 2 2 6 110 110 110 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 94 94 94 - 54 54 54 26 26 26 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 90 90 90 26 26 26 2 2 6 2 2 6 - 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 86 86 86 50 50 50 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 38 38 38 82 82 82 - 34 34 34 2 2 6 2 2 6 2 2 6 - 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 38 38 38 82 82 82 42 42 42 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 62 62 62 66 66 66 - 2 2 6 2 2 6 2 2 6 6 6 6 - 70 70 70 170 170 170 206 206 206 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 -226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 -214 214 214 206 206 206 202 202 202 202 202 202 -198 198 198 202 202 202 182 182 182 18 18 18 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 62 62 62 66 66 66 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 82 82 82 18 18 18 - 2 2 6 2 2 6 2 2 6 10 10 10 - 94 94 94 182 182 182 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 -234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 158 158 158 - 6 6 6 14 14 14 50 50 50 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 86 86 86 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 70 70 70 2 2 6 - 2 2 6 10 10 10 2 2 6 22 22 22 -166 166 166 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 206 206 206 198 198 198 226 226 226 - 94 94 94 2 2 6 6 6 6 38 38 38 - 30 30 30 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 62 62 62 66 66 66 - 26 26 26 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 50 50 50 2 2 6 - 26 26 26 26 26 26 2 2 6 106 106 106 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 -210 210 210 14 14 14 2 2 6 2 2 6 - 30 30 30 22 22 22 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 86 86 86 - 42 42 42 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 90 90 90 22 22 22 2 2 6 - 42 42 42 2 2 6 18 18 18 218 218 218 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 -218 218 218 101 101 101 2 2 6 14 14 14 - 18 18 18 38 38 38 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 58 58 58 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 82 82 82 2 2 6 26 26 26 - 22 22 22 2 2 6 123 123 123 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -238 238 238 198 198 198 6 6 6 38 38 38 - 58 58 58 26 26 26 38 38 38 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 78 78 78 30 30 30 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 30 30 30 - 74 74 74 58 58 58 2 2 6 42 42 42 - 2 2 6 22 22 22 231 231 231 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 46 46 46 38 38 38 - 42 42 42 14 14 14 38 38 38 14 14 14 - 2 2 6 2 2 6 2 2 6 6 6 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 42 42 42 - 90 90 90 18 18 18 18 18 18 26 26 26 - 2 2 6 116 116 116 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 94 94 94 6 6 6 - 2 2 6 2 2 6 10 10 10 34 34 34 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 26 26 26 66 66 66 - 82 82 82 2 2 6 38 38 38 6 6 6 - 14 14 14 210 210 210 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 144 144 144 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 74 74 74 30 30 30 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 42 42 42 90 90 90 - 26 26 26 6 6 6 42 42 42 2 2 6 - 74 74 74 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 182 182 182 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 10 10 10 86 86 86 38 38 38 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 66 66 66 82 82 82 - 2 2 6 22 22 22 18 18 18 2 2 6 -149 149 149 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 86 86 86 46 46 46 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 46 46 46 86 86 86 18 18 18 - 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 221 221 221 6 6 6 - 2 2 6 2 2 6 6 6 6 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 26 26 26 66 66 66 62 62 62 2 2 6 - 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 6 6 6 - 2 2 6 2 2 6 10 10 10 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 78 78 78 6 6 6 2 2 6 - 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 10 10 10 - 2 2 6 2 2 6 22 22 22 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 74 74 74 2 2 6 2 2 6 - 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 14 14 14 - 2 2 6 2 2 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 62 62 62 2 2 6 2 2 6 - 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 226 226 226 10 10 10 - 2 2 6 6 6 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 62 62 62 2 2 6 2 2 6 - 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 22 22 22 34 34 34 18 14 6 22 22 22 - 26 26 26 18 18 18 6 6 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 26 26 26 - 62 62 62 106 106 106 74 54 14 185 133 11 -210 162 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 158 158 158 18 18 18 - 14 14 14 2 2 6 2 2 6 2 2 6 - 6 6 6 18 18 18 66 66 66 38 38 38 - 6 6 6 94 94 94 50 50 50 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 10 10 10 10 10 10 18 18 18 38 38 38 - 78 78 78 142 134 106 216 158 10 242 186 14 -246 190 14 246 190 14 156 118 10 10 10 10 - 90 90 90 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 -238 204 91 238 204 91 181 142 44 37 26 9 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 38 38 38 46 46 46 - 26 26 26 106 106 106 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 22 22 22 - 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 190 142 34 226 170 11 242 186 14 -246 190 14 246 190 14 246 190 14 154 114 10 - 6 6 6 74 74 74 226 226 226 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 228 184 62 -241 196 14 241 208 19 232 195 16 38 30 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 30 30 30 26 26 26 -203 166 17 154 142 90 66 66 66 26 26 26 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 38 38 38 58 58 58 - 78 78 78 86 86 86 101 101 101 123 123 123 -175 146 61 210 150 10 234 174 13 246 186 14 -246 190 14 246 190 14 246 190 14 238 190 10 -102 78 10 2 2 6 46 46 46 198 198 198 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 224 178 62 -242 186 14 241 196 14 210 166 10 22 18 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 38 38 38 70 70 70 154 122 46 -190 142 34 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -225 175 15 46 32 6 2 2 6 22 22 22 -158 158 158 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 224 178 62 -239 182 13 236 186 11 213 154 11 46 32 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 225 175 15 -238 190 10 236 186 11 112 100 78 42 42 42 - 14 14 14 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 154 122 46 213 154 11 -226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 144 12 10 10 10 2 2 6 - 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 214 170 54 -236 178 12 236 178 12 210 150 10 137 92 6 - 18 14 6 2 2 6 2 2 6 2 2 6 - 6 6 6 70 47 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 70 70 70 180 133 36 226 170 11 -239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 - 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 206 206 206 198 198 198 214 166 58 -230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 116 81 8 102 78 10 116 81 8 -167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 162 146 94 78 78 78 - 34 34 34 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 190 142 34 226 170 11 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 203 166 17 22 18 6 - 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 206 206 206 198 198 198 202 162 69 -226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 -210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 225 175 15 124 112 88 - 62 62 62 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 174 135 50 224 166 10 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 - 2 2 6 2 2 6 2 2 6 2 2 6 - 78 78 78 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 190 150 46 -219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 -226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 206 162 42 -101 101 101 58 58 58 30 30 30 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 174 135 50 216 158 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 226 184 13 - 61 42 6 2 2 6 2 2 6 2 2 6 - 22 22 22 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 180 133 36 -216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 -206 162 42 106 106 106 66 66 66 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 213 154 11 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 -190 146 13 18 14 6 2 2 6 2 2 6 - 46 46 46 246 246 246 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 -216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 225 175 15 142 122 72 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 210 150 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 18 14 6 163 110 8 -216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 163 133 67 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 163 133 67 210 150 10 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 215 174 15 190 178 144 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 218 218 218 - 58 58 58 2 2 6 22 18 6 167 114 7 -216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 186 14 242 186 14 190 150 46 - 54 54 54 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 38 38 38 86 86 86 180 133 36 213 154 11 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 170 170 170 26 26 26 - 2 2 6 2 2 6 37 26 9 163 110 8 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 224 166 10 142 122 72 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 109 106 95 192 133 9 224 166 10 -242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 226 184 13 210 162 10 142 110 46 -226 226 226 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -198 198 198 66 66 66 2 2 6 2 2 6 - 2 2 6 2 2 6 50 34 6 156 107 11 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 -234 174 13 213 154 11 154 122 46 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 154 121 60 206 145 10 234 174 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 210 162 10 163 110 8 - 61 42 6 138 138 138 218 218 218 250 250 250 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 144 144 144 66 66 66 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 163 110 8 -216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 -190 142 34 124 112 88 70 70 70 38 38 38 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 62 62 62 168 124 44 206 145 10 224 166 10 -236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 236 178 12 216 158 10 175 118 6 - 80 54 7 2 2 6 6 6 6 30 30 30 - 54 54 54 62 62 62 50 50 50 38 38 38 - 14 14 14 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 167 114 7 -213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 135 50 124 112 88 - 82 82 82 54 54 54 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 158 118 36 192 133 9 200 144 11 -216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 91 60 6 167 114 7 -206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 -239 182 13 230 174 11 224 166 10 213 154 11 -180 133 36 124 112 88 86 86 86 58 58 58 - 38 38 38 22 22 22 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 70 70 70 138 110 50 158 118 36 -167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 -224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 -239 182 13 216 158 10 185 133 11 152 99 6 -104 69 6 18 14 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 152 99 6 -192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 -224 166 10 206 145 10 192 133 9 154 121 60 - 94 94 94 62 62 62 42 42 42 22 22 22 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 34 34 34 58 58 58 78 78 78 -101 98 89 124 112 88 142 110 46 156 107 11 -163 110 8 167 114 7 175 118 6 180 123 7 -185 133 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 -219 162 10 197 138 11 163 110 8 130 83 6 - 91 60 6 10 10 10 2 2 6 2 2 6 - 18 18 18 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 26 26 26 2 2 6 - 2 2 6 6 6 6 70 47 6 137 92 6 -175 118 6 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 -192 133 9 163 110 8 124 112 88 82 82 82 - 50 50 50 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 22 22 22 34 34 34 - 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 122 102 70 130 98 46 121 87 25 -137 92 6 152 99 6 163 110 8 180 123 7 -185 133 11 197 138 11 206 145 10 200 144 11 -180 123 7 156 107 11 130 83 6 104 69 6 - 50 34 6 54 54 54 110 110 110 101 98 89 - 86 86 86 82 82 82 78 78 78 78 78 78 - 78 78 78 78 78 78 78 78 78 78 78 78 - 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 86 66 34 124 80 6 -156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 175 118 6 -139 102 15 109 106 95 70 70 70 42 42 42 - 22 22 22 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 10 10 10 - 14 14 14 22 22 22 30 30 30 38 38 38 - 50 50 50 62 62 62 74 74 74 90 90 90 -101 98 89 112 100 78 121 87 25 124 80 6 -137 92 6 152 99 6 152 99 6 152 99 6 -138 86 6 124 80 6 98 70 6 86 66 30 -101 98 89 82 82 82 58 58 58 46 46 46 - 38 38 38 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 38 38 38 42 42 42 - 54 54 54 82 82 82 94 86 76 91 60 6 -134 86 6 156 107 11 167 114 7 175 118 6 -175 118 6 167 114 7 152 99 6 121 87 25 -101 98 89 62 62 62 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 6 6 6 10 10 10 - 18 18 18 22 22 22 30 30 30 42 42 42 - 50 50 50 66 66 66 86 86 86 101 98 89 -106 86 58 98 70 6 104 69 6 104 69 6 -104 69 6 91 60 6 82 62 34 90 90 90 - 62 62 62 38 38 38 22 22 22 14 14 14 - 10 10 10 10 10 10 10 10 10 10 10 10 - 10 10 10 10 10 10 6 6 6 10 10 10 - 10 10 10 10 10 10 10 10 10 14 14 14 - 22 22 22 42 42 42 70 70 70 89 81 66 - 80 54 7 104 69 6 124 80 6 137 92 6 -134 86 6 116 81 8 100 82 52 86 86 86 - 58 58 58 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 18 18 18 26 26 26 38 38 38 54 54 54 - 70 70 70 86 86 86 94 86 76 89 81 66 - 89 81 66 86 86 86 74 74 74 50 50 50 - 30 30 30 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 34 34 34 58 58 58 - 82 82 82 89 81 66 89 81 66 89 81 66 - 94 86 66 94 86 76 74 74 74 50 50 50 - 26 26 26 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 14 14 14 18 18 18 - 30 30 30 38 38 38 46 46 46 54 54 54 - 50 50 50 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 26 26 26 - 38 38 38 50 50 50 58 58 58 58 58 58 - 54 54 54 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 6 6 6 10 10 10 14 14 14 18 18 18 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 18 18 18 22 22 22 22 22 22 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 3 3 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 0 0 0 +0 0 0 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 2 1 0 2 1 0 3 2 2 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 2 2 2 0 0 0 3 4 3 26 28 28 +37 38 37 37 38 37 14 17 19 2 2 2 0 0 0 2 2 2 +5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 3 3 3 0 0 0 1 1 1 6 6 6 +2 2 2 0 0 0 3 3 3 4 4 4 4 4 4 4 4 4 +4 4 5 3 3 3 1 0 0 0 0 0 1 0 0 0 0 0 +1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +2 2 2 0 0 0 0 0 0 14 17 19 60 74 84 137 136 137 +153 152 153 137 136 137 125 124 125 60 73 81 6 6 6 3 1 0 +0 0 0 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 0 0 0 4 4 4 41 54 63 125 124 125 +60 73 81 6 6 6 4 0 0 3 3 3 4 4 4 4 4 4 +4 4 4 0 0 0 6 9 11 41 54 63 41 65 82 22 30 35 +2 2 2 2 1 0 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 5 5 5 5 5 5 2 2 2 0 0 0 +4 0 0 6 6 6 41 54 63 137 136 137 174 174 174 167 166 167 +165 164 165 165 164 165 163 162 163 163 162 163 125 124 125 41 54 63 +1 1 1 0 0 0 0 0 0 3 3 3 5 5 5 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 +3 3 3 2 0 0 4 0 0 60 73 81 156 155 156 167 166 167 +163 162 163 85 115 134 5 7 8 0 0 0 4 4 4 5 5 5 +0 0 0 2 5 5 55 98 126 90 154 193 90 154 193 72 125 159 +37 51 59 2 0 0 1 1 1 4 5 5 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 4 4 4 1 1 1 0 0 0 3 3 3 +37 38 37 125 124 125 163 162 163 174 174 174 158 157 158 158 157 158 +156 155 156 156 155 156 158 157 158 165 164 165 174 174 174 166 165 166 +125 124 125 16 19 21 1 0 0 0 0 0 0 0 0 4 4 4 +5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 1 1 1 +0 0 0 0 0 0 37 38 37 153 152 153 174 174 174 158 157 158 +174 174 174 163 162 163 37 38 37 4 3 3 4 0 0 1 1 1 +0 0 0 22 40 52 101 161 196 101 161 196 90 154 193 101 161 196 +64 123 161 14 17 19 0 0 0 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 +5 5 5 2 2 2 0 0 0 4 0 0 24 26 27 85 115 134 +156 155 156 174 174 174 167 166 167 156 155 156 154 153 154 157 156 157 +156 155 156 156 155 156 155 154 155 153 152 153 158 157 158 167 166 167 +174 174 174 156 155 156 60 74 84 16 19 21 0 0 0 0 0 0 +1 1 1 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 6 6 6 3 3 3 0 0 0 4 0 0 +13 16 17 60 73 81 137 136 137 165 164 165 156 155 156 153 152 153 +174 174 174 177 184 187 60 73 81 3 1 0 0 0 0 1 1 2 +22 30 35 64 123 161 136 185 209 90 154 193 90 154 193 90 154 193 +90 154 193 21 29 34 0 0 0 3 2 2 4 4 5 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 3 3 3 +0 0 0 0 0 0 10 13 16 60 74 84 157 156 157 174 174 174 +174 174 174 158 157 158 153 152 153 154 153 154 156 155 156 155 154 155 +156 155 156 155 154 155 154 153 154 157 156 157 154 153 154 153 152 153 +163 162 163 174 174 174 177 184 187 137 136 137 60 73 81 13 16 17 +4 0 0 0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 +5 5 5 4 4 4 1 1 1 0 0 0 3 3 3 41 54 63 +131 129 131 174 174 174 174 174 174 174 174 174 167 166 167 174 174 174 +190 197 201 137 136 137 24 26 27 4 0 0 16 21 25 50 82 103 +90 154 193 136 185 209 90 154 193 101 161 196 101 161 196 101 161 196 +31 91 132 3 6 7 0 0 0 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 2 2 2 0 0 0 4 0 0 +4 0 0 43 57 68 137 136 137 177 184 187 174 174 174 163 162 163 +155 154 155 155 154 155 156 155 156 155 154 155 158 157 158 165 164 165 +167 166 167 166 165 166 163 162 163 157 156 157 155 154 155 155 154 155 +153 152 153 156 155 156 167 166 167 174 174 174 174 174 174 131 129 131 +41 54 63 5 5 5 0 0 0 0 0 0 3 3 3 4 4 4 +1 1 1 0 0 0 1 0 0 26 28 28 125 124 125 174 174 174 +177 184 187 174 174 174 174 174 174 156 155 156 131 129 131 137 136 137 +125 124 125 24 26 27 4 0 0 41 65 82 90 154 193 136 185 209 +136 185 209 101 161 196 53 118 160 37 112 160 90 154 193 34 86 122 +7 12 15 0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 3 3 3 0 0 0 0 0 0 5 5 5 37 38 37 +125 124 125 167 166 167 174 174 174 167 166 167 158 157 158 155 154 155 +156 155 156 156 155 156 156 155 156 163 162 163 167 166 167 155 154 155 +137 136 137 153 152 153 156 155 156 165 164 165 163 162 163 156 155 156 +156 155 156 156 155 156 155 154 155 158 157 158 166 165 166 174 174 174 +167 166 167 125 124 125 37 38 37 1 0 0 0 0 0 0 0 0 +0 0 0 24 26 27 60 74 84 158 157 158 174 174 174 174 174 174 +166 165 166 158 157 158 125 124 125 41 54 63 13 16 17 6 6 6 +6 6 6 37 38 37 80 127 157 136 185 209 101 161 196 101 161 196 +90 154 193 28 67 93 6 10 14 13 20 25 13 20 25 6 10 14 +1 1 2 4 3 3 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +1 1 1 1 0 0 4 3 3 37 38 37 60 74 84 153 152 153 +167 166 167 167 166 167 158 157 158 154 153 154 155 154 155 156 155 156 +157 156 157 158 157 158 167 166 167 167 166 167 131 129 131 43 57 68 +26 28 28 37 38 37 60 73 81 131 129 131 165 164 165 166 165 166 +158 157 158 155 154 155 156 155 156 156 155 156 156 155 156 158 157 158 +165 164 165 174 174 174 163 162 163 60 74 84 16 19 21 13 16 17 +60 73 81 131 129 131 174 174 174 174 174 174 167 166 167 165 164 165 +137 136 137 60 73 81 24 26 27 4 0 0 4 0 0 16 19 21 +52 104 138 101 161 196 136 185 209 136 185 209 90 154 193 27 99 146 +13 20 25 4 5 7 2 5 5 4 5 7 1 1 2 0 0 0 +4 4 4 4 4 4 3 3 3 2 2 2 2 2 2 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 0 0 0 +0 0 0 13 16 17 60 73 81 137 136 137 174 174 174 166 165 166 +158 157 158 156 155 156 157 156 157 156 155 156 155 154 155 158 157 158 +167 166 167 174 174 174 153 152 153 60 73 81 16 19 21 4 0 0 +4 0 0 4 0 0 6 6 6 26 28 28 60 74 84 158 157 158 +174 174 174 166 165 166 157 156 157 155 154 155 156 155 156 156 155 156 +155 154 155 158 157 158 167 166 167 167 166 167 131 129 131 125 124 125 +137 136 137 167 166 167 167 166 167 174 174 174 158 157 158 125 124 125 +16 19 21 4 0 0 4 0 0 10 13 16 49 76 92 107 159 188 +136 185 209 136 185 209 90 154 193 26 108 161 22 40 52 6 10 14 +2 3 3 1 1 2 1 1 2 4 4 5 4 4 5 4 4 5 +4 4 5 2 2 1 0 0 0 0 0 0 0 0 0 2 2 2 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 3 3 3 0 0 0 1 0 0 4 0 0 +37 51 59 131 129 131 167 166 167 167 166 167 163 162 163 157 156 157 +157 156 157 155 154 155 153 152 153 157 156 157 167 166 167 174 174 174 +153 152 153 125 124 125 37 38 37 4 0 0 4 0 0 4 0 0 +4 3 3 4 3 3 4 0 0 6 6 6 4 0 0 37 38 37 +125 124 125 174 174 174 174 174 174 165 164 165 156 155 156 154 153 154 +156 155 156 156 155 156 155 154 155 163 162 163 158 157 158 163 162 163 +174 174 174 174 174 174 174 174 174 125 124 125 37 38 37 0 0 0 +4 0 0 6 9 11 41 54 63 90 154 193 136 185 209 146 190 211 +136 185 209 37 112 160 22 40 52 6 10 14 3 6 7 1 1 2 +1 1 2 3 3 3 1 1 2 3 3 3 4 4 4 4 4 4 +2 2 2 2 0 0 16 19 21 37 38 37 24 26 27 0 0 0 +0 0 0 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 +4 4 4 0 0 0 0 0 0 0 0 0 26 28 28 120 125 127 +158 157 158 174 174 174 165 164 165 157 156 157 155 154 155 156 155 156 +153 152 153 153 152 153 167 166 167 174 174 174 174 174 174 125 124 125 +37 38 37 4 0 0 0 0 0 4 0 0 4 3 3 4 4 4 +4 4 4 4 4 4 5 5 5 4 0 0 4 0 0 4 0 0 +4 3 3 43 57 68 137 136 137 174 174 174 174 174 174 165 164 165 +154 153 154 153 152 153 153 152 153 153 152 153 163 162 163 174 174 174 +174 174 174 153 152 153 60 73 81 6 6 6 4 0 0 4 3 3 +32 43 50 80 127 157 136 185 209 146 190 211 146 190 211 90 154 193 +28 67 93 28 67 93 40 71 93 3 6 7 1 1 2 2 5 5 +50 82 103 79 117 143 26 37 45 0 0 0 3 3 3 1 1 1 +0 0 0 41 54 63 137 136 137 174 174 174 153 152 153 60 73 81 +2 0 0 0 0 0 +4 4 4 4 4 4 4 4 4 4 4 4 6 6 6 2 2 2 +0 0 0 2 0 0 24 26 27 60 74 84 153 152 153 174 174 174 +174 174 174 157 156 157 154 153 154 156 155 156 154 153 154 153 152 153 +165 164 165 174 174 174 177 184 187 137 136 137 43 57 68 6 6 6 +4 0 0 2 0 0 3 3 3 5 5 5 5 5 5 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 6 6 6 4 3 3 +4 0 0 4 0 0 24 26 27 60 73 81 153 152 153 174 174 174 +174 174 174 158 157 158 158 157 158 174 174 174 174 174 174 158 157 158 +60 74 84 24 26 27 4 0 0 4 0 0 17 23 27 59 113 148 +136 185 209 191 222 234 146 190 211 136 185 209 31 91 132 7 11 13 +22 40 52 101 161 196 90 154 193 6 9 11 3 4 4 43 95 132 +136 185 209 172 205 220 55 98 126 0 0 0 0 0 0 2 0 0 +26 28 28 153 152 153 177 184 187 167 166 167 177 184 187 165 164 165 +37 38 37 0 0 0 +4 4 4 4 4 4 5 5 5 5 5 5 1 1 1 0 0 0 +13 16 17 60 73 81 137 136 137 174 174 174 174 174 174 165 164 165 +153 152 153 153 152 153 155 154 155 154 153 154 158 157 158 174 174 174 +177 184 187 163 162 163 60 73 81 16 19 21 4 0 0 4 0 0 +4 3 3 4 4 4 5 5 5 5 5 5 4 4 4 5 5 5 +5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 5 5 5 +6 6 6 4 0 0 4 0 0 4 0 0 24 26 27 60 74 84 +166 165 166 174 174 174 177 184 187 165 164 165 125 124 125 24 26 27 +4 0 0 4 0 0 5 5 5 50 82 103 136 185 209 172 205 220 +146 190 211 136 185 209 26 108 161 22 40 52 7 12 15 44 81 103 +71 116 144 28 67 93 37 51 59 41 65 82 100 139 164 101 161 196 +90 154 193 90 154 193 28 67 93 0 0 0 0 0 0 26 28 28 +125 124 125 167 166 167 163 162 163 153 152 153 163 162 163 174 174 174 +85 115 134 4 0 0 +4 4 4 5 5 5 4 4 4 1 0 0 4 0 0 34 47 55 +125 124 125 174 174 174 174 174 174 167 166 167 157 156 157 153 152 153 +155 154 155 155 154 155 158 157 158 166 165 166 167 166 167 154 153 154 +125 124 125 26 28 28 4 0 0 4 0 0 4 0 0 5 5 5 +5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 +0 0 0 0 0 0 1 1 1 4 4 4 4 4 4 4 4 4 +5 5 5 5 5 5 4 3 3 4 0 0 4 0 0 6 6 6 +37 38 37 131 129 131 137 136 137 37 38 37 0 0 0 4 0 0 +4 5 5 43 61 72 90 154 193 172 205 220 146 190 211 136 185 209 +90 154 193 28 67 93 13 20 25 43 61 72 71 116 144 44 81 103 +2 5 5 7 11 13 59 113 148 101 161 196 90 154 193 28 67 93 +13 20 25 6 10 14 0 0 0 13 16 17 60 73 81 137 136 137 +166 165 166 158 157 158 156 155 156 154 153 154 167 166 167 174 174 174 +60 73 81 4 0 0 +4 4 4 4 4 4 0 0 0 3 3 3 60 74 84 174 174 174 +174 174 174 167 166 167 163 162 163 155 154 155 157 156 157 155 154 155 +156 155 156 163 162 163 167 166 167 158 157 158 125 124 125 37 38 37 +4 3 3 4 0 0 4 0 0 6 6 6 6 6 6 5 5 5 +4 4 4 4 4 4 4 4 4 1 1 1 0 0 0 2 3 3 +10 13 16 7 11 13 1 0 0 0 0 0 2 2 1 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 4 3 3 4 0 0 +4 0 0 7 11 13 13 16 17 4 0 0 3 3 3 34 47 55 +80 127 157 146 190 211 172 205 220 136 185 209 136 185 209 136 185 209 +28 67 93 22 40 52 55 98 126 55 98 126 21 29 34 7 11 13 +50 82 103 101 161 196 101 161 196 35 83 115 13 20 25 2 2 1 +1 1 2 1 1 2 37 51 59 131 129 131 174 174 174 174 174 174 +167 166 167 163 162 163 163 162 163 167 166 167 174 174 174 125 124 125 +16 19 21 4 0 0 +4 4 4 4 0 0 4 0 0 60 74 84 174 174 174 174 174 174 +158 157 158 155 154 155 155 154 155 156 155 156 155 154 155 158 157 158 +167 166 167 165 164 165 131 129 131 60 73 81 13 16 17 4 0 0 +4 0 0 4 3 3 6 6 6 4 3 3 5 5 5 4 4 4 +4 4 4 3 2 2 0 0 0 0 0 0 7 11 13 45 69 86 +80 127 157 71 116 144 43 61 72 7 11 13 0 0 0 1 1 1 +4 3 3 4 4 4 4 4 4 4 4 4 6 6 6 5 5 5 +3 2 2 4 0 0 1 0 0 21 29 34 59 113 148 136 185 209 +146 190 211 136 185 209 136 185 209 136 185 209 136 185 209 136 185 209 +68 124 159 44 81 103 22 40 52 13 16 17 43 61 72 90 154 193 +136 185 209 59 113 148 21 29 34 3 4 3 1 1 1 0 0 0 +24 26 27 125 124 125 163 162 163 174 174 174 166 165 166 165 164 165 +163 162 163 125 124 125 125 124 125 125 124 125 125 124 125 26 28 28 +4 0 0 4 3 3 +3 3 3 0 0 0 24 26 27 153 152 153 177 184 187 158 157 158 +156 155 156 156 155 156 155 154 155 155 154 155 165 164 165 174 174 174 +155 154 155 60 74 84 26 28 28 4 0 0 4 0 0 3 1 0 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 +2 0 0 0 0 0 0 0 0 32 43 50 72 125 159 101 161 196 +136 185 209 101 161 196 101 161 196 79 117 143 32 43 50 0 0 0 +0 0 0 2 2 2 4 4 4 4 4 4 3 3 3 1 0 0 +0 0 0 4 5 5 49 76 92 101 161 196 146 190 211 146 190 211 +136 185 209 136 185 209 136 185 209 136 185 209 136 185 209 90 154 193 +28 67 93 13 16 17 37 51 59 80 127 157 136 185 209 90 154 193 +22 40 52 6 9 11 3 4 3 2 2 1 16 19 21 60 73 81 +137 136 137 163 162 163 158 157 158 166 165 166 167 166 167 153 152 153 +60 74 84 37 38 37 6 6 6 13 16 17 4 0 0 1 0 0 +3 2 2 4 4 4 +3 2 2 4 0 0 37 38 37 137 136 137 167 166 167 158 157 158 +157 156 157 154 153 154 157 156 157 167 166 167 174 174 174 125 124 125 +37 38 37 4 0 0 4 0 0 4 0 0 4 3 3 4 4 4 +4 4 4 4 4 4 5 5 5 5 5 5 1 1 1 0 0 0 +0 0 0 16 21 25 55 98 126 90 154 193 136 185 209 101 161 196 +101 161 196 101 161 196 136 185 209 136 185 209 101 161 196 55 98 126 +14 17 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +22 40 52 90 154 193 146 190 211 146 190 211 136 185 209 136 185 209 +136 185 209 136 185 209 136 185 209 101 161 196 35 83 115 7 11 13 +17 23 27 59 113 148 136 185 209 101 161 196 34 86 122 7 12 15 +2 5 5 3 4 3 6 6 6 60 73 81 131 129 131 163 162 163 +166 165 166 174 174 174 174 174 174 163 162 163 125 124 125 41 54 63 +13 16 17 4 0 0 4 0 0 4 0 0 1 0 0 2 2 2 +4 4 4 4 4 4 +1 1 1 2 1 0 43 57 68 137 136 137 153 152 153 153 152 153 +163 162 163 156 155 156 165 164 165 167 166 167 60 74 84 6 6 6 +4 0 0 4 0 0 5 5 5 4 4 4 4 4 4 4 4 4 +4 5 5 6 6 6 4 3 3 0 0 0 0 0 0 11 15 18 +40 71 93 100 139 164 101 161 196 101 161 196 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 136 185 209 136 185 209 +101 161 196 45 69 86 6 6 6 0 0 0 17 23 27 55 98 126 +136 185 209 146 190 211 136 185 209 136 185 209 136 185 209 136 185 209 +136 185 209 136 185 209 90 154 193 22 40 52 7 11 13 50 82 103 +136 185 209 136 185 209 53 118 160 22 40 52 7 11 13 2 5 5 +3 4 3 37 38 37 125 124 125 157 156 157 166 165 166 167 166 167 +174 174 174 174 174 174 137 136 137 60 73 81 4 0 0 4 0 0 +4 0 0 4 0 0 5 5 5 3 3 3 3 3 3 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 41 54 63 137 136 137 125 124 125 131 129 131 +155 154 155 167 166 167 174 174 174 60 74 84 6 6 6 4 0 0 +4 3 3 6 6 6 4 4 4 4 4 4 4 4 4 5 5 5 +4 4 4 1 1 1 0 0 0 3 6 7 41 65 82 72 125 159 +101 161 196 101 161 196 101 161 196 90 154 193 90 154 193 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 136 185 209 +136 185 209 136 185 209 80 127 157 55 98 126 101 161 196 146 190 211 +136 185 209 136 185 209 136 185 209 101 161 196 136 185 209 101 161 196 +136 185 209 101 161 196 35 83 115 22 30 35 101 161 196 172 205 220 +90 154 193 28 67 93 7 11 13 2 5 5 3 4 3 13 16 17 +85 115 134 167 166 167 174 174 174 174 174 174 174 174 174 174 174 174 +167 166 167 60 74 84 13 16 17 4 0 0 4 0 0 4 3 3 +6 6 6 5 5 5 4 4 4 5 5 5 4 4 4 5 5 5 +5 5 5 5 5 5 +1 1 1 4 0 0 41 54 63 137 136 137 137 136 137 125 124 125 +131 129 131 167 166 167 157 156 157 37 38 37 6 6 6 4 0 0 +6 6 6 5 5 5 4 4 4 4 4 4 4 5 5 2 2 1 +0 0 0 0 0 0 26 37 45 58 111 146 101 161 196 101 161 196 +101 161 196 90 154 193 90 154 193 90 154 193 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 +101 161 196 136 185 209 136 185 209 136 185 209 146 190 211 136 185 209 +136 185 209 101 161 196 136 185 209 136 185 209 101 161 196 136 185 209 +101 161 196 136 185 209 136 185 209 136 185 209 136 185 209 16 89 141 +7 11 13 2 5 5 2 5 5 13 16 17 60 73 81 154 154 154 +174 174 174 174 174 174 174 174 174 174 174 174 163 162 163 125 124 125 +24 26 27 4 0 0 4 0 0 4 0 0 5 5 5 5 5 5 +4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 +5 5 5 4 4 4 +4 0 0 6 6 6 37 38 37 137 136 137 137 136 137 131 129 131 +131 129 131 153 152 153 131 129 131 26 28 28 4 0 0 4 3 3 +6 6 6 4 4 4 4 4 4 4 4 4 0 0 0 0 0 0 +13 20 25 51 88 114 90 154 193 101 161 196 101 161 196 90 154 193 +90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 136 185 209 101 161 196 +101 161 196 136 185 209 101 161 196 136 185 209 136 185 209 101 161 196 +136 185 209 101 161 196 136 185 209 101 161 196 101 161 196 101 161 196 +136 185 209 136 185 209 136 185 209 37 112 160 21 29 34 5 7 8 +2 5 5 13 16 17 43 57 68 131 129 131 174 174 174 174 174 174 +174 174 174 167 166 167 157 156 157 125 124 125 37 38 37 4 0 0 +4 0 0 4 0 0 5 5 5 5 5 5 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +1 1 1 4 0 0 41 54 63 153 152 153 137 136 137 137 136 137 +137 136 137 153 152 153 125 124 125 24 26 27 4 0 0 3 2 2 +4 4 4 4 4 4 4 3 3 4 0 0 3 6 7 43 61 72 +64 123 161 101 161 196 90 154 193 90 154 193 90 154 193 90 154 193 +90 154 193 90 154 193 90 154 193 90 154 193 101 161 196 90 154 193 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 +136 185 209 101 161 196 101 161 196 136 185 209 136 185 209 101 161 196 +101 161 196 90 154 193 28 67 93 13 16 17 7 11 13 3 6 7 +37 51 59 125 124 125 163 162 163 174 174 174 167 166 167 166 165 166 +167 166 167 131 129 131 60 73 81 4 0 0 4 0 0 4 0 0 +3 3 3 5 5 5 6 6 6 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 41 54 63 137 136 137 153 152 153 137 136 137 +153 152 153 157 156 157 125 124 125 24 26 27 0 0 0 2 2 2 +4 4 4 4 4 4 2 0 0 0 0 0 28 67 93 90 154 193 +90 154 193 90 154 193 90 154 193 90 154 193 64 123 161 90 154 193 +90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 101 161 196 +90 154 193 101 161 196 101 161 196 101 161 196 90 154 193 136 185 209 +101 161 196 101 161 196 136 185 209 101 161 196 136 185 209 101 161 196 +101 161 196 101 161 196 136 185 209 101 161 196 101 161 196 90 154 193 +35 83 115 13 16 17 3 6 7 2 5 5 13 16 17 60 74 84 +154 154 154 166 165 166 165 164 165 158 157 158 163 162 163 157 156 157 +60 74 84 13 16 17 4 0 0 4 0 0 3 2 2 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +1 1 1 4 0 0 41 54 63 157 156 157 155 154 155 137 136 137 +153 152 153 158 157 158 137 136 137 26 28 28 2 0 0 2 2 2 +4 4 4 4 4 4 1 0 0 6 10 14 34 86 122 90 154 193 +64 123 161 90 154 193 64 123 161 90 154 193 90 154 193 90 154 193 +64 123 161 90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 +136 185 209 101 161 196 136 185 209 90 154 193 26 108 161 22 40 52 +13 16 17 5 7 8 2 5 5 2 5 5 37 38 37 165 164 165 +174 174 174 163 162 163 154 154 154 165 164 165 167 166 167 60 73 81 +6 6 6 4 0 0 4 0 0 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 41 54 63 156 155 156 158 157 158 153 152 153 +156 155 156 165 164 165 137 136 137 26 28 28 0 0 0 2 2 2 +4 4 5 4 4 4 2 0 0 7 12 15 31 96 139 64 123 161 +90 154 193 64 123 161 90 154 193 90 154 193 64 123 161 90 154 193 +90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 +90 154 193 90 154 193 90 154 193 101 161 196 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 101 161 196 101 161 196 136 185 209 +101 161 196 136 185 209 26 108 161 22 40 52 7 11 13 5 7 8 +2 5 5 2 5 5 2 5 5 2 2 1 37 38 37 158 157 158 +174 174 174 154 154 154 156 155 156 167 166 167 165 164 165 37 38 37 +4 0 0 4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +3 1 0 4 0 0 60 73 81 157 156 157 163 162 163 153 152 153 +158 157 158 167 166 167 137 136 137 26 28 28 2 0 0 2 2 2 +4 5 5 4 4 4 4 0 0 7 12 15 24 86 132 26 108 161 +37 112 160 64 123 161 90 154 193 64 123 161 90 154 193 90 154 193 +90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 90 154 193 +90 154 193 101 161 196 90 154 193 101 161 196 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 136 185 209 101 161 196 136 185 209 +90 154 193 35 83 115 13 16 17 13 16 17 7 11 13 3 6 7 +5 7 8 6 6 6 3 4 3 2 2 1 30 32 34 154 154 154 +167 166 167 154 154 154 154 154 154 174 174 174 165 164 165 37 38 37 +6 6 6 4 0 0 6 6 6 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 41 54 63 163 162 163 166 165 166 154 154 154 +163 162 163 174 174 174 137 136 137 26 28 28 0 0 0 2 2 2 +4 5 5 4 4 5 1 1 2 6 10 14 28 67 93 18 97 151 +18 97 151 18 97 151 26 108 161 37 112 160 37 112 160 90 154 193 +64 123 161 90 154 193 90 154 193 90 154 193 90 154 193 101 161 196 +90 154 193 101 161 196 101 161 196 90 154 193 101 161 196 101 161 196 +101 161 196 101 161 196 101 161 196 136 185 209 90 154 193 16 89 141 +13 20 25 7 11 13 5 7 8 5 7 8 2 5 5 4 5 5 +3 4 3 4 5 5 3 4 3 0 0 0 37 38 37 158 157 158 +174 174 174 158 157 158 158 157 158 167 166 167 174 174 174 41 54 63 +4 0 0 3 2 2 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +1 1 1 4 0 0 60 73 81 165 164 165 174 174 174 158 157 158 +167 166 167 174 174 174 153 152 153 26 28 28 2 0 0 2 2 2 +4 5 5 4 4 4 4 0 0 7 12 15 10 87 144 10 87 144 +18 97 151 18 97 151 18 97 151 26 108 161 26 108 161 26 108 161 +26 108 161 37 112 160 53 118 160 90 154 193 90 154 193 90 154 193 +90 154 193 90 154 193 101 161 196 101 161 196 101 161 196 101 161 196 +101 161 196 136 185 209 90 154 193 26 108 161 22 40 52 13 16 17 +7 11 13 3 6 7 5 7 8 5 7 8 2 5 5 4 5 5 +4 5 5 6 6 6 3 4 3 0 0 0 30 32 34 158 157 158 +174 174 174 156 155 156 155 154 155 165 164 165 154 153 154 37 38 37 +4 0 0 4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 167 166 167 174 174 174 163 162 163 +174 174 174 174 174 174 153 152 153 26 28 28 0 0 0 3 3 3 +5 5 5 4 4 4 1 1 2 7 12 15 28 67 93 18 97 151 +18 97 151 18 97 151 18 97 151 18 97 151 18 97 151 26 108 161 +26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 +90 154 193 26 108 161 90 154 193 90 154 193 90 154 193 101 161 196 +101 161 196 26 108 161 22 40 52 13 16 17 7 11 13 2 5 5 +2 5 5 6 6 6 2 5 5 4 5 5 4 5 5 4 5 5 +3 4 3 5 5 5 3 4 3 2 0 0 30 32 34 137 136 137 +153 152 153 137 136 137 131 129 131 137 136 137 131 129 131 37 38 37 +4 0 0 4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +1 1 1 4 0 0 60 73 81 167 166 167 174 174 174 166 165 166 +174 174 174 177 184 187 153 152 153 30 32 34 1 0 0 3 3 3 +5 5 5 4 3 3 4 0 0 7 12 15 10 87 144 10 87 144 +18 97 151 18 97 151 18 97 151 26 108 161 26 108 161 26 108 161 +26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 +26 108 161 26 108 161 26 108 161 90 154 193 90 154 193 26 108 161 +35 83 115 13 16 17 7 11 13 5 7 8 3 6 7 5 7 8 +2 5 5 6 6 6 4 5 5 4 5 5 3 4 3 4 5 5 +3 4 3 6 6 6 3 4 3 0 0 0 26 28 28 125 124 125 +131 129 131 125 124 125 125 124 125 131 129 131 131 129 131 37 38 37 +4 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +3 1 0 4 0 0 60 73 81 174 174 174 177 184 187 167 166 167 +174 174 174 177 184 187 153 152 153 30 32 34 0 0 0 3 3 3 +5 5 5 4 4 4 1 1 2 6 10 14 28 67 93 18 97 151 +18 97 151 18 97 151 18 97 151 18 97 151 18 97 151 26 108 161 +26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 +26 108 161 90 154 193 26 108 161 26 108 161 24 86 132 13 20 25 +7 11 13 13 20 25 22 40 52 5 7 8 3 4 3 3 4 3 +4 5 5 3 4 3 4 5 5 3 4 3 4 5 5 3 4 3 +4 4 4 5 5 5 3 3 3 2 0 0 26 28 28 125 124 125 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +1 1 1 4 0 0 60 73 81 174 174 174 177 184 187 174 174 174 +174 174 174 190 197 201 157 156 157 30 32 34 1 0 0 3 3 3 +5 5 5 4 3 3 4 0 0 7 12 15 10 87 144 10 87 144 +18 97 151 19 95 150 19 95 150 18 97 151 18 97 151 26 108 161 +18 97 151 26 108 161 26 108 161 26 108 161 26 108 161 90 154 193 +26 108 161 26 108 161 26 108 161 22 40 52 2 5 5 3 4 3 +28 67 93 37 112 160 34 86 122 2 5 5 3 4 3 3 4 3 +3 4 3 3 4 3 3 4 3 2 2 1 3 4 3 4 4 4 +4 5 5 5 5 5 3 3 3 0 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 174 174 174 177 184 187 174 174 174 +174 174 174 190 197 201 158 157 158 30 32 34 0 0 0 2 2 2 +5 5 5 4 4 4 1 1 2 6 10 14 28 67 93 18 97 151 +10 87 144 19 95 150 19 95 150 18 97 151 18 97 151 18 97 151 +26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 +18 97 151 22 40 52 2 5 5 2 2 1 22 40 52 26 108 161 +90 154 193 37 112 160 22 40 52 3 4 3 13 20 25 22 30 35 +3 6 7 1 1 1 2 2 2 6 9 11 5 5 5 4 3 3 +4 4 4 5 5 5 3 3 3 2 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +1 1 1 4 0 0 60 73 81 177 184 187 193 200 203 174 174 174 +177 184 187 193 200 203 163 162 163 30 32 34 4 0 0 2 2 2 +5 5 5 4 3 3 4 0 0 6 10 14 24 86 132 10 87 144 +10 87 144 10 87 144 19 95 150 19 95 150 19 95 150 18 97 151 +26 108 161 26 108 161 26 108 161 90 154 193 26 108 161 28 67 93 +6 10 14 2 5 5 13 20 25 24 86 132 37 112 160 90 154 193 +10 87 144 7 12 15 2 5 5 28 67 93 37 112 160 28 67 93 +2 2 1 7 12 15 35 83 115 28 67 93 3 6 7 1 0 0 +4 4 4 5 5 5 3 3 3 0 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 174 174 174 190 197 201 174 174 174 +177 184 187 193 200 203 163 162 163 30 32 34 0 0 0 2 2 2 +5 5 5 4 4 4 1 1 2 6 10 14 28 67 93 10 87 144 +10 87 144 16 89 141 19 95 150 10 87 144 26 108 161 26 108 161 +26 108 161 26 108 161 26 108 161 28 67 93 6 10 14 1 1 2 +7 12 15 28 67 93 26 108 161 16 89 141 24 86 132 21 29 34 +3 4 3 21 29 34 37 112 160 37 112 160 27 99 146 21 29 34 +21 29 34 26 108 161 90 154 193 35 83 115 1 1 2 2 0 0 +4 4 4 5 5 5 3 3 3 2 0 0 26 28 28 125 124 125 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +3 1 0 4 0 0 60 73 81 193 200 203 193 200 203 174 174 174 +190 197 201 193 200 203 165 164 165 37 38 37 4 0 0 2 2 2 +5 5 5 4 3 3 4 0 0 6 10 14 24 86 132 10 87 144 +10 87 144 10 87 144 16 89 141 18 97 151 18 97 151 10 87 144 +24 86 132 24 86 132 13 20 25 4 5 7 4 5 7 22 40 52 +18 97 151 37 112 160 26 108 161 7 12 15 1 1 1 0 0 0 +28 67 93 37 112 160 26 108 161 28 67 93 22 40 52 28 67 93 +26 108 161 90 154 193 26 108 161 10 87 144 0 0 0 2 0 0 +4 4 4 5 5 5 3 3 3 0 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 60 73 81 174 174 174 193 200 203 174 174 174 +190 197 201 193 200 203 165 164 165 30 32 34 0 0 0 2 2 2 +5 5 5 4 4 4 1 1 2 6 10 14 28 67 93 10 87 144 +10 87 144 10 87 144 10 87 144 18 97 151 28 67 93 6 10 14 +0 0 0 1 1 2 4 5 7 13 20 25 16 89 141 26 108 161 +26 108 161 26 108 161 24 86 132 6 9 11 2 3 3 22 40 52 +37 112 160 16 89 141 22 40 52 28 67 93 26 108 161 26 108 161 +90 154 193 26 108 161 26 108 161 28 67 93 1 1 1 4 0 0 +4 4 4 5 5 5 3 3 3 4 0 0 26 28 28 124 126 130 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 193 200 203 193 200 203 174 174 174 +193 200 203 193 200 203 167 166 167 37 38 37 4 0 0 2 2 2 +5 5 5 4 4 4 4 0 0 6 10 14 28 67 93 10 87 144 +10 87 144 10 87 144 18 97 151 10 87 144 13 20 25 4 5 7 +1 1 2 1 1 1 22 40 52 26 108 161 26 108 161 26 108 161 +26 108 161 26 108 161 26 108 161 24 86 132 22 40 52 22 40 52 +22 40 52 22 40 52 10 87 144 26 108 161 26 108 161 26 108 161 +26 108 161 26 108 161 90 154 193 10 87 144 0 0 0 4 0 0 +4 4 4 5 5 5 3 3 3 0 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 60 73 81 174 174 174 220 221 221 174 174 174 +190 197 201 205 212 215 167 166 167 30 32 34 0 0 0 2 2 2 +5 5 5 4 4 4 1 1 2 6 10 14 28 67 93 10 87 144 +10 87 144 10 87 144 10 87 144 10 87 144 22 40 52 1 1 2 +2 0 0 1 1 2 24 86 132 26 108 161 26 108 161 26 108 161 +26 108 161 19 95 150 16 89 141 10 87 144 22 40 52 22 40 52 +10 87 144 26 108 161 37 112 160 26 108 161 26 108 161 26 108 161 +26 108 161 26 108 161 26 108 161 28 67 93 2 0 0 3 1 0 +4 4 4 5 5 5 3 3 3 2 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 220 221 221 190 197 201 174 174 174 +193 200 203 193 200 203 174 174 174 37 38 37 4 0 0 2 2 2 +5 5 5 4 4 4 3 2 2 1 1 2 13 20 25 10 87 144 +10 87 144 10 87 144 10 87 144 10 87 144 10 87 144 13 20 25 +13 20 25 22 40 52 10 87 144 18 97 151 18 97 151 26 108 161 +10 87 144 13 20 25 6 10 14 21 29 34 24 86 132 18 97 151 +26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 +26 108 161 90 154 193 18 97 151 13 20 25 0 0 0 4 3 3 +4 4 4 5 5 5 3 3 3 0 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 60 73 81 174 174 174 220 221 221 174 174 174 +190 197 201 220 221 221 167 166 167 30 32 34 1 0 0 2 2 2 +5 5 5 4 4 4 4 4 5 2 5 5 4 5 7 13 20 25 +28 67 93 10 87 144 10 87 144 10 87 144 10 87 144 10 87 144 +10 87 144 10 87 144 18 97 151 10 87 144 18 97 151 18 97 151 +28 67 93 2 3 3 0 0 0 28 67 93 26 108 161 26 108 161 +26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 26 108 161 +26 108 161 10 87 144 13 20 25 1 1 2 3 2 2 4 4 4 +4 4 4 5 5 5 3 3 3 2 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 220 221 221 190 197 201 174 174 174 +193 200 203 193 200 203 174 174 174 26 28 28 4 0 0 4 3 3 +5 5 5 4 4 4 4 4 4 4 4 5 1 1 2 2 5 5 +4 5 7 22 40 52 10 87 144 10 87 144 18 97 151 10 87 144 +10 87 144 10 87 144 10 87 144 10 87 144 10 87 144 18 97 151 +10 87 144 28 67 93 22 40 52 10 87 144 26 108 161 18 97 151 +18 97 151 18 97 151 26 108 161 26 108 161 26 108 161 26 108 161 +22 40 52 1 1 2 0 0 0 2 3 3 4 4 4 4 4 4 +4 4 4 5 5 5 4 4 4 0 0 0 26 28 28 131 129 131 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 60 73 81 174 174 174 220 221 221 174 174 174 +190 197 201 220 221 221 190 197 201 41 54 63 4 0 0 2 2 2 +6 6 6 4 4 4 4 4 4 4 4 5 4 4 5 3 3 3 +1 1 2 1 1 2 6 10 14 22 40 52 10 87 144 18 97 151 +18 97 151 10 87 144 10 87 144 10 87 144 18 97 151 10 87 144 +10 87 144 18 97 151 26 108 161 18 97 151 18 97 151 10 87 144 +26 108 161 26 108 161 26 108 161 10 87 144 28 67 93 6 10 14 +1 1 2 1 1 2 4 3 3 4 4 5 4 4 4 4 4 4 +5 5 5 5 5 5 1 1 1 4 0 0 37 51 59 137 136 137 +137 136 137 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 4 0 0 60 73 81 220 221 221 193 200 203 174 174 174 +193 200 203 193 200 203 220 221 221 137 136 137 13 16 17 4 0 0 +2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 +4 4 5 4 3 3 1 1 2 4 5 7 13 20 25 28 67 93 +10 87 144 10 87 144 10 87 144 10 87 144 10 87 144 10 87 144 +10 87 144 18 97 151 18 97 151 10 87 144 18 97 151 26 108 161 +26 108 161 18 97 151 28 67 93 6 10 14 0 0 0 0 0 0 +2 3 3 4 5 5 4 4 5 4 4 4 4 4 4 5 5 5 +3 3 3 1 1 1 0 0 0 16 19 21 125 124 125 137 136 137 +131 129 131 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 60 73 81 174 174 174 220 221 221 174 174 174 +193 200 203 190 197 201 220 221 221 220 221 221 153 152 153 30 32 34 +0 0 0 0 0 0 2 2 2 4 4 4 4 4 4 4 4 4 +4 4 4 4 5 5 4 5 7 1 1 2 1 1 2 4 5 7 +13 20 25 28 67 93 10 87 144 18 97 151 10 87 144 10 87 144 +10 87 144 10 87 144 10 87 144 18 97 151 26 108 161 18 97 151 +28 67 93 7 12 15 0 0 0 0 0 0 2 2 1 4 4 4 +4 5 5 4 5 5 4 4 4 4 4 4 3 3 3 0 0 0 +0 0 0 0 0 0 37 38 37 125 124 125 158 157 158 131 129 131 +125 124 125 125 124 125 125 124 125 137 136 137 131 129 131 37 38 37 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 3 3 4 0 0 41 54 63 193 200 203 220 221 221 174 174 174 +193 200 203 193 200 203 193 200 203 220 221 221 244 246 246 193 200 203 +120 125 127 5 5 5 1 0 0 0 0 0 1 1 1 4 4 4 +4 4 4 4 4 4 4 5 5 4 5 5 4 4 5 1 1 2 +4 5 7 4 5 7 22 40 52 10 87 144 10 87 144 10 87 144 +10 87 144 10 87 144 18 97 151 10 87 144 10 87 144 13 20 25 +4 5 7 2 3 3 1 1 2 4 4 4 4 5 5 4 4 4 +4 4 4 4 4 4 4 4 4 1 1 1 0 0 0 1 1 2 +24 26 27 60 74 84 153 152 153 163 162 163 137 136 137 125 124 125 +125 124 125 125 124 125 125 124 125 137 136 137 125 124 125 26 28 28 +0 0 0 3 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 0 0 6 6 6 26 28 28 156 155 156 220 221 221 220 221 221 +174 174 174 193 200 203 193 200 203 193 200 203 205 212 215 220 221 221 +220 221 221 167 166 167 60 73 81 7 11 13 0 0 0 0 0 0 +3 3 3 4 4 4 4 4 4 4 4 4 4 4 5 4 4 5 +4 4 5 1 1 2 1 1 2 4 5 7 22 40 52 10 87 144 +10 87 144 10 87 144 10 87 144 22 40 52 4 5 7 1 1 2 +1 1 2 4 4 5 4 4 4 4 4 4 4 4 4 4 4 4 +5 5 5 2 2 2 0 0 0 4 0 0 16 19 21 60 73 81 +137 136 137 167 166 167 158 157 158 137 136 137 131 129 131 131 129 131 +125 124 125 125 124 125 131 129 131 155 154 155 60 74 84 5 7 8 +0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +5 5 5 4 0 0 4 0 0 60 73 81 193 200 203 220 221 221 +193 200 203 193 200 203 193 200 203 193 200 203 205 212 215 220 221 221 +220 221 221 220 221 221 220 221 221 137 136 137 43 57 68 6 6 6 +4 0 0 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 5 4 4 5 3 2 2 1 1 2 2 5 5 13 20 25 +22 40 52 22 40 52 13 20 25 2 3 3 1 1 2 3 3 3 +4 5 7 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +1 1 1 0 0 0 2 3 3 41 54 63 131 129 131 166 165 166 +166 165 166 155 154 155 153 152 153 137 136 137 137 136 137 125 124 125 +125 124 125 137 136 137 137 136 137 125 124 125 37 38 37 4 3 3 +4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 3 3 6 6 6 6 6 6 13 16 17 60 73 81 167 166 167 +220 221 221 220 221 221 220 221 221 193 200 203 193 200 203 193 200 203 +205 212 215 220 221 221 220 221 221 244 246 246 205 212 215 125 124 125 +24 26 27 0 0 0 0 0 0 2 2 2 5 5 5 5 5 5 +4 4 4 4 4 4 4 4 4 4 4 5 1 1 2 4 5 7 +4 5 7 4 5 7 1 1 2 3 2 2 4 4 5 4 4 4 +4 4 4 4 4 4 5 5 5 4 4 4 0 0 0 0 0 0 +2 0 0 26 28 28 125 124 125 174 174 174 174 174 174 166 165 166 +156 155 156 153 152 153 137 136 137 137 136 137 131 129 131 137 136 137 +137 136 137 137 136 137 60 74 84 30 32 34 4 0 0 4 0 0 +5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +5 5 5 6 6 6 4 0 0 4 0 0 6 6 6 26 28 28 +125 124 125 174 174 174 220 221 221 220 221 221 220 221 221 193 200 203 +205 212 215 220 221 221 205 212 215 220 221 221 220 221 221 244 246 246 +193 200 203 60 74 84 13 16 17 4 0 0 0 0 0 3 3 3 +5 5 5 5 5 5 4 4 4 4 4 4 4 4 5 3 3 3 +1 1 2 3 3 3 4 4 5 4 4 5 4 4 4 4 4 4 +5 5 5 5 5 5 2 2 2 0 0 0 0 0 0 13 16 17 +60 74 84 174 174 174 193 200 203 174 174 174 167 166 167 163 162 163 +153 152 153 153 152 153 137 136 137 137 136 137 153 152 153 137 136 137 +125 124 125 41 54 63 24 26 27 4 0 0 4 0 0 5 5 5 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 3 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +6 6 6 37 38 37 131 129 131 220 221 221 220 221 221 220 221 221 +193 200 203 193 200 203 220 221 221 205 212 215 220 221 221 244 246 246 +244 246 246 244 246 246 174 174 174 41 54 63 0 0 0 0 0 0 +0 0 0 4 4 4 5 5 5 5 5 5 4 4 4 4 4 5 +4 4 5 4 4 5 4 4 4 4 4 4 6 6 6 6 6 6 +3 3 3 0 0 0 2 0 0 13 16 17 60 73 81 156 155 156 +220 221 221 193 200 203 174 174 174 165 164 165 163 162 163 154 153 154 +153 152 153 153 152 153 158 157 158 163 162 163 137 136 137 60 73 81 +13 16 17 4 0 0 4 0 0 4 3 3 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +5 5 5 4 3 3 4 3 3 6 6 6 6 6 6 6 6 6 +6 6 6 6 6 6 6 6 6 37 38 37 167 166 167 244 246 246 +244 246 246 220 221 221 205 212 215 205 212 215 220 221 221 193 200 203 +220 221 221 244 246 246 244 246 246 244 246 246 137 136 137 37 38 37 +3 2 2 0 0 0 1 1 1 5 5 5 5 5 5 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 4 4 4 1 1 1 +0 0 0 5 5 5 43 57 68 153 152 153 193 200 203 220 221 221 +177 184 187 174 174 174 167 166 167 166 165 166 158 157 158 157 156 157 +158 157 158 166 165 166 156 155 156 85 115 134 13 16 17 4 0 0 +4 0 0 4 0 0 5 5 5 5 5 5 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +5 5 5 4 3 3 6 6 6 6 6 6 4 0 0 6 6 6 +6 6 6 6 6 6 6 6 6 6 6 6 13 16 17 60 73 81 +177 184 187 220 221 221 220 221 221 220 221 221 205 212 215 220 221 221 +220 221 221 205 212 215 220 221 221 244 246 246 244 246 246 205 212 215 +125 124 125 30 32 34 0 0 0 0 0 0 2 2 2 5 5 5 +4 4 4 4 4 4 4 4 4 1 1 1 0 0 0 1 0 0 +37 38 37 131 129 131 205 212 215 220 221 221 193 200 203 174 174 174 +174 174 174 174 174 174 167 166 167 165 164 165 166 165 166 167 166 167 +158 157 158 125 124 125 37 38 37 4 0 0 4 0 0 4 0 0 +4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 5 5 5 4 3 3 4 3 3 6 6 6 6 6 6 +4 0 0 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +26 28 28 125 124 125 205 212 215 220 221 221 220 221 221 220 221 221 +205 212 215 220 221 221 205 212 215 220 221 221 220 221 221 244 246 246 +244 246 246 190 197 201 60 74 84 16 19 21 4 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 19 21 120 125 127 +177 184 187 220 221 221 205 212 215 177 184 187 174 174 174 177 184 187 +174 174 174 174 174 174 167 166 167 174 174 174 166 165 166 137 136 137 +60 73 81 13 16 17 4 0 0 4 0 0 4 3 3 6 6 6 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +5 5 5 4 3 3 5 5 5 4 3 3 6 6 6 4 0 0 +6 6 6 6 6 6 4 0 0 6 6 6 4 0 0 6 6 6 +6 6 6 6 6 6 37 38 37 137 136 137 193 200 203 220 221 221 +220 221 221 205 212 215 220 221 221 205 212 215 205 212 215 220 221 221 +220 221 221 220 221 221 244 246 246 166 165 166 43 57 68 2 2 2 +0 0 0 4 0 0 16 19 21 60 73 81 157 156 157 202 210 214 +220 221 221 193 200 203 177 184 187 177 184 187 177 184 187 174 174 174 +174 174 174 174 174 174 174 174 174 157 156 157 60 74 84 24 26 27 +4 0 0 4 0 0 4 0 0 6 6 6 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 5 5 5 4 3 3 5 5 5 6 6 6 +6 6 6 4 0 0 6 6 6 6 6 6 6 6 6 4 0 0 +4 0 0 4 0 0 6 6 6 24 26 27 60 73 81 167 166 167 +220 221 221 220 221 221 220 221 221 205 212 215 205 212 215 205 212 215 +205 212 215 220 221 221 220 221 221 220 221 221 205 212 215 137 136 137 +60 74 84 125 124 125 137 136 137 190 197 201 220 221 221 193 200 203 +177 184 187 177 184 187 177 184 187 174 174 174 174 174 174 177 184 187 +190 197 201 174 174 174 125 124 125 37 38 37 6 6 6 4 0 0 +4 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 5 5 5 5 5 5 4 3 3 6 6 6 +4 0 0 6 6 6 6 6 6 6 6 6 4 0 0 6 6 6 +6 6 6 6 6 6 4 0 0 4 0 0 6 6 6 6 6 6 +125 124 125 193 200 203 244 246 246 220 221 221 205 212 215 205 212 215 +205 212 215 193 200 203 205 212 215 205 212 215 220 221 221 220 221 221 +193 200 203 193 200 203 205 212 215 193 200 203 193 200 203 177 184 187 +190 197 201 190 197 201 174 174 174 190 197 201 193 200 203 190 197 201 +153 152 153 60 73 81 4 0 0 4 0 0 4 0 0 3 2 2 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 4 3 3 +6 6 6 4 3 3 4 3 3 4 3 3 6 6 6 6 6 6 +4 0 0 6 6 6 6 6 6 6 6 6 4 0 0 4 0 0 +4 0 0 26 28 28 131 129 131 220 221 221 244 246 246 220 221 221 +205 212 215 193 200 203 205 212 215 193 200 203 193 200 203 205 212 215 +220 221 221 193 200 203 193 200 203 193 200 203 190 197 201 174 174 174 +174 174 174 190 197 201 193 200 203 193 200 203 167 166 167 125 124 125 +6 6 6 4 0 0 4 0 0 4 3 3 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 +5 5 5 4 3 3 5 5 5 6 6 6 4 3 3 5 5 5 +6 6 6 6 6 6 4 0 0 6 6 6 6 6 6 6 6 6 +4 0 0 4 0 0 6 6 6 41 54 63 158 157 158 220 221 221 +220 221 221 220 221 221 193 200 203 193 200 203 193 200 203 190 197 201 +190 197 201 190 197 201 190 197 201 190 197 201 174 174 174 193 200 203 +193 200 203 220 221 221 174 174 174 125 124 125 37 38 37 4 0 0 +4 0 0 4 3 3 6 6 6 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 4 3 3 4 3 3 4 3 3 5 5 5 +4 3 3 6 6 6 5 5 5 4 3 3 6 6 6 6 6 6 +6 6 6 6 6 6 4 0 0 4 0 0 13 16 17 60 73 81 +174 174 174 220 221 221 220 221 221 205 212 215 190 197 201 174 174 174 +193 200 203 174 174 174 190 197 201 174 174 174 193 200 203 220 221 221 +193 200 203 131 129 131 37 38 37 6 6 6 4 0 0 4 0 0 +6 6 6 6 6 6 4 3 3 5 5 5 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 +5 5 5 4 3 3 4 3 3 5 5 5 4 3 3 4 3 3 +5 5 5 6 6 6 6 6 6 4 0 0 6 6 6 6 6 6 +6 6 6 125 124 125 174 174 174 220 221 221 220 221 221 193 200 203 +193 200 203 193 200 203 193 200 203 193 200 203 220 221 221 158 157 158 +60 73 81 6 6 6 4 0 0 4 0 0 5 5 5 6 6 6 +5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 5 5 5 4 3 3 5 5 5 4 3 3 +5 5 5 5 5 5 6 6 6 6 6 6 4 0 0 4 0 0 +4 0 0 4 0 0 26 28 28 125 124 125 174 174 174 193 200 203 +193 200 203 174 174 174 193 200 203 167 166 167 125 124 125 6 6 6 +6 6 6 6 6 6 4 0 0 6 6 6 6 6 6 5 5 5 +4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 +4 3 3 6 6 6 4 0 0 6 6 6 6 6 6 6 6 6 +6 6 6 4 0 0 4 0 0 6 6 6 37 38 37 125 124 125 +153 152 153 131 129 131 125 124 125 37 38 37 6 6 6 6 6 6 +6 6 6 4 0 0 6 6 6 6 6 6 4 3 3 5 5 5 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 5 5 5 4 3 3 5 5 5 4 3 3 +6 6 6 6 6 6 4 0 0 4 0 0 6 6 6 6 6 6 +24 26 27 24 26 27 6 6 6 6 6 6 6 6 6 4 0 0 +6 6 6 6 6 6 4 0 0 6 6 6 5 5 5 4 3 3 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 5 5 5 4 3 3 5 5 5 6 6 6 +4 0 0 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +6 6 6 6 6 6 6 6 6 4 0 0 6 6 6 6 6 6 +4 0 0 6 6 6 6 6 6 4 3 3 5 5 5 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 4 3 3 5 5 5 +5 5 5 5 5 5 4 0 0 6 6 6 4 0 0 6 6 6 +6 6 6 6 6 6 6 6 6 4 0 0 6 6 6 4 0 0 +6 6 6 4 3 3 5 5 5 4 3 3 5 5 5 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 +4 3 3 6 6 6 4 3 3 6 6 6 6 6 6 6 6 6 +4 0 0 6 6 6 4 0 0 6 6 6 6 6 6 6 6 6 +6 6 6 4 3 3 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 4 3 3 5 5 5 4 0 0 6 6 6 +6 6 6 4 0 0 6 6 6 6 6 6 4 0 0 6 6 6 +4 3 3 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 5 5 5 4 3 3 5 5 5 6 6 6 4 3 3 +4 3 3 6 6 6 6 6 6 4 3 3 6 6 6 4 3 3 +5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 5 5 5 4 3 3 6 6 6 +5 5 5 4 3 3 4 3 3 4 3 3 5 5 5 5 5 5 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 4 3 3 +5 5 5 4 3 3 5 5 5 5 5 5 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +4 4 4 4 4 4 diff --git a/drivers/video/mb862xx/mb862xxfb_accel.c b/drivers/video/mb862xx/mb862xxfb_accel.c index fe92eed..106e085 100644 --- a/drivers/video/mb862xx/mb862xxfb_accel.c +++ b/drivers/video/mb862xx/mb862xxfb_accel.c @@ -312,14 +312,18 @@ void mb862xxfb_init_accel(struct fb_info *info, int xres) struct mb862xxfb_par *par = info->par; if (info->var.bits_per_pixel == 32) { - info->fbops->fb_fillrect = cfb_fillrect; - info->fbops->fb_copyarea = cfb_copyarea; - info->fbops->fb_imageblit = cfb_imageblit; + pax_open_kernel(); + *(void **)&info->fbops->fb_fillrect = cfb_fillrect; + *(void **)&info->fbops->fb_copyarea = cfb_copyarea; + *(void **)&info->fbops->fb_imageblit = cfb_imageblit; + pax_close_kernel(); } else { outreg(disp, GC_L0EM, 3); - info->fbops->fb_fillrect = mb86290fb_fillrect; - info->fbops->fb_copyarea = mb86290fb_copyarea; - info->fbops->fb_imageblit = mb86290fb_imageblit; + pax_open_kernel(); + *(void **)&info->fbops->fb_fillrect = mb86290fb_fillrect; + *(void **)&info->fbops->fb_copyarea = mb86290fb_copyarea; + *(void **)&info->fbops->fb_imageblit = mb86290fb_imageblit; + pax_close_kernel(); } outreg(draw, GDC_REG_DRAW_BASE, 0); outreg(draw, GDC_REG_MODE_MISC, 0x8000); diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index ff22871..b129bed 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -669,19 +669,23 @@ static int nvidiafb_set_par(struct fb_info *info) info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 3; if (info->var.accel_flags) { - info->fbops->fb_imageblit = nvidiafb_imageblit; - info->fbops->fb_fillrect = nvidiafb_fillrect; - info->fbops->fb_copyarea = nvidiafb_copyarea; - info->fbops->fb_sync = nvidiafb_sync; + pax_open_kernel(); + *(void **)&info->fbops->fb_imageblit = nvidiafb_imageblit; + *(void **)&info->fbops->fb_fillrect = nvidiafb_fillrect; + *(void **)&info->fbops->fb_copyarea = nvidiafb_copyarea; + *(void **)&info->fbops->fb_sync = nvidiafb_sync; + pax_close_kernel(); info->pixmap.scan_align = 4; info->flags &= ~FBINFO_HWACCEL_DISABLED; info->flags |= FBINFO_READS_FAST; NVResetGraphics(info); } else { - info->fbops->fb_imageblit = cfb_imageblit; - info->fbops->fb_fillrect = cfb_fillrect; - info->fbops->fb_copyarea = cfb_copyarea; - info->fbops->fb_sync = NULL; + pax_open_kernel(); + *(void **)&info->fbops->fb_imageblit = cfb_imageblit; + *(void **)&info->fbops->fb_fillrect = cfb_fillrect; + *(void **)&info->fbops->fb_copyarea = cfb_copyarea; + *(void **)&info->fbops->fb_sync = NULL; + pax_close_kernel(); info->pixmap.scan_align = 1; info->flags |= FBINFO_HWACCEL_DISABLED; info->flags &= ~FBINFO_READS_FAST; @@ -1173,8 +1177,11 @@ static int nvidia_set_fbinfo(struct fb_info *info) info->pixmap.size = 8 * 1024; info->pixmap.flags = FB_PIXMAP_SYSTEM; - if (!hwcur) - info->fbops->fb_cursor = NULL; + if (!hwcur) { + pax_open_kernel(); + *(void **)&info->fbops->fb_cursor = NULL; + pax_close_kernel(); + } info->var.accel_flags = (!noaccel); diff --git a/drivers/video/output.c b/drivers/video/output.c index 0d6f2cd..6285b97 100644 --- a/drivers/video/output.c +++ b/drivers/video/output.c @@ -97,7 +97,7 @@ struct output_device *video_output_register(const char *name, new_dev->props = op; new_dev->dev.class = &video_output_class; new_dev->dev.parent = dev; - dev_set_name(&new_dev->dev, name); + dev_set_name(&new_dev->dev, "%s", name); dev_set_drvdata(&new_dev->dev, devdata); ret_code = device_register(&new_dev->dev); if (ret_code) { diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index 05c2dc3..ea1f391 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -881,8 +881,10 @@ static int s1d13xxxfb_probe(struct platform_device *pdev) switch(prod_id) { case S1D13506_PROD_ID: /* activate acceleration */ - s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill; - s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea; + pax_open_kernel(); + *(void **)&s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill; + *(void **)&s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea; + pax_close_kernel(); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; break; diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c index b2b33fc..f9f4658 100644 --- a/drivers/video/smscufx.c +++ b/drivers/video/smscufx.c @@ -1175,7 +1175,9 @@ static int ufx_ops_release(struct fb_info *info, int user) fb_deferred_io_cleanup(info); kfree(info->fbdefio); info->fbdefio = NULL; - info->fbops->fb_mmap = ufx_ops_mmap; + pax_open_kernel(); + *(void **)&info->fbops->fb_mmap = ufx_ops_mmap; + pax_close_kernel(); } pr_debug("released /dev/fb%d user=%d count=%d", diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index ec03e72..f578436 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -623,11 +623,11 @@ int dlfb_handle_damage(struct dlfb_data *dev, int x, int y, dlfb_urb_completion(urb); error: - atomic_add(bytes_sent, &dev->bytes_sent); - atomic_add(bytes_identical, &dev->bytes_identical); - atomic_add(width*height*2, &dev->bytes_rendered); + atomic_add_unchecked(bytes_sent, &dev->bytes_sent); + atomic_add_unchecked(bytes_identical, &dev->bytes_identical); + atomic_add_unchecked(width*height*2, &dev->bytes_rendered); end_cycles = get_cycles(); - atomic_add(((unsigned int) ((end_cycles - start_cycles) + atomic_add_unchecked(((unsigned int) ((end_cycles - start_cycles) >> 10)), /* Kcycles */ &dev->cpu_kcycles_used); @@ -748,11 +748,11 @@ static void dlfb_dpy_deferred_io(struct fb_info *info, dlfb_urb_completion(urb); error: - atomic_add(bytes_sent, &dev->bytes_sent); - atomic_add(bytes_identical, &dev->bytes_identical); - atomic_add(bytes_rendered, &dev->bytes_rendered); + atomic_add_unchecked(bytes_sent, &dev->bytes_sent); + atomic_add_unchecked(bytes_identical, &dev->bytes_identical); + atomic_add_unchecked(bytes_rendered, &dev->bytes_rendered); end_cycles = get_cycles(); - atomic_add(((unsigned int) ((end_cycles - start_cycles) + atomic_add_unchecked(((unsigned int) ((end_cycles - start_cycles) >> 10)), /* Kcycles */ &dev->cpu_kcycles_used); } @@ -993,7 +993,9 @@ static int dlfb_ops_release(struct fb_info *info, int user) fb_deferred_io_cleanup(info); kfree(info->fbdefio); info->fbdefio = NULL; - info->fbops->fb_mmap = dlfb_ops_mmap; + pax_open_kernel(); + *(void **)&info->fbops->fb_mmap = dlfb_ops_mmap; + pax_close_kernel(); } pr_warn("released /dev/fb%d user=%d count=%d\n", @@ -1376,7 +1378,7 @@ static ssize_t metrics_bytes_rendered_show(struct device *fbdev, struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dev = fb_info->par; return snprintf(buf, PAGE_SIZE, "%u\n", - atomic_read(&dev->bytes_rendered)); + atomic_read_unchecked(&dev->bytes_rendered)); } static ssize_t metrics_bytes_identical_show(struct device *fbdev, @@ -1384,7 +1386,7 @@ static ssize_t metrics_bytes_identical_show(struct device *fbdev, struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dev = fb_info->par; return snprintf(buf, PAGE_SIZE, "%u\n", - atomic_read(&dev->bytes_identical)); + atomic_read_unchecked(&dev->bytes_identical)); } static ssize_t metrics_bytes_sent_show(struct device *fbdev, @@ -1392,7 +1394,7 @@ static ssize_t metrics_bytes_sent_show(struct device *fbdev, struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dev = fb_info->par; return snprintf(buf, PAGE_SIZE, "%u\n", - atomic_read(&dev->bytes_sent)); + atomic_read_unchecked(&dev->bytes_sent)); } static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev, @@ -1400,7 +1402,7 @@ static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev, struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dev = fb_info->par; return snprintf(buf, PAGE_SIZE, "%u\n", - atomic_read(&dev->cpu_kcycles_used)); + atomic_read_unchecked(&dev->cpu_kcycles_used)); } static ssize_t edid_show( @@ -1460,10 +1462,10 @@ static ssize_t metrics_reset_store(struct device *fbdev, struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dev = fb_info->par; - atomic_set(&dev->bytes_rendered, 0); - atomic_set(&dev->bytes_identical, 0); - atomic_set(&dev->bytes_sent, 0); - atomic_set(&dev->cpu_kcycles_used, 0); + atomic_set_unchecked(&dev->bytes_rendered, 0); + atomic_set_unchecked(&dev->bytes_identical, 0); + atomic_set_unchecked(&dev->bytes_sent, 0); + atomic_set_unchecked(&dev->cpu_kcycles_used, 0); return count; } diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index e328a61..1b08ecb 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -19,6 +19,7 @@ #include #include #include +#include #include