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