public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [gentoo-commits] proj/hardened-patchset:master commit in: 4.5.5/
@ 2016-05-30  7:59 99% Anthony G. Basile
  0 siblings, 0 replies; 1+ results
From: Anthony G. Basile @ 2016-05-30  7:59 UTC (permalink / raw
  To: gentoo-commits

commit:     91c3b96e63792590118e17193061908a07017497
Author:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
AuthorDate: Mon May 30 08:00:17 2016 +0000
Commit:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
CommitDate: Mon May 30 08:00:17 2016 +0000
URL:        https://gitweb.gentoo.org/proj/hardened-patchset.git/commit/?id=91c3b96e

grsecurity-3.1-4.5.5-201605291201

 4.5.5/0000_README                                  |     2 +-
 ...> 4420_grsecurity-3.1-4.5.5-201605291201.patch} | 18852 ++++++++++---------
 2 files changed, 9793 insertions(+), 9061 deletions(-)

diff --git a/4.5.5/0000_README b/4.5.5/0000_README
index febdb77..71dba33 100644
--- a/4.5.5/0000_README
+++ b/4.5.5/0000_README
@@ -2,7 +2,7 @@ README
 -----------------------------------------------------------------------------
 Individual Patch Descriptions:
 -----------------------------------------------------------------------------
-Patch:	4420_grsecurity-3.1-4.5.5-201605211442.patch
+Patch:	4420_grsecurity-3.1-4.5.5-201605291201.patch
 From:	http://www.grsecurity.net
 Desc:	hardened-sources base patch from upstream grsecurity
 

diff --git a/4.5.5/4420_grsecurity-3.1-4.5.5-201605211442.patch b/4.5.5/4420_grsecurity-3.1-4.5.5-201605291201.patch
similarity index 99%
rename from 4.5.5/4420_grsecurity-3.1-4.5.5-201605211442.patch
rename to 4.5.5/4420_grsecurity-3.1-4.5.5-201605291201.patch
index 7202c18..1fb08ce 100644
--- a/4.5.5/4420_grsecurity-3.1-4.5.5-201605211442.patch
+++ b/4.5.5/4420_grsecurity-3.1-4.5.5-201605291201.patch
@@ -408,7 +408,7 @@ index a93b414..f50a50b 100644
  
  A toggle value indicating if modules are allowed to be loaded
 diff --git a/Makefile b/Makefile
-index a23df41..314f8da 100644
+index a23df41..db4f30b 100644
 --- a/Makefile
 +++ b/Makefile
 @@ -298,7 +298,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@@ -422,27 +422,41 @@ index a23df41..314f8da 100644
  
  ifeq ($(shell $(HOSTCC) -v 2>&1 | grep -c "clang version"), 1)
  HOSTCFLAGS  += -Wno-unused-value -Wno-unused-parameter \
-@@ -434,8 +436,8 @@ export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \
- # Rules shared between *config targets and build targets
- 
- # Basic helpers built in scripts/
--PHONY += scripts_basic
--scripts_basic:
-+PHONY += scripts_basic gcc-plugins
-+scripts_basic: gcc-plugins
- 	$(Q)$(MAKE) $(build)=scripts/basic
- 	$(Q)rm -f .tmp_quiet_recordmcount
- 
-@@ -622,6 +624,8 @@ endif
+@@ -417,6 +419,8 @@ export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
+ export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
+ export KBUILD_ARFLAGS
+ 
++export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGINS_AFLAGS
++
+ # When compiling out-of-tree modules, put MODVERDIR in the module
+ # tree rather than in the kernel tree. The kernel tree might
+ # even be read-only.
+@@ -547,7 +551,7 @@ ifeq ($(KBUILD_EXTMOD),)
+ # in parallel
+ PHONY += scripts
+ scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
+-	 asm-generic
++	 asm-generic gcc-plugins
+ 	$(Q)$(MAKE) $(build)=$(@)
+ 
+ # Objects we will link into vmlinux / subdirs we need to visit
+@@ -622,6 +626,15 @@ endif
  # Tell gcc to never replace conditional load with a non-conditional one
  KBUILD_CFLAGS	+= $(call cc-option,--param=allow-store-data-races=0)
  
++PHONY += gcc-plugins
++gcc-plugins: scripts_basic
++ifdef CONFIG_GCC_PLUGINS
++	$(Q)$(MAKE) $(build)=scripts/gcc-plugins
++endif
++	@:
++
 +include scripts/Makefile.gcc-plugins
 +
  ifdef CONFIG_READABLE_ASM
  # Disable optimizations that make assembler listings hard to read.
  # reorder blocks reorders the control in the function
-@@ -714,7 +718,7 @@ KBUILD_CFLAGS   += $(call cc-option, -gsplit-dwarf, -g)
+@@ -714,7 +727,7 @@ KBUILD_CFLAGS   += $(call cc-option, -gsplit-dwarf, -g)
  else
  KBUILD_CFLAGS	+= -g
  endif
@@ -451,7 +465,7 @@ index a23df41..314f8da 100644
  endif
  ifdef CONFIG_DEBUG_INFO_DWARF4
  KBUILD_CFLAGS	+= $(call cc-option, -gdwarf-4,)
-@@ -886,7 +890,7 @@ export mod_sign_cmd
+@@ -886,7 +899,7 @@ export mod_sign_cmd
  
  
  ifeq ($(KBUILD_EXTMOD),)
@@ -460,57 +474,16 @@ index a23df41..314f8da 100644
  
  vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
  		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
-@@ -937,6 +941,8 @@ endif
- 
- # The actual objects are generated when descending,
- # make sure no implicit rule kicks in
-+$(filter-out $(init-y),$(vmlinux-deps)): KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+$(filter-out $(init-y),$(vmlinux-deps)): KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
- $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
- 
- # Handle descending into subdirectories listed in $(vmlinux-dirs)
-@@ -946,7 +952,7 @@ $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
- # Error messages still appears in the original language
- 
- PHONY += $(vmlinux-dirs)
--$(vmlinux-dirs): prepare scripts
-+$(vmlinux-dirs): gcc-plugins prepare scripts
- 	$(Q)$(MAKE) $(build)=$@
- 
- define filechk_kernel.release
-@@ -989,10 +995,13 @@ prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
+@@ -989,7 +1002,7 @@ prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
  
  archprepare: archheaders archscripts prepare1 scripts_basic
  
-+prepare0: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+prepare0: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
- prepare0: archprepare FORCE
+-prepare0: archprepare FORCE
++prepare0: archprepare gcc-plugins FORCE
  	$(Q)$(MAKE) $(build)=.
  
  # All the preparing..
-+prepare: KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS))
- prepare: prepare0
- 
- # Generate some files
-@@ -1103,6 +1112,8 @@ all: modules
- # using awk while concatenating to the final file.
- 
- PHONY += modules
-+modules: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+modules: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
- modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
- 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
- 	@$(kecho) '  Building modules, stage 2.';
-@@ -1118,7 +1129,7 @@ modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
- 
- # Target to prepare building external modules
- PHONY += modules_prepare
--modules_prepare: prepare scripts
-+modules_prepare: gcc-plugins prepare scripts
- 
- # Target to install modules
- PHONY += modules_install
-@@ -1184,7 +1195,11 @@ MRPROPER_FILES += .config .config.old .version .old_version \
+@@ -1184,7 +1197,11 @@ MRPROPER_FILES += .config .config.old .version .old_version \
  		  Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
  		  signing_key.pem signing_key.priv signing_key.x509	\
  		  x509.genkey extra_certificates signing_key.x509.keyid	\
@@ -523,7 +496,7 @@ index a23df41..314f8da 100644
  
  # clean - Delete most, but leave enough to build external modules
  #
-@@ -1223,7 +1238,7 @@ distclean: mrproper
+@@ -1223,7 +1240,7 @@ distclean: mrproper
  	@find $(srctree) $(RCS_FIND_IGNORE) \
  		\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
  		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
@@ -532,59 +505,31 @@ index a23df41..314f8da 100644
  		-type f -print | xargs rm -f
  
  
-@@ -1390,6 +1405,8 @@ PHONY += $(module-dirs) modules
- $(module-dirs): crmodverdir $(objtree)/Module.symvers
- 	$(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
+diff --git a/arch/Kconfig b/arch/Kconfig
+index f6b649d..5ba628b 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -353,6 +353,20 @@ config SECCOMP_FILTER
  
-+modules: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+modules: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
- modules: $(module-dirs)
- 	@$(kecho) '  Building modules, stage 2.';
- 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
-@@ -1531,17 +1548,21 @@ else
-         target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
- endif
+ 	  See Documentation/prctl/seccomp_filter.txt for details.
  
--%.s: %.c prepare scripts FORCE
-+%.s: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+%.s: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
-+%.s: %.c gcc-plugins prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
- %.i: %.c prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.o: %.c prepare scripts FORCE
-+%.o: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+%.o: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
-+%.o: %.c gcc-plugins prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
- %.lst: %.c prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.s: %.S prepare scripts FORCE
-+%.s: %.S gcc-plugins prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
--%.o: %.S prepare scripts FORCE
-+%.o: %.S gcc-plugins prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
- %.symtypes: %.c prepare scripts FORCE
- 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
-@@ -1553,11 +1574,15 @@ endif
- 	$(build)=$(build-dir)
- # Make sure the latest headers are built for Documentation
- Documentation/: headers_install
--%/: prepare scripts FORCE
-+%/: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+%/: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
-+%/: gcc-plugins prepare scripts FORCE
- 	$(cmd_crmodverdir)
- 	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
- 	$(build)=$(build-dir)
--%.ko: prepare scripts FORCE
-+%.ko: KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
-+%.ko: KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
-+%.ko: gcc-plugins prepare scripts FORCE
- 	$(cmd_crmodverdir)
- 	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
- 	$(build)=$(build-dir) $(@:.ko=.o)
++config HAVE_GCC_PLUGINS
++	bool
++	help
++	  An arch should select this symbol if it supports building with
++	  GCC plugins.
++
++menuconfig GCC_PLUGINS
++	bool "GCC plugins"
++	depends on HAVE_GCC_PLUGINS
++	default y
++	help
++	  GCC plugins are loadable modules that provide extra features to the
++	  compiler. They are useful for runtime instrumentation and static analysis.
++
+ config HAVE_CC_STACKPROTECTOR
+ 	bool
+ 	help
 diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
 index 572b228..e03acdd 100644
 --- a/arch/alpha/include/asm/atomic.h
@@ -928,10 +873,18 @@ index 8a188bc..26608f1 100644
  	  Counts number of I and D TLB Misses and exports them via Debugfs
  	  The counters can be cleared via Debugfs as well
 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 4f799e5..cc1200e 100644
+index 4f799e5..c1e2b95 100644
 --- a/arch/arm/Kconfig
 +++ b/arch/arm/Kconfig
-@@ -1622,6 +1622,7 @@ config HIGHPTE
+@@ -53,6 +53,7 @@ config ARM
+ 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
+ 	select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
+ 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
++	select HAVE_GCC_PLUGINS
+ 	select HAVE_GENERIC_DMA_COHERENT
+ 	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
+ 	select HAVE_IDE if PCI || ISA || PCMCIA
+@@ -1622,6 +1623,7 @@ config HIGHPTE
  config CPU_SW_DOMAIN_PAN
  	bool "Enable use of CPU domains to implement privileged no-access"
  	depends on MMU && !ARM_LPAE
@@ -939,7 +892,7 @@ index 4f799e5..cc1200e 100644
  	default y
  	help
  	  Increase kernel security by ensuring that normal kernel accesses
-@@ -1698,7 +1699,7 @@ config ALIGNMENT_TRAP
+@@ -1698,7 +1700,7 @@ config ALIGNMENT_TRAP
  
  config UACCESS_WITH_MEMCPY
  	bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user()"
@@ -948,7 +901,7 @@ index 4f799e5..cc1200e 100644
  	default y if CPU_FEROCEON
  	help
  	  Implement faster copy_to_user and clear_user methods for CPU
-@@ -1953,6 +1954,7 @@ config KEXEC
+@@ -1953,6 +1955,7 @@ config KEXEC
  	depends on (!SMP || PM_SLEEP_SMP)
  	depends on !CPU_V7M
  	select KEXEC_CORE
@@ -956,7 +909,7 @@ index 4f799e5..cc1200e 100644
  	help
  	  kexec is a system call that implements the ability to shutdown your
  	  current kernel, and to start another kernel.  It is like a reboot
-@@ -1997,7 +1999,7 @@ config EFI_STUB
+@@ -1997,7 +2000,7 @@ config EFI_STUB
  
  config EFI
  	bool "UEFI runtime support"
@@ -977,6 +930,19 @@ index c6b6175..2884505 100644
  	---help---
  	  Say Y here if you want to show the kernel pagetable layout in a
  	  debugfs file. This information is only useful for kernel developers
+diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
+index 43788b1..2efefcf 100644
+--- a/arch/arm/boot/compressed/Makefile
++++ b/arch/arm/boot/compressed/Makefile
+@@ -106,6 +106,8 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS)
+ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
+ endif
+ 
++KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS))
++
+ # -fstack-protector-strong triggers protection checks in this code,
+ # but it is being used too early to link to meaningful stack_chk logic.
+ nossp_flags := $(call cc-option, -fno-stack-protector)
 diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
 index 9e10c45..24a14ce 100644
 --- a/arch/arm/include/asm/atomic.h
@@ -3357,7 +3323,7 @@ index 6bd1089..e999400 100644
  {
  	unsigned long ua_flags;
 diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
-index c169cc3..f290a77 100644
+index c169cc3..b007ec6 100644
 --- a/arch/arm/mach-exynos/suspend.c
 +++ b/arch/arm/mach-exynos/suspend.c
 @@ -734,8 +734,10 @@ void __init exynos_pm_init(void)
@@ -3367,8 +3333,8 @@ index c169cc3..f290a77 100644
 -	exynos_pm_syscore_ops.suspend	= pm_data->pm_suspend;
 -	exynos_pm_syscore_ops.resume	= pm_data->pm_resume;
 +	pax_open_kernel();
-+	*(void **)&exynos_pm_syscore_ops.suspend	= pm_data->pm_suspend;
-+	*(void **)&exynos_pm_syscore_ops.resume	= pm_data->pm_resume;
++	const_cast(exynos_pm_syscore_ops.suspend)	= pm_data->pm_suspend;
++	const_cast(exynos_pm_syscore_ops.resume)	= pm_data->pm_resume;
 +	pax_close_kernel();
  
  	register_syscore_ops(&exynos_pm_syscore_ops);
@@ -3501,7 +3467,7 @@ index 2af6ff6..1f2959f 100644
  /* omap_hwmod_list contains all registered struct omap_hwmods */
  static LIST_HEAD(omap_hwmod_list);
 diff --git a/arch/arm/mach-omap2/powerdomains43xx_data.c b/arch/arm/mach-omap2/powerdomains43xx_data.c
-index 95fee54..cfa9cf1 100644
+index 95fee54..b5dd79d 100644
 --- a/arch/arm/mach-omap2/powerdomains43xx_data.c
 +++ b/arch/arm/mach-omap2/powerdomains43xx_data.c
 @@ -10,6 +10,7 @@
@@ -3518,7 +3484,7 @@ index 95fee54..cfa9cf1 100644
  {
 -	omap4_pwrdm_operations.pwrdm_has_voltdm = am43xx_check_vcvp;
 +	pax_open_kernel();
-+	*(void **)&omap4_pwrdm_operations.pwrdm_has_voltdm = am43xx_check_vcvp;
++	const_cast(omap4_pwrdm_operations.pwrdm_has_voltdm) = am43xx_check_vcvp;
 +	pax_close_kernel();
  	pwrdm_register_platform_funcs(&omap4_pwrdm_operations);
  	pwrdm_register_pwrdms(powerdomains_am43xx);
@@ -3548,7 +3514,7 @@ index ff0a68c..b312aa0 100644
  				 sizeof(struct omap_wd_timer_platform_data));
  	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
-index aba75c8..b55a9d7 100644
+index aba75c8..b2b340f 100644
 --- a/arch/arm/mach-shmobile/platsmp-apmu.c
 +++ b/arch/arm/mach-shmobile/platsmp-apmu.c
 @@ -22,6 +22,7 @@
@@ -3565,7 +3531,7 @@ index aba75c8..b55a9d7 100644
  {
 -	shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
 +	pax_open_kernel();
-+	*(void **)&shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
++	const_cast(shmobile_suspend_ops.enter) = shmobile_smp_apmu_enter_suspend;
 +	pax_close_kernel();
  }
  #endif
@@ -3727,7 +3693,7 @@ index c8c8b9e..c55cc79 100644
  		atomic64_set(&mm->context.id, asid);
  	}
 diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
-index daafcf1..8205ed6 100644
+index daafcf1..a04e1fd 100644
 --- a/arch/arm/mm/fault.c
 +++ b/arch/arm/mm/fault.c
 @@ -25,6 +25,7 @@
@@ -3841,7 +3807,7 @@ index daafcf1..8205ed6 100644
  	pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n",
  		inf->name, fsr, addr);
  	show_pte(current->mm, addr);
-@@ -574,15 +647,104 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *
+@@ -574,15 +647,118 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *
  	ifsr_info[nr].name = name;
  }
  
@@ -3879,6 +3845,13 @@ index daafcf1..8205ed6 100644
 +			 */
 +			// dmb(); implied by the exception
 +			regs->ARM_pc = regs->ARM_lr;
++#ifdef CONFIG_ARM_THUMB
++			if (regs->ARM_lr & 1) {
++				regs->ARM_cpsr |= PSR_T_BIT;
++				regs->ARM_pc &= ~0x1U;
++			} else
++				regs->ARM_cpsr &= ~PSR_T_BIT;
++#endif
 +			return;
 +		}
 +		if (pc == 0xffff0fc0UL) {
@@ -3901,6 +3874,13 @@ index daafcf1..8205ed6 100644
 +			 */
 +			regs->ARM_r0 = current_thread_info()->tp_value[0];
 +			regs->ARM_pc = regs->ARM_lr;
++#ifdef CONFIG_ARM_THUMB
++			if (regs->ARM_lr & 1) {
++				regs->ARM_cpsr |= PSR_T_BIT;
++				regs->ARM_pc &= ~0x1U;
++			} else
++				regs->ARM_cpsr &= ~PSR_T_BIT;
++#endif
 +			return;
 +		}
 +	}
@@ -4655,6 +4635,18 @@ index a5bc92d..0bb4730 100644
  		  omap_sram_size - omap_sram_skip);
 +	pax_close_kernel();
  }
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 8cc6228..6d6e4f8 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -70,6 +70,7 @@ config ARM64
+ 	select HAVE_FTRACE_MCOUNT_RECORD
+ 	select HAVE_FUNCTION_TRACER
+ 	select HAVE_FUNCTION_GRAPH_TRACER
++	select HAVE_GCC_PLUGINS
+ 	select HAVE_GENERIC_DMA_COHERENT
+ 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
+ 	select HAVE_IRQ_TIME_ACCOUNTING
 diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
 index e13c4bf..3feaea7 100644
 --- a/arch/arm64/Kconfig.debug
@@ -5602,10 +5594,18 @@ index 4efe96a..60e8699 100644
  #define SMP_CACHE_BYTES	L1_CACHE_BYTES
  
 diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
-index d3da79d..e607104 100644
+index d3da79d..e317c97 100644
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -2656,6 +2656,7 @@ source "kernel/Kconfig.preempt"
+@@ -49,6 +49,7 @@ config MIPS
+ 	select GENERIC_CMOS_UPDATE
+ 	select HAVE_MOD_ARCH_SPECIFIC
+ 	select VIRT_TO_BUS
++	select HAVE_GCC_PLUGINS
+ 	select MODULES_USE_ELF_REL if MODULES
+ 	select MODULES_USE_ELF_RELA if MODULES && 64BIT
+ 	select CLONE_BACKWARDS
+@@ -2656,6 +2657,7 @@ source "kernel/Kconfig.preempt"
  config KEXEC
  	bool "Kexec system call"
  	select KEXEC_CORE
@@ -7607,10 +7607,18 @@ index f906444..0bb73ae 100644
  	/*
  	 * If for any reason at all we couldn't handle the fault, make
 diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
-index 9faa18c..6061610 100644
+index 9faa18c..b24277a 100644
 --- a/arch/powerpc/Kconfig
 +++ b/arch/powerpc/Kconfig
-@@ -419,6 +419,7 @@ config KEXEC
+@@ -143,6 +143,7 @@ config PPC
+ 	select ARCH_USE_BUILTIN_BSWAP
+ 	select OLD_SIGSUSPEND
+ 	select OLD_SIGACTION if PPC32
++	select HAVE_GCC_PLUGINS
+ 	select HAVE_DEBUG_STACKOVERFLOW
+ 	select HAVE_IRQ_EXIT_ON_IRQ_STACK
+ 	select ARCH_USE_CMPXCHG_LOCKREF if PPC64
+@@ -419,6 +420,7 @@ config KEXEC
  	bool "kexec system call"
  	depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) || PPC_BOOK3E
  	select KEXEC_CORE
@@ -7619,7 +7627,7 @@ index 9faa18c..6061610 100644
  	  kexec is a system call that implements the ability to shutdown your
  	  current kernel, and to start another kernel.  It is like a reboot
 diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
-index 55f106e..70cc82a 100644
+index 55f106e..5968afb 100644
 --- a/arch/powerpc/include/asm/atomic.h
 +++ b/arch/powerpc/include/asm/atomic.h
 @@ -12,6 +12,11 @@
@@ -7886,19 +7894,7 @@ index 55f106e..70cc82a 100644
  	PPC_ATOMIC_EXIT_BARRIER
  "	subf	%0,%2,%0 \n\
  2:"
-@@ -252,6 +299,11 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
- }
- #define atomic_dec_if_positive atomic_dec_if_positive
- 
-+#define smp_mb__before_atomic_dec()     smp_mb()
-+#define smp_mb__after_atomic_dec()      smp_mb()
-+#define smp_mb__before_atomic_inc()     smp_mb()
-+#define smp_mb__after_atomic_inc()      smp_mb()
-+
- #ifdef __powerpc64__
- 
- #define ATOMIC64_INIT(i)	{ (i) }
-@@ -265,37 +317,60 @@ static __inline__ long atomic64_read(const atomic64_t *v)
+@@ -265,37 +312,60 @@ static __inline__ long atomic64_read(const atomic64_t *v)
  	return t;
  }
  
@@ -7963,7 +7959,7 @@ index 55f106e..70cc82a 100644
  	PPC_ATOMIC_EXIT_BARRIER						\
  	: "=&r" (t)							\
  	: "r" (a), "r" (&v->counter)					\
-@@ -304,6 +379,9 @@ static __inline__ long atomic64_##op##_return(long a, atomic64_t *v)	\
+@@ -304,6 +374,9 @@ static __inline__ long atomic64_##op##_return(long a, atomic64_t *v)	\
  	return t;							\
  }
  
@@ -7973,7 +7969,7 @@ index 55f106e..70cc82a 100644
  #define ATOMIC64_OPS(op, asm_op) ATOMIC64_OP(op, asm_op) ATOMIC64_OP_RETURN(op, asm_op)
  
  ATOMIC64_OPS(add, add)
-@@ -314,40 +392,33 @@ ATOMIC64_OP(xor, xor)
+@@ -314,40 +387,33 @@ ATOMIC64_OP(xor, xor)
  
  #undef ATOMIC64_OPS
  #undef ATOMIC64_OP_RETURN
@@ -8033,7 +8029,7 @@ index 55f106e..70cc82a 100644
  }
  
  /*
-@@ -360,36 +431,18 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
+@@ -360,36 +426,18 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
   */
  #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
  
@@ -8081,7 +8077,7 @@ index 55f106e..70cc82a 100644
  }
  
  #define atomic64_sub_and_test(a, v)	(atomic64_sub_return((a), (v)) == 0)
-@@ -422,6 +475,16 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
+@@ -422,6 +470,16 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
  #define atomic64_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
  #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
  
@@ -8090,7 +8086,7 @@ index 55f106e..70cc82a 100644
 +	return cmpxchg(&(v->counter), old, new);
 +}
 +
-+static inline long atomic64_xchg_unchecked(atomic64_unchecked_t *v, long new) 
++static inline long atomic64_xchg_unchecked(atomic64_unchecked_t *v, long new)
 +{
 +	return xchg(&(v->counter), new);
 +}
@@ -8098,7 +8094,7 @@ index 55f106e..70cc82a 100644
  /**
   * atomic64_add_unless - add unless the number is a given value
   * @v: pointer of type atomic64_t
-@@ -437,13 +500,29 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+@@ -437,13 +495,29 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
  
  	__asm__ __volatile__ (
  	PPC_ATOMIC_ENTRY_BARRIER
@@ -8698,17 +8694,17 @@ index b7c20f0..4adc0f1 100644
  
  static inline unsigned long clear_user(void __user *addr, unsigned long size)
 diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
-index 794f22a..f8de42b 100644
+index 794f22a..9a76447 100644
 --- a/arch/powerpc/kernel/Makefile
 +++ b/arch/powerpc/kernel/Makefile
 @@ -14,6 +14,11 @@ CFLAGS_prom_init.o      += -fPIC
  CFLAGS_btext.o		+= -fPIC
  endif
  
-+CFLAGS_REMOVE_cputable.o = $(LATENT_ENTROPY_PLUGIN_CFLAGS)
-+CFLAGS_REMOVE_prom_init.o = $(LATENT_ENTROPY_PLUGIN_CFLAGS)
-+CFLAGS_REMOVE_btext.o = $(LATENT_ENTROPY_PLUGIN_CFLAGS)
-+CFLAGS_REMOVE_prom.o = $(LATENT_ENTROPY_PLUGIN_CFLAGS)
++CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
++CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
++CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
++CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 +
  ifdef CONFIG_FUNCTION_TRACER
  # Do not trace early boot code
@@ -9678,6 +9674,18 @@ index 6777177..d44b592 100644
  		info.high_limit = TASK_SIZE;
  		addr = vm_unmapped_area(&info);
  	}
+diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
+index 57ffaf2..4d1fe9a 100644
+--- a/arch/sparc/Kconfig
++++ b/arch/sparc/Kconfig
+@@ -39,6 +39,7 @@ config SPARC
+ 	select GENERIC_STRNCPY_FROM_USER
+ 	select GENERIC_STRNLEN_USER
+ 	select MODULES_USE_ELF_RELA
++	select HAVE_GCC_PLUGINS
+ 	select ODD_RT_SIGACTION
+ 	select OLD_SIGSUSPEND
+ 	select ARCH_HAS_SG_CHAIN
 diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
 index f2fbf9e..fea461e 100644
 --- a/arch/sparc/include/asm/atomic_64.h
@@ -12221,16 +12229,14 @@ index c034dc3..cf1cc96 100644
  
  	/*
 diff --git a/arch/um/Makefile b/arch/um/Makefile
-index e3abe6f..ae224ef 100644
+index e3abe6f..33a363c 100644
 --- a/arch/um/Makefile
 +++ b/arch/um/Makefile
-@@ -73,6 +73,10 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
+@@ -73,6 +73,8 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
  		-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
  		-idirafter $(obj)/include -D__KERNEL__ -D__UM_HOST__
  
-+ifdef CONSTIFY_PLUGIN
-+USER_CFLAGS	+= -fplugin-arg-constify_plugin-no-constify
-+endif
++USER_CFLAGS	:= $(filter-out $(GCC_PLUGINS_CFLAGS),$(USER_CFLAGS))
 +
  #This will adjust *FLAGS accordingly to the platform.
  include $(ARCH_DIR)/Makefile-os-$(OS)
@@ -12338,7 +12344,7 @@ index ad8f795..2c7eec6 100644
  /*
   * Memory returned by kmalloc() may be used for DMA, so we must make
 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 3bf45a0..7b04039 100644
+index 3bf45a0..25ca7da 100644
 --- a/arch/x86/Kconfig
 +++ b/arch/x86/Kconfig
 @@ -38,14 +38,13 @@ config X86
@@ -12366,7 +12372,15 @@ index 3bf45a0..7b04039 100644
  	select HAVE_CMPXCHG_DOUBLE
  	select HAVE_CMPXCHG_LOCAL
  	select HAVE_CONTEXT_TRACKING		if X86_64
-@@ -290,7 +289,7 @@ config X86_64_SMP
+@@ -109,6 +108,7 @@ config X86
+ 	select HAVE_FUNCTION_GRAPH_FP_TEST
+ 	select HAVE_FUNCTION_GRAPH_TRACER
+ 	select HAVE_FUNCTION_TRACER
++	select HAVE_GCC_PLUGINS
+ 	select HAVE_GENERIC_DMA_COHERENT	if X86_32
+ 	select HAVE_HW_BREAKPOINT
+ 	select HAVE_IDE
+@@ -290,7 +290,7 @@ config X86_64_SMP
  
  config X86_32_LAZY_GS
  	def_bool y
@@ -12375,7 +12389,7 @@ index 3bf45a0..7b04039 100644
  
  config ARCH_HWEIGHT_CFLAGS
  	string
-@@ -674,6 +673,7 @@ config SCHED_OMIT_FRAME_POINTER
+@@ -674,6 +674,7 @@ config SCHED_OMIT_FRAME_POINTER
  
  menuconfig HYPERVISOR_GUEST
  	bool "Linux guest support"
@@ -12383,7 +12397,7 @@ index 3bf45a0..7b04039 100644
  	---help---
  	  Say Y here to enable options for running Linux under various hyper-
  	  visors. This option enables basic hypervisor detection and platform
-@@ -1073,6 +1073,7 @@ config VM86
+@@ -1073,6 +1074,7 @@ config VM86
  
  config X86_16BIT
  	bool "Enable support for 16-bit segments" if EXPERT
@@ -12391,7 +12405,7 @@ index 3bf45a0..7b04039 100644
  	default y
  	depends on MODIFY_LDT_SYSCALL
  	---help---
-@@ -1227,6 +1228,7 @@ choice
+@@ -1227,6 +1229,7 @@ choice
  
  config NOHIGHMEM
  	bool "off"
@@ -12399,7 +12413,7 @@ index 3bf45a0..7b04039 100644
  	---help---
  	  Linux can use up to 64 Gigabytes of physical memory on x86 systems.
  	  However, the address space of 32-bit x86 processors is only 4
-@@ -1263,6 +1265,7 @@ config NOHIGHMEM
+@@ -1263,6 +1266,7 @@ config NOHIGHMEM
  
  config HIGHMEM4G
  	bool "4GB"
@@ -12407,7 +12421,7 @@ index 3bf45a0..7b04039 100644
  	---help---
  	  Select this if you have a 32-bit processor and between 1 and 4
  	  gigabytes of physical RAM.
-@@ -1315,7 +1318,7 @@ config PAGE_OFFSET
+@@ -1315,7 +1319,7 @@ config PAGE_OFFSET
  	hex
  	default 0xB0000000 if VMSPLIT_3G_OPT
  	default 0x80000000 if VMSPLIT_2G
@@ -12416,7 +12430,7 @@ index 3bf45a0..7b04039 100644
  	default 0x40000000 if VMSPLIT_1G
  	default 0xC0000000
  	depends on X86_32
-@@ -1336,7 +1339,6 @@ config X86_PAE
+@@ -1336,7 +1340,6 @@ config X86_PAE
  
  config ARCH_PHYS_ADDR_T_64BIT
  	def_bool y
@@ -12424,7 +12438,7 @@ index 3bf45a0..7b04039 100644
  
  config ARCH_DMA_ADDR_T_64BIT
  	def_bool y
-@@ -1467,7 +1469,7 @@ config ARCH_PROC_KCORE_TEXT
+@@ -1467,7 +1470,7 @@ config ARCH_PROC_KCORE_TEXT
  
  config ILLEGAL_POINTER_VALUE
         hex
@@ -12433,7 +12447,7 @@ index 3bf45a0..7b04039 100644
         default 0xdead000000000000 if X86_64
  
  source "mm/Kconfig"
-@@ -1776,6 +1778,7 @@ source kernel/Kconfig.hz
+@@ -1776,6 +1779,7 @@ source kernel/Kconfig.hz
  config KEXEC
  	bool "kexec system call"
  	select KEXEC_CORE
@@ -12441,7 +12455,7 @@ index 3bf45a0..7b04039 100644
  	---help---
  	  kexec is a system call that implements the ability to shutdown your
  	  current kernel, and to start another kernel.  It is like a reboot
-@@ -1958,7 +1961,9 @@ config X86_NEED_RELOCS
+@@ -1958,7 +1962,9 @@ config X86_NEED_RELOCS
  
  config PHYSICAL_ALIGN
  	hex "Alignment value to which kernel should be aligned"
@@ -12452,7 +12466,7 @@ index 3bf45a0..7b04039 100644
  	range 0x2000 0x1000000 if X86_32
  	range 0x200000 0x1000000 if X86_64
  	---help---
-@@ -2041,6 +2046,7 @@ config COMPAT_VDSO
+@@ -2041,6 +2047,7 @@ config COMPAT_VDSO
  	def_bool n
  	prompt "Disable the 32-bit vDSO (needed for glibc 2.3.3)"
  	depends on X86_32 || IA32_EMULATION
@@ -12460,7 +12474,7 @@ index 3bf45a0..7b04039 100644
  	---help---
  	  Certain buggy versions of glibc will crash if they are
  	  presented with a 32-bit vDSO that is not mapped at the address
-@@ -2081,15 +2087,6 @@ choice
+@@ -2081,15 +2088,6 @@ choice
  
  	  If unsure, select "Emulate".
  
@@ -12476,7 +12490,7 @@ index 3bf45a0..7b04039 100644
  	config LEGACY_VSYSCALL_EMULATE
  		bool "Emulate"
  		help
-@@ -2170,6 +2167,22 @@ config MODIFY_LDT_SYSCALL
+@@ -2170,6 +2168,22 @@ config MODIFY_LDT_SYSCALL
  
  	  Saying 'N' here may make sense for embedded or server kernels.
  
@@ -12610,20 +12624,6 @@ index 4086abc..52a0a9b 100644
 +*** ${VERSION}.${PATCHLEVEL} PaX kernels no longer build correctly with old versions of binutils.
 +*** Please upgrade your binutils to 2.18 or newer
 +endef
-diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
-index bbe1a62..ec6a3ec 100644
---- a/arch/x86/boot/Makefile
-+++ b/arch/x86/boot/Makefile
-@@ -58,6 +58,9 @@ clean-files += cpustr.h
- # ---------------------------------------------------------------------------
- 
- KBUILD_CFLAGS	:= $(USERINCLUDE) $(REALMODE_CFLAGS) -D_SETUP
-+ifdef CONSTIFY_PLUGIN
-+KBUILD_CFLAGS	+= -fplugin-arg-constify_plugin-no-constify
-+endif
- KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
- GCOV_PROFILE := n
- UBSAN_SANITIZE := n
 diff --git a/arch/x86/boot/bitops.h b/arch/x86/boot/bitops.h
 index 878e4b9..20537ab 100644
 --- a/arch/x86/boot/bitops.h
@@ -12660,17 +12660,13 @@ index 9011a88..06aa820 100644
  }
  
 diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
-index f9ce75d..0b1600d 100644
+index f9ce75d..245ea76 100644
 --- a/arch/x86/boot/compressed/Makefile
 +++ b/arch/x86/boot/compressed/Makefile
-@@ -30,6 +30,26 @@ KBUILD_CFLAGS += $(cflags-y)
- KBUILD_CFLAGS += -mno-mmx -mno-sse
+@@ -31,6 +31,23 @@ KBUILD_CFLAGS += -mno-mmx -mno-sse
  KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
  KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
-+ifdef CONSTIFY_PLUGIN
-+KBUILD_CFLAGS += -fplugin-arg-constify_plugin-no-constify
-+endif
-+
+ 
 +ifdef CONFIG_DEBUG_INFO
 +ifdef CONFIG_DEBUG_INFO_SPLIT
 +KBUILD_CFLAGS   += $(call cc-option, -gsplit-dwarf, -g)
@@ -12687,9 +12683,10 @@ index f9ce75d..0b1600d 100644
 +KBUILD_CFLAGS 	+= $(call cc-option, -femit-struct-debug-baseonly) \
 +		   $(call cc-option,-fno-var-tracking)
 +endif
- 
++
  KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
  GCOV_PROFILE := n
+ UBSAN_SANITIZE :=n
 diff --git a/arch/x86/boot/compressed/efi_stub_32.S b/arch/x86/boot/compressed/efi_stub_32.S
 index a53440e..c3dbf1e 100644
 --- a/arch/x86/boot/compressed/efi_stub_32.S
@@ -15756,7 +15753,7 @@ index e32206e0..809adae 100644
  
  	.macro REMOVE_PT_GPREGS_FROM_STACK addskip=0
 diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
-index 1a4477c..95199ec4 100644
+index 1a4477c..7061819 100644
 --- a/arch/x86/entry/common.c
 +++ b/arch/x86/entry/common.c
 @@ -32,9 +32,7 @@
@@ -15869,7 +15866,7 @@ index 1a4477c..95199ec4 100644
 +			  [param4] "m" (regs->si),
 +			  [param5] "m" (regs->di),
 +			  [param6] "m" (regs->bp)
-+			: "di", "si", "dx", "cx", "r8", "r9", "memory");
++			: "ax", "di", "si", "dx", "cx", "r8", "r9", "r10", "r11", "memory");
 +#else
 +		asm volatile("pushl %[param6]\n\t"
 +			     "pushl %[param5]\n\t"
@@ -22879,7 +22876,7 @@ index 82c34ee..940fa40 100644
  				unsigned, unsigned, unsigned);
  
 diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
-index c7b5510..2ab8977 100644
+index c7b5510..f6d5ca4 100644
 --- a/arch/x86/include/asm/thread_info.h
 +++ b/arch/x86/include/asm/thread_info.h
 @@ -39,7 +39,7 @@
@@ -22961,7 +22958,7 @@ index c7b5510..2ab8977 100644
  }
  
  static inline unsigned long current_stack_pointer(void)
-@@ -179,14 +182,9 @@ static inline unsigned long current_stack_pointer(void)
+@@ -179,41 +182,9 @@ static inline unsigned long current_stack_pointer(void)
  
  #else /* !__ASSEMBLY__ */
  
@@ -22973,11 +22970,38 @@ index c7b5510..2ab8977 100644
  #define GET_THREAD_INFO(reg) \
 -	_ASM_MOV PER_CPU_VAR(cpu_current_top_of_stack),reg ; \
 -	_ASM_SUB $(THREAD_SIZE),reg ;
+-
+-/*
+- * ASM operand which evaluates to a 'thread_info' address of
+- * the current task, if it is known that "reg" is exactly "off"
+- * bytes below the top of the stack currently.
+- *
+- * ( The kernel stack's size is known at build time, it is usually
+- *   2 or 4 pages, and the bottom  of the kernel stack contains
+- *   the thread_info structure. So to access the thread_info very
+- *   quickly from assembly code we can calculate down from the
+- *   top of the kernel stack to the bottom, using constant,
+- *   build-time calculations only. )
+- *
+- * For example, to fetch the current thread_info->flags value into %eax
+- * on x86-64 defconfig kernels, in syscall entry code where RSP is
+- * currently at exactly SIZEOF_PTREGS bytes away from the top of the
+- * stack:
+- *
+- *      mov ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS), %eax
+- *
+- * will translate to:
+- *
+- *      8b 84 24 b8 c0 ff ff      mov    -0x3f48(%rsp), %eax
+- *
+- * which is below the current RSP by almost 16K.
+- */
+-#define ASM_THREAD_INFO(field, reg, off) ((field)+(off)-THREAD_SIZE)(reg)
 +	_ASM_MOV PER_CPU_VAR(current_tinfo),reg ;
  
- /*
-  * ASM operand which evaluates to a 'thread_info' address of
-@@ -279,5 +277,12 @@ static inline bool is_ia32_task(void)
+ #endif
+ 
+@@ -279,5 +250,12 @@ static inline bool is_ia32_task(void)
  extern void arch_task_cache_init(void);
  extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
  extern void arch_release_task_struct(struct task_struct *tsk);
@@ -25722,7 +25746,7 @@ index 2cad71d..5f1baf2 100644
  	__bts_event_stop(event);
  
 diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
-index a316ca9..99344f4 100644
+index a316ca9..07e219e 100644
 --- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c
 +++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
 @@ -1364,7 +1364,9 @@ static int __init intel_cqm_init(void)
@@ -25731,7 +25755,7 @@ index a316ca9..99344f4 100644
  
 -	event_attr_intel_cqm_llc_scale.event_str = str;
 +	pax_open_kernel();
-+	*(const char **)&event_attr_intel_cqm_llc_scale.event_str = str;
++	const_cast(event_attr_intel_cqm_llc_scale.event_str) = str;
 +	pax_close_kernel();
  
  	ret = intel_cqm_setup_rmid_cache();
@@ -25798,7 +25822,7 @@ index 653f88d..11b6b78 100644
  	if (!insn.opcode.got)
  		return X86_BR_ABORT;
 diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
-index c0bbd10..727ae15e 100644
+index c0bbd10..53a5dc6 100644
 --- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
 +++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
 @@ -133,14 +133,10 @@ static const struct attribute_group *pt_attr_groups[] = {
@@ -25839,22 +25863,22 @@ index c0bbd10..727ae15e 100644
 +		struct dev_ext_attribute *de_attr = &de_attrs[i];
  
 -		de_attr->attr.attr.name = pt_caps[i].name;
-+		*(const char **)&de_attr->attr.attr.name = pt_caps[i].name;
++		const_cast(de_attr->attr.attr.name) = pt_caps[i].name;
  
  		sysfs_attr_init(&de_attr->attr.attr);
  
 -		de_attr->attr.attr.mode		= S_IRUGO;
 -		de_attr->attr.show		= pt_cap_show;
 -		de_attr->var			= (void *)i;
-+		*(umode_t *)&de_attr->attr.attr.mode	= S_IRUGO;
-+		*(void **)&de_attr->attr.show		= pt_cap_show;
-+		*(void **)&de_attr->var			= (void *)i;
++		const_cast(de_attr->attr.attr.mode)	= S_IRUGO;
++		const_cast(de_attr->attr.show)		= pt_cap_show;
++		const_cast(de_attr->var)		= (void *)i;
  
  		attrs[i] = &de_attr->attr.attr;
  	}
  
 -	pt_cap_group.attrs = attrs;
-+	*(struct attribute ***)&pt_cap_group.attrs = attrs;
++	const_cast(pt_cap_group.attrs) = attrs;
 +	pax_close_kernel();
  
  	return 0;
@@ -27813,7 +27837,7 @@ index 64341aa..b1e6632 100644
 +EXPORT_SYMBOL(cpu_pgd);
 +#endif
 diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
-index be22f5a..c5d0e1f 100644
+index be22f5a..a04fa14 100644
 --- a/arch/x86/kernel/i8259.c
 +++ b/arch/x86/kernel/i8259.c
 @@ -110,7 +110,7 @@ static int i8259A_irq_pending(unsigned int irq)
@@ -27845,10 +27869,10 @@ index be22f5a..c5d0e1f 100644
  		 * when acking.
  		 */
 -		i8259A_chip.irq_mask_ack = disable_8259A_irq;
-+		*(void **)&i8259A_chip.irq_mask_ack = disable_8259A_irq;
++		const_cast(i8259A_chip.irq_mask_ack) = disable_8259A_irq;
  	else
 -		i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
-+		*(void **)&i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
++		const_cast(i8259A_chip.irq_mask_ack) = mask_and_ack_8259A;
 +	pax_close_kernel();
  
  	udelay(100);		/* wait for 8259A to initialize */
@@ -29041,7 +29065,7 @@ index 6d9582e..f746287 100644
  		return;
  	}
 diff --git a/arch/x86/kernel/paravirt-spinlocks.c b/arch/x86/kernel/paravirt-spinlocks.c
-index 33ee3e0..ca43dee 100644
+index 33ee3e0..6d23e5c 100644
 --- a/arch/x86/kernel/paravirt-spinlocks.c
 +++ b/arch/x86/kernel/paravirt-spinlocks.c
 @@ -23,16 +23,32 @@ bool pv_is_native_spin_unlock(void)
@@ -29058,7 +29082,7 @@ index 33ee3e0..ca43dee 100644
 +static void native_kick(int cpu)
 +{
 +}
-+//#else /* !CONFIG_QUEUED_SPINLOCKS */
++#else /* !CONFIG_QUEUED_SPINLOCKS */
 +static void native_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
 +{
 +}
@@ -37439,7 +37463,7 @@ index 4e664bd..2beeaa2 100644
  		return NULL;
  
 diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
-index 1d2e639..d7f0e67 100644
+index 1d2e639..6473b8a 100644
 --- a/arch/x86/oprofile/nmi_int.c
 +++ b/arch/x86/oprofile/nmi_int.c
 @@ -23,6 +23,7 @@
@@ -37467,14 +37491,14 @@ index 1d2e639..d7f0e67 100644
 -		model->num_virt_counters = model->num_counters;
 +	if (!model->num_virt_counters) {
 +		pax_open_kernel();
-+		*(unsigned int *)&model->num_virt_counters = model->num_counters;
++		const_cast(model->num_virt_counters) = model->num_counters;
 +		pax_close_kernel();
 +	}
  
  	mux_init(ops);
  
 diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
-index 50d86c0..7985318 100644
+index 50d86c0..b0b9ae0 100644
 --- a/arch/x86/oprofile/op_model_amd.c
 +++ b/arch/x86/oprofile/op_model_amd.c
 @@ -519,9 +519,11 @@ static int op_amd_init(struct oprofile_operations *ops)
@@ -37485,15 +37509,15 @@ index 50d86c0..7985318 100644
 -	op_amd_spec.num_controls = num_counters;
 -	op_amd_spec.num_virt_counters = max(num_counters, NUM_VIRT_COUNTERS);
 +	pax_open_kernel();
-+	*(unsigned int *)&op_amd_spec.num_counters = num_counters;
-+	*(unsigned int *)&op_amd_spec.num_controls = num_counters;
-+	*(unsigned int *)&op_amd_spec.num_virt_counters = max(num_counters, NUM_VIRT_COUNTERS);
++	const_cast(op_amd_spec.num_counters) = num_counters;
++	const_cast(op_amd_spec.num_controls) = num_counters;
++	const_cast(op_amd_spec.num_virt_counters) = max(num_counters, NUM_VIRT_COUNTERS);
 +	pax_close_kernel();
  
  	return 0;
  }
 diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
-index d90528e..0127e2b 100644
+index d90528e..a44aa09 100644
 --- a/arch/x86/oprofile/op_model_ppro.c
 +++ b/arch/x86/oprofile/op_model_ppro.c
 @@ -19,6 +19,7 @@
@@ -37511,8 +37535,8 @@ index d90528e..0127e2b 100644
 -	op_arch_perfmon_spec.num_counters = num_counters;
 -	op_arch_perfmon_spec.num_controls = num_counters;
 +	pax_open_kernel();
-+	*(unsigned int *)&op_arch_perfmon_spec.num_counters = num_counters;
-+	*(unsigned int *)&op_arch_perfmon_spec.num_controls = num_counters;
++	const_cast(op_arch_perfmon_spec.num_counters) = num_counters;
++	const_cast(op_arch_perfmon_spec.num_controls) = num_counters;
 +	pax_close_kernel();
  }
  
@@ -37808,7 +37832,7 @@ index 9770e55..76067ec 100644
  }
  EXPORT_SYMBOL(pcibios_set_irq_routing);
 diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
-index d57e480..20eb97a 100644
+index d57e480..fc4db30 100644
 --- a/arch/x86/pci/vmd.c
 +++ b/arch/x86/pci/vmd.c
 @@ -374,7 +374,7 @@ static void vmd_teardown_dma_ops(struct vmd_dev *vmd)
@@ -37816,7 +37840,7 @@ index d57e480..20eb97a 100644
  	do {					\
  		if (source->fn)			\
 -			dest->fn = vmd_##fn;	\
-+			*(void **)&dest->fn = vmd_##fn;	\
++			const_cast(dest->fn) = vmd_##fn;	\
  	} while (0)
  
  static void vmd_setup_dma_ops(struct vmd_dev *vmd)
@@ -38238,20 +38262,6 @@ index 0b7a63d..dff2199 100644
  	trampoline_pgd[511] = init_level4_pgt[511].pgd;
  #endif
  }
-diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
-index 3e75fcf..4cfefb8 100644
---- a/arch/x86/realmode/rm/Makefile
-+++ b/arch/x86/realmode/rm/Makefile
-@@ -68,6 +68,9 @@ $(obj)/realmode.relocs: $(obj)/realmode.elf FORCE
- 
- KBUILD_CFLAGS	:= $(LINUXINCLUDE) $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \
- 		   -I$(srctree)/arch/x86/boot
-+ifdef CONSTIFY_PLUGIN
-+KBUILD_CFLAGS	+= -fplugin-arg-constify_plugin-no-constify
-+endif
- KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
- GCOV_PROFILE := n
- UBSAN_SANITIZE := n
 diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
 index a28221d..93c40f1 100644
 --- a/arch/x86/realmode/rm/header.S
@@ -39659,7 +39669,7 @@ index b719ab3..371e2a6 100644
  enum acpi_battery_files {
  	info_tag = 0,
 diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
-index a83e3c6..c3d617f 100644
+index a83e3c6..7f4a90b 100644
 --- a/drivers/acpi/bgrt.c
 +++ b/drivers/acpi/bgrt.c
 @@ -86,8 +86,10 @@ static int __init bgrt_init(void)
@@ -39669,8 +39679,8 @@ index a83e3c6..c3d617f 100644
 -	bin_attr_image.private = bgrt_image;
 -	bin_attr_image.size = bgrt_image_size;
 +	pax_open_kernel();
-+	*(void **)&bin_attr_image.private = bgrt_image;
-+	*(size_t *)&bin_attr_image.size = bgrt_image_size;
++	const_cast(bin_attr_image.private) = bgrt_image;
++	const_cast(bin_attr_image.size) = bgrt_image_size;
 +	pax_close_kernel();
  
  	bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
@@ -39966,7 +39976,7 @@ index 7d00b7a..d5fd80d 100644
  	int ret;
  
 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index 55e257c..28b9a25 100644
+index 55e257c..554c697 100644
 --- a/drivers/ata/libata-core.c
 +++ b/drivers/ata/libata-core.c
 @@ -103,7 +103,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
@@ -40009,7 +40019,7 @@ index 55e257c..28b9a25 100644
  			*pp = NULL;
  
 -	ops->inherits = NULL;
-+	*(struct ata_port_operations **)&ops->inherits = NULL;
++	const_cast(ops->inherits) = NULL;
  
 +	pax_close_kernel();
  	spin_unlock(&lock);
@@ -40051,7 +40061,7 @@ index f840ca1..edd6ef3 100644
  extern int libata_fua;
  extern int libata_noacpi;
 diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
-index 80fe0f6..8c0fa3f 100644
+index 80fe0f6..d95a192 100644
 --- a/drivers/ata/pata_arasan_cf.c
 +++ b/drivers/ata/pata_arasan_cf.c
 @@ -864,7 +864,9 @@ static int arasan_cf_probe(struct platform_device *pdev)
@@ -40060,7 +40070,7 @@ index 80fe0f6..8c0fa3f 100644
  		if (quirk & CF_BROKEN_PIO) {
 -			ap->ops->set_piomode = NULL;
 +			pax_open_kernel();
-+			*(void **)&ap->ops->set_piomode = NULL;
++			const_cast(ap->ops->set_piomode) = NULL;
 +			pax_close_kernel();
  			ap->pio_mask = 0;
  		}
@@ -41138,7 +41148,7 @@ index 560751b..3a4847a 100644
  static ssize_t show_node_state(struct device *dev,
  			       struct device_attribute *attr, char *buf)
 diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
-index 279e539..b87ed03 100644
+index 279e539..4c9d7fb 100644
 --- a/drivers/base/platform-msi.c
 +++ b/drivers/base/platform-msi.c
 @@ -24,6 +24,8 @@
@@ -41157,10 +41167,10 @@ index 279e539..b87ed03 100644
 +	pax_open_kernel();
  	if (ops->msi_init == NULL)
 -		ops->msi_init = platform_msi_init;
-+		*(void **)&ops->msi_init = platform_msi_init;
++		const_cast(ops->msi_init) = platform_msi_init;
  	if (ops->set_desc == NULL)
 -		ops->set_desc = platform_msi_set_desc;
-+		*(void **)&ops->set_desc = platform_msi_set_desc;
++		const_cast(ops->set_desc) = platform_msi_set_desc;
 +	pax_close_kernel();
  }
  
@@ -41172,25 +41182,25 @@ index 279e539..b87ed03 100644
 +	pax_open_kernel();
  	if (!chip->irq_mask)
 -		chip->irq_mask = irq_chip_mask_parent;
-+		*(void **)&chip->irq_mask = irq_chip_mask_parent;
++		const_cast(chip->irq_mask) = irq_chip_mask_parent;
  	if (!chip->irq_unmask)
 -		chip->irq_unmask = irq_chip_unmask_parent;
-+		*(void **)&chip->irq_unmask = irq_chip_unmask_parent;
++		const_cast(chip->irq_unmask) = irq_chip_unmask_parent;
  	if (!chip->irq_eoi)
 -		chip->irq_eoi = irq_chip_eoi_parent;
-+		*(void **)&chip->irq_eoi = irq_chip_eoi_parent;
++		const_cast(chip->irq_eoi) = irq_chip_eoi_parent;
  	if (!chip->irq_set_affinity)
 -		chip->irq_set_affinity = msi_domain_set_affinity;
-+		*(void **)&chip->irq_set_affinity = msi_domain_set_affinity;
++		const_cast(chip->irq_set_affinity) = msi_domain_set_affinity;
  	if (!chip->irq_write_msi_msg)
 -		chip->irq_write_msi_msg = platform_msi_write_msg;
-+		*(void **)&chip->irq_write_msi_msg = platform_msi_write_msg;
++		const_cast(chip->irq_write_msi_msg) = platform_msi_write_msg;
 +	pax_close_kernel();
  }
  
  static void platform_msi_free_descs(struct device *dev, int base, int nvec)
 diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
-index 0caf92a..cff4879 100644
+index 0caf92a..62c184c 100644
 --- a/drivers/base/power/domain.c
 +++ b/drivers/base/power/domain.c
 @@ -1804,8 +1804,10 @@ int genpd_dev_pm_attach(struct device *dev)
@@ -41200,8 +41210,8 @@ index 0caf92a..cff4879 100644
 -	dev->pm_domain->detach = genpd_dev_pm_detach;
 -	dev->pm_domain->sync = genpd_dev_pm_sync;
 +	pax_open_kernel();
-+	*(void **)&dev->pm_domain->detach = genpd_dev_pm_detach;
-+	*(void **)&dev->pm_domain->sync = genpd_dev_pm_sync;
++	const_cast(dev->pm_domain->detach) = genpd_dev_pm_detach;
++	const_cast(dev->pm_domain->sync) = genpd_dev_pm_sync;
 +	pax_close_kernel();
  
  	mutex_lock(&pd->lock);
@@ -42349,7 +42359,7 @@ index 24a652f..2dffae6 100644
  	int err;
  
 diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
-index 577cc4b..bfe0c2d 100644
+index 577cc4b..129a13e 100644
 --- a/drivers/bus/arm-cci.c
 +++ b/drivers/bus/arm-cci.c
 @@ -1249,16 +1249,22 @@ static int cci_pmu_init_attrs(struct cci_pmu *cci_pmu, struct platform_device *p
@@ -42358,7 +42368,7 @@ index 577cc4b..bfe0c2d 100644
  			return -ENOMEM;
 -		pmu_event_attr_group.attrs = attrs;
 +		pax_open_kernel();
-+		*(struct attribute ***)&pmu_event_attr_group.attrs = attrs;
++		const_cast(pmu_event_attr_group.attrs) = attrs;
 +		pax_close_kernel();
  	}
  	if (model->nformat_attrs) {
@@ -42368,18 +42378,18 @@ index 577cc4b..bfe0c2d 100644
  			return -ENOMEM;
 -		pmu_format_attr_group.attrs = attrs;
 +		pax_open_kernel();
-+		*(struct attribute ***)&pmu_format_attr_group.attrs = attrs;
++		const_cast(pmu_format_attr_group.attrs) = attrs;
 +		pax_close_kernel();
  	}
 -	pmu_cpumask_attr.var = cci_pmu;
 +	pax_open_kernel();
-+	*(void **)&pmu_cpumask_attr.var = cci_pmu;
++	const_cast(pmu_cpumask_attr.var) = cci_pmu;
 +	pax_close_kernel();
  
  	return 0;
  }
 diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
-index 1b257ea..ea76b22 100644
+index 1b257ea..2280898 100644
 --- a/drivers/cdrom/cdrom.c
 +++ b/drivers/cdrom/cdrom.c
 @@ -610,7 +610,6 @@ int register_cdrom(struct cdrom_device_info *cdi)
@@ -42398,7 +42408,7 @@ index 1b257ea..ea76b22 100644
 -		cdo->generic_packet = cdrom_dummy_generic_packet;
 +	if (!cdo->generic_packet) {
 +		pax_open_kernel();
-+		*(void **)&cdo->generic_packet = cdrom_dummy_generic_packet;
++		const_cast(cdo->generic_packet) = cdrom_dummy_generic_packet;
 +		pax_close_kernel();
 +	}
  
@@ -43150,7 +43160,7 @@ index aa872d2..afeae37 100644
  /**
   * struct samsung_clk_reg_dump: register dump of clock controller registers.
 diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
-index aa7a6e6..e67210d 100644
+index aa7a6e6..1e9b426 100644
 --- a/drivers/clk/socfpga/clk-gate.c
 +++ b/drivers/clk/socfpga/clk-gate.c
 @@ -21,6 +21,7 @@
@@ -43177,14 +43187,14 @@ index aa7a6e6..e67210d 100644
 -		gateclk_ops.enable = clk_gate_ops.enable;
 -		gateclk_ops.disable = clk_gate_ops.disable;
 +		pax_open_kernel();
-+		*(void **)&gateclk_ops.enable = clk_gate_ops.enable;
-+		*(void **)&gateclk_ops.disable = clk_gate_ops.disable;
++		const_cast(gateclk_ops.enable) = clk_gate_ops.enable;
++		const_cast(gateclk_ops.disable) = clk_gate_ops.disable;
 +		pax_close_kernel();
  	}
  
  	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
 diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
-index c7f4631..463813a 100644
+index c7f4631..8d1b7d0 100644
 --- a/drivers/clk/socfpga/clk-pll.c
 +++ b/drivers/clk/socfpga/clk-pll.c
 @@ -20,6 +20,7 @@
@@ -43211,14 +43221,14 @@ index c7f4631..463813a 100644
 -	clk_pll_ops.enable = clk_gate_ops.enable;
 -	clk_pll_ops.disable = clk_gate_ops.disable;
 +	pax_open_kernel();
-+	*(void **)&clk_pll_ops.enable = clk_gate_ops.enable;
-+	*(void **)&clk_pll_ops.disable = clk_gate_ops.disable;
++	const_cast(clk_pll_ops.enable) = clk_gate_ops.enable;
++	const_cast(clk_pll_ops.disable) = clk_gate_ops.disable;
 +	pax_close_kernel();
  
  	clk = clk_register(NULL, &pll_clk->hw.hw);
  	if (WARN_ON(IS_ERR(clk))) {
 diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
-index b5bcd77..0f7bd99 100644
+index b5bcd77..fc230cb 100644
 --- a/drivers/clk/ti/clk.c
 +++ b/drivers/clk/ti/clk.c
 @@ -25,6 +25,8 @@
@@ -43237,14 +43247,14 @@ index b5bcd77..0f7bd99 100644
 -	ops->clk_readl = clk_memmap_readl;
 -	ops->clk_writel = clk_memmap_writel;
 +	pax_open_kernel();
-+	*(void **)&ops->clk_readl = clk_memmap_readl;
-+	*(void **)&ops->clk_writel = clk_memmap_writel;
++	const_cast(ops->clk_readl) = clk_memmap_readl;
++	const_cast(ops->clk_writel) = clk_memmap_writel;
 +	pax_close_kernel();
  
  	return 0;
  }
 diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
-index 51eef87..d944fa7 100644
+index 51eef87..f530cf9 100644
 --- a/drivers/cpufreq/acpi-cpufreq.c
 +++ b/drivers/cpufreq/acpi-cpufreq.c
 @@ -682,8 +682,11 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
@@ -43255,7 +43265,7 @@ index 51eef87..d944fa7 100644
 -		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
 +	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
 +		pax_open_kernel();
-+		*(u8 *)&acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
++		const_cast(acpi_cpufreq_driver.flags) |= CPUFREQ_CONST_LOOPS;
 +		pax_close_kernel();
 +	}
  
@@ -43267,7 +43277,7 @@ index 51eef87..d944fa7 100644
  	case ACPI_ADR_SPACE_FIXED_HARDWARE:
 -		acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
 +		pax_open_kernel();
-+		*(void **)&acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
++		const_cast(acpi_cpufreq_driver.get) = get_cur_freq_on_cpu;
 +		pax_close_kernel();
  		break;
  	default:
@@ -43279,14 +43289,14 @@ index 51eef87..d944fa7 100644
 -		acpi_cpufreq_driver.set_boost = set_boost;
 -		acpi_cpufreq_driver.boost_enabled = boost_state(0);
 +		pax_open_kernel();
-+		*(void **)&acpi_cpufreq_driver.set_boost = set_boost;
-+		*(bool *)&acpi_cpufreq_driver.boost_enabled = boost_state(0);
++		const_cast(acpi_cpufreq_driver.set_boost) = set_boost;
++		const_cast(acpi_cpufreq_driver.boost_enabled) = boost_state(0);
 +		pax_close_kernel();
  
  		cpu_notifier_register_begin();
  
 diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
-index 0ca74d0..15705fb 100644
+index 0ca74d0..1a0d302 100644
 --- a/drivers/cpufreq/cpufreq-dt.c
 +++ b/drivers/cpufreq/cpufreq-dt.c
 @@ -461,7 +461,9 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
@@ -43295,13 +43305,13 @@ index 0ca74d0..15705fb 100644
  
 -	dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev);
 +	pax_open_kernel();
-+	*(void **)&dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev);
++	const_cast(dt_cpufreq_driver.driver_data) = dev_get_platdata(&pdev->dev);
 +	pax_close_kernel();
  
  	ret = cpufreq_register_driver(&dt_cpufreq_driver);
  	if (ret)
 diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
-index e979ec7..a024e16 100644
+index e979ec7..a76375c 100644
 --- a/drivers/cpufreq/cpufreq.c
 +++ b/drivers/cpufreq/cpufreq.c
 @@ -474,12 +474,12 @@ EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end);
@@ -43343,7 +43353,7 @@ index e979ec7..a024e16 100644
  	write_lock_irqsave(&cpufreq_driver_lock, flags);
 -	cpufreq_driver->boost_enabled = state;
 +	pax_open_kernel();
-+	*(bool *)&cpufreq_driver->boost_enabled = state;
++	const_cast(cpufreq_driver->boost_enabled) = state;
 +	pax_close_kernel();
  	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
  
@@ -43352,7 +43362,7 @@ index e979ec7..a024e16 100644
  		write_lock_irqsave(&cpufreq_driver_lock, flags);
 -		cpufreq_driver->boost_enabled = !state;
 +		pax_open_kernel();
-+		*(bool *)&cpufreq_driver->boost_enabled = !state;
++		const_cast(cpufreq_driver->boost_enabled) = !state;
 +		pax_close_kernel();
  		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
  
@@ -43363,7 +43373,7 @@ index e979ec7..a024e16 100644
  
 -	cpufreq_driver->set_boost = cpufreq_boost_set_sw;
 +	pax_open_kernel();
-+	*(void **)&cpufreq_driver->set_boost = cpufreq_boost_set_sw;
++	const_cast(cpufreq_driver->set_boost) = cpufreq_boost_set_sw;
 +	pax_close_kernel();
  
  	/* This will get removed on driver unregister */
@@ -43376,7 +43386,7 @@ index e979ec7..a024e16 100644
 -		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 +	if (driver_data->setpolicy) {
 +		pax_open_kernel();
-+		*(u8 *)&driver_data->flags |= CPUFREQ_CONST_LOOPS;
++		const_cast(driver_data->flags) |= CPUFREQ_CONST_LOOPS;
 +		pax_close_kernel();
 +	}
  
@@ -43445,7 +43455,7 @@ index 91e767a0..3b40724 100644
  	struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data;		\
  	return sprintf(buf, "%u\n", dbs_data->min_sampling_rate);	\
 diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
-index eae5107..26e7a39 100644
+index eae5107..3dd6408 100644
 --- a/drivers/cpufreq/cpufreq_ondemand.c
 +++ b/drivers/cpufreq/cpufreq_ondemand.c
 @@ -534,7 +534,7 @@ static void od_exit(struct dbs_data *dbs_data, bool notify)
@@ -43463,7 +43473,7 @@ index eae5107..26e7a39 100644
  {
 -	od_ops.powersave_bias_target = f;
 +	pax_open_kernel();
-+	*(void **)&od_ops.powersave_bias_target = f;
++	const_cast(od_ops.powersave_bias_target) = f;
 +	pax_close_kernel();
  	od_set_powersave_bias(powersave_bias);
  }
@@ -43473,7 +43483,7 @@ index eae5107..26e7a39 100644
  {
 -	od_ops.powersave_bias_target = generic_powersave_bias_target;
 +	pax_open_kernel();
-+	*(void **)&od_ops.powersave_bias_target = generic_powersave_bias_target;
++	const_cast(od_ops.powersave_bias_target) = generic_powersave_bias_target;
 +	pax_close_kernel();
  	od_set_powersave_bias(0);
  }
@@ -43634,7 +43644,7 @@ index e895123..05de99b 100644
  
  #if IS_ENABLED(CONFIG_ACPI)
 diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
-index 5dd95da..abc3837 100644
+index 5dd95da..ac41e5e 100644
 --- a/drivers/cpufreq/p4-clockmod.c
 +++ b/drivers/cpufreq/p4-clockmod.c
 @@ -134,10 +134,14 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
@@ -43643,13 +43653,13 @@ index 5dd95da..abc3837 100644
  		case 0x1C: /* Atom */
 -			p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 +			pax_open_kernel();
-+			*(u8 *)&p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
++			const_cast(p4clockmod_driver.flags) |= CPUFREQ_CONST_LOOPS;
 +			pax_close_kernel();
  			return speedstep_get_frequency(SPEEDSTEP_CPU_PCORE);
  		case 0x0D: /* Pentium M (Dothan) */
 -			p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 +			pax_open_kernel();
-+			*(u8 *)&p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
++			const_cast(p4clockmod_driver.flags) |= CPUFREQ_CONST_LOOPS;
 +			pax_close_kernel();
  			/* fall through */
  		case 0x09: /* Pentium M (Banias) */
@@ -43660,7 +43670,7 @@ index 5dd95da..abc3837 100644
  	 * throttling is active or not. */
 -	p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 +	pax_open_kernel();
-+	*(u8 *)&p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
++	const_cast(p4clockmod_driver.flags) |= CPUFREQ_CONST_LOOPS;
 +	pax_close_kernel();
  
  	if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4M) {
@@ -43776,7 +43786,7 @@ index 9bb42ba..b01b4a2 100644
  
  MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
 diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
-index 7d4a315..21bb886 100644
+index 7d4a315..ce41fb3 100644
 --- a/drivers/cpufreq/speedstep-centrino.c
 +++ b/drivers/cpufreq/speedstep-centrino.c
 @@ -351,8 +351,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
@@ -43787,7 +43797,7 @@ index 7d4a315..21bb886 100644
 -		centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
 +	if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) {
 +		pax_open_kernel();
-+		*(u8 *)&centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
++		const_cast(centrino_driver.flags) |= CPUFREQ_CONST_LOOPS;
 +		pax_close_kernel();
 +	}
  
@@ -44575,7 +44585,7 @@ index 94a58a0..5b8dd03 100644
  };
  
 diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
-index 88bebe1..c7b636f 100644
+index 88bebe1..e599fad 100644
 --- a/drivers/firmware/dmi_scan.c
 +++ b/drivers/firmware/dmi_scan.c
 @@ -712,14 +712,18 @@ static int __init dmi_init(void)
@@ -44585,8 +44595,8 @@ index 88bebe1..c7b636f 100644
 -	bin_attr_smbios_entry_point.size = smbios_entry_point_size;
 -	bin_attr_smbios_entry_point.private = smbios_entry_point;
 +	pax_open_kernel();
-+	*(size_t *)&bin_attr_smbios_entry_point.size = smbios_entry_point_size;
-+	*(void **)&bin_attr_smbios_entry_point.private = smbios_entry_point;
++	const_cast(bin_attr_smbios_entry_point.size) = smbios_entry_point_size;
++	const_cast(bin_attr_smbios_entry_point.private) = smbios_entry_point;
 +	pax_close_kernel();
  	ret = sysfs_create_bin_file(tables_kobj, &bin_attr_smbios_entry_point);
  	if (ret)
@@ -44595,8 +44605,8 @@ index 88bebe1..c7b636f 100644
 -	bin_attr_DMI.size = dmi_len;
 -	bin_attr_DMI.private = dmi_table;
 +	pax_open_kernel();
-+	*(size_t *)&bin_attr_DMI.size = dmi_len;
-+	*(void **)&bin_attr_DMI.private = dmi_table;
++	const_cast(bin_attr_DMI.size) = dmi_len;
++	const_cast(bin_attr_DMI.private) = dmi_table;
 +	pax_close_kernel();
  	ret = sysfs_create_bin_file(tables_kobj, &bin_attr_DMI);
  	if (!ret)
@@ -44623,7 +44633,7 @@ index d425374..1da1716 100644
  EXPORT_SYMBOL_GPL(cper_next_record_id);
  
 diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
-index c51f3b2..d1cc54e 100644
+index c51f3b2..54523fd 100644
 --- a/drivers/firmware/efi/efi.c
 +++ b/drivers/firmware/efi/efi.c
 @@ -176,15 +176,17 @@ static struct attribute_group efi_subsys_attr_group = {
@@ -44641,11 +44651,11 @@ index c51f3b2..d1cc54e 100644
 -	generic_ops.get_next_variable = efi.get_next_variable;
 -	generic_ops.query_variable_store = efi_query_variable_store;
 +	pax_open_kernel();
-+	*(void **)&generic_ops.get_variable = efi.get_variable;
-+	*(void **)&generic_ops.set_variable = efi.set_variable;
-+	*(void **)&generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
-+	*(void **)&generic_ops.get_next_variable = efi.get_next_variable;
-+	*(void **)&generic_ops.query_variable_store = efi_query_variable_store;
++	const_cast(generic_ops.get_variable) = efi.get_variable;
++	const_cast(generic_ops.set_variable) = efi.set_variable;
++	const_cast(generic_ops.set_variable_nonblocking) = efi.set_variable_nonblocking;
++	const_cast(generic_ops.get_next_variable) = efi.get_next_variable;
++	const_cast(generic_ops.query_variable_store) = efi_query_variable_store;
 +	pax_close_kernel();
  
  	return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
@@ -44690,7 +44700,7 @@ index f1ab05e..ab51228 100644
  		.ident = "Google Board",
  		.matches = {
 diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c
-index 2f569aa..26e4f39 100644
+index 2f569aa..3af5497 100644
 --- a/drivers/firmware/google/memconsole.c
 +++ b/drivers/firmware/google/memconsole.c
 @@ -136,7 +136,7 @@ static bool __init found_memconsole(void)
@@ -44708,7 +44718,7 @@ index 2f569aa..26e4f39 100644
  
 -	memconsole_bin_attr.size = memconsole_length;
 +	pax_open_kernel();
-+	*(size_t *)&memconsole_bin_attr.size = memconsole_length;
++	const_cast(memconsole_bin_attr.size) = memconsole_length;
 +	pax_close_kernel();
 +
  	return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
@@ -44840,7 +44850,7 @@ index ac8deb0..f3caa10 100644
  	return -EINVAL;
  }
 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index 5c1ba87..ab4a059 100644
+index 5c1ba87..f711915 100644
 --- a/drivers/gpio/gpiolib.c
 +++ b/drivers/gpio/gpiolib.c
 @@ -669,8 +669,10 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
@@ -44850,8 +44860,8 @@ index 5c1ba87..ab4a059 100644
 -		gpiochip->irqchip->irq_request_resources = NULL;
 -		gpiochip->irqchip->irq_release_resources = NULL;
 +		pax_open_kernel();
-+		*(void **)&gpiochip->irqchip->irq_request_resources = NULL;
-+		*(void **)&gpiochip->irqchip->irq_release_resources = NULL;
++		const_cast(gpiochip->irqchip->irq_request_resources) = NULL;
++		const_cast(gpiochip->irqchip->irq_release_resources) = NULL;
 +		pax_close_kernel();
  		gpiochip->irqchip = NULL;
  	}
@@ -44863,8 +44873,8 @@ index 5c1ba87..ab4a059 100644
 -		irqchip->irq_request_resources = gpiochip_irq_reqres;
 -		irqchip->irq_release_resources = gpiochip_irq_relres;
 +		pax_open_kernel();
-+		*(void **)&irqchip->irq_request_resources = gpiochip_irq_reqres;
-+		*(void **)&irqchip->irq_release_resources = gpiochip_irq_relres;
++		const_cast(irqchip->irq_request_resources) = gpiochip_irq_reqres;
++		const_cast(irqchip->irq_release_resources) = gpiochip_irq_relres;
 +		pax_close_kernel();
  	}
  
@@ -45050,7 +45060,7 @@ index 51bfc11..4d4112a 100644
  
  static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
-index 9ef1db8..bfd5d78 100644
+index 9ef1db8..5eec19b 100644
 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
 +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
 @@ -495,7 +495,7 @@ static struct drm_driver kms_driver = {
@@ -45082,7 +45092,7 @@ index 9ef1db8..bfd5d78 100644
 -	driver->num_ioctls = amdgpu_max_kms_ioctl;
 +
 +	pax_open_kernel();
-+	*(int *)&kms_driver.num_ioctls = amdgpu_max_kms_ioctl;
++	const_cast(kms_driver.num_ioctls) = amdgpu_max_kms_ioctl;
 +	pax_close_kernel();
 +
  	amdgpu_register_atpx_handler();
@@ -46288,7 +46298,7 @@ index d918567..6cfd904 100644
  /**
   * Determine if the device really is AGP or not.
 diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
-index 44f4a13..0063c1b 100644
+index 44f4a13..af9f6f5 100644
 --- a/drivers/gpu/drm/i810/i810_drv.c
 +++ b/drivers/gpu/drm/i810/i810_drv.c
 @@ -87,7 +87,11 @@ static int __init i810_init(void)
@@ -46298,7 +46308,7 @@ index 44f4a13..0063c1b 100644
 -	driver.num_ioctls = i810_max_ioctl;
 +
 +	pax_open_kernel();
-+	*(int *)&driver.num_ioctls = i810_max_ioctl;
++	const_cast(driver.num_ioctls) = i810_max_ioctl;
 +	pax_close_kernel();
 +
  	return drm_pci_init(&driver, &i810_pci_driver);
@@ -46547,7 +46557,7 @@ index 97f3a56..32c712e 100644
  		ret = drm_ioctl(filp, cmd, arg);
  
 diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index fa8afa7..0bac957 100644
+index fa8afa7..7375300 100644
 --- a/drivers/gpu/drm/i915/i915_irq.c
 +++ b/drivers/gpu/drm/i915/i915_irq.c
 @@ -4490,14 +4490,15 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
@@ -46558,14 +46568,14 @@ index fa8afa7..0bac957 100644
  	if (IS_GEN2(dev_priv)) {
  		dev->max_vblank_count = 0;
 -		dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
-+		*(void **)&dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
++		const_cast(dev->driver->get_vblank_counter) = i8xx_get_vblank_counter;
  	} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
  		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
 -		dev->driver->get_vblank_counter = g4x_get_vblank_counter;
-+		*(void **)&dev->driver->get_vblank_counter = g4x_get_vblank_counter;
++		const_cast(dev->driver->get_vblank_counter) = g4x_get_vblank_counter;
  	} else {
 -		dev->driver->get_vblank_counter = i915_get_vblank_counter;
-+		*(void **)&dev->driver->get_vblank_counter = i915_get_vblank_counter;
++		const_cast(dev->driver->get_vblank_counter) = i915_get_vblank_counter;
  		dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
  	}
  
@@ -46575,8 +46585,8 @@ index fa8afa7..0bac957 100644
  
 -	dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
 -	dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
-+	*(void **)&dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
-+	*(void **)&dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
++	const_cast(dev->driver->get_vblank_timestamp) = i915_get_vblank_timestamp;
++	const_cast(dev->driver->get_scanout_position) = i915_get_crtc_scanoutpos;
  
  	if (IS_CHERRYVIEW(dev_priv)) {
 -		dev->driver->irq_handler = cherryview_irq_handler;
@@ -46585,12 +46595,12 @@ index fa8afa7..0bac957 100644
 -		dev->driver->irq_uninstall = cherryview_irq_uninstall;
 -		dev->driver->enable_vblank = valleyview_enable_vblank;
 -		dev->driver->disable_vblank = valleyview_disable_vblank;
-+		*(void **)&dev->driver->irq_handler = cherryview_irq_handler;
-+		*(void **)&dev->driver->irq_preinstall = cherryview_irq_preinstall;
-+		*(void **)&dev->driver->irq_postinstall = cherryview_irq_postinstall;
-+		*(void **)&dev->driver->irq_uninstall = cherryview_irq_uninstall;
-+		*(void **)&dev->driver->enable_vblank = valleyview_enable_vblank;
-+		*(void **)&dev->driver->disable_vblank = valleyview_disable_vblank;
++		const_cast(dev->driver->irq_handler) = cherryview_irq_handler;
++		const_cast(dev->driver->irq_preinstall) = cherryview_irq_preinstall;
++		const_cast(dev->driver->irq_postinstall) = cherryview_irq_postinstall;
++		const_cast(dev->driver->irq_uninstall) = cherryview_irq_uninstall;
++		const_cast(dev->driver->enable_vblank) = valleyview_enable_vblank;
++		const_cast(dev->driver->disable_vblank) = valleyview_disable_vblank;
  		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
  	} else if (IS_VALLEYVIEW(dev_priv)) {
 -		dev->driver->irq_handler = valleyview_irq_handler;
@@ -46599,12 +46609,12 @@ index fa8afa7..0bac957 100644
 -		dev->driver->irq_uninstall = valleyview_irq_uninstall;
 -		dev->driver->enable_vblank = valleyview_enable_vblank;
 -		dev->driver->disable_vblank = valleyview_disable_vblank;
-+		*(void **)&dev->driver->irq_handler = valleyview_irq_handler;
-+		*(void **)&dev->driver->irq_preinstall = valleyview_irq_preinstall;
-+		*(void **)&dev->driver->irq_postinstall = valleyview_irq_postinstall;
-+		*(void **)&dev->driver->irq_uninstall = valleyview_irq_uninstall;
-+		*(void **)&dev->driver->enable_vblank = valleyview_enable_vblank;
-+		*(void **)&dev->driver->disable_vblank = valleyview_disable_vblank;
++		const_cast(dev->driver->irq_handler) = valleyview_irq_handler;
++		const_cast(dev->driver->irq_preinstall) = valleyview_irq_preinstall;
++		const_cast(dev->driver->irq_postinstall) = valleyview_irq_postinstall;
++		const_cast(dev->driver->irq_uninstall) = valleyview_irq_uninstall;
++		const_cast(dev->driver->enable_vblank) = valleyview_enable_vblank;
++		const_cast(dev->driver->disable_vblank) = valleyview_disable_vblank;
  		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
  	} else if (INTEL_INFO(dev_priv)->gen >= 8) {
 -		dev->driver->irq_handler = gen8_irq_handler;
@@ -46613,12 +46623,12 @@ index fa8afa7..0bac957 100644
 -		dev->driver->irq_uninstall = gen8_irq_uninstall;
 -		dev->driver->enable_vblank = gen8_enable_vblank;
 -		dev->driver->disable_vblank = gen8_disable_vblank;
-+		*(void **)&dev->driver->irq_handler = gen8_irq_handler;
-+		*(void **)&dev->driver->irq_preinstall = gen8_irq_reset;
-+		*(void **)&dev->driver->irq_postinstall = gen8_irq_postinstall;
-+		*(void **)&dev->driver->irq_uninstall = gen8_irq_uninstall;
-+		*(void **)&dev->driver->enable_vblank = gen8_enable_vblank;
-+		*(void **)&dev->driver->disable_vblank = gen8_disable_vblank;
++		const_cast(dev->driver->irq_handler) = gen8_irq_handler;
++		const_cast(dev->driver->irq_preinstall) = gen8_irq_reset;
++		const_cast(dev->driver->irq_postinstall) = gen8_irq_postinstall;
++		const_cast(dev->driver->irq_uninstall) = gen8_irq_uninstall;
++		const_cast(dev->driver->enable_vblank) = gen8_enable_vblank;
++		const_cast(dev->driver->disable_vblank) = gen8_disable_vblank;
  		if (IS_BROXTON(dev))
  			dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
  		else if (HAS_PCH_SPT(dev))
@@ -46632,12 +46642,12 @@ index fa8afa7..0bac957 100644
 -		dev->driver->irq_uninstall = ironlake_irq_uninstall;
 -		dev->driver->enable_vblank = ironlake_enable_vblank;
 -		dev->driver->disable_vblank = ironlake_disable_vblank;
-+		*(void **)&dev->driver->irq_handler = ironlake_irq_handler;
-+		*(void **)&dev->driver->irq_preinstall = ironlake_irq_reset;
-+		*(void **)&dev->driver->irq_postinstall = ironlake_irq_postinstall;
-+		*(void **)&dev->driver->irq_uninstall = ironlake_irq_uninstall;
-+		*(void **)&dev->driver->enable_vblank = ironlake_enable_vblank;
-+		*(void **)&dev->driver->disable_vblank = ironlake_disable_vblank;
++		const_cast(dev->driver->irq_handler) = ironlake_irq_handler;
++		const_cast(dev->driver->irq_preinstall) = ironlake_irq_reset;
++		const_cast(dev->driver->irq_postinstall) = ironlake_irq_postinstall;
++		const_cast(dev->driver->irq_uninstall) = ironlake_irq_uninstall;
++		const_cast(dev->driver->enable_vblank) = ironlake_enable_vblank;
++		const_cast(dev->driver->disable_vblank) = ironlake_disable_vblank;
  		dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
  	} else {
  		if (INTEL_INFO(dev_priv)->gen == 2) {
@@ -46645,42 +46655,42 @@ index fa8afa7..0bac957 100644
 -			dev->driver->irq_postinstall = i8xx_irq_postinstall;
 -			dev->driver->irq_handler = i8xx_irq_handler;
 -			dev->driver->irq_uninstall = i8xx_irq_uninstall;
-+			*(void **)&dev->driver->irq_preinstall = i8xx_irq_preinstall;
-+			*(void **)&dev->driver->irq_postinstall = i8xx_irq_postinstall;
-+			*(void **)&dev->driver->irq_handler = i8xx_irq_handler;
-+			*(void **)&dev->driver->irq_uninstall = i8xx_irq_uninstall;
++			const_cast(dev->driver->irq_preinstall) = i8xx_irq_preinstall;
++			const_cast(dev->driver->irq_postinstall) = i8xx_irq_postinstall;
++			const_cast(dev->driver->irq_handler) = i8xx_irq_handler;
++			const_cast(dev->driver->irq_uninstall) = i8xx_irq_uninstall;
  		} else if (INTEL_INFO(dev_priv)->gen == 3) {
 -			dev->driver->irq_preinstall = i915_irq_preinstall;
 -			dev->driver->irq_postinstall = i915_irq_postinstall;
 -			dev->driver->irq_uninstall = i915_irq_uninstall;
 -			dev->driver->irq_handler = i915_irq_handler;
-+			*(void **)&dev->driver->irq_preinstall = i915_irq_preinstall;
-+			*(void **)&dev->driver->irq_postinstall = i915_irq_postinstall;
-+			*(void **)&dev->driver->irq_uninstall = i915_irq_uninstall;
-+			*(void **)&dev->driver->irq_handler = i915_irq_handler;
++			const_cast(dev->driver->irq_preinstall) = i915_irq_preinstall;
++			const_cast(dev->driver->irq_postinstall) = i915_irq_postinstall;
++			const_cast(dev->driver->irq_uninstall) = i915_irq_uninstall;
++			const_cast(dev->driver->irq_handler) = i915_irq_handler;
  		} else {
 -			dev->driver->irq_preinstall = i965_irq_preinstall;
 -			dev->driver->irq_postinstall = i965_irq_postinstall;
 -			dev->driver->irq_uninstall = i965_irq_uninstall;
 -			dev->driver->irq_handler = i965_irq_handler;
-+			*(void **)&dev->driver->irq_preinstall = i965_irq_preinstall;
-+			*(void **)&dev->driver->irq_postinstall = i965_irq_postinstall;
-+			*(void **)&dev->driver->irq_uninstall = i965_irq_uninstall;
-+			*(void **)&dev->driver->irq_handler = i965_irq_handler;
++			const_cast(dev->driver->irq_preinstall) = i965_irq_preinstall;
++			const_cast(dev->driver->irq_postinstall) = i965_irq_postinstall;
++			const_cast(dev->driver->irq_uninstall) = i965_irq_uninstall;
++			const_cast(dev->driver->irq_handler) = i965_irq_handler;
  		}
  		if (I915_HAS_HOTPLUG(dev_priv))
  			dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
 -		dev->driver->enable_vblank = i915_enable_vblank;
 -		dev->driver->disable_vblank = i915_disable_vblank;
-+		*(void **)&dev->driver->enable_vblank = i915_enable_vblank;
-+		*(void **)&dev->driver->disable_vblank = i915_disable_vblank;
++		const_cast(dev->driver->enable_vblank) = i915_enable_vblank;
++		const_cast(dev->driver->disable_vblank) = i915_disable_vblank;
  	}
 +	pax_close_kernel();
  }
  
  /**
 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
-index 39b00b9..aa9fc8a 100644
+index 39b00b9..244538d 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -15111,13 +15111,13 @@ struct intel_quirk {
@@ -46693,8 +46703,9 @@ index 39b00b9..aa9fc8a 100644
  /* For systems that don't have a meaningful PCI subdevice/subvendor ID */
  struct intel_dmi_quirk {
  	void (*hook)(struct drm_device *dev);
- 	const struct dmi_system_id (*dmi_id_list)[];
+-	const struct dmi_system_id (*dmi_id_list)[];
 -};
++	const struct dmi_system_id *dmi_id_list;
 +} __do_const;
  
  static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
@@ -46726,10 +46737,19 @@ index 39b00b9..aa9fc8a 100644
 +
 +static const struct intel_dmi_quirk intel_dmi_quirks[] = {
 +	{
-+		.dmi_id_list = &intel_dmi_quirks_table,
++		.dmi_id_list = intel_dmi_quirks_table,
  		.hook = quirk_invert_brightness,
  	},
  };
+@@ -15219,7 +15221,7 @@ static void intel_init_quirks(struct drm_device *dev)
+ 			q->hook(dev);
+ 	}
+ 	for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
+-		if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
++		if (dmi_check_system(intel_dmi_quirks[i].dmi_id_list) != 0)
+ 			intel_dmi_quirks[i].hook(dev);
+ 	}
+ }
 diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
 index 2f57d79..7152e6e 100644
 --- a/drivers/gpu/drm/imx/imx-drm-core.c
@@ -46744,7 +46764,7 @@ index 2f57d79..7152e6e 100644
  
  	imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
 diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
-index 5e2f131..d227dbc 100644
+index 5e2f131..c134c7c 100644
 --- a/drivers/gpu/drm/mga/mga_drv.c
 +++ b/drivers/gpu/drm/mga/mga_drv.c
 @@ -92,7 +92,10 @@ static struct pci_driver mga_pci_driver = {
@@ -46753,7 +46773,7 @@ index 5e2f131..d227dbc 100644
  {
 -	driver.num_ioctls = mga_max_ioctl;
 +	pax_open_kernel();
-+	*(int *)&driver.num_ioctls = mga_max_ioctl;
++	const_cast(driver.num_ioctls) = mga_max_ioctl;
 +	pax_close_kernel();
 +
  	return drm_pci_init(&driver, &mga_pci_driver);
@@ -47140,7 +47160,7 @@ index fe4c222..48b7b75 100644
  	omap_irq.o \
  	omap_debugfs.o \
 diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
-index ef5b902..47cf7f5 100644
+index ef5b902..2ae011b 100644
 --- a/drivers/gpu/drm/omapdrm/dss/display.c
 +++ b/drivers/gpu/drm/omapdrm/dss/display.c
 @@ -161,12 +161,14 @@ int omapdss_register_display(struct omap_dss_device *dssdev)
@@ -47150,13 +47170,13 @@ index ef5b902..47cf7f5 100644
 +	pax_open_kernel();
  	if (drv && drv->get_resolution == NULL)
 -		drv->get_resolution = omapdss_default_get_resolution;
-+		*(void **)&drv->get_resolution = omapdss_default_get_resolution;
++		const_cast(drv->get_resolution) = omapdss_default_get_resolution;
  	if (drv && drv->get_recommended_bpp == NULL)
 -		drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
-+		*(void **)&drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
++		const_cast(drv->get_recommended_bpp) = omapdss_default_get_recommended_bpp;
  	if (drv && drv->get_timings == NULL)
 -		drv->get_timings = omapdss_default_get_timings;
-+		*(void **)&drv->get_timings = omapdss_default_get_timings;
++		const_cast(drv->get_timings) = omapdss_default_get_timings;
 +	pax_close_kernel();
  
  	mutex_lock(&panel_list_mutex);
@@ -47232,7 +47252,7 @@ index 47e5264..3393741 100644
  {
  	struct drm_device *ddev = connector->dev;
 diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
-index 7307b07..8eecdd0 100644
+index 7307b07..3346540 100644
 --- a/drivers/gpu/drm/qxl/qxl_drv.c
 +++ b/drivers/gpu/drm/qxl/qxl_drv.c
 @@ -37,7 +37,7 @@
@@ -47251,7 +47271,7 @@ index 7307b07..8eecdd0 100644
 -	qxl_driver.num_ioctls = qxl_max_ioctls;
 +
 +	pax_open_kernel();
-+	*(int *)&qxl_driver.num_ioctls = qxl_max_ioctls;
++	const_cast(qxl_driver.num_ioctls) = qxl_max_ioctls;
 +	pax_close_kernel();
 +
  	return drm_pci_init(&qxl_driver, &qxl_pci_driver);
@@ -47362,7 +47382,7 @@ index 0bf1e20..42a7310 100644
  	ret = drm_irq_install(qdev->ddev, qdev->ddev->pdev->irq);
  	qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
 diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c
-index 9534127..3fbab8c 100644
+index 9534127..1d17b3f 100644
 --- a/drivers/gpu/drm/qxl/qxl_ttm.c
 +++ b/drivers/gpu/drm/qxl/qxl_ttm.c
 @@ -103,7 +103,7 @@ static void qxl_ttm_global_fini(struct qxl_device *qdev)
@@ -47416,8 +47436,8 @@ index 9534127..3fbab8c 100644
 -		else
 -			qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_PRIV0].priv;
 +	pax_open_kernel();
-+	*(void **)&qxl_mem_types_list[0].data = qdev->mman.bdev.man[TTM_PL_VRAM].priv;
-+	*(void **)&qxl_mem_types_list[1].data = qdev->mman.bdev.man[TTM_PL_PRIV0].priv;
++	const_cast(qxl_mem_types_list[0].data) = qdev->mman.bdev.man[TTM_PL_VRAM].priv;
++	const_cast(qxl_mem_types_list[1].data) = qdev->mman.bdev.man[TTM_PL_PRIV0].priv;
 +	pax_close_kernel();
  
 -	}
@@ -47440,7 +47460,7 @@ index 14fd83b5f..b2acbd19 100644
  	/* We don't support anything other than bus-mastering ring mode,
  	 * but the ring can be in either AGP or PCI space for the ring
 diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
-index c57b4de..2614d79 100644
+index c57b4de..1a875fb 100644
 --- a/drivers/gpu/drm/r128/r128_drv.c
 +++ b/drivers/gpu/drm/r128/r128_drv.c
 @@ -94,7 +94,9 @@ static struct pci_driver r128_pci_driver = {
@@ -47449,7 +47469,7 @@ index c57b4de..2614d79 100644
  {
 -	driver.num_ioctls = r128_max_ioctl;
 +	pax_open_kernel();
-+	*(int *)&driver.num_ioctls = r128_max_ioctl;
++	const_cast(driver.num_ioctls) = r128_max_ioctl;
 +	pax_close_kernel();
  
  	return drm_pci_init(&driver, &r128_pci_driver);
@@ -47659,7 +47679,7 @@ index 4197ca1..f07709e 100644
  
  static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
-index e266ffc..0392d08 100644
+index e266ffc..e510e3f 100644
 --- a/drivers/gpu/drm/radeon/radeon_drv.c
 +++ b/drivers/gpu/drm/radeon/radeon_drv.c
 @@ -130,7 +130,7 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int crtc,
@@ -47688,7 +47708,7 @@ index e266ffc..0392d08 100644
 -		driver->num_ioctls = radeon_max_kms_ioctl;
 +
 +		pax_open_kernel();
-+		*(int *)&driver->num_ioctls = radeon_max_kms_ioctl;
++		const_cast(driver->num_ioctls) = radeon_max_kms_ioctl;
 +		pax_close_kernel();
 +
  		radeon_register_atpx_handler();
@@ -47808,7 +47828,7 @@ index d47dff9..0752202 100644
 -int savage_max_ioctl = ARRAY_SIZE(savage_ioctls);
 +const int savage_max_ioctl = ARRAY_SIZE(savage_ioctls);
 diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
-index 21aed1f..5db7419 100644
+index 21aed1f..85d23a0 100644
 --- a/drivers/gpu/drm/savage/savage_drv.c
 +++ b/drivers/gpu/drm/savage/savage_drv.c
 @@ -76,7 +76,10 @@ static struct pci_driver savage_pci_driver = {
@@ -47817,7 +47837,7 @@ index 21aed1f..5db7419 100644
  {
 -	driver.num_ioctls = savage_max_ioctl;
 +	pax_open_kernel();
-+	*(int *)&driver.num_ioctls = savage_max_ioctl;
++	const_cast(driver.num_ioctls) = savage_max_ioctl;
 +	pax_close_kernel();
 +
  	return drm_pci_init(&driver, &savage_pci_driver);
@@ -47837,7 +47857,7 @@ index 37b6995..9b31aaf 100644
  #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
  
 diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
-index 79bce76..4fd9a20 100644
+index 79bce76..6c02219 100644
 --- a/drivers/gpu/drm/sis/sis_drv.c
 +++ b/drivers/gpu/drm/sis/sis_drv.c
 @@ -128,7 +128,10 @@ static struct pci_driver sis_pci_driver = {
@@ -47846,7 +47866,7 @@ index 79bce76..4fd9a20 100644
  {
 -	driver.num_ioctls = sis_max_ioctl;
 +	pax_open_kernel();
-+	*(int *)&driver.num_ioctls = sis_max_ioctl;
++	const_cast(driver.num_ioctls) = sis_max_ioctl;
 +	pax_close_kernel();
 +
  	return drm_pci_init(&driver, &sis_pci_driver);
@@ -47875,7 +47895,7 @@ index 93ad8a5..48f0a57 100644
 -int sis_max_ioctl = ARRAY_SIZE(sis_ioctls);
 +const int sis_max_ioctl = ARRAY_SIZE(sis_ioctls);
 diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
-index dde6f20..1969ca6 100644
+index dde6f20..a74f8b9 100644
 --- a/drivers/gpu/drm/tegra/dc.c
 +++ b/drivers/gpu/drm/tegra/dc.c
 @@ -1657,7 +1657,7 @@ static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
@@ -47883,7 +47903,7 @@ index dde6f20..1969ca6 100644
  
  	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
 -		dc->debugfs_files[i].data = dc;
-+		*(void **)&dc->debugfs_files[i].data = dc;
++		const_cast(dc->debugfs_files[i].data) = dc;
  
  	err = drm_debugfs_create_files(dc->debugfs_files,
  				       ARRAY_SIZE(debugfs_files),
@@ -47914,7 +47934,7 @@ index b7ef492..8968507 100644
  	struct dentry *debugfs;
  };
 diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
-index 757c6e8..710a6ff 100644
+index 757c6e8..36532d6 100644
 --- a/drivers/gpu/drm/tegra/sor.c
 +++ b/drivers/gpu/drm/tegra/sor.c
 @@ -1003,8 +1003,11 @@ static int tegra_sor_debugfs_init(struct tegra_sor *sor,
@@ -47925,7 +47945,7 @@ index 757c6e8..710a6ff 100644
 -		sor->debugfs_files[i].data = sor;
 +	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++) {
 +		pax_open_kernel();
-+		*(void **)&sor->debugfs_files[i].data = sor;
++		const_cast(sor->debugfs_files[i].data) = sor;
 +		pax_close_kernel();
 +	}
  
@@ -48205,7 +48225,7 @@ index d17d8f2..67e8e48b 100644
 -int via_max_ioctl = ARRAY_SIZE(via_ioctls);
 +const int via_max_ioctl = ARRAY_SIZE(via_ioctls);
 diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
-index ed8aa8f..16c84fc 100644
+index ed8aa8f..114cc8d 100644
 --- a/drivers/gpu/drm/via/via_drv.c
 +++ b/drivers/gpu/drm/via/via_drv.c
 @@ -107,7 +107,10 @@ static struct pci_driver via_pci_driver = {
@@ -48214,7 +48234,7 @@ index ed8aa8f..16c84fc 100644
  {
 -	driver.num_ioctls = via_max_ioctl;
 +	pax_open_kernel();
-+	*(int *)&driver.num_ioctls = via_max_ioctl;
++	const_cast(driver.num_ioctls) = via_max_ioctl;
 +	pax_close_kernel();
 +
  	via_init_command_verifier();
@@ -49094,7 +49114,7 @@ index d127ace..6ee866f 100644
  	int i, j = 1;
  
 diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
-index 146eed70b..7679efd 100644
+index 146eed70b..7312f08 100644
 --- a/drivers/idle/intel_idle.c
 +++ b/drivers/idle/intel_idle.c
 @@ -1060,8 +1060,10 @@ static void sklh_idle_state_table_update(void)
@@ -49104,8 +49124,8 @@ index 146eed70b..7679efd 100644
 -	skl_cstates[5].disabled = 1;	/* C8-SKL */
 -	skl_cstates[6].disabled = 1;	/* C9-SKL */
 +	pax_open_kernel();
-+	*(bool *)&skl_cstates[5].disabled = 1;	/* C8-SKL */
-+	*(bool *)&skl_cstates[6].disabled = 1;	/* C9-SKL */
++	const_cast(skl_cstates[5].disabled) = 1;	/* C8-SKL */
++	const_cast(skl_cstates[6].disabled) = 1;	/* C9-SKL */
 +	pax_close_kernel();
  }
  /*
@@ -50103,18 +50123,6 @@ index 8c4daf7..77a87ab 100644
  	nesqp->destroyed = 1;
  
  	/* Blow away the connection if it exists. */
-diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
-index 7df16f7..7e1b21e 100644
---- a/drivers/infiniband/hw/qib/qib.h
-+++ b/drivers/infiniband/hw/qib/qib.h
-@@ -52,6 +52,7 @@
- #include <linux/kref.h>
- #include <linux/sched.h>
- #include <linux/kthread.h>
-+#include <linux/slab.h>
- 
- #include "qib_common.h"
- #include "qib_verbs.h"
 diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
 index 6c8ff10..73cfbb6 100644
 --- a/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -50492,7 +50500,7 @@ index 2087534..c3f6b6c 100644
  		return -ENOMEM;
  
 diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
-index 59ee4b8..6632759 100644
+index 59ee4b8..e4b6234 100644
 --- a/drivers/iommu/arm-smmu.c
 +++ b/drivers/iommu/arm-smmu.c
 @@ -341,7 +341,7 @@ enum arm_smmu_domain_stage {
@@ -50528,7 +50536,7 @@ index 59ee4b8..6632759 100644
  	/* Update our support page sizes to reflect the page table format */
 -	arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
 +	pax_open_kernel();
-+	*(unsigned long *)&arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
++	const_cast(arm_smmu_ops.pgsize_bitmap) = pgtbl_cfg.pgsize_bitmap;
 +	pax_close_kernel();
  
  	/* Initialise the context bank with our page table cfg */
@@ -50630,7 +50638,7 @@ index 59ee4b8..6632759 100644
  
 -	arm_smmu_ops.pgsize_bitmap &= size;
 +	pax_open_kernel();
-+	*(unsigned long *)&arm_smmu_ops.pgsize_bitmap &= size;
++	const_cast(arm_smmu_ops.pgsize_bitmap) &= size;
 +	pax_close_kernel();
  	dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", size);
  
@@ -51582,7 +51590,7 @@ index fef6586..22353ff 100644
  		} else if ((DIDD_Table[x].type > 0)
  			   && (DIDD_Table[x].type < 16)) {	/* IDI Adapter found */
 diff --git a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
-index 1cd9aff..1a3e2b6 100644
+index 1cd9aff..3775d52 100644
 --- a/drivers/isdn/hardware/eicon/mntfunc.c
 +++ b/drivers/isdn/hardware/eicon/mntfunc.c
 @@ -26,8 +26,13 @@ extern void DIVA_DIDD_Read(void *, int);
@@ -51592,7 +51600,7 @@ index 1cd9aff..1a3e2b6 100644
 +
 +static void didd_nothing(ENTITY IDI_CALL_ENTITY_T *e)
 +{
-+	diva_maint_prtComp(e);
++	diva_maint_prtComp((char *)e);
 +}
  static DESCRIPTOR MaintDescriptor =
 -{ IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
@@ -52967,10 +52975,50 @@ index 6b420a5..d5acb8f 100644
  
  struct gc_stat {
 diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
-index 22b9e34..ac456ec 100644
+index 22b9e34..d8406e7 100644
 --- a/drivers/md/bcache/btree.c
 +++ b/drivers/md/bcache/btree.c
-@@ -468,7 +468,7 @@ void __bch_btree_node_write(struct btree *b, struct closure *parent)
+@@ -337,15 +337,17 @@ static void btree_complete_write(struct btree *b, struct btree_write *w)
+ 	w->journal	= NULL;
+ }
+ 
+-static void btree_node_write_unlock(struct closure *cl)
++static void btree_node_write_unlock(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct btree *b = container_of(cl, struct btree, io);
+ 
+ 	up(&b->io_mutex);
+ }
+ 
+-static void __btree_node_write_done(struct closure *cl)
++static void __btree_node_write_done(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct btree *b = container_of(cl, struct btree, io);
+ 	struct btree_write *w = btree_prev_write(b);
+ 
+@@ -359,8 +361,9 @@ static void __btree_node_write_done(struct closure *cl)
+ 	closure_return_with_destructor(cl, btree_node_write_unlock);
+ }
+ 
+-static void btree_node_write_done(struct closure *cl)
++static void btree_node_write_done(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct btree *b = container_of(cl, struct btree, io);
+ 	struct bio_vec *bv;
+ 	int n;
+@@ -368,7 +371,7 @@ static void btree_node_write_done(struct closure *cl)
+ 	bio_for_each_segment_all(bv, b->bio, n)
+ 		__free_page(bv->bv_page);
+ 
+-	__btree_node_write_done(cl);
++	__btree_node_write_done(&cl->work);
+ }
+ 
+ static void btree_node_write_endio(struct bio *bio)
+@@ -468,7 +471,7 @@ void __bch_btree_node_write(struct btree *b, struct closure *parent)
  
  	do_btree_node_write(b);
  
@@ -52979,12 +53027,44 @@ index 22b9e34..ac456ec 100644
  			&PTR_CACHE(b->c, &b->key, 0)->btree_sectors_written);
  
  	b->written += set_blocks(i, block_bytes(b->c));
+diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c
+index 9eaf1d6..86e6fa1 100644
+--- a/drivers/md/bcache/closure.c
++++ b/drivers/md/bcache/closure.c
+@@ -29,12 +29,12 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
+ 			closure_queue(cl);
+ 		} else {
+ 			struct closure *parent = cl->parent;
+-			closure_fn *destructor = cl->fn;
++			work_func_t destructor = cl->fn;
+ 
+ 			closure_debug_destroy(cl);
+ 
+ 			if (destructor)
+-				destructor(cl);
++				destructor(&cl->work);
+ 
+ 			if (parent)
+ 				closure_put(parent);
 diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h
-index 782cc2c..4fdd593 100644
+index 782cc2c..34864f4 100644
 --- a/drivers/md/bcache/closure.h
 +++ b/drivers/md/bcache/closure.h
-@@ -238,7 +238,7 @@ static inline void closure_set_stopped(struct closure *cl)
- static inline void set_closure_fn(struct closure *cl, closure_fn *fn,
+@@ -151,7 +151,7 @@ struct closure {
+ 			struct workqueue_struct *wq;
+ 			struct task_struct	*task;
+ 			struct llist_node	list;
+-			closure_fn		*fn;
++			work_func_t		fn;
+ 		};
+ 		struct work_struct	work;
+ 	};
+@@ -235,10 +235,10 @@ static inline void closure_set_stopped(struct closure *cl)
+ 	atomic_sub(CLOSURE_RUNNING, &cl->remaining);
+ }
+ 
+-static inline void set_closure_fn(struct closure *cl, closure_fn *fn,
++static inline void set_closure_fn(struct closure *cl, work_func_t fn,
  				  struct workqueue_struct *wq)
  {
 -	BUG_ON(object_is_on_stack(cl));
@@ -52992,6 +53072,24 @@ index 782cc2c..4fdd593 100644
  	closure_set_ip(cl);
  	cl->fn = fn;
  	cl->wq = wq;
+@@ -253,7 +253,7 @@ static inline void closure_queue(struct closure *cl)
+ 		INIT_WORK(&cl->work, cl->work.func);
+ 		BUG_ON(!queue_work(wq, &cl->work));
+ 	} else
+-		cl->fn(cl);
++		cl->fn(&cl->work);
+ }
+ 
+ /**
+@@ -372,7 +372,7 @@ do {									\
+  * asynchronously out of a new closure - @parent will then wait for @cl to
+  * finish.
+  */
+-static inline void closure_call(struct closure *cl, closure_fn fn,
++static inline void closure_call(struct closure *cl, work_func_t fn,
+ 				struct workqueue_struct *wq,
+ 				struct closure *parent)
+ {
 diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
 index 86a0bb8..0832b32 100644
 --- a/drivers/md/bcache/io.c
@@ -53035,10 +53133,46 @@ index 86a0bb8..0832b32 100644
  		errors >>= IO_ERROR_SHIFT;
  
 diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
-index 29eba72..348efc9 100644
+index 29eba72..1d0108a 100644
 --- a/drivers/md/bcache/journal.c
 +++ b/drivers/md/bcache/journal.c
-@@ -621,7 +621,7 @@ static void journal_write_unlocked(struct closure *cl)
+@@ -555,10 +555,11 @@ static void journal_write_endio(struct bio *bio)
+ 	closure_put(&w->c->journal.io);
+ }
+ 
+-static void journal_write(struct closure *);
++static void journal_write(struct work_struct *);
+ 
+-static void journal_write_done(struct closure *cl)
++static void journal_write_done(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct journal *j = container_of(cl, struct journal, io);
+ 	struct journal_write *w = (j->cur == j->w)
+ 		? &j->w[1]
+@@ -568,17 +569,19 @@ static void journal_write_done(struct closure *cl)
+ 	continue_at_nobarrier(cl, journal_write, system_wq);
+ }
+ 
+-static void journal_write_unlock(struct closure *cl)
++static void journal_write_unlock(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, journal.io);
+ 
+ 	c->journal.io_in_flight = 0;
+ 	spin_unlock(&c->journal.lock);
+ }
+ 
+-static void journal_write_unlocked(struct closure *cl)
++static void journal_write_unlocked(struct work_struct *work)
+ 	__releases(c->journal.lock)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, journal.io);
+ 	struct cache *ca;
+ 	struct journal_write *w = c->journal.cur;
+@@ -621,7 +624,7 @@ static void journal_write_unlocked(struct closure *cl)
  		ca = PTR_CACHE(c, k, i);
  		bio = &ca->journal.bio;
  
@@ -53047,6 +53181,278 @@ index 29eba72..348efc9 100644
  
  		bio_reset(bio);
  		bio->bi_iter.bi_sector	= PTR_OFFSET(k, i);
+@@ -653,12 +656,13 @@ static void journal_write_unlocked(struct closure *cl)
+ 	continue_at(cl, journal_write_done, NULL);
+ }
+ 
+-static void journal_write(struct closure *cl)
++static void journal_write(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, journal.io);
+ 
+ 	spin_lock(&c->journal.lock);
+-	journal_write_unlocked(cl);
++	journal_write_unlocked(&cl->work);
+ }
+ 
+ static void journal_try_write(struct cache_set *c)
+diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
+index b929fc9..4557031 100644
+--- a/drivers/md/bcache/movinggc.c
++++ b/drivers/md/bcache/movinggc.c
+@@ -34,14 +34,16 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
+ 
+ /* Moving GC - IO loop */
+ 
+-static void moving_io_destructor(struct closure *cl)
++static void moving_io_destructor(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct moving_io *io = container_of(cl, struct moving_io, cl);
+ 	kfree(io);
+ }
+ 
+-static void write_moving_finish(struct closure *cl)
++static void write_moving_finish(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct moving_io *io = container_of(cl, struct moving_io, cl);
+ 	struct bio *bio = &io->bio.bio;
+ 	struct bio_vec *bv;
+@@ -92,8 +94,9 @@ static void moving_init(struct moving_io *io)
+ 	bch_bio_map(bio, NULL);
+ }
+ 
+-static void write_moving(struct closure *cl)
++static void write_moving(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct moving_io *io = container_of(cl, struct moving_io, cl);
+ 	struct data_insert_op *op = &io->op;
+ 
+@@ -116,8 +119,9 @@ static void write_moving(struct closure *cl)
+ 	continue_at(cl, write_moving_finish, op->wq);
+ }
+ 
+-static void read_moving_submit(struct closure *cl)
++static void read_moving_submit(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct moving_io *io = container_of(cl, struct moving_io, cl);
+ 	struct bio *bio = &io->bio.bio;
+ 
+diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
+index 25fa844..8181a97 100644
+--- a/drivers/md/bcache/request.c
++++ b/drivers/md/bcache/request.c
+@@ -24,7 +24,7 @@
+ 
+ struct kmem_cache *bch_search_cache;
+ 
+-static void bch_data_insert_start(struct closure *);
++static void bch_data_insert_start(struct work_struct *);
+ 
+ static unsigned cache_mode(struct cached_dev *dc, struct bio *bio)
+ {
+@@ -53,8 +53,9 @@ static void bio_csum(struct bio *bio, struct bkey *k)
+ 
+ /* Insert data into cache */
+ 
+-static void bch_data_insert_keys(struct closure *cl)
++static void bch_data_insert_keys(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ 	atomic_t *journal_ref = NULL;
+ 	struct bkey *replace_key = op->replace ? &op->replace_key : NULL;
+@@ -143,8 +144,9 @@ out:
+ 	continue_at(cl, bch_data_insert_keys, op->wq);
+ }
+ 
+-static void bch_data_insert_error(struct closure *cl)
++static void bch_data_insert_error(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ 
+ 	/*
+@@ -170,7 +172,7 @@ static void bch_data_insert_error(struct closure *cl)
+ 
+ 	op->insert_keys.top = dst;
+ 
+-	bch_data_insert_keys(cl);
++	bch_data_insert_keys(&cl->work);
+ }
+ 
+ static void bch_data_insert_endio(struct bio *bio)
+@@ -191,8 +193,9 @@ static void bch_data_insert_endio(struct bio *bio)
+ 	bch_bbio_endio(op->c, bio, bio->bi_error, "writing data to cache");
+ }
+ 
+-static void bch_data_insert_start(struct closure *cl)
++static void bch_data_insert_start(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ 	struct bio *bio = op->bio, *n;
+ 
+@@ -313,8 +316,9 @@ err:
+  * If s->bypass is true, instead of inserting the data it invalidates the
+  * region of the cache represented by s->cache_bio and op->inode.
+  */
+-void bch_data_insert(struct closure *cl)
++void bch_data_insert(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ 
+ 	trace_bcache_write(op->c, op->inode, op->bio,
+@@ -322,7 +326,7 @@ void bch_data_insert(struct closure *cl)
+ 
+ 	bch_keylist_init(&op->insert_keys);
+ 	bio_get(op->bio);
+-	bch_data_insert_start(cl);
++	bch_data_insert_start(&cl->work);
+ }
+ 
+ /* Congested? */
+@@ -570,8 +574,9 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
+ 	return n == bio ? MAP_DONE : MAP_CONTINUE;
+ }
+ 
+-static void cache_lookup(struct closure *cl)
++static void cache_lookup(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, iop.cl);
+ 	struct bio *bio = &s->bio.bio;
+ 	int ret;
+@@ -631,8 +636,9 @@ static void do_bio_hook(struct search *s, struct bio *orig_bio)
+ 	bio_cnt_set(bio, 3);
+ }
+ 
+-static void search_free(struct closure *cl)
++static void search_free(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	bio_complete(s);
+ 
+@@ -676,19 +682,21 @@ static inline struct search *search_alloc(struct bio *bio,
+ 
+ /* Cached devices */
+ 
+-static void cached_dev_bio_complete(struct closure *cl)
++static void cached_dev_bio_complete(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ 
+-	search_free(cl);
++	search_free(&cl->work);
+ 	cached_dev_put(dc);
+ }
+ 
+ /* Process reads */
+ 
+-static void cached_dev_cache_miss_done(struct closure *cl)
++static void cached_dev_cache_miss_done(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 
+ 	if (s->iop.replace_collision)
+@@ -702,11 +710,12 @@ static void cached_dev_cache_miss_done(struct closure *cl)
+ 			__free_page(bv->bv_page);
+ 	}
+ 
+-	cached_dev_bio_complete(cl);
++	cached_dev_bio_complete(&cl->work);
+ }
+ 
+-static void cached_dev_read_error(struct closure *cl)
++static void cached_dev_read_error(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	struct bio *bio = &s->bio.bio;
+ 
+@@ -725,8 +734,9 @@ static void cached_dev_read_error(struct closure *cl)
+ 	continue_at(cl, cached_dev_cache_miss_done, NULL);
+ }
+ 
+-static void cached_dev_read_done(struct closure *cl)
++static void cached_dev_read_done(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ 
+@@ -765,8 +775,9 @@ static void cached_dev_read_done(struct closure *cl)
+ 	continue_at(cl, cached_dev_cache_miss_done, NULL);
+ }
+ 
+-static void cached_dev_read_done_bh(struct closure *cl)
++static void cached_dev_read_done_bh(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ 
+@@ -864,13 +875,14 @@ static void cached_dev_read(struct cached_dev *dc, struct search *s)
+ 
+ /* Process writes */
+ 
+-static void cached_dev_write_complete(struct closure *cl)
++static void cached_dev_write_complete(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ 
+ 	up_read_non_owner(&dc->writeback_lock);
+-	cached_dev_bio_complete(cl);
++	cached_dev_bio_complete(&cl->work);
+ }
+ 
+ static void cached_dev_write(struct cached_dev *dc, struct search *s)
+@@ -942,8 +954,9 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s)
+ 	continue_at(cl, cached_dev_write_complete, NULL);
+ }
+ 
+-static void cached_dev_nodata(struct closure *cl)
++static void cached_dev_nodata(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 	struct bio *bio = &s->bio.bio;
+ 
+@@ -1063,8 +1076,9 @@ static int flash_dev_cache_miss(struct btree *b, struct search *s,
+ 	return MAP_CONTINUE;
+ }
+ 
+-static void flash_dev_nodata(struct closure *cl)
++static void flash_dev_nodata(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct search *s = container_of(cl, struct search, cl);
+ 
+ 	if (s->iop.flush_journal)
+diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h
+index 1ff3687..b8f4a05 100644
+--- a/drivers/md/bcache/request.h
++++ b/drivers/md/bcache/request.h
+@@ -33,7 +33,7 @@ struct data_insert_op {
+ };
+ 
+ unsigned bch_get_congested(struct cache_set *);
+-void bch_data_insert(struct closure *cl);
++void bch_data_insert(struct work_struct *work);
+ 
+ void bch_cached_dev_request_init(struct cached_dev *dc);
+ void bch_flash_dev_request_init(struct bcache_device *d);
 diff --git a/drivers/md/bcache/stats.c b/drivers/md/bcache/stats.c
 index 0ca072c..5e6e5c3 100644
 --- a/drivers/md/bcache/stats.c
@@ -53161,10 +53567,43 @@ index adbff14..018c2d2 100644
  	struct cache_stat_collector collector;
  
 diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
-index a296425..397607e 100644
+index a296425..c5d881c 100644
 --- a/drivers/md/bcache/super.c
 +++ b/drivers/md/bcache/super.c
-@@ -530,7 +530,7 @@ void bch_prio_write(struct cache *ca)
+@@ -241,8 +241,9 @@ static void __write_super(struct cache_sb *sb, struct bio *bio)
+ 	submit_bio(REQ_WRITE, bio);
+ }
+ 
+-static void bch_write_bdev_super_unlock(struct closure *cl)
++static void bch_write_bdev_super_unlock(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cached_dev *dc = container_of(cl, struct cached_dev, sb_write);
+ 
+ 	up(&dc->sb_write_mutex);
+@@ -275,8 +276,9 @@ static void write_super_endio(struct bio *bio)
+ 	closure_put(&ca->set->sb_write);
+ }
+ 
+-static void bcache_write_super_unlock(struct closure *cl)
++static void bcache_write_super_unlock(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, sb_write);
+ 
+ 	up(&c->sb_write_mutex);
+@@ -326,8 +328,9 @@ static void uuid_endio(struct bio *bio)
+ 	closure_put(cl);
+ }
+ 
+-static void uuid_io_unlock(struct closure *cl)
++static void uuid_io_unlock(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, uuid_write);
+ 
+ 	up(&c->uuid_write_mutex);
+@@ -530,7 +533,7 @@ void bch_prio_write(struct cache *ca)
  
  	ca->disk_buckets->seq++;
  
@@ -53173,6 +53612,83 @@ index a296425..397607e 100644
  			&ca->meta_sectors_written);
  
  	//pr_debug("free %zu, free_inc %zu, unused %zu", fifo_used(&ca->free),
+@@ -1049,8 +1052,9 @@ void bch_cached_dev_release(struct kobject *kobj)
+ 	module_put(THIS_MODULE);
+ }
+ 
+-static void cached_dev_free(struct closure *cl)
++static void cached_dev_free(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
+ 
+ 	cancel_delayed_work_sync(&dc->writeback_rate_update);
+@@ -1074,8 +1078,9 @@ static void cached_dev_free(struct closure *cl)
+ 	kobject_put(&dc->disk.kobj);
+ }
+ 
+-static void cached_dev_flush(struct closure *cl)
++static void cached_dev_flush(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
+ 	struct bcache_device *d = &dc->disk;
+ 
+@@ -1191,8 +1196,9 @@ void bch_flash_dev_release(struct kobject *kobj)
+ 	kfree(d);
+ }
+ 
+-static void flash_dev_free(struct closure *cl)
++static void flash_dev_free(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+ 	mutex_lock(&bch_register_lock);
+ 	bcache_device_free(d);
+@@ -1200,8 +1206,9 @@ static void flash_dev_free(struct closure *cl)
+ 	kobject_put(&d->kobj);
+ }
+ 
+-static void flash_dev_flush(struct closure *cl)
++static void flash_dev_flush(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+ 
+ 	mutex_lock(&bch_register_lock);
+@@ -1320,8 +1327,9 @@ void bch_cache_set_release(struct kobject *kobj)
+ 	module_put(THIS_MODULE);
+ }
+ 
+-static void cache_set_free(struct closure *cl)
++static void cache_set_free(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, cl);
+ 	struct cache *ca;
+ 	unsigned i;
+@@ -1366,8 +1374,9 @@ static void cache_set_free(struct closure *cl)
+ 	kobject_put(&c->kobj);
+ }
+ 
+-static void cache_set_flush(struct closure *cl)
++static void cache_set_flush(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, caching);
+ 	struct cache *ca;
+ 	struct btree *b;
+@@ -1408,8 +1417,9 @@ static void cache_set_flush(struct closure *cl)
+ 	closure_return(cl);
+ }
+ 
+-static void __cache_set_unregister(struct closure *cl)
++static void __cache_set_unregister(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct cache_set *c = container_of(cl, struct cache_set, caching);
+ 	struct cached_dev *dc;
+ 	size_t i;
 diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
 index b3ff57d..b2e30fb 100644
 --- a/drivers/md/bcache/sysfs.c
@@ -53215,6 +53731,51 @@ index b3ff57d..b2e30fb 100644
  	}
  
  	return size;
+diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
+index b9346cd..708ea8f 100644
+--- a/drivers/md/bcache/writeback.c
++++ b/drivers/md/bcache/writeback.c
+@@ -118,14 +118,16 @@ static void dirty_init(struct keybuf_key *w)
+ 	bch_bio_map(bio, NULL);
+ }
+ 
+-static void dirty_io_destructor(struct closure *cl)
++static void dirty_io_destructor(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+ 	kfree(io);
+ }
+ 
+-static void write_dirty_finish(struct closure *cl)
++static void write_dirty_finish(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+ 	struct keybuf_key *w = io->bio.bi_private;
+ 	struct cached_dev *dc = io->dc;
+@@ -177,8 +179,9 @@ static void dirty_endio(struct bio *bio)
+ 	closure_put(&io->cl);
+ }
+ 
+-static void write_dirty(struct closure *cl)
++static void write_dirty(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+ 	struct keybuf_key *w = io->bio.bi_private;
+ 
+@@ -204,8 +207,9 @@ static void read_dirty_endio(struct bio *bio)
+ 	dirty_endio(bio);
+ }
+ 
+-static void read_dirty_submit(struct closure *cl)
++static void read_dirty_submit(struct work_struct *work)
+ {
++	struct closure *cl = container_of(work, struct closure, work);
+ 	struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+ 
+ 	closure_bio_submit(&io->bio, cl);
 diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
 index d80cce4..d7f15c4 100644
 --- a/drivers/md/bitmap.c
@@ -54725,6 +55286,19 @@ index 80caa70..d076ecf 100644
  
  	vma->vm_ops = &zoran_vm_ops;
  	vma->vm_flags |= VM_DONTEXPAND;
+diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
+index de32e3a..e6a7bff 100644
+--- a/drivers/media/platform/am437x/am437x-vpfe.c
++++ b/drivers/media/platform/am437x/am437x-vpfe.c
+@@ -1706,7 +1706,7 @@ static int vpfe_get_app_input_index(struct vpfe_device *vpfe,
+ 		sdinfo = &cfg->sub_devs[i];
+ 		client = v4l2_get_subdevdata(sdinfo->sd);
+ 		if (client->addr == curr_client->addr &&
+-		    client->adapter->nr == client->adapter->nr) {
++		    client->adapter->nr == curr_client->adapter->nr) {
+ 			if (vpfe->current_input >= 1)
+ 				return -1;
+ 			*app_input_index = j + vpfe->current_input;
 diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
 index 70c28d1..ff21b13 100644
 --- a/drivers/media/platform/omap/omap_vout.c
@@ -56578,7 +57152,7 @@ index f7ab115..16b2087 100644
  	if (!irq) {
  		dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
 diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
-index 40e51b0..b986312 100644
+index 40e51b0..af35565 100644
 --- a/drivers/mfd/twl4030-irq.c
 +++ b/drivers/mfd/twl4030-irq.c
 @@ -34,6 +34,7 @@
@@ -56597,16 +57171,16 @@ index 40e51b0..b986312 100644
 -	twl4030_irq_chip.name = "twl4030";
 +	pax_open_kernel();
 +	memcpy((void *)&twl4030_irq_chip, &dummy_irq_chip, sizeof twl4030_irq_chip);
-+	*(const char **)&twl4030_irq_chip.name = "twl4030";
++	const_cast(twl4030_irq_chip.name) = "twl4030";
  
 -	twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
-+	*(void **)&twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
++	const_cast(twl4030_sih_irq_chip.irq_ack) = dummy_irq_chip.irq_ack;
 +	pax_close_kernel();
  
  	for (i = irq_base; i < irq_end; i++) {
  		irq_set_chip_and_handler(i, &twl4030_irq_chip,
 diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
-index cc8645b..7cc15e4 100644
+index cc8645b..ab85ae4 100644
 --- a/drivers/misc/c2port/core.c
 +++ b/drivers/misc/c2port/core.c
 @@ -922,7 +922,9 @@ struct c2port_device *c2port_device_register(char *name,
@@ -56615,7 +57189,7 @@ index cc8645b..7cc15e4 100644
  
 -	bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
 +	pax_open_kernel();
-+	*(size_t *)&bin_attr_flash_data.size = ops->blocks_num * ops->block_size;
++	const_cast(bin_attr_flash_data.size) = ops->blocks_num * ops->block_size;
 +	pax_close_kernel();
  
  	c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
@@ -56705,7 +57279,7 @@ index c439c82..1f20f57 100644
  	int			mapped_btns[3];
  
 diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c
-index ddc9e4b..7b9c669 100644
+index ddc9e4b..9e27f41 100644
 --- a/drivers/misc/mic/scif/scif_api.c
 +++ b/drivers/misc/mic/scif/scif_api.c
 @@ -1486,10 +1486,12 @@ int scif_client_register(struct scif_client *client)
@@ -56717,10 +57291,10 @@ index ddc9e4b..7b9c669 100644
 -	si->add_dev = scif_add_client_dev;
 -	si->remove_dev = scif_remove_client_dev;
 +	pax_open_kernel();
-+	*(const char **)&si->name = client->name;
-+	*(struct bus_type **)&si->subsys = &scif_peer_bus;
-+	*(void **)&si->add_dev = scif_add_client_dev;
-+	*(void **)&si->remove_dev = scif_remove_client_dev;
++	const_cast(si->name) = client->name;
++	const_cast(si->subsys) = &scif_peer_bus;
++	const_cast(si->add_dev) = scif_add_client_dev;
++	const_cast(si->remove_dev) = scif_remove_client_dev;
 +	pax_close_kernel();
  
  	return subsys_interface_register(&client->si);
@@ -57235,7 +57809,7 @@ index f695b58..7b7d017 100644
 +} __do_const;
  #endif /* _DW_MMC_H_ */
 diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
-index 0d6ca41..d438654 100644
+index 0d6ca41..bdc6710 100644
 --- a/drivers/mmc/host/mmci.c
 +++ b/drivers/mmc/host/mmci.c
 @@ -1634,7 +1634,9 @@ static int mmci_probe(struct amba_device *dev,
@@ -57244,13 +57818,13 @@ index 0d6ca41..d438654 100644
  	if (variant->busy_detect) {
 -		mmci_ops.card_busy = mmci_card_busy;
 +		pax_open_kernel();
-+		*(void **)&mmci_ops.card_busy = mmci_card_busy;
++		const_cast(mmci_ops.card_busy) = mmci_card_busy;
 +		pax_close_kernel();
  		mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
  		mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
  		mmc->max_busy_timeout = 0;
 diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
-index f6e4d97..57358ff 100644
+index f6e4d97..8bd8c05 100644
 --- a/drivers/mmc/host/omap_hsmmc.c
 +++ b/drivers/mmc/host/omap_hsmmc.c
 @@ -2088,7 +2088,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
@@ -57259,13 +57833,13 @@ index f6e4d97..57358ff 100644
  		dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
 -		omap_hsmmc_ops.multi_io_quirk = omap_hsmmc_multi_io_quirk;
 +		pax_open_kernel();
-+		*(void **)&omap_hsmmc_ops.multi_io_quirk = omap_hsmmc_multi_io_quirk;
++		const_cast(omap_hsmmc_ops.multi_io_quirk) = omap_hsmmc_multi_io_quirk;
 +		pax_close_kernel();
  	}
  
  	device_init_wakeup(&pdev->dev, true);
 diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
-index f25f292..a0e1250 100644
+index f25f292..7f4b03f 100644
 --- a/drivers/mmc/host/sdhci-esdhc-imx.c
 +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
 @@ -1194,9 +1194,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
@@ -57276,7 +57850,7 @@ index f25f292..a0e1250 100644
 -		sdhci_esdhc_ops.platform_execute_tuning =
 +	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
 +		pax_open_kernel();
-+		*(void **)&sdhci_esdhc_ops.platform_execute_tuning =
++		const_cast(sdhci_esdhc_ops.platform_execute_tuning) =
  					esdhc_executing_tuning;
 +		pax_close_kernel();
 +	}
@@ -57284,7 +57858,7 @@ index f25f292..a0e1250 100644
  	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
  		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
 diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
-index 70c724b..308aafc 100644
+index 70c724b..0c24beb 100644
 --- a/drivers/mmc/host/sdhci-s3c.c
 +++ b/drivers/mmc/host/sdhci-s3c.c
 @@ -598,9 +598,11 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
@@ -57295,9 +57869,9 @@ index 70c724b..308aafc 100644
 -		sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
 -		sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
 +		pax_open_kernel();
-+		*(void **)&sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
-+		*(void **)&sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
-+		*(void **)&sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
++		const_cast(sdhci_s3c_ops.set_clock) = sdhci_cmu_set_clock;
++		const_cast(sdhci_s3c_ops.get_min_clock) = sdhci_cmu_get_min_clock;
++		const_cast(sdhci_s3c_ops.get_max_clock) = sdhci_cmu_get_max_clock;
 +		pax_close_kernel();
  	}
  
@@ -59971,7 +60545,7 @@ index 245c063..74ed9c9 100644
  	mdio_cmd->op = op;
  	mdio_cmd->mdio_addr = loc;
 diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
-index 34d269c..43dcc17 100644
+index 34d269c..69e1ac2 100644
 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
 +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
 @@ -475,7 +475,7 @@ static void stop_pci_io(struct octeon_device *oct)
@@ -60018,7 +60592,7 @@ index 34d269c..43dcc17 100644
 -			lionetdevops.ndo_select_queue = select_q;
 +		if (num_iqueues > 1) {
 +			pax_open_kernel();
-+			*(void **)&lionetdevops.ndo_select_queue = select_q;
++			const_cast(lionetdevops.ndo_select_queue) = select_q;
 +			pax_close_kernel();
 +		}
  
@@ -60316,7 +60890,7 @@ index e51892d..3e645f4 100644
  	struct hix5hd2_priv *priv = netdev_priv(dev);
  	struct hix5hd2_desc *desc;
 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
-index d4f92ed..38fdf5b 100644
+index d4f92ed..d4755e0 100644
 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
 +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
 @@ -857,16 +857,18 @@ int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev)
@@ -60327,11 +60901,11 @@ index d4f92ed..38fdf5b 100644
  	switch (dsaf_dev->dsaf_ver) {
  	case AE_VERSION_1:
 -		hns_dsaf_ops.toggle_ring_irq = hns_ae_toggle_ring_irq;
-+		*(void **)&hns_dsaf_ops.toggle_ring_irq = hns_ae_toggle_ring_irq;
++		const_cast(hns_dsaf_ops.toggle_ring_irq) = hns_ae_toggle_ring_irq;
  		break;
  	case AE_VERSION_2:
 -		hns_dsaf_ops.toggle_ring_irq = hns_aev2_toggle_ring_irq;
-+		*(void **)&hns_dsaf_ops.toggle_ring_irq = hns_aev2_toggle_ring_irq;
++		const_cast(hns_dsaf_ops.toggle_ring_irq) = hns_aev2_toggle_ring_irq;
  		break;
  	default:
  		break;
@@ -60809,7 +61383,7 @@ index 6409a06..e5bd4d6 100644
  	struct netxen_adapter *adapter = pci_get_drvdata(pdev);
  
 diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
-index bf89216..4044d8c 100644
+index bf89216..b08442a 100644
 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
 @@ -2324,7 +2324,9 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
@@ -60818,13 +61392,13 @@ index bf89216..4044d8c 100644
  		ahw->nic_mode = QLCNIC_DEFAULT_MODE;
 -		adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
 +		pax_open_kernel();
-+		*(void **)&adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
++		const_cast(adapter->nic_ops->init_driver) = qlcnic_83xx_init_default_driver;
 +		pax_close_kernel();
  		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
  		max_sds_rings = QLCNIC_MAX_SDS_RINGS;
  		max_tx_rings = QLCNIC_MAX_TX_RINGS;
 diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
-index 3490675..0b9e15a 100644
+index 3490675..cf148ea 100644
 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
 @@ -207,17 +207,23 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
@@ -60833,7 +61407,7 @@ index 3490675..0b9e15a 100644
  		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
 -		nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
 +		pax_open_kernel();
-+		*(void **)&nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
++		const_cast(nic_ops->init_driver) = qlcnic_83xx_init_non_privileged_vnic;
 +		pax_close_kernel();
  		break;
  	case QLCNIC_PRIV_FUNC:
@@ -60841,7 +61415,7 @@ index 3490675..0b9e15a 100644
  		ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry;
 -		nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
 +		pax_open_kernel();
-+		*(void **)&nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
++		const_cast(nic_ops->init_driver) = qlcnic_83xx_init_privileged_vnic;
 +		pax_close_kernel();
  		break;
  	case QLCNIC_MGMT_FUNC:
@@ -60849,7 +61423,7 @@ index 3490675..0b9e15a 100644
  		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
 -		nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
 +		pax_open_kernel();
-+		*(void **)&nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
++		const_cast(nic_ops->init_driver) = qlcnic_83xx_init_mgmt_vnic;
 +		pax_close_kernel();
  		break;
  	default:
@@ -61604,7 +62178,7 @@ index f9db2ce..6cd460c 100644
  }
  
 diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
-index 94e6888..1d08b6a 100644
+index 94e6888..c5c3f55 100644
 --- a/drivers/net/macvlan.c
 +++ b/drivers/net/macvlan.c
 @@ -335,7 +335,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
@@ -61628,13 +62202,13 @@ index 94e6888..1d08b6a 100644
 -	ops->get_size		= macvlan_get_size;
 -	ops->fill_info		= macvlan_fill_info;
 +	pax_open_kernel();
-+	*(size_t *)&ops->priv_size	= sizeof(struct macvlan_dev);
-+	*(void **)&ops->validate	= macvlan_validate;
-+	*(int *)&ops->maxtype		= IFLA_MACVLAN_MAX;
-+	*(const void **)&ops->policy	= macvlan_policy;
-+	*(void **)&ops->changelink	= macvlan_changelink;
-+	*(void **)&ops->get_size	= macvlan_get_size;
-+	*(void **)&ops->fill_info	= macvlan_fill_info;
++	const_cast(ops->priv_size)	= sizeof(struct macvlan_dev);
++	const_cast(ops->validate)	= macvlan_validate;
++	const_cast(ops->maxtype)	= IFLA_MACVLAN_MAX;
++	const_cast(ops->policy)		= macvlan_policy;
++	const_cast(ops->changelink)	= macvlan_changelink;
++	const_cast(ops->get_size)	= macvlan_get_size;
++	const_cast(ops->fill_info)	= macvlan_fill_info;
 +	pax_close_kernel();
  
  	return rtnl_link_register(ops);
@@ -62585,7 +63159,7 @@ index 831a544..d846785 100644
  struct ath_nf_limits {
  	s16 max;
 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
-index c1b33fd..9f904b1 100644
+index c1b33fd..d61f3b4 100644
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
 @@ -2589,16 +2589,18 @@ void ath9k_fill_chanctx_ops(void)
@@ -62603,16 +63177,16 @@ index c1b33fd..9f904b1 100644
 -	ath9k_ops.unassign_vif_chanctx     = ath9k_unassign_vif_chanctx;
 -	ath9k_ops.mgd_prepare_tx           = ath9k_mgd_prepare_tx;
 +	pax_open_kernel();
-+	*(void **)&ath9k_ops.hw_scan                  = ath9k_hw_scan;
-+	*(void **)&ath9k_ops.cancel_hw_scan           = ath9k_cancel_hw_scan;
-+	*(void **)&ath9k_ops.remain_on_channel        = ath9k_remain_on_channel;
-+	*(void **)&ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
-+	*(void **)&ath9k_ops.add_chanctx              = ath9k_add_chanctx;
-+	*(void **)&ath9k_ops.remove_chanctx           = ath9k_remove_chanctx;
-+	*(void **)&ath9k_ops.change_chanctx           = ath9k_change_chanctx;
-+	*(void **)&ath9k_ops.assign_vif_chanctx       = ath9k_assign_vif_chanctx;
-+	*(void **)&ath9k_ops.unassign_vif_chanctx     = ath9k_unassign_vif_chanctx;
-+	*(void **)&ath9k_ops.mgd_prepare_tx           = ath9k_mgd_prepare_tx;
++	const_cast(ath9k_ops.hw_scan)                  = ath9k_hw_scan;
++	const_cast(ath9k_ops.cancel_hw_scan)           = ath9k_cancel_hw_scan;
++	const_cast(ath9k_ops.remain_on_channel)        = ath9k_remain_on_channel;
++	const_cast(ath9k_ops.cancel_remain_on_channel) = ath9k_cancel_remain_on_channel;
++	const_cast(ath9k_ops.add_chanctx)              = ath9k_add_chanctx;
++	const_cast(ath9k_ops.remove_chanctx)           = ath9k_remove_chanctx;
++	const_cast(ath9k_ops.change_chanctx)           = ath9k_change_chanctx;
++	const_cast(ath9k_ops.assign_vif_chanctx)       = ath9k_assign_vif_chanctx;
++	const_cast(ath9k_ops.unassign_vif_chanctx)     = ath9k_unassign_vif_chanctx;
++	const_cast(ath9k_ops.mgd_prepare_tx)           = ath9k_mgd_prepare_tx;
 +	pax_close_kernel();
  }
  
@@ -63861,7 +64435,7 @@ index ed0adaf..4bb4f53 100644
  	return ret;
  }
 diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
-index af1b3e6..9bc08d3 100644
+index af1b3e6..c014779 100644
 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
 +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
 @@ -1399,8 +1399,9 @@ il3945_dump_nic_error_log(struct il_priv *il)
@@ -63899,7 +64473,7 @@ index af1b3e6..9bc08d3 100644
  		D_INFO("Disabling hw_scan\n");
 -		il3945_mac_ops.hw_scan = NULL;
 +		pax_open_kernel();
-+		*(void **)&il3945_mac_ops.hw_scan = NULL;
++		const_cast(il3945_mac_ops.hw_scan) = NULL;
 +		pax_close_kernel();
  	}
  
@@ -65682,7 +66256,7 @@ index 48e8a97..3499ec8 100644
  
  const struct iw_handler_def prism54_handler_def = {
 diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
-index a28414c..26c8768 100644
+index a28414c..ad61156 100644
 --- a/drivers/net/wireless/mac80211_hwsim.c
 +++ b/drivers/net/wireless/mac80211_hwsim.c
 @@ -3218,20 +3218,20 @@ static int __init init_mac80211_hwsim(void)
@@ -65705,17 +66279,17 @@ index a28414c..26c8768 100644
 -		mac80211_hwsim_unassign_vif_chanctx;
 +	pax_open_kernel();
 +	memcpy((void *)&mac80211_hwsim_mchan_ops, &mac80211_hwsim_ops, sizeof mac80211_hwsim_mchan_ops);
-+	*(void **)&mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
-+	*(void **)&mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
-+	*(void **)&mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
-+	*(void **)&mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
-+	*(void **)&mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
-+	*(void **)&mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
-+	*(void **)&mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
-+	*(void **)&mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
-+	*(void **)&mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
-+	*(void **)&mac80211_hwsim_mchan_ops.assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx;
-+	*(void **)&mac80211_hwsim_mchan_ops.unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx;
++	const_cast(mac80211_hwsim_mchan_ops.hw_scan) = mac80211_hwsim_hw_scan;
++	const_cast(mac80211_hwsim_mchan_ops.cancel_hw_scan) = mac80211_hwsim_cancel_hw_scan;
++	const_cast(mac80211_hwsim_mchan_ops.sw_scan_start) = NULL;
++	const_cast(mac80211_hwsim_mchan_ops.sw_scan_complete) = NULL;
++	const_cast(mac80211_hwsim_mchan_ops.remain_on_channel) = mac80211_hwsim_roc;
++	const_cast(mac80211_hwsim_mchan_ops.cancel_remain_on_channel) = mac80211_hwsim_croc;
++	const_cast(mac80211_hwsim_mchan_ops.add_chanctx) = mac80211_hwsim_add_chanctx;
++	const_cast(mac80211_hwsim_mchan_ops.remove_chanctx) = mac80211_hwsim_remove_chanctx;
++	const_cast(mac80211_hwsim_mchan_ops.change_chanctx) = mac80211_hwsim_change_chanctx;
++	const_cast(mac80211_hwsim_mchan_ops.assign_vif_chanctx) = mac80211_hwsim_assign_vif_chanctx;
++	const_cast(mac80211_hwsim_mchan_ops.unassign_vif_chanctx) = mac80211_hwsim_unassign_vif_chanctx;
 +	pax_close_kernel();
  
  	spin_lock_init(&hwsim_radio_lock);
@@ -66131,7 +66705,7 @@ index 29dfc51..8297755 100644
  void rtl_swlps_rf_sleep(struct ieee80211_hw *hw);
  void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state);
 diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c
-index b661f896..ddf7d2b 100644
+index b661f896..ebea675 100644
 --- a/drivers/net/wireless/ti/wl1251/sdio.c
 +++ b/drivers/net/wireless/ti/wl1251/sdio.c
 @@ -282,13 +282,17 @@ static int wl1251_sdio_probe(struct sdio_func *func,
@@ -66141,8 +66715,8 @@ index b661f896..ddf7d2b 100644
 -		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
 -		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
 +		pax_open_kernel();
-+		*(void **)&wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
-+		*(void **)&wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
++		const_cast(wl1251_sdio_ops.enable_irq) = wl1251_enable_line_irq;
++		const_cast(wl1251_sdio_ops.disable_irq) = wl1251_disable_line_irq;
 +		pax_close_kernel();
  
  		wl1251_info("using dedicated interrupt line");
@@ -66150,14 +66724,14 @@ index b661f896..ddf7d2b 100644
 -		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
 -		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
 +		pax_open_kernel();
-+		*(void **)&wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq;
-+		*(void **)&wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq;
++		const_cast(wl1251_sdio_ops.enable_irq) = wl1251_sdio_enable_irq;
++		const_cast(wl1251_sdio_ops.disable_irq) = wl1251_sdio_disable_irq;
 +		pax_close_kernel();
  
  		wl1251_info("using SDIO interrupt");
  	}
 diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
-index a0d6ccc..93d9ac5 100644
+index a0d6ccc..36e1ae3 100644
 --- a/drivers/net/wireless/ti/wl12xx/main.c
 +++ b/drivers/net/wireless/ti/wl12xx/main.c
 @@ -656,7 +656,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
@@ -66166,7 +66740,7 @@ index a0d6ccc..93d9ac5 100644
  		/* read data preparation is only needed by wl127x */
 -		wl->ops->prepare_read = wl127x_prepare_read;
 +		pax_open_kernel();
-+		*(void **)&wl->ops->prepare_read = wl127x_prepare_read;
++		const_cast(wl->ops->prepare_read) = wl127x_prepare_read;
 +		pax_close_kernel();
  
  		wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
@@ -66177,13 +66751,13 @@ index a0d6ccc..93d9ac5 100644
  		/* read data preparation is only needed by wl127x */
 -		wl->ops->prepare_read = wl127x_prepare_read;
 +		pax_open_kernel();
-+		*(void **)&wl->ops->prepare_read = wl127x_prepare_read;
++		const_cast(wl->ops->prepare_read) = wl127x_prepare_read;
 +		pax_close_kernel();
  
  		wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
  			      WL127X_IFTYPE_SR_VER,  WL127X_MAJOR_SR_VER,
 diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
-index 1bf26cc..3b15c02 100644
+index 1bf26cc..7dd1267 100644
 --- a/drivers/net/wireless/ti/wl18xx/main.c
 +++ b/drivers/net/wireless/ti/wl18xx/main.c
 @@ -2018,8 +2018,10 @@ static int wl18xx_setup(struct wl1271 *wl)
@@ -66193,8 +66767,8 @@ index 1bf26cc..3b15c02 100644
 -		wl18xx_ops.set_rx_csum = NULL;
 -		wl18xx_ops.init_vif = NULL;
 +		pax_open_kernel();
-+		*(void **)&wl18xx_ops.set_rx_csum = NULL;
-+		*(void **)&wl18xx_ops.init_vif = NULL;
++		const_cast(wl18xx_ops.set_rx_csum) = NULL;
++		const_cast(wl18xx_ops.init_vif) = NULL;
 +		pax_close_kernel();
  	}
  
@@ -66687,7 +67261,7 @@ index 680f578..cf80097 100644
  	struct nvme_dev *dev = pci_get_drvdata(pdev);
  
 diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
-index 655f79d..509e3cd 100644
+index 655f79d..c684ede 100644
 --- a/drivers/of/fdt.c
 +++ b/drivers/of/fdt.c
 @@ -1170,7 +1170,9 @@ static int __init of_fdt_raw_init(void)
@@ -66696,7 +67270,7 @@ index 655f79d..509e3cd 100644
  	}
 -	of_fdt_raw_attr.size = fdt_totalsize(initial_boot_params);
 +	pax_open_kernel();
-+	*(size_t *)&of_fdt_raw_attr.size = fdt_totalsize(initial_boot_params);
++	const_cast(of_fdt_raw_attr.size) = fdt_totalsize(initial_boot_params);
 +	pax_close_kernel();
  	return sysfs_create_bin_file(firmware_kobj, &of_fdt_raw_attr);
  }
@@ -66881,7 +67455,7 @@ index 1652bc7..4f999c4 100644
  struct gen_pci_cfg_windows {
  	struct resource				res;
 diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
-index 2f6d3a1..5bc1bf1 100644
+index 2f6d3a1..cb43cfc 100644
 --- a/drivers/pci/hotplug/acpiphp_ibm.c
 +++ b/drivers/pci/hotplug/acpiphp_ibm.c
 @@ -463,7 +463,9 @@ static int __init ibm_acpiphp_init(void)
@@ -66890,7 +67464,7 @@ index 2f6d3a1..5bc1bf1 100644
  
 -	ibm_apci_table_attr.size = ibm_get_table_from_acpi(NULL);
 +	pax_open_kernel();
-+	*(size_t *)&ibm_apci_table_attr.size = ibm_get_table_from_acpi(NULL);
++	const_cast(ibm_apci_table_attr.size) = ibm_get_table_from_acpi(NULL);
 +	pax_close_kernel();
  	retval = sysfs_create_bin_file(sysdir, &ibm_apci_table_attr);
  
@@ -66927,7 +67501,7 @@ index 88a44a7..de358ce 100644
  
  	status = cpci_hp_register_controller(&generic_hpc);
 diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
-index 5f49c3f..989cd41 100644
+index 5f49c3f..438f019 100644
 --- a/drivers/pci/hotplug/cpcihp_zt5550.c
 +++ b/drivers/pci/hotplug/cpcihp_zt5550.c
 @@ -59,7 +59,6 @@
@@ -66964,9 +67538,9 @@ index 5f49c3f..989cd41 100644
 -		zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
 -		zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
 +		pax_open_kernel();
-+		*(void **)&zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq;
-+		*(void **)&zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
-+		*(void **)&zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
++		const_cast(zt5550_hpc_ops.enable_irq) = zt5550_hc_enable_irq;
++		const_cast(zt5550_hpc_ops.disable_irq) = zt5550_hc_disable_irq;
++		const_cast(zt5550_hpc_ops.check_irq) = zt5550_hc_check_irq;
 +		pax_open_kernel();
  	} else {
  		info("using ENUM# polling mode");
@@ -66987,7 +67561,7 @@ index c25fc90..b054774 100644
  	dbg("int15 entry  = %p\n", compaq_int15_entry_point);
  
 diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
-index 9acd199..0645a09 100644
+index 9acd199..1b19f5b 100644
 --- a/drivers/pci/hotplug/pci_hotplug_core.c
 +++ b/drivers/pci/hotplug/pci_hotplug_core.c
 @@ -434,8 +434,10 @@ int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,
@@ -66997,8 +67571,8 @@ index 9acd199..0645a09 100644
 -	slot->ops->owner = owner;
 -	slot->ops->mod_name = mod_name;
 +	pax_open_kernel();
-+	*(struct module **)&slot->ops->owner = owner;
-+	*(const char **)&slot->ops->mod_name = mod_name;
++	const_cast(slot->ops->owner) = owner;
++	const_cast(slot->ops->mod_name) = mod_name;
 +	pax_close_kernel();
  
  	mutex_lock(&pci_hp_mutex);
@@ -67017,7 +67591,7 @@ index ac531e6..716d058 100644
  	int retval = -ENOMEM;
  
 diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
-index a080f44..9ff42d9 100644
+index a080f44..24ad26c 100644
 --- a/drivers/pci/msi.c
 +++ b/drivers/pci/msi.c
 @@ -474,8 +474,8 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
@@ -67047,13 +67621,13 @@ index a080f44..9ff42d9 100644
 +		pax_open_kernel();
  		if (ops->set_desc == NULL)
 -			ops->set_desc = pci_msi_domain_set_desc;
-+			*(void **)&ops->set_desc = pci_msi_domain_set_desc;
++			const_cast(ops->set_desc) = pci_msi_domain_set_desc;
  		if (ops->msi_check == NULL)
 -			ops->msi_check = pci_msi_domain_check_cap;
-+			*(void **)&ops->msi_check = pci_msi_domain_check_cap;
++			const_cast(ops->msi_check) = pci_msi_domain_check_cap;
  		if (ops->handle_error == NULL)
 -			ops->handle_error = pci_msi_domain_handle_error;
-+			*(void **)&ops->handle_error = pci_msi_domain_handle_error;
++			const_cast(ops->handle_error) = pci_msi_domain_handle_error;
 +		pax_close_kernel();
  	}
  }
@@ -67065,13 +67639,13 @@ index a080f44..9ff42d9 100644
 +	pax_open_kernel();
  	if (!chip->irq_write_msi_msg)
 -		chip->irq_write_msi_msg = pci_msi_domain_write_msg;
-+		*(void **)&chip->irq_write_msi_msg = pci_msi_domain_write_msg;
++		const_cast(chip->irq_write_msi_msg) = pci_msi_domain_write_msg;
  	if (!chip->irq_mask)
 -		chip->irq_mask = pci_msi_mask_irq;
-+		*(void **)&chip->irq_mask = pci_msi_mask_irq;
++		const_cast(chip->irq_mask) = pci_msi_mask_irq;
  	if (!chip->irq_unmask)
 -		chip->irq_unmask = pci_msi_unmask_irq;
-+		*(void **)&chip->irq_unmask = pci_msi_unmask_irq;
++		const_cast(chip->irq_unmask) = pci_msi_unmask_irq;
 +	pax_close_kernel();
  }
  
@@ -67238,7 +67812,7 @@ index c8969dd..4764267 100644
  	bool supports_sleepmode;
  	int irq;
 diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
-index 523b6b7..e9aa88d 100644
+index 523b6b7..eb4c74d 100644
 --- a/drivers/pinctrl/pinctrl-at91.c
 +++ b/drivers/pinctrl/pinctrl-at91.c
 @@ -24,6 +24,7 @@
@@ -67255,7 +67829,7 @@ index 523b6b7..e9aa88d 100644
  	/* Setup proper .irq_set_type function */
 -	gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
 +	pax_open_kernel();
-+	*(void **)&gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
++	const_cast(gpio_irqchip.irq_set_type) = at91_gpio->ops->irq_type;
 +	pax_close_kernel();
  
  	/* Disable irqs of this PIO controller */
@@ -67398,7 +67972,7 @@ index 6aa33c4..cfb5425 100644
  		.ident = "OakTrail platform",
  		.matches = {
 diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
-index 4231770..10a6caf 100644
+index 4231770..cbf93a6 100644
 --- a/drivers/platform/x86/msi-laptop.c
 +++ b/drivers/platform/x86/msi-laptop.c
 @@ -605,7 +605,7 @@ static int dmi_check_cb(const struct dmi_system_id *dmi)
@@ -67421,12 +67995,12 @@ index 4231770..10a6caf 100644
 -		dev_attr_wlan.attr.mode |= S_IWUSR;
 -		dev_attr_threeg.attr.mode |= S_IWUSR;
 +		pax_open_kernel();
-+		*(void **)&dev_attr_bluetooth.store = store_bluetooth;
-+		*(void **)&dev_attr_wlan.store = store_wlan;
-+		*(void **)&dev_attr_threeg.store = store_threeg;
-+		*(umode_t *)&dev_attr_bluetooth.attr.mode |= S_IWUSR;
-+		*(umode_t *)&dev_attr_wlan.attr.mode |= S_IWUSR;
-+		*(umode_t *)&dev_attr_threeg.attr.mode |= S_IWUSR;
++		const_cast(dev_attr_bluetooth.store) = store_bluetooth;
++		const_cast(dev_attr_wlan.store) = store_wlan;
++		const_cast(dev_attr_threeg.store) = store_threeg;
++		const_cast(dev_attr_bluetooth.attr.mode) |= S_IWUSR;
++		const_cast(dev_attr_wlan.attr.mode) |= S_IWUSR;
++		const_cast(dev_attr_threeg.attr.mode) |= S_IWUSR;
 +		pax_close_kernel();
  	}
  
@@ -67756,7 +68330,7 @@ index ed2d7fd..266b28f 100644
  		__power_supply_attrs[i] = &power_supply_attrs[i].attr;
  }
 diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
-index 1b5d450..3257054 100644
+index 1b5d450..b6042f8 100644
 --- a/drivers/power/reset/at91-reset.c
 +++ b/drivers/power/reset/at91-reset.c
 @@ -17,6 +17,7 @@
@@ -67773,13 +68347,13 @@ index 1b5d450..3257054 100644
  	match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
 -	at91_restart_nb.notifier_call = match->data;
 +	pax_open_kernel();
-+	*(void **)&at91_restart_nb.notifier_call = match->data;
++	const_cast(at91_restart_nb.notifier_call) = match->data;
 +	pax_close_kernel();
  
  	sclk = devm_clk_get(&pdev->dev, NULL);
  	if (IS_ERR(sclk))
 diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
-index 14bde0d..89f2669 100644
+index 14bde0d..9391277 100644
 --- a/drivers/powercap/powercap_sys.c
 +++ b/drivers/powercap/powercap_sys.c
 @@ -154,8 +154,77 @@ struct powercap_constraint_attr {
@@ -67887,7 +68461,7 @@ index 14bde0d..89f2669 100644
 -	dev_attr->store = store;
 +
 +	pax_open_kernel();
-+	*(const char **)&dev_attr->attr.name = name;
++	const_cast(dev_attr->attr.name) = name;
 +	pax_close_kernel();
  
  	return 0;
@@ -67959,10 +68533,10 @@ index 14bde0d..89f2669 100644
 +		pax_open_kernel();
  		if (power_zone->ops->reset_energy_uj)
 -			dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
-+			*(umode_t *)&dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
++			const_cast(dev_attr_energy_uj.attr.mode) = S_IWUSR | S_IRUGO;
  		else
 -			dev_attr_energy_uj.attr.mode = S_IRUGO;
-+			*(umode_t *)&dev_attr_energy_uj.attr.mode = S_IRUGO;
++			const_cast(dev_attr_energy_uj.attr.mode) = S_IRUGO;
 +		pax_close_kernel();
  		power_zone->zone_dev_attrs[count++] =
  					&dev_attr_energy_uj.attr;
@@ -68016,7 +68590,7 @@ index 744c988..a269ffb 100644
  	if (ret != 0) {
  		put_device(&rdev->dev);
 diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
-index b87f62d..345b9a1 100644
+index b87f62d..34f1cdf 100644
 --- a/drivers/regulator/max8660.c
 +++ b/drivers/regulator/max8660.c
 @@ -423,8 +423,10 @@ static int max8660_probe(struct i2c_client *client,
@@ -68026,14 +68600,14 @@ index b87f62d..345b9a1 100644
 -		max8660_dcdc_ops.enable = max8660_dcdc_enable;
 -		max8660_dcdc_ops.disable = max8660_dcdc_disable;
 +		pax_open_kernel();
-+		*(void **)&max8660_dcdc_ops.enable = max8660_dcdc_enable;
-+		*(void **)&max8660_dcdc_ops.disable = max8660_dcdc_disable;
++		const_cast(max8660_dcdc_ops.enable) = max8660_dcdc_enable;
++		const_cast(max8660_dcdc_ops.disable) = max8660_dcdc_disable;
 +		pax_close_kernel();
  	}
  
  	/*
 diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
-index 5b75b7c..142c226 100644
+index 5b75b7c..8b1bb06 100644
 --- a/drivers/regulator/max8973-regulator.c
 +++ b/drivers/regulator/max8973-regulator.c
 @@ -658,9 +658,11 @@ static int max8973_probe(struct i2c_client *client,
@@ -68044,9 +68618,9 @@ index 5b75b7c..142c226 100644
 -			max->ops.disable = regulator_disable_regmap;
 -			max->ops.is_enabled = regulator_is_enabled_regmap;
 +			pax_open_kernel();
-+			*(void **)&max->ops.enable = regulator_enable_regmap;
-+			*(void **)&max->ops.disable = regulator_disable_regmap;
-+			*(void **)&max->ops.is_enabled = regulator_is_enabled_regmap;
++			const_cast(max->ops.enable) = regulator_enable_regmap;
++			const_cast(max->ops.disable) = regulator_disable_regmap;
++			const_cast(max->ops.is_enabled) = regulator_is_enabled_regmap;
 +			pax_close_kernel();
  			break;
  		}
@@ -68059,15 +68633,15 @@ index 5b75b7c..142c226 100644
 -		max->ops.disable = regulator_disable_regmap;
 -		max->ops.is_enabled = regulator_is_enabled_regmap;
 +		pax_open_kernel();
-+		*(void **)&max->ops.enable = regulator_enable_regmap;
-+		*(void **)&max->ops.disable = regulator_disable_regmap;
-+		*(void **)&max->ops.is_enabled = regulator_is_enabled_regmap;
++		const_cast(max->ops.enable) = regulator_enable_regmap;
++		const_cast(max->ops.disable) = regulator_disable_regmap;
++		const_cast(max->ops.is_enabled) = regulator_is_enabled_regmap;
 +		pax_close_kernel();
  		max->ops.set_current_limit = max8973_set_current_limit;
  		max->ops.get_current_limit = max8973_get_current_limit;
  		break;
 diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
-index 0d17c92..a29f627 100644
+index 0d17c92..ce5897e 100644
 --- a/drivers/regulator/mc13892-regulator.c
 +++ b/drivers/regulator/mc13892-regulator.c
 @@ -584,10 +584,12 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
@@ -68080,8 +68654,8 @@ index 0d17c92..a29f627 100644
  						sizeof(struct regulator_ops));
 -	mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode,
 -	mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode,
-+	*(void **)&mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode,
-+	*(void **)&mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode,
++	const_cast(mc13892_vcam_ops.set_mode) = mc13892_vcam_set_mode,
++	const_cast(mc13892_vcam_ops.get_mode) = mc13892_vcam_get_mode,
 +	pax_close_kernel();
  	mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops;
  
@@ -68177,7 +68751,7 @@ index 9e03d15..36e341c 100644
  
  /* handle firmware resource entries before booting the remote processor */
 diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
-index 9a3f2a6..604f463 100644
+index 9a3f2a6..c19b00a 100644
 --- a/drivers/rtc/rtc-armada38x.c
 +++ b/drivers/rtc/rtc-armada38x.c
 @@ -18,6 +18,7 @@
@@ -68195,14 +68769,14 @@ index 9a3f2a6..604f463 100644
 -		armada38x_rtc_ops.set_alarm = NULL;
 -		armada38x_rtc_ops.alarm_irq_enable = NULL;
 +		pax_open_kernel();
-+		*(void **)&armada38x_rtc_ops.set_alarm = NULL;
-+		*(void **)&armada38x_rtc_ops.alarm_irq_enable = NULL;
++		const_cast(armada38x_rtc_ops.set_alarm) = NULL;
++		const_cast(armada38x_rtc_ops.alarm_irq_enable) = NULL;
 +		pax_close_kernel();
  	}
  	platform_set_drvdata(pdev, rtc);
  	if (rtc->irq != -1)
 diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
-index 84fb541..fee0421a 100644
+index 84fb541..a526dd0 100644
 --- a/drivers/rtc/rtc-cmos.c
 +++ b/drivers/rtc/rtc-cmos.c
 @@ -735,7 +735,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
@@ -68211,7 +68785,7 @@ index 84fb541..fee0421a 100644
  	/* export at least the first block of NVRAM */
 -	nvram.size = address_space - NVRAM_OFFSET;
 +	pax_open_kernel();
-+	*(size_t *)&nvram.size = address_space - NVRAM_OFFSET;
++	const_cast(nvram.size) = address_space - NVRAM_OFFSET;
 +	pax_close_kernel();
  	retval = sysfs_create_bin_file(&dev->kobj, &nvram);
  	if (retval < 0) {
@@ -68251,7 +68825,7 @@ index cf685f6..2311b8f 100644
  	unsigned long		flags;
  #define HAS_NVRAM	0		/* bit 0 == sysfs file active */
 diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
-index d99a705..f8ebd79 100644
+index d99a705..99654e7 100644
 --- a/drivers/rtc/rtc-m48t59.c
 +++ b/drivers/rtc/rtc-m48t59.c
 @@ -485,7 +485,9 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
@@ -68260,7 +68834,7 @@ index d99a705..f8ebd79 100644
  
 -	m48t59_nvram_attr.size = pdata->offset;
 +	pax_open_kernel();
-+	*(size_t *)&m48t59_nvram_attr.size = pdata->offset;
++	const_cast(m48t59_nvram_attr.size) = pdata->offset;
 +	pax_close_kernel();
  
  	ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
@@ -68303,7 +68877,7 @@ index 7155c08..10ba718 100644
  		dev_err(&client->dev, "unable to register the class device\n");
  		return PTR_ERR(rv8803->rtc);
 diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
-index 772d221..60e31aa 100644
+index 772d221..3a56e42 100644
 --- a/drivers/rtc/rtc-rx8010.c
 +++ b/drivers/rtc/rtc-rx8010.c
 @@ -489,9 +489,11 @@ static int rx8010_probe(struct i2c_client *client,
@@ -68314,15 +68888,15 @@ index 772d221..60e31aa 100644
 -			rx8010_rtc_ops.set_alarm = rx8010_set_alarm;
 -			rx8010_rtc_ops.alarm_irq_enable = rx8010_alarm_irq_enable;
 +			pax_open_kernel();
-+			*(void **)&rx8010_rtc_ops.read_alarm = rx8010_read_alarm;
-+			*(void **)&rx8010_rtc_ops.set_alarm = rx8010_set_alarm;
-+			*(void **)&rx8010_rtc_ops.alarm_irq_enable = rx8010_alarm_irq_enable;
++			const_cast(rx8010_rtc_ops.read_alarm) = rx8010_read_alarm;
++			const_cast(rx8010_rtc_ops.set_alarm) = rx8010_set_alarm;
++			const_cast(rx8010_rtc_ops.alarm_irq_enable) = rx8010_alarm_irq_enable;
 +			pax_close_kernel();
  		}
  	}
  
 diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
-index 3a2da4c..e88493c 100644
+index 3a2da4c..1d1d4b1 100644
 --- a/drivers/rtc/rtc-test.c
 +++ b/drivers/rtc/rtc-test.c
 @@ -112,8 +112,10 @@ static int test_probe(struct platform_device *plat_dev)
@@ -68332,34 +68906,16 @@ index 3a2da4c..e88493c 100644
 -		test_rtc_ops.set_mmss64 = test_rtc_set_mmss64;
 -		test_rtc_ops.set_mmss = NULL;
 +		pax_open_kernel();
-+		*(void **)&test_rtc_ops.set_mmss64 = test_rtc_set_mmss64;
-+		*(void **)&test_rtc_ops.set_mmss = NULL;
++		const_cast(test_rtc_ops.set_mmss64) = test_rtc_set_mmss64;
++		const_cast(test_rtc_ops.set_mmss) = NULL;
 +		pax_close_kernel();
  	}
  
  	rtc = devm_rtc_device_register(&plat_dev->dev, "test",
 diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
-index e4c2437..2297164 100644
+index e4c2437..3b3cd62 100644
 --- a/drivers/scsi/aacraid/aachba.c
 +++ b/drivers/scsi/aacraid/aachba.c
-@@ -647,7 +647,7 @@ static void _aac_probe_container2(void * context, struct fib * fibptr)
- 	}
- 	aac_fib_complete(fibptr);
- 	aac_fib_free(fibptr);
--	callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
-+	callback = scsicmd->SCp.ptr;
- 	scsicmd->SCp.ptr = NULL;
- 	(*callback)(scsicmd);
- 	return;
-@@ -726,7 +726,7 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru
- 
- 		dinfo->count = cpu_to_le32(scmd_id(scsicmd));
- 		dinfo->type = cpu_to_le32(FT_FILESYS);
--		scsicmd->SCp.ptr = (char *)callback;
-+		scsicmd->SCp.ptr = callback;
- 
- 		status = aac_fib_send(ContainerCommand,
- 			  fibptr,
 @@ -775,6 +775,11 @@ static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
  	return 0;
  }
@@ -70641,7 +71197,7 @@ index 25aa9b9..d700a65 100644
  	snprintf(name, sizeof(name), "discovery_trace");
  	vport->debug_disc_trc =
 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
-index f57d02c..ab7b70c 100644
+index f57d02c..6ba534b 100644
 --- a/drivers/scsi/lpfc/lpfc_init.c
 +++ b/drivers/scsi/lpfc/lpfc_init.c
 @@ -11028,7 +11028,7 @@ lpfc_pci_resume_one(struct pci_dev *pdev)
@@ -70660,8 +71216,8 @@ index f57d02c..ab7b70c 100644
 -		lpfc_transport_functions.vport_create = lpfc_vport_create;
 -		lpfc_transport_functions.vport_delete = lpfc_vport_delete;
 +		pax_open_kernel();
-+		*(void **)&lpfc_transport_functions.vport_create = lpfc_vport_create;
-+		*(void **)&lpfc_transport_functions.vport_delete = lpfc_vport_delete;
++		const_cast(lpfc_transport_functions.vport_create) = lpfc_vport_create;
++		const_cast(lpfc_transport_functions.vport_delete) = lpfc_vport_delete;
 +		pax_close_kernel();
  	}
  	lpfc_transport_template =
@@ -71004,7 +71560,7 @@ index 0103e46..6220a84 100644
  extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *, bool);
  extern void qla2x00_init_host_attr(scsi_qla_host_t *);
 diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
-index f6c7ce3..2dd675b 100644
+index f6c7ce3..dccd3d4 100644
 --- a/drivers/scsi/qla2xxx/qla_os.c
 +++ b/drivers/scsi/qla2xxx/qla_os.c
 @@ -291,12 +291,12 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
@@ -71029,8 +71585,8 @@ index f6c7ce3..2dd675b 100644
 -			ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
 -			ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64;
 +			pax_open_kernel();
-+			*(void **)&ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
-+			*(void **)&ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64;
++			const_cast(ha->isp_ops->calc_req_entries) = qla2x00_calc_iocbs_64;
++			const_cast(ha->isp_ops->build_iocbs) = qla2x00_build_scsi_iocbs_64;
 +			pax_close_kernel();
  			return;
  		}
@@ -74424,7 +74980,7 @@ index 9a14074..3d02410 100644
  	struct rtw_adapter *padapter = netdev_priv(pnetdev);
  	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
-index c78421b..f75c4c4 100644
+index c78421b..e1ba746 100644
 --- a/drivers/staging/sm750fb/sm750.c
 +++ b/drivers/staging/sm750fb/sm750.c
 @@ -720,6 +720,7 @@ static struct fb_ops lynxfb_ops = {
@@ -74449,7 +75005,7 @@ index c78421b..f75c4c4 100644
  	if (!g_hwcursor) {
 -		lynxfb_ops.fb_cursor = NULL;
 +		pax_open_kernel();
-+		*(void **)&lynxfb_ops.fb_cursor = NULL;
++		const_cast(lynxfb_ops.fb_cursor) = NULL;
 +		pax_close_kernel();
  		hw_cursor_disable(&crtc->cursor);
  	}
@@ -74461,9 +75017,9 @@ index c78421b..f75c4c4 100644
 -		lynxfb_ops.fb_copyarea = lynxfb_ops_copyarea;
 -		lynxfb_ops.fb_imageblit = lynxfb_ops_imageblit;
 +		pax_open_kernel();
-+		*(void **)&lynxfb_ops.fb_fillrect = lynxfb_ops_fillrect;
-+		*(void **)&lynxfb_ops.fb_copyarea = lynxfb_ops_copyarea;
-+		*(void **)&lynxfb_ops.fb_imageblit = lynxfb_ops_imageblit;
++		const_cast(lynxfb_ops.fb_fillrect) = lynxfb_ops_fillrect;
++		const_cast(lynxfb_ops.fb_copyarea) = lynxfb_ops_copyarea;
++		const_cast(lynxfb_ops.fb_imageblit) = lynxfb_ops_imageblit;
 +		pax_close_kernel();
  	}
  	info->fbops = &lynxfb_ops;
@@ -74589,7 +75145,7 @@ index 3072f1a..1071742 100644
  	login->tgt_agt = sbp_target_agent_register(login);
  	if (IS_ERR(login->tgt_agt)) {
 diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
-index 6ceac4f..b2ed52c 100644
+index 6ceac4f..f8059ccd 100644
 --- a/drivers/thermal/cpu_cooling.c
 +++ b/drivers/thermal/cpu_cooling.c
 @@ -838,10 +838,11 @@ __cpufreq_cooling_register(struct device_node *np,
@@ -74601,9 +75157,9 @@ index 6ceac4f..b2ed52c 100644
 -		cpufreq_cooling_ops.state2power = cpufreq_state2power;
 -		cpufreq_cooling_ops.power2state = cpufreq_power2state;
 +		pax_open_kernel();
-+		*(void **)&cpufreq_cooling_ops.get_requested_power = cpufreq_get_requested_power;
-+		*(void **)&cpufreq_cooling_ops.state2power = cpufreq_state2power;
-+		*(void **)&cpufreq_cooling_ops.power2state = cpufreq_power2state;
++		const_cast(cpufreq_cooling_ops.get_requested_power) = cpufreq_get_requested_power;
++		const_cast(cpufreq_cooling_ops.state2power) = cpufreq_state2power;
++		const_cast(cpufreq_cooling_ops.power2state) = cpufreq_power2state;
 +		pax_close_kernel();
  		cpufreq_dev->plat_get_static_power = plat_static_func;
  
@@ -74655,7 +75211,7 @@ index 01f0015..aa56551 100644
  		err = PTR_ERR(cdev);
  		dev_err(df->dev.parent,
 diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
-index 5836e55..740ab89 100644
+index 5836e55..708bbd6 100644
 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c
 +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
 @@ -272,8 +272,10 @@ static int int3400_thermal_probe(struct platform_device *pdev)
@@ -74665,14 +75221,14 @@ index 5836e55..740ab89 100644
 -		int3400_thermal_ops.get_mode = int3400_thermal_get_mode;
 -		int3400_thermal_ops.set_mode = int3400_thermal_set_mode;
 +		pax_open_kernel();
-+		*(void **)&int3400_thermal_ops.get_mode = int3400_thermal_get_mode;
-+		*(void **)&int3400_thermal_ops.set_mode = int3400_thermal_set_mode;
++		const_cast(int3400_thermal_ops.get_mode) = int3400_thermal_get_mode;
++		const_cast(int3400_thermal_ops.set_mode) = int3400_thermal_set_mode;
 +		pax_close_kernel();
  	}
  	priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0,
  						priv, &int3400_thermal_ops,
 diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
-index 9043f8f..ab0f354 100644
+index 9043f8f..1b53349 100644
 --- a/drivers/thermal/of-thermal.c
 +++ b/drivers/thermal/of-thermal.c
 @@ -31,6 +31,7 @@
@@ -74691,9 +75247,9 @@ index 9043f8f..ab0f354 100644
 -	tzd->ops->get_trend = of_thermal_get_trend;
 -	tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
 +	pax_open_kernel();
-+	*(void **)&tzd->ops->get_temp = of_thermal_get_temp;
-+	*(void **)&tzd->ops->get_trend = of_thermal_get_trend;
-+	*(void **)&tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
++	const_cast(tzd->ops->get_temp) = of_thermal_get_temp;
++	const_cast(tzd->ops->get_trend) = of_thermal_get_trend;
++	const_cast(tzd->ops->set_emul_temp) = of_thermal_set_emul_temp;
 +	pax_close_kernel();
  	mutex_unlock(&tzd->lock);
  
@@ -74706,9 +75262,9 @@ index 9043f8f..ab0f354 100644
 -	tzd->ops->get_trend = NULL;
 -	tzd->ops->set_emul_temp = NULL;
 +	pax_open_kernel();
-+	*(void **)&tzd->ops->get_temp = NULL;
-+	*(void **)&tzd->ops->get_trend = NULL;
-+	*(void **)&tzd->ops->set_emul_temp = NULL;
++	const_cast(tzd->ops->get_temp) = NULL;
++	const_cast(tzd->ops->get_trend) = NULL;
++	const_cast(tzd->ops->set_emul_temp) = NULL;
 +	pax_close_kernel();
  
  	tz->ops = NULL;
@@ -75289,7 +75845,7 @@ index b280abaa..3ccd7d1 100644
  }
  EXPORT_SYMBOL_GPL(n_tty_inherit_ops);
 diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
-index 2348fa6..14894f4 100644
+index 2348fa6..490e407 100644
 --- a/drivers/tty/pty.c
 +++ b/drivers/tty/pty.c
 @@ -879,8 +879,10 @@ static void __init unix98_pty_init(void)
@@ -75299,7 +75855,7 @@ index 2348fa6..14894f4 100644
 +	pax_open_kernel();
  	tty_default_fops(&ptmx_fops);
 -	ptmx_fops.open = ptmx_open;
-+	*(void **)&ptmx_fops.open = ptmx_open;
++	const_cast(ptmx_fops.open) = ptmx_open;
 +	pax_close_kernel();
  
  	cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -75336,7 +75892,7 @@ index 802eac7..f5dcf07 100644
  	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
  	spin_unlock_irqrestore(&info->port.lock, flags);
 diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
-index c9720a9..f6c9276 100644
+index c9720a9..964f2d9 100644
 --- a/drivers/tty/serial/8250/8250_core.c
 +++ b/drivers/tty/serial/8250/8250_core.c
 @@ -488,9 +488,9 @@ static void univ8250_release_port(struct uart_port *port)
@@ -75346,9 +75902,9 @@ index c9720a9..f6c9276 100644
 -	ops->config_port  = univ8250_config_port;
 -	ops->request_port = univ8250_request_port;
 -	ops->release_port = univ8250_release_port;
-+	*(void **)&ops->config_port  = univ8250_config_port;
-+	*(void **)&ops->request_port = univ8250_request_port;
-+	*(void **)&ops->release_port = univ8250_release_port;
++	const_cast(ops->config_port)  = univ8250_config_port;
++	const_cast(ops->request_port) = univ8250_request_port;
++	const_cast(ops->release_port) = univ8250_release_port;
  }
  
  #else
@@ -75435,7 +75991,7 @@ index a119f11..120444e 100644
  	struct jsm_board *brd = pci_get_drvdata(pdev);
  
 diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
-index 117df15..2f7dfcf 100644
+index 117df15..8f7486f 100644
 --- a/drivers/tty/serial/kgdb_nmi.c
 +++ b/drivers/tty/serial/kgdb_nmi.c
 @@ -53,7 +53,9 @@ static int kgdb_nmi_console_setup(struct console *co, char *options)
@@ -75444,7 +76000,7 @@ index 117df15..2f7dfcf 100644
  	 */
 -	dbg_io_ops->is_console = true;
 +	pax_open_kernel();
-+	*(int *)&dbg_io_ops->is_console = true;
++	const_cast(dbg_io_ops->is_console) = true;
 +	pax_close_kernel();
  
  	return 0;
@@ -76984,6 +77540,105 @@ index 48672fa..9245081 100644
  
  /* Device for a quirk */
  #define PCI_VENDOR_ID_FRESCO_LOGIC	0x1b73
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index a85a1c9..0f198bc 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1861,9 +1861,9 @@ td_cleanup:
+ 	 * unsigned).  Play it safe and say we didn't transfer anything.
+ 	 */
+ 	if (urb->actual_length > urb->transfer_buffer_length) {
+-		xhci_warn(xhci, "URB transfer length is wrong, xHC issue? req. len = %u, act. len = %u\n",
++		xhci_warn(xhci, "URB transfer length is wrong, xHC issue? req. len = %u, trans. len = %u\n",
+ 			urb->transfer_buffer_length,
+-			urb->actual_length);
++			EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+ 		urb->actual_length = 0;
+ 		if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+ 			*status = -EREMOTEIO;
+@@ -1942,10 +1942,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ 		return finish_td(xhci, td, event_trb, event, ep, status, false);
+ 	case COMP_STOP:
+ 		/* Did we stop at data stage? */
+-		if (event_trb != ep_ring->dequeue && event_trb != td->last_trb)
+-			td->urb->actual_length =
+-				td->urb->transfer_buffer_length -
+-				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
++		if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) {
++			if (td->urb->transfer_buffer_length >= EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)))
++				td->urb->actual_length =
++					td->urb->transfer_buffer_length -
++					EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
++			else
++				td->urb->actual_length =
++					td->urb->transfer_buffer_length + 1;
++		}
+ 		/* fall through */
+ 	case COMP_STOP_INVAL:
+ 		return finish_td(xhci, td, event_trb, event, ep, status, false);
+@@ -1959,12 +1964,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ 		/* else fall through */
+ 	case COMP_STALL:
+ 		/* Did we transfer part of the data (middle) phase? */
+-		if (event_trb != ep_ring->dequeue &&
+-				event_trb != td->last_trb)
+-			td->urb->actual_length =
+-				td->urb->transfer_buffer_length -
+-				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+-		else if (!td->urb_length_set)
++		if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) {
++			if (td->urb->transfer_buffer_length >= EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)))
++				td->urb->actual_length =
++					td->urb->transfer_buffer_length -
++					EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
++			else
++				td->urb->actual_length =
++					td->urb->transfer_buffer_length + 1;
++		} else if (!td->urb_length_set)
+ 			td->urb->actual_length = 0;
+ 
+ 		return finish_td(xhci, td, event_trb, event, ep, status, false);
+@@ -1997,9 +2005,12 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ 			 * the last TRB.
+ 			 */
+ 			td->urb_length_set = true;
+-			td->urb->actual_length =
+-				td->urb->transfer_buffer_length -
+-				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
++			if (td->urb->transfer_buffer_length >= EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)))
++				td->urb->actual_length =
++					td->urb->transfer_buffer_length -
++					EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
++			else
++				BUG();
+ 			xhci_dbg(xhci, "Waiting for status "
+ 					"stage event\n");
+ 			return 0;
+@@ -2194,11 +2205,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ 	/* Fast path - was this the last TRB in the TD for this URB? */
+ 	} else if (event_trb == td->last_trb) {
+ 		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+-			td->urb->actual_length =
+-				td->urb->transfer_buffer_length -
+-				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+-			if (td->urb->transfer_buffer_length <
+-					td->urb->actual_length) {
++			if (td->urb->transfer_buffer_length < EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))) {
+ 				xhci_warn(xhci, "HC gave bad length "
+ 						"of %d bytes left\n",
+ 					  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+@@ -2207,7 +2214,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ 					*status = -EREMOTEIO;
+ 				else
+ 					*status = 0;
+-			}
++			} else
++				td->urb->actual_length =
++					td->urb->transfer_buffer_length -
++					EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+ 			/* Don't overwrite a previously set error code */
+ 			if (*status == -EINPROGRESS) {
+ 				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
 diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
 index 8e713cc..8c92a15 100644
 --- a/drivers/usb/host/xhci.c
@@ -77621,7 +78276,7 @@ index c42ce2f..4c8bc59 100644
  	"PCI",
  	"PRO AGP",
 diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
-index f34ed47f..026367f 100644
+index f34ed47f..7283c9f 100644
 --- a/drivers/video/fbdev/aty/atyfb_base.c
 +++ b/drivers/video/fbdev/aty/atyfb_base.c
 @@ -1335,10 +1335,14 @@ static int atyfb_set_par(struct fb_info *info)
@@ -77630,13 +78285,13 @@ index f34ed47f..026367f 100644
  	if (var->accel_flags) {
 -		info->fbops->fb_sync = atyfb_sync;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_sync = atyfb_sync;
++		const_cast(info->fbops->fb_sync) = atyfb_sync;
 +		pax_close_kernel();
  		info->flags &= ~FBINFO_HWACCEL_DISABLED;
  	} else {
 -		info->fbops->fb_sync = NULL;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_sync = NULL;
++		const_cast(info->fbops->fb_sync) = NULL;
 +		pax_close_kernel();
  		info->flags |= FBINFO_HWACCEL_DISABLED;
  	}
@@ -77663,7 +78318,7 @@ index 51f29d6..2c15339 100644
  
  const struct aty_pll_ops aty_pll_ct = {
 diff --git a/drivers/video/fbdev/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c
-index 2fa0317..4983f2a 100644
+index 2fa0317..d687dab 100644
 --- a/drivers/video/fbdev/aty/mach64_cursor.c
 +++ b/drivers/video/fbdev/aty/mach64_cursor.c
 @@ -8,6 +8,7 @@
@@ -77680,7 +78335,7 @@ index 2fa0317..4983f2a 100644
  
 -	info->fbops->fb_cursor = atyfb_cursor;
 +	pax_open_kernel();
-+	*(void **)&info->fbops->fb_cursor = atyfb_cursor;
++	const_cast(info->fbops->fb_cursor) = atyfb_cursor;
 +	pax_close_kernel();
  
  	return 0;
@@ -77721,7 +78376,7 @@ index 10c988a..f7d9299 100644
 +	.set_pll	= aty_set_pll,
  };
 diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
-index 57721c7..55142ed 100644
+index 57721c7..332b94b 100644
 --- a/drivers/video/fbdev/core/fb_defio.c
 +++ b/drivers/video/fbdev/core/fb_defio.c
 @@ -207,7 +207,9 @@ void fb_deferred_io_init(struct fb_info *info)
@@ -77730,17 +78385,19 @@ index 57721c7..55142ed 100644
  	mutex_init(&fbdefio->lock);
 -	info->fbops->fb_mmap = fb_deferred_io_mmap;
 +	pax_open_kernel();
-+	*(void **)&info->fbops->fb_mmap = fb_deferred_io_mmap;
++	const_cast(info->fbops->fb_mmap) = fb_deferred_io_mmap;
 +	pax_close_kernel();
  	INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work);
  	INIT_LIST_HEAD(&fbdefio->pagelist);
  	if (fbdefio->delay == 0) /* set a default of 1 s */
-@@ -238,7 +240,7 @@ void fb_deferred_io_cleanup(struct fb_info *info)
+@@ -238,7 +240,9 @@ void fb_deferred_io_cleanup(struct fb_info *info)
  		page->mapping = NULL;
  	}
  
 -	info->fbops->fb_mmap = NULL;
-+	*(void **)&info->fbops->fb_mmap = NULL;
++	pax_open_kernel();
++	const_cast(info->fbops->fb_mmap) = NULL;
++	pax_close_kernel();
  	mutex_destroy(&fbdefio->lock);
  }
  EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
@@ -77872,7 +78529,7 @@ index 11eb094..622ee31 100644
  	{  640,  480,  48, 16, 33, 10,  96, 2, 60 },
  	{  800,  600, 144, 24, 28,  8, 112, 6, 60 },
 diff --git a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
-index fe92eed..106e085 100644
+index fe92eed..239e386 100644
 --- a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
 +++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
 @@ -312,14 +312,18 @@ void mb862xxfb_init_accel(struct fb_info *info, int xres)
@@ -77883,9 +78540,9 @@ index fe92eed..106e085 100644
 -		info->fbops->fb_copyarea = cfb_copyarea;
 -		info->fbops->fb_imageblit = cfb_imageblit;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_fillrect = cfb_fillrect;
-+		*(void **)&info->fbops->fb_copyarea = cfb_copyarea;
-+		*(void **)&info->fbops->fb_imageblit = cfb_imageblit;
++		const_cast(info->fbops->fb_fillrect) = cfb_fillrect;
++		const_cast(info->fbops->fb_copyarea) = cfb_copyarea;
++		const_cast(info->fbops->fb_imageblit) = cfb_imageblit;
 +		pax_close_kernel();
  	} else {
  		outreg(disp, GC_L0EM, 3);
@@ -77893,15 +78550,15 @@ index fe92eed..106e085 100644
 -		info->fbops->fb_copyarea = mb86290fb_copyarea;
 -		info->fbops->fb_imageblit = mb86290fb_imageblit;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_fillrect = mb86290fb_fillrect;
-+		*(void **)&info->fbops->fb_copyarea = mb86290fb_copyarea;
-+		*(void **)&info->fbops->fb_imageblit = mb86290fb_imageblit;
++		const_cast(info->fbops->fb_fillrect) = mb86290fb_fillrect;
++		const_cast(info->fbops->fb_copyarea) = mb86290fb_copyarea;
++		const_cast(info->fbops->fb_imageblit) = mb86290fb_imageblit;
 +		pax_close_kernel();
  	}
  	outreg(draw, GDC_REG_DRAW_BASE, 0);
  	outreg(draw, GDC_REG_MODE_MISC, 0x8000);
 diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c
-index ce7dab7..a87baf8 100644
+index ce7dab7..89d6521 100644
 --- a/drivers/video/fbdev/nvidia/nvidia.c
 +++ b/drivers/video/fbdev/nvidia/nvidia.c
 @@ -660,19 +660,23 @@ static int nvidiafb_set_par(struct fb_info *info)
@@ -77913,10 +78570,10 @@ index ce7dab7..a87baf8 100644
 -		info->fbops->fb_copyarea = nvidiafb_copyarea;
 -		info->fbops->fb_sync = nvidiafb_sync;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_imageblit = nvidiafb_imageblit;
-+		*(void **)&info->fbops->fb_fillrect = nvidiafb_fillrect;
-+		*(void **)&info->fbops->fb_copyarea = nvidiafb_copyarea;
-+		*(void **)&info->fbops->fb_sync = nvidiafb_sync;
++		const_cast(info->fbops->fb_imageblit) = nvidiafb_imageblit;
++		const_cast(info->fbops->fb_fillrect) = nvidiafb_fillrect;
++		const_cast(info->fbops->fb_copyarea) = nvidiafb_copyarea;
++		const_cast(info->fbops->fb_sync) = nvidiafb_sync;
 +		pax_close_kernel();
  		info->pixmap.scan_align = 4;
  		info->flags &= ~FBINFO_HWACCEL_DISABLED;
@@ -77928,10 +78585,10 @@ index ce7dab7..a87baf8 100644
 -		info->fbops->fb_copyarea = cfb_copyarea;
 -		info->fbops->fb_sync = NULL;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_imageblit = cfb_imageblit;
-+		*(void **)&info->fbops->fb_fillrect = cfb_fillrect;
-+		*(void **)&info->fbops->fb_copyarea = cfb_copyarea;
-+		*(void **)&info->fbops->fb_sync = NULL;
++		const_cast(info->fbops->fb_imageblit) = cfb_imageblit;
++		const_cast(info->fbops->fb_fillrect) = cfb_fillrect;
++		const_cast(info->fbops->fb_copyarea) = cfb_copyarea;
++		const_cast(info->fbops->fb_sync) = NULL;
 +		pax_close_kernel();
  		info->pixmap.scan_align = 1;
  		info->flags |= FBINFO_HWACCEL_DISABLED;
@@ -77944,14 +78601,14 @@ index ce7dab7..a87baf8 100644
 -	    info->fbops->fb_cursor = NULL;
 +	if (!hwcur) {
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_cursor = NULL;
++		const_cast(info->fbops->fb_cursor) = NULL;
 +		pax_close_kernel();
 +	}
  
  	info->var.accel_flags = (!noaccel);
  
 diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display.c b/drivers/video/fbdev/omap2/omapfb/dss/display.c
-index ef5b902..47cf7f5 100644
+index ef5b902..2ae011b 100644
 --- a/drivers/video/fbdev/omap2/omapfb/dss/display.c
 +++ b/drivers/video/fbdev/omap2/omapfb/dss/display.c
 @@ -161,12 +161,14 @@ int omapdss_register_display(struct omap_dss_device *dssdev)
@@ -77961,19 +78618,19 @@ index ef5b902..47cf7f5 100644
 +	pax_open_kernel();
  	if (drv && drv->get_resolution == NULL)
 -		drv->get_resolution = omapdss_default_get_resolution;
-+		*(void **)&drv->get_resolution = omapdss_default_get_resolution;
++		const_cast(drv->get_resolution) = omapdss_default_get_resolution;
  	if (drv && drv->get_recommended_bpp == NULL)
 -		drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
-+		*(void **)&drv->get_recommended_bpp = omapdss_default_get_recommended_bpp;
++		const_cast(drv->get_recommended_bpp) = omapdss_default_get_recommended_bpp;
  	if (drv && drv->get_timings == NULL)
 -		drv->get_timings = omapdss_default_get_timings;
-+		*(void **)&drv->get_timings = omapdss_default_get_timings;
++		const_cast(drv->get_timings) = omapdss_default_get_timings;
 +	pax_close_kernel();
  
  	mutex_lock(&panel_list_mutex);
  	list_add_tail(&dssdev->panel_list, &panel_list);
 diff --git a/drivers/video/fbdev/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c
-index 96aa46d..c67c213 100644
+index 96aa46d..65e2554 100644
 --- a/drivers/video/fbdev/s1d13xxxfb.c
 +++ b/drivers/video/fbdev/s1d13xxxfb.c
 @@ -880,8 +880,10 @@ static int s1d13xxxfb_probe(struct platform_device *pdev)
@@ -77983,8 +78640,8 @@ index 96aa46d..c67c213 100644
 -		s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill;
 -		s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea;
 +		pax_open_kernel();
-+		*(void **)&s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill;
-+		*(void **)&s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea;
++		const_cast(s1d13xxxfb_fbops.fb_fillrect) = s1d13xxxfb_bitblt_solidfill;
++		const_cast(s1d13xxxfb_fbops.fb_copyarea) = s1d13xxxfb_bitblt_copyarea;
 +		pax_close_kernel();
  		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
  			FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
@@ -78020,7 +78677,7 @@ index 32e23c2..7b73082 100644
  extern void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
  extern unsigned short	SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
 diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
-index 9279e5f..d5f5276 100644
+index 9279e5f..d9fb0bd 100644
 --- a/drivers/video/fbdev/smscufx.c
 +++ b/drivers/video/fbdev/smscufx.c
 @@ -1174,7 +1174,9 @@ static int ufx_ops_release(struct fb_info *info, int user)
@@ -78029,13 +78686,13 @@ index 9279e5f..d5f5276 100644
  		info->fbdefio = NULL;
 -		info->fbops->fb_mmap = ufx_ops_mmap;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_mmap = ufx_ops_mmap;
++		const_cast(info->fbops->fb_mmap) = ufx_ops_mmap;
 +		pax_close_kernel();
  	}
  
  	pr_debug("released /dev/fb%d user=%d count=%d",
 diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
-index e9c2f7b..8df1264 100644
+index e9c2f7b..87506f4 100644
 --- a/drivers/video/fbdev/udlfb.c
 +++ b/drivers/video/fbdev/udlfb.c
 @@ -623,11 +623,11 @@ static int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
@@ -78076,7 +78733,7 @@ index e9c2f7b..8df1264 100644
  		info->fbdefio = NULL;
 -		info->fbops->fb_mmap = dlfb_ops_mmap;
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_mmap = dlfb_ops_mmap;
++		const_cast(info->fbops->fb_mmap) = dlfb_ops_mmap;
 +		pax_close_kernel();
  	}
  
@@ -78133,7 +78790,7 @@ index e9c2f7b..8df1264 100644
  	return count;
  }
 diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c
-index 178ae93..624b2eb 100644
+index 178ae93..043ddca 100644
 --- a/drivers/video/fbdev/uvesafb.c
 +++ b/drivers/video/fbdev/uvesafb.c
 @@ -19,6 +19,7 @@
@@ -78202,7 +78859,7 @@ index 178ae93..624b2eb 100644
 -		info->fbops->fb_blank = NULL;
 +	if (!blank) {
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_blank = NULL;
++		const_cast(info->fbops->fb_blank) = NULL;
 +		pax_close_kernel();
 +	}
  
@@ -78216,7 +78873,7 @@ index 178ae93..624b2eb 100644
 -		info->fbops->fb_pan_display = NULL;
 +	if (!par->ypan) {
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_pan_display = NULL;
++		const_cast(info->fbops->fb_pan_display) = NULL;
 +		pax_close_kernel();
 +	}
  }
@@ -78247,7 +78904,7 @@ index 178ae93..624b2eb 100644
  	}
  	return 0;
 diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
-index 528fe91..6fd29fe 100644
+index 528fe91..475d9e6 100644
 --- a/drivers/video/fbdev/vesafb.c
 +++ b/drivers/video/fbdev/vesafb.c
 @@ -9,6 +9,7 @@
@@ -78348,7 +79005,7 @@ index 528fe91..6fd29fe 100644
 -		info->fbops->fb_pan_display = NULL;
 +	if (!ypan) {
 +		pax_open_kernel();
-+		*(void **)&info->fbops->fb_pan_display = NULL;
++		const_cast(info->fbops->fb_pan_display) = NULL;
 +		pax_close_kernel();
 +	}
  
@@ -99826,7 +100483,7 @@ index 7cfa0aa..d5ef97b7 100644
  	seq_printf(m, "CacheOp: alo=%d luo=%d luc=%d gro=%d\n",
  		   atomic_read(&fscache_n_cop_alloc_object),
 diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
-index c5b6b71..3949af6 100644
+index c5b6b71..527e347 100644
 --- a/fs/fuse/cuse.c
 +++ b/fs/fuse/cuse.c
 @@ -611,10 +611,12 @@ static int __init cuse_init(void)
@@ -99839,9 +100496,9 @@ index c5b6b71..3949af6 100644
 -	cuse_channel_fops.release	= cuse_channel_release;
 +	pax_open_kernel();
 +	memcpy((void *)&cuse_channel_fops, &fuse_dev_operations, sizeof(fuse_dev_operations));
-+	*(void **)&cuse_channel_fops.owner	= THIS_MODULE;
-+	*(void **)&cuse_channel_fops.open	= cuse_channel_open;
-+	*(void **)&cuse_channel_fops.release	= cuse_channel_release;
++	const_cast(cuse_channel_fops.owner)	= THIS_MODULE;
++	const_cast(cuse_channel_fops.open)	= cuse_channel_open;
++	const_cast(cuse_channel_fops.release)	= cuse_channel_release;
 +	pax_close_kernel();
  
  	cuse_class = class_create(THIS_MODULE, "cuse");
@@ -100191,7 +100848,7 @@ index 4a6cf28..d3a29d3 100644
  
  		jffs2_prealloc_raw_node_refs(c, jeb, 1);
 diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
-index cad86ba..a0bfc33 100644
+index cad86ba..7de4d99 100644
 --- a/fs/jffs2/file.c
 +++ b/fs/jffs2/file.c
 @@ -111,8 +111,9 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
@@ -100205,6 +100862,15 @@ index cad86ba..a0bfc33 100644
  	int ret = jffs2_do_readpage_nolock(inode, pg);
  	unlock_page(pg);
  	return ret;
+@@ -125,7 +126,7 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
+ 	int ret;
+ 
+ 	mutex_lock(&f->sem);
+-	ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
++	ret = jffs2_do_readpage_unlock((struct file *)pg->mapping->host, pg);
+ 	mutex_unlock(&f->sem);
+ 	return ret;
+ }
 diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
 index bead25a..5186b1c 100644
 --- a/fs/jffs2/fs.c
@@ -110271,7 +110937,7 @@ index d955481..a985dc41 100644
  
  #endif
 diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
-index 52ccd34..7a6b202 100644
+index 52ccd34..a166501 100644
 --- a/fs/nls/nls_base.c
 +++ b/fs/nls/nls_base.c
 @@ -234,21 +234,25 @@ EXPORT_SYMBOL(utf16s_to_utf8s);
@@ -110286,7 +110952,7 @@ index 52ccd34..7a6b202 100644
  
 -	nls->owner = owner;
 +	pax_open_kernel();
-+	*(void **)&nls->owner = owner;
++	const_cast(nls->owner) = owner;
 +	pax_close_kernel();
  	spin_lock(&nls_lock);
 -	while (*tmp) {
@@ -110301,7 +110967,7 @@ index 52ccd34..7a6b202 100644
  	}
 -	nls->next = tables;
 +	pax_open_kernel();
-+	*(struct nls_table **)&nls->next = tables;
++	const_cast(nls->next) = tables;
 +	pax_close_kernel();
  	tables = nls;
  	spin_unlock(&nls_lock);
@@ -110394,7 +111060,7 @@ index 8e14187..d9cec2f 100644
  {
  	const unsigned char *uni2charset;
 diff --git a/fs/nls/nls_euc-jp.c b/fs/nls/nls_euc-jp.c
-index 162b3f1..2cb932a 100644
+index 162b3f1..b9121f8 100644
 --- a/fs/nls/nls_euc-jp.c
 +++ b/fs/nls/nls_euc-jp.c
 @@ -406,7 +406,7 @@ static inline int sjisnec2sjisibm(unsigned char *sjisibm,
@@ -110413,14 +111079,14 @@ index 162b3f1..2cb932a 100644
 -		table.charset2upper = p_nls->charset2upper;
 -		table.charset2lower = p_nls->charset2lower;
 +		pax_open_kernel();
-+		*(const unsigned char **)&table.charset2upper = p_nls->charset2upper;
-+		*(const unsigned char **)&table.charset2lower = p_nls->charset2lower;
++		const_cast(table.charset2upper) = p_nls->charset2upper;
++		const_cast(table.charset2lower) = p_nls->charset2lower;
 +		pax_close_kernel();
  		return register_nls(&table);
  	}
  
 diff --git a/fs/nls/nls_koi8-ru.c b/fs/nls/nls_koi8-ru.c
-index a80a741..13030f7 100644
+index a80a741..f28c9c9 100644
 --- a/fs/nls/nls_koi8-ru.c
 +++ b/fs/nls/nls_koi8-ru.c
 @@ -13,7 +13,7 @@
@@ -110439,8 +111105,8 @@ index a80a741..13030f7 100644
 -		table.charset2upper = p_nls->charset2upper;
 -		table.charset2lower = p_nls->charset2lower;
 +		pax_open_kernel();
-+		*(const unsigned char **)&table.charset2upper = p_nls->charset2upper;
-+		*(const unsigned char **)&table.charset2lower = p_nls->charset2lower;
++		const_cast(table.charset2upper) = p_nls->charset2upper;
++		const_cast(table.charset2lower) = p_nls->charset2lower;
 +		pax_close_kernel();
  		return register_nls(&table);
  	}
@@ -112482,7 +113148,7 @@ index 350984a..0fb02a9 100644
  	net = get_proc_net(inode);
  	if (net == NULL)
 diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
-index fe5b6e6..e5f3883 100644
+index fe5b6e6..cd2913c 100644
 --- a/fs/proc/proc_sysctl.c
 +++ b/fs/proc/proc_sysctl.c
 @@ -11,13 +11,21 @@
@@ -112515,7 +113181,7 @@ index fe5b6e6..e5f3883 100644
  {
 -	dir->header.ctl_table[0].child = sysctl_mount_point;
 +	pax_open_kernel();
-+	*(const void **)&dir->header.ctl_table[0].child = sysctl_mount_point;
++	const_cast(dir->header.ctl_table[0].child) = sysctl_mount_point;
 +	pax_close_kernel();
  }
  
@@ -112524,7 +113190,7 @@ index fe5b6e6..e5f3883 100644
  {
 -	dir->header.ctl_table[0].child = NULL;
 +	pax_open_kernel();
-+	*(void **)&dir->header.ctl_table[0].child = NULL;
++	const_cast(dir->header.ctl_table[0].child) = NULL;
 +	pax_close_kernel();
  }
  
@@ -112565,7 +113231,7 @@ index fe5b6e6..e5f3883 100644
 +	if (gr_handle_chroot_sysctl(op))
 +		goto out;
 +	dget(filp->f_path.dentry);
-+	if (gr_handle_sysctl_mod(filp->f_path.dentry->d_parent->d_name.name, table->procname, op)) {
++	if (gr_handle_sysctl_mod((const char *)filp->f_path.dentry->d_parent->d_name.name, table->procname, op)) {
 +		dput(filp->f_path.dentry);
 +		goto out;
 +	}
@@ -113941,7 +114607,7 @@ index 6c21228..9afd5fe 100644
  	if (sbi->s_bytesex == BYTESEX_PDP)
  		return PDP_swab((__force __u32)n);
 diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
-index 4a0e48f..ca5b016 100644
+index 4a0e48f..d3e1fbf 100644
 --- a/fs/tracefs/inode.c
 +++ b/fs/tracefs/inode.c
 @@ -53,7 +53,7 @@ static const struct file_operations tracefs_file_operations = {
@@ -113960,8 +114626,8 @@ index 4a0e48f..ca5b016 100644
 -	tracefs_ops.mkdir = mkdir;
 -	tracefs_ops.rmdir = rmdir;
 +	pax_open_kernel();
-+	*(void **)&tracefs_ops.mkdir = mkdir;
-+	*(void **)&tracefs_ops.rmdir = rmdir;
++	const_cast(tracefs_ops.mkdir) = mkdir;
++	const_cast(tracefs_ops.rmdir) = rmdir;
 +	pax_close_kernel();
  
  	return dentry;
@@ -115665,7 +116331,7 @@ index 0000000..e136e5f
 +endif
 diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c
 new file mode 100644
-index 0000000..7ad630a
+index 0000000..3c66319
 --- /dev/null
 +++ b/grsecurity/gracl.c
 @@ -0,0 +1,2757 @@
@@ -115867,7 +116533,7 @@ index 0000000..7ad630a
 +
 +static int prepend_name(char **buffer, int *buflen, struct qstr *name)
 +{
-+	return prepend(buffer, buflen, name->name, name->len);
++	return prepend(buffer, buflen, (const char *)name->name, name->len);
 +}
 +
 +static int prepend_path(const struct path *path, struct path *root,
@@ -116231,7 +116897,7 @@ index 0000000..7ad630a
 +__lookup_name_entry(const struct gr_policy_state *state, const char *name)
 +{
 +	unsigned int len = strlen(name);
-+	unsigned int key = full_name_hash(name, len);
++	unsigned int key = full_name_hash((const unsigned char *)name, len);
 +	unsigned int index = key % state->name_set.n_size;
 +	struct name_entry *match;
 +
@@ -116253,7 +116919,7 @@ index 0000000..7ad630a
 +lookup_name_entry_create(const char *name)
 +{
 +	unsigned int len = strlen(name);
-+	unsigned int key = full_name_hash(name, len);
++	unsigned int key = full_name_hash((const unsigned char *)name, len);
 +	unsigned int index = key % running_polstate.name_set.n_size;
 +	struct name_entry *match;
 +
@@ -120006,7 +120672,7 @@ index 0000000..25f54ef
 +};
 diff --git a/grsecurity/gracl_policy.c b/grsecurity/gracl_policy.c
 new file mode 100644
-index 0000000..302bda8
+index 0000000..2fc92ec
 --- /dev/null
 +++ b/grsecurity/gracl_policy.c
 @@ -0,0 +1,1784 @@
@@ -120362,7 +121028,7 @@ index 0000000..302bda8
 +	struct name_entry **curr, *nentry;
 +	struct inodev_entry *ientry;
 +	unsigned int len = strlen(name);
-+	unsigned int key = full_name_hash(name, len);
++	unsigned int key = full_name_hash((const unsigned char *)name, len);
 +	unsigned int index = key % polstate->name_set.n_size;
 +
 +	curr = &polstate->name_set.n_hash[index];
@@ -121387,7 +122053,7 @@ index 0000000..302bda8
 +	FOR_EACH_ROLE_END(r)
 +
 +	for (i = 0; i < polstate->num_sprole_pws; i++) {
-+		if (!strcmp(rolename, polstate->acl_special_roles[i]->rolename)) {
++		if (!strcmp(rolename, (const char *)polstate->acl_special_roles[i]->rolename)) {
 +			*salt = polstate->acl_special_roles[i]->salt;
 +			*sum = polstate->acl_special_roles[i]->sum;
 +			return 1;
@@ -121674,11 +122340,11 @@ index 0000000..302bda8
 +		}
 +
 +		if (lookup_special_role_auth
-+		    (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum)
++		    (gr_usermode->mode, (const char *)gr_usermode->sp_role, &sprole_salt, &sprole_sum)
 +		    && ((!sprole_salt && !sprole_sum)
 +			|| !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) {
 +			char *p = "";
-+			assign_special_role(gr_usermode->sp_role);
++			assign_special_role((const char *)gr_usermode->sp_role);
 +			read_lock(&tasklist_lock);
 +			if (current->real_parent)
 +				p = current->real_parent->role->rolename;
@@ -125636,7 +126302,7 @@ index 0000000..ae02d8e
 +EXPORT_SYMBOL_GPL(gr_handle_new_usb);
 diff --git a/grsecurity/grsum.c b/grsecurity/grsum.c
 new file mode 100644
-index 0000000..4fb2ce6
+index 0000000..aef6b92
 --- /dev/null
 +++ b/grsecurity/grsum.c
 @@ -0,0 +1,54 @@
@@ -125674,12 +126340,12 @@ index 0000000..4fb2ce6
 +
 +	sg_init_table(sg, 2);
 +	sg_set_buf(&sg[0], salt, GR_SALT_LEN);
-+	sg_set_buf(&sg[1], entry->pw, strlen(entry->pw));
++	sg_set_buf(&sg[1], entry->pw, strlen((const char *)entry->pw));
 +
 +	desc.tfm = tfm;
 +	desc.flags = 0;
 +
-+	cryptres = crypto_hash_digest(&desc, sg, GR_SALT_LEN + strlen(entry->pw),
++	cryptres = crypto_hash_digest(&desc, sg, GR_SALT_LEN + strlen((const char *)entry->pw),
 +					temp_sum);
 +
 +	memset(entry->pw, 0, GR_PW_LEN);
@@ -127062,7 +127728,7 @@ index a76c917..75d6aeb 100644
  asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, compat_size_t);
  /*
 diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
-index eeae401..a2a9f48 100644
+index eeae401..c108d27 100644
 --- a/include/linux/compiler-gcc.h
 +++ b/include/linux/compiler-gcc.h
 @@ -116,9 +116,9 @@
@@ -127078,7 +127744,7 @@ index eeae401..a2a9f48 100644
  #define __maybe_unused		__attribute__((unused))
  #define __always_unused		__attribute__((unused))
  
-@@ -184,9 +184,38 @@
+@@ -184,9 +184,39 @@
  # define __compiletime_warning(message) __attribute__((warning(message)))
  # define __compiletime_error(message) __attribute__((error(message)))
  #endif /* __CHECKER__ */
@@ -127099,6 +127765,7 @@ index eeae401..a2a9f48 100644
 +#ifdef CONSTIFY_PLUGIN
 +#define __no_const __attribute__((no_const))
 +#define __do_const __attribute__((do_const))
++#define const_cast(x) (*(typeof((typeof(x))0) *)&(x))
 +#endif
 +
 +#ifdef SIZE_OVERFLOW_PLUGIN
@@ -127118,7 +127785,7 @@ index eeae401..a2a9f48 100644
   * Mark a position in code as unreachable.  This can be used to
   * suppress control flow warnings after asm blocks that transfer
 diff --git a/include/linux/compiler.h b/include/linux/compiler.h
-index 48f5aab..2d1c52f 100644
+index 48f5aab..4206700 100644
 --- a/include/linux/compiler.h
 +++ b/include/linux/compiler.h
 @@ -5,11 +5,14 @@
@@ -127340,7 +128007,7 @@ index 48f5aab..2d1c52f 100644
  })
  
  /**
-@@ -416,6 +432,38 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
+@@ -416,6 +432,42 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  # define __attribute_const__	/* unimplemented */
  #endif
  
@@ -127376,10 +128043,14 @@ index 48f5aab..2d1c52f 100644
 +# define __nocapture(...)
 +#endif
 +
++#ifndef const_cast
++# define const_cast(x)	(x)
++#endif
++
  /*
   * Tell gcc if a function is cold. The compiler will assume any path
   * directly leading to the call is unlikely.
-@@ -425,6 +473,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
+@@ -425,6 +477,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  #define __cold
  #endif
  
@@ -127402,7 +128073,7 @@ index 48f5aab..2d1c52f 100644
  /* Simple shorthand for a section definition */
  #ifndef __section
  # define __section(S) __attribute__ ((__section__(#S)))
-@@ -447,6 +511,8 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
+@@ -447,6 +515,8 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
  #endif
  
@@ -127411,7 +128082,7 @@ index 48f5aab..2d1c52f 100644
  /* Is this type a native word size -- useful for atomic operations */
  #ifndef __native_word
  # define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
-@@ -526,8 +592,9 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
+@@ -526,8 +596,9 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
   */
  #define __ACCESS_ONCE(x) ({ \
  	 __maybe_unused typeof(x) __var = (__force typeof(x)) 0; \
@@ -131980,7 +132651,7 @@ index 556ec1e..38c19c9 100644
  
  /*
 diff --git a/include/linux/sched.h b/include/linux/sched.h
-index a10494a..2facd6d 100644
+index a10494a..9f25fd6 100644
 --- a/include/linux/sched.h
 +++ b/include/linux/sched.h
 @@ -7,7 +7,7 @@
@@ -132253,7 +132924,7 @@ index a10494a..2facd6d 100644
  {
  	return tsk->pid;
  }
-@@ -2289,6 +2397,25 @@ extern u64 sched_clock_cpu(int cpu);
+@@ -2289,6 +2397,26 @@ extern u64 sched_clock_cpu(int cpu);
  
  extern void sched_clock_init(void);
  
@@ -132267,6 +132938,7 @@ index a10494a..2facd6d 100644
 +
 +	while (ptr < end) {
 +		c = *(volatile int *)ptr;
++		(void)c;
 +		ptr += PAGE_SIZE/sizeof(int);
 +	}
 +}
@@ -132279,7 +132951,7 @@ index a10494a..2facd6d 100644
  #ifndef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
  static inline void sched_clock_tick(void)
  {
-@@ -2417,7 +2544,9 @@ extern void set_curr_task(int cpu, struct task_struct *p);
+@@ -2417,7 +2545,9 @@ extern void set_curr_task(int cpu, struct task_struct *p);
  void yield(void);
  
  union thread_union {
@@ -132289,7 +132961,7 @@ index a10494a..2facd6d 100644
  	unsigned long stack[THREAD_SIZE/sizeof(long)];
  };
  
-@@ -2450,6 +2579,7 @@ extern struct pid_namespace init_pid_ns;
+@@ -2450,6 +2580,7 @@ extern struct pid_namespace init_pid_ns;
   */
  
  extern struct task_struct *find_task_by_vpid(pid_t nr);
@@ -132297,7 +132969,7 @@ index a10494a..2facd6d 100644
  extern struct task_struct *find_task_by_pid_ns(pid_t nr,
  		struct pid_namespace *ns);
  
-@@ -2481,7 +2611,7 @@ extern void proc_caches_init(void);
+@@ -2481,7 +2612,7 @@ extern void proc_caches_init(void);
  extern void flush_signals(struct task_struct *);
  extern void ignore_signals(struct task_struct *);
  extern void flush_signal_handlers(struct task_struct *, int force_default);
@@ -132306,7 +132978,7 @@ index a10494a..2facd6d 100644
  
  static inline int kernel_dequeue_signal(siginfo_t *info)
  {
-@@ -2635,7 +2765,7 @@ extern void __cleanup_sighand(struct sighand_struct *);
+@@ -2635,7 +2766,7 @@ extern void __cleanup_sighand(struct sighand_struct *);
  extern void exit_itimers(struct signal_struct *);
  extern void flush_itimer_signals(void);
  
@@ -132315,7 +132987,7 @@ index a10494a..2facd6d 100644
  
  extern int do_execve(struct filename *,
  		     const char __user * const __user *,
-@@ -2750,11 +2880,13 @@ static inline int thread_group_empty(struct task_struct *p)
+@@ -2750,11 +2881,13 @@ static inline int thread_group_empty(struct task_struct *p)
   * It must not be nested with write_lock_irq(&tasklist_lock),
   * neither inside nor outside.
   */
@@ -132329,7 +133001,7 @@ index a10494a..2facd6d 100644
  static inline void task_unlock(struct task_struct *p)
  {
  	spin_unlock(&p->alloc_lock);
-@@ -2840,9 +2972,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
+@@ -2840,9 +2973,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
  #define task_stack_end_corrupted(task) \
  		(*(end_of_stack(task)) != STACK_END_MAGIC)
  
@@ -132404,6 +133076,19 @@ index dc368b8..e895209 100644
  extern int __must_check down_killable(struct semaphore *sem);
  extern int __must_check down_trylock(struct semaphore *sem);
  extern int __must_check down_timeout(struct semaphore *sem, long jiffies);
+diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h
+index fb7eb9c..1b493dc 100644
+--- a/include/linux/seq_buf.h
++++ b/include/linux/seq_buf.h
+@@ -16,7 +16,7 @@
+  * @readpos:	The next position to read in the buffer.
+  */
+ struct seq_buf {
+-	char			*buffer;
++	unsigned char		*buffer;
+ 	size_t			size;
+ 	size_t			len;
+ 	loff_t			readpos;
 diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
 index dde00de..202bfd3 100644
 --- a/include/linux/seq_file.h
@@ -133368,7 +134053,7 @@ index fa7bc29..0d96561 100644
  struct ctl_node {
  	struct rb_node node;
 diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
-index c6f0f0d..a34ab2d 100644
+index c6f0f0d..e663567 100644
 --- a/include/linux/sysfs.h
 +++ b/include/linux/sysfs.h
 @@ -34,7 +34,8 @@ struct attribute {
@@ -133401,6 +134086,15 @@ index c6f0f0d..a34ab2d 100644
  
  /**
   *	sysfs_bin_attr_init - initialize a dynamically allocated bin_attribute
+@@ -512,7 +515,7 @@ static inline void sysfs_notify_dirent(struct kernfs_node *kn)
+ }
+ 
+ static inline struct kernfs_node *sysfs_get_dirent(struct kernfs_node *parent,
+-						   const unsigned char *name)
++						   const char *name)
+ {
+ 	return kernfs_find_and_get(parent, name);
+ }
 diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
 index 387fa7d..3fcde6b 100644
 --- a/include/linux/sysrq.h
@@ -136761,7 +137455,7 @@ index 45432b5..988f1e4 100644
 +}
 +EXPORT_SYMBOL(capable_wrt_inode_uidgid_nolog);
 diff --git a/kernel/cgroup.c b/kernel/cgroup.c
-index 355cd5f..6273802 100644
+index 355cd5f..93e1510 100644
 --- a/kernel/cgroup.c
 +++ b/kernel/cgroup.c
 @@ -3333,7 +3333,7 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
@@ -136781,12 +137475,12 @@ index 355cd5f..6273802 100644
 -		cft->ss = NULL;
 +
 +		pax_open_kernel();
-+		*(void **)&cft->kf_ops = NULL;
-+		*(void **)&cft->ss = NULL;
++		const_cast(cft->kf_ops) = NULL;
++		const_cast(cft->ss) = NULL;
  
  		/* revert flags set by cgroup core while adding @cfts */
 -		cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL);
-+		*(unsigned int *)&cft->flags &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL);
++		const_cast(cft->flags) &= ~(__CFTYPE_ONLY_ON_DFL | __CFTYPE_NOT_ON_DFL);
 +		pax_close_kernel();
  	}
  }
@@ -136798,8 +137492,8 @@ index 355cd5f..6273802 100644
 -		cft->kf_ops = kf_ops;
 -		cft->ss = ss;
 +		pax_open_kernel();
-+		*(void **)&cft->kf_ops = kf_ops;
-+		*(void **)&cft->ss = ss;
++		const_cast(cft->kf_ops) = kf_ops;
++		const_cast(cft->ss) = ss;
 +		pax_close_kernel();
  	}
  
@@ -136829,7 +137523,7 @@ index 355cd5f..6273802 100644
 +	pax_open_kernel();
  	for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
 -		cft->flags |= __CFTYPE_ONLY_ON_DFL;
-+		*(unsigned int *)&cft->flags |= __CFTYPE_ONLY_ON_DFL;
++		const_cast(cft->flags) |= __CFTYPE_ONLY_ON_DFL;
 +	pax_close_kernel();
  	return cgroup_add_cftypes(ss, cfts);
  }
@@ -136841,7 +137535,7 @@ index 355cd5f..6273802 100644
 +	pax_open_kernel();
  	for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
 -		cft->flags |= __CFTYPE_NOT_ON_DFL;
-+		*(unsigned int *)&cft->flags |= __CFTYPE_NOT_ON_DFL;
++		const_cast(cft->flags) |= __CFTYPE_NOT_ON_DFL;
 +	pax_close_kernel();
  	return cgroup_add_cftypes(ss, cfts);
  }
@@ -138224,7 +138918,7 @@ index 84118723..317f7a5 100644
  			irq_wake_secondary(desc, action);
  
 diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
-index 38e89ce..58960ac 100644
+index 38e89ce..8b7a537 100644
 --- a/kernel/irq/msi.c
 +++ b/kernel/irq/msi.c
 @@ -214,16 +214,18 @@ static void msi_domain_update_dom_ops(struct msi_domain_info *info)
@@ -138234,19 +138928,19 @@ index 38e89ce..58960ac 100644
 +	pax_open_kernel();
  	if (ops->get_hwirq == NULL)
 -		ops->get_hwirq = msi_domain_ops_default.get_hwirq;
-+		*(void **)&ops->get_hwirq = msi_domain_ops_default.get_hwirq;
++		const_cast(ops->get_hwirq) = msi_domain_ops_default.get_hwirq;
  	if (ops->msi_init == NULL)
 -		ops->msi_init = msi_domain_ops_default.msi_init;
-+		*(void **)&ops->msi_init = msi_domain_ops_default.msi_init;
++		const_cast(ops->msi_init) = msi_domain_ops_default.msi_init;
  	if (ops->msi_check == NULL)
 -		ops->msi_check = msi_domain_ops_default.msi_check;
-+		*(void **)&ops->msi_check = msi_domain_ops_default.msi_check;
++		const_cast(ops->msi_check) = msi_domain_ops_default.msi_check;
  	if (ops->msi_prepare == NULL)
 -		ops->msi_prepare = msi_domain_ops_default.msi_prepare;
-+		*(void **)&ops->msi_prepare = msi_domain_ops_default.msi_prepare;
++		const_cast(ops->msi_prepare) = msi_domain_ops_default.msi_prepare;
  	if (ops->set_desc == NULL)
 -		ops->set_desc = msi_domain_ops_default.set_desc;
-+		*(void **)&ops->set_desc = msi_domain_ops_default.set_desc;
++		const_cast(ops->set_desc) = msi_domain_ops_default.set_desc;
 +	pax_close_kernel();
  }
  
@@ -138259,7 +138953,7 @@ index 38e89ce..58960ac 100644
 -		chip->irq_set_affinity = msi_domain_set_affinity;
 +	if (!chip->irq_set_affinity) {
 +		pax_open_kernel();
-+		*(void **)&chip->irq_set_affinity = msi_domain_set_affinity;
++		const_cast(chip->irq_set_affinity) = msi_domain_set_affinity;
 +		pax_close_kernel();
 +	}
  }
@@ -139888,7 +140582,7 @@ index 794ebe8..f81f123 100644
  	}
  	return mod;
 diff --git a/kernel/notifier.c b/kernel/notifier.c
-index fd2c9ac..95e58f6 100644
+index fd2c9ac..6263e05 100644
 --- a/kernel/notifier.c
 +++ b/kernel/notifier.c
 @@ -5,6 +5,7 @@
@@ -139908,7 +140602,7 @@ index fd2c9ac..95e58f6 100644
  	}
 -	n->next = *nl;
 +	pax_open_kernel();
-+	*(const void **)&n->next = *nl;
++	const_cast(n->next) = *nl;
  	rcu_assign_pointer(*nl, n);
 +	pax_close_kernel();
  	return 0;
@@ -139923,7 +140617,7 @@ index fd2c9ac..95e58f6 100644
  	}
 -	n->next = *nl;
 +	pax_open_kernel();
-+	*(const void **)&n->next = *nl;
++	const_cast(n->next) = *nl;
  	rcu_assign_pointer(*nl, n);
 +	pax_close_kernel();
  	return 0;
@@ -140025,7 +140719,7 @@ index d96469d..81d6d28 100644
  }
  EXPORT_SYMBOL(__stack_chk_fail);
 diff --git a/kernel/pid.c b/kernel/pid.c
-index 4d73a83..4712357 100644
+index 4d73a83..9df1950 100644
 --- a/kernel/pid.c
 +++ b/kernel/pid.c
 @@ -33,6 +33,7 @@
@@ -140078,15 +140772,18 @@ index 4d73a83..4712357 100644
  struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
  {
  	struct pid *pid;
-@@ -497,7 +513,7 @@ struct pid *find_get_pid(pid_t nr)
+@@ -497,9 +513,9 @@ struct pid *find_get_pid(pid_t nr)
  }
  EXPORT_SYMBOL_GPL(find_get_pid);
  
 -pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
 +pid_t pid_nr_ns(const struct pid *pid, const struct pid_namespace *ns)
  {
- 	struct upid *upid;
+-	struct upid *upid;
++	const struct upid *upid;
  	pid_t nr = 0;
+ 
+ 	if (pid && ns->level <= pid->level) {
 @@ -511,7 +527,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
  }
  EXPORT_SYMBOL_GPL(pid_nr_ns);
@@ -143248,7 +143945,7 @@ index 2be8c4f..444ecfb 100644
  	}
  	entry	= ring_buffer_event_data(event);
 diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
-index 2829821..a290dc89 100644
+index 2829821..cd4ea77 100644
 --- a/kernel/trace/trace_output.c
 +++ b/kernel/trace/trace_output.c
 @@ -713,14 +713,16 @@ int register_trace_event(struct trace_event *event)
@@ -143258,16 +143955,16 @@ index 2829821..a290dc89 100644
 +	pax_open_kernel();
  	if (event->funcs->trace == NULL)
 -		event->funcs->trace = trace_nop_print;
-+		*(void **)&event->funcs->trace = trace_nop_print;
++		const_cast(event->funcs->trace) = trace_nop_print;
  	if (event->funcs->raw == NULL)
 -		event->funcs->raw = trace_nop_print;
-+		*(void **)&event->funcs->raw = trace_nop_print;
++		const_cast(event->funcs->raw) = trace_nop_print;
  	if (event->funcs->hex == NULL)
 -		event->funcs->hex = trace_nop_print;
-+		*(void **)&event->funcs->hex = trace_nop_print;
++		const_cast(event->funcs->hex) = trace_nop_print;
  	if (event->funcs->binary == NULL)
 -		event->funcs->binary = trace_nop_print;
-+		*(void **)&event->funcs->binary = trace_nop_print;
++		const_cast(event->funcs->binary) = trace_nop_print;
 +	pax_close_kernel();
  
  	key = event->type & (EVENT_HASHSIZE - 1);
@@ -151655,7 +152352,7 @@ index 1474cfd..961bc9f 100644
  		pr_warn("cannot create /proc/net/%s\n", PG_PROC_DIR);
  		return -ENODEV;
 diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
-index 482c371..b02a761 100644
+index 482c371..150e1ee 100644
 --- a/net/core/rtnetlink.c
 +++ b/net/core/rtnetlink.c
 @@ -61,7 +61,7 @@ struct rtnl_link {
@@ -151675,7 +152372,7 @@ index 482c371..b02a761 100644
 -		ops->dellink = unregister_netdevice_queue;
 +	if (ops->setup && !ops->dellink) {
 +		pax_open_kernel();
-+		*(void **)&ops->dellink = unregister_netdevice_queue;
++		const_cast(ops->dellink) = unregister_netdevice_queue;
 +		pax_close_kernel();
 +	}
  
@@ -160008,7 +160705,7 @@ index b5e665b..3030b1d 100644
  	}
  
 diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
-index 9895a8c..705c302 100644
+index 9895a8c..e7c5936 100644
 --- a/net/xfrm/xfrm_state.c
 +++ b/net/xfrm/xfrm_state.c
 @@ -166,12 +166,14 @@ int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
@@ -160082,7 +160779,7 @@ index 9895a8c..705c302 100644
  
 -	mode->afinfo = afinfo;
 +	pax_open_kernel();
-+	*(const void **)&mode->afinfo = afinfo;
++	const_cast(mode->afinfo) = afinfo;
  	modemap[mode->encap] = mode;
 +	pax_close_kernel();
  	err = 0;
@@ -160172,6 +160869,18 @@ index 1db6d73..0819042 100644
  
  # ld-option
  # Usage: LDFLAGS += $(call ld-option, -X)
+diff --git a/scripts/Makefile b/scripts/Makefile
+index fd0d53d..1471190 100644
+--- a/scripts/Makefile
++++ b/scripts/Makefile
+@@ -44,6 +44,7 @@ subdir-y                     += mod
+ subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+ subdir-$(CONFIG_DTC)         += dtc
+ subdir-$(CONFIG_GDB_SCRIPTS) += gdb
++subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
+ 
+ # Let clean descend into subdirs
+ subdir-	+= basic kconfig package
 diff --git a/scripts/Makefile.build b/scripts/Makefile.build
 index 2c47f9c..9d46008 100644
 --- a/scripts/Makefile.build
@@ -160216,81 +160925,83 @@ index f9e47a7..b72022a 100644
  warning-2 += -Wdisabled-optimization
 diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
 new file mode 100644
-index 0000000..02fd848
+index 0000000..08d4e22
 --- /dev/null
 +++ b/scripts/Makefile.gcc-plugins
-@@ -0,0 +1,69 @@
-+__PLUGINCC := $(call cc-ifversion, -ge, 0408, $(HOSTCXX), $(HOSTCC))
-+PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
-+ifneq ($(PLUGINCC),)
-+ifdef CONFIG_PAX_CONSTIFY_PLUGIN
-+CONSTIFY_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/constify_plugin.so -DCONSTIFY_PLUGIN
-+endif
-+ifdef CONFIG_PAX_MEMORY_STACKLEAK
-+STACKLEAK_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/stackleak_plugin.so -DSTACKLEAK_PLUGIN
-+STACKLEAK_PLUGIN_CFLAGS += -fplugin-arg-stackleak_plugin-track-lowest-sp=100
-+endif
-+ifdef CONFIG_KALLOCSTAT_PLUGIN
-+KALLOCSTAT_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/kallocstat_plugin.so
-+endif
-+ifdef CONFIG_PAX_KERNEXEC_PLUGIN
-+KERNEXEC_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/kernexec_plugin.so
-+KERNEXEC_PLUGIN_CFLAGS += -fplugin-arg-kernexec_plugin-method=$(CONFIG_PAX_KERNEXEC_PLUGIN_METHOD) -DKERNEXEC_PLUGIN
-+KERNEXEC_PLUGIN_AFLAGS := -DKERNEXEC_PLUGIN
-+endif
-+ifdef CONFIG_CHECKER_PLUGIN
-+ifeq ($(call cc-ifversion, -ge, 0406, y), y)
-+CHECKER_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/checker_plugin.so -DCHECKER_PLUGIN
-+ifdef CONFIG_CHECKER_PLUGIN_USER
-+CHECKER_PLUGIN_CFLAGS += -fplugin-arg-checker_plugin-user -DCHECKER_PLUGIN_USER
-+endif
-+ifdef CONFIG_CHECKER_PLUGIN_CONTEXT
-+CHECKER_PLUGIN_CFLAGS += -fplugin-arg-checker_plugin-context -DCHECKER_PLUGIN_CONTEXT
-+endif
-+endif
-+endif
-+COLORIZE_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/colorize_plugin.so
-+ifdef CONFIG_PAX_SIZE_OVERFLOW
-+SIZE_OVERFLOW_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/size_overflow_plugin/size_overflow_plugin.so -DSIZE_OVERFLOW_PLUGIN
-+endif
-+ifdef CONFIG_PAX_LATENT_ENTROPY
-+LATENT_ENTROPY_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/latent_entropy_plugin.so -DLATENT_ENTROPY_PLUGIN
-+endif
-+ifdef CONFIG_PAX_MEMORY_STRUCTLEAK
-+STRUCTLEAK_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/structleak_plugin.so -DSTRUCTLEAK_PLUGIN
-+endif
-+INITIFY_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/initify_plugin.so -DINITIFY_PLUGIN
-+ifdef CONFIG_PAX_RAP
-+RAP_PLUGIN_CFLAGS := -fplugin=$(objtree)/tools/gcc/rap_plugin/rap_plugin.so -fplugin-arg-rap_plugin-check=call -DRAP_PLUGIN
-+#RAP_PLUGIN_CFLAGS += -fplugin-arg-rap_plugin-report=func,fptr,abs
-+RAP_PLUGIN_ABS_CFLAGS := -fplugin-arg-rap_plugin-hash=abs-finish
-+RAP_PLUGIN_AFLAGS := -DRAP_PLUGIN
-+endif
-+GCC_PLUGINS_CFLAGS := $(CONSTIFY_PLUGIN_CFLAGS) $(STACKLEAK_PLUGIN_CFLAGS) $(KALLOCSTAT_PLUGIN_CFLAGS)
-+GCC_PLUGINS_CFLAGS += $(KERNEXEC_PLUGIN_CFLAGS) $(CHECKER_PLUGIN_CFLAGS) $(COLORIZE_PLUGIN_CFLAGS)
-+GCC_PLUGINS_CFLAGS += $(SIZE_OVERFLOW_PLUGIN_CFLAGS) $(LATENT_ENTROPY_PLUGIN_CFLAGS) $(STRUCTLEAK_PLUGIN_CFLAGS)
-+GCC_PLUGINS_CFLAGS += $(INITIFY_PLUGIN_CFLAGS)
-+GCC_PLUGINS_CFLAGS += $(RAP_PLUGIN_CFLAGS) $(RAP_PLUGIN_ABS_CFLAGS)
-+GCC_PLUGINS_AFLAGS := $(KERNEXEC_PLUGIN_AFLAGS) $(RAP_PLUGIN_AFLAGS)
-+export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGINS_AFLAGS CONSTIFY_PLUGIN LATENT_ENTROPY_PLUGIN_CFLAGS RAP_PLUGIN_CFLAGS RAP_PLUGIN_ABS_CFLAGS
-+ifeq ($(KBUILD_EXTMOD),)
-+gcc-plugins:
-+	$(Q)$(MAKE) $(build)=tools/gcc
-+else
-+gcc-plugins: ;
-+endif
-+else
-+gcc-plugins:
-+ifeq ($(call cc-ifversion, -ge, 0405, y), y)
-+	$(warning warning, your gcc installation does not support plugins, perhaps the necessary headers are missing?)
-+	$(CONFIG_SHELL) -x $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)"
-+else
-+	$(warning warning, your gcc version does not support plugins, you should upgrade it to gcc 4.5 at least)
-+endif
-+	$(warning PAX_MEMORY_STACKLEAK and other features will be less secure)
+@@ -0,0 +1,71 @@
++ifdef CONFIG_GCC_PLUGINS
++  __PLUGINCC := $(call cc-ifversion, -ge, 0408, $(HOSTCXX), $(HOSTCC))
++  PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
++
++  gcc-plugin-$(CONFIG_PAX_CONSTIFY_PLUGIN)		+= constify_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_CONSTIFY_PLUGIN)	+= -DCONSTIFY_PLUGIN
++
++  gcc-plugin-$(CONFIG_PAX_MEMORY_STACKLEAK)		+= stackleak_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_MEMORY_STACKLEAK)	+= -DSTACKLEAK_PLUGIN -fplugin-arg-stackleak_plugin-track-lowest-sp=100
++
++  gcc-plugin-$(CONFIG_KALLOCSTAT_PLUGIN)		+= kallocstat_plugin.so
++
++  gcc-plugin-$(CONFIG_PAX_KERNEXEC_PLUGIN)		+= kernexec_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_KERNEXEC_PLUGIN)	+= -DKERNEXEC_PLUGIN -fplugin-arg-kernexec_plugin-method=$(CONFIG_PAX_KERNEXEC_PLUGIN_METHOD)
++  gcc-plugin-aflags-$(CONFIG_PAX_KERNEXEC_PLUGIN)	+= -DKERNEXEC_PLUGIN
++
++  ifdef CONFIG_CHECKER_PLUGIN
++    ifeq ($(call cc-ifversion, -ge, 0406, y), y)
++      gcc-plugin-$(CONFIG_CHECKER_PLUGIN)		+= checker_plugin.so
++      gcc-plugin-cflags-$(CONFIG_CHECKER_PLUGIN)	+= -DCHECKER_PLUGIN
++      gcc-plugin-cflags-$(CONFIG_CHECKER_PLUGIN_USER)	+= -DCHECKER_PLUGIN_USER -fplugin-arg-checker_plugin-user
++      gcc-plugin-cflags-$(CONFIG_CHECKER_PLUGIN_CONTEXT)+= -DCHECKER_PLUGIN_CONTEXT -fplugin-arg-checker_plugin-context
++    endif
++  endif
++
++  gcc-plugin-y						+= colorize_plugin.so
++
++  gcc-plugin-$(CONFIG_PAX_SIZE_OVERFLOW)		+= size_overflow_plugin/size_overflow_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_SIZE_OVERFLOW)		+= -DSIZE_OVERFLOW_PLUGIN
++
++  gcc-plugin-$(CONFIG_PAX_LATENT_ENTROPY)		+= latent_entropy_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_LATENT_ENTROPY)	+= -DLATENT_ENTROPY_PLUGIN
++  ifdef CONFIG_PAX_LATENT_ENTROPY
++    DISABLE_LATENT_ENTROPY_PLUGIN				+= -fplugin-arg-latent_entropy_plugin-disable
++  endif
++
++  gcc-plugin-$(CONFIG_PAX_MEMORY_STRUCTLEAK)		+= structleak_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_MEMORY_STRUCTLEAK)	+= -DSTRUCTLEAK_PLUGIN
++
++  gcc-plugin-y						+= initify_plugin.so
++  gcc-plugin-cflags-y					+= -DINITIFY_PLUGIN
++
++  gcc-plugin-$(CONFIG_PAX_RAP)				+= rap_plugin/rap_plugin.so
++  gcc-plugin-cflags-$(CONFIG_PAX_RAP)			+= -DRAP_PLUGIN -fplugin-arg-rap_plugin-check=call
++#  gcc-plugin-cflags-$(CONFIG_PAX_RAP)			+= -fplugin-arg-rap_plugin-report=func,fptr,abs
++  gcc-plugin-aflags-$(CONFIG_PAX_RAP)			+= -DRAP_PLUGIN
++  ifdef CONFIG_PAX_RAP
++    RAP_PLUGIN_ABS_CFLAGS				:= -fplugin-arg-rap_plugin-hash=abs-finish
++  endif
++  gcc-plugin-cflags-$(CONFIG_PAX_RAP)			+= $(RAP_PLUGIN_ABS_CFLAGS)
++
++  GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
++  GCC_PLUGINS_AFLAGS := $(gcc-plugin-aflags-y)
++
++  export DISABLE_LATENT_ENTROPY_PLUGIN RAP_PLUGIN_ABS_CFLAGS
++
++  ifeq ($(PLUGINCC),)
++    ifneq ($(GCC_PLUGINS_CFLAGS),)
++      ifeq ($(call cc-ifversion, -ge, 0405, y), y)
++        PLUGINCC := $(shell $(CONFIG_SHELL) -x $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
++        $(warning warning, your gcc installation does not support plugins, perhaps the necessary headers are missing?)
++      else
++        $(warning warning, your gcc version does not support plugins, you should upgrade it to gcc 4.5 at least)
++      endif
++      $(warning PAX_MEMORY_STACKLEAK and other features will be less secure)
++    endif
++  endif
++
++  KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
++  KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS)
 +endif
 diff --git a/scripts/Makefile.host b/scripts/Makefile.host
-index 133edfa..3cc6af2 100644
+index 133edfa..3439bd8 100644
 --- a/scripts/Makefile.host
 +++ b/scripts/Makefile.host
 @@ -20,7 +20,25 @@
@@ -160349,7 +161060,7 @@ index 133edfa..3cc6af2 100644
  host-objdirs    := $(addprefix $(obj)/,$(host-objdirs))
  
  obj-dirs += $(host-objdirs)
-@@ -124,5 +158,37 @@ quiet_cmd_host-cxxobjs	= HOSTCXX $@
+@@ -124,5 +158,39 @@ quiet_cmd_host-cxxobjs	= HOSTCXX $@
  $(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE
  	$(call if_changed_dep,host-cxxobjs)
  
@@ -160373,8 +161084,9 @@ index 133edfa..3cc6af2 100644
 +      cmd_host-cshlib	= $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
 +			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \
 +			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-+$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE
++$(host-cshlib): FORCE
 +	$(call if_changed,host-cshlib)
++$(call multi_depend, $(host-cshlib), .so, -objs -cshobjs)
 +
 +# Link a shared library, based on position independent .o files
 +# *.o -> .so shared library (host-cxxshlib)
@@ -160382,8 +161094,9 @@ index 133edfa..3cc6af2 100644
 +      cmd_host-cxxshlib	= $(HOSTCXX) $(HOSTLDFLAGS) -shared -o $@ \
 +			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \
 +			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-+$(host-cxxshlib): $(obj)/%: $(host-cxxshobjs) FORCE
++$(host-cxxshlib): FORCE
 +	$(call if_changed,host-cxxshlib)
++$(call multi_depend, $(host-cxxshlib), .so, -objs -cxxshobjs)
 +
  targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
 -	   $(host-cxxmulti) $(host-cxxobjs)
@@ -160592,14 +161305,14 @@ index e229b84..7141e8e 100644
  	while (get_node_by_phandle(root, phandle))
 diff --git a/scripts/gcc-plugin.sh b/scripts/gcc-plugin.sh
 new file mode 100644
-index 0000000..eaa4fce
+index 0000000..fb92075
 --- /dev/null
 +++ b/scripts/gcc-plugin.sh
 @@ -0,0 +1,51 @@
 +#!/bin/sh
 +srctree=$(dirname "$0")
 +gccplugins_dir=$($3 -print-file-name=plugin)
-+plugincc=$($1 -E -x c++ - -o /dev/null -I"${srctree}"/../tools/gcc -I"${gccplugins_dir}"/include 2>&1 <<EOF
++plugincc=$($1 -E -x c++ - -o /dev/null -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
 +#include "gcc-common.h"
 +#if BUILDING_GCC_VERSION >= 4008 || defined(ENABLE_BUILD_WITH_CXX)
 +#warning $2 CXX
@@ -160630,7 +161343,7 @@ index 0000000..eaa4fce
 +esac
 +
 +# we need a c++ compiler that supports the designated initializer GNU extension
-+plugincc=$($2 -c -x c++ -std=gnu++98 - -fsyntax-only -I"${srctree}"/../tools/gcc -I"${gccplugins_dir}"/include 2>&1 <<EOF
++plugincc=$($2 -c -x c++ -std=gnu++98 - -fsyntax-only -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
 +#include "gcc-common.h"
 +class test {
 +public:
@@ -160647,4765 +161360,1324 @@ index 0000000..eaa4fce
 +	exit 0
 +fi
 +exit 1
-diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
-index fdebd66..a349e33 100755
---- a/scripts/headers_install.sh
-+++ b/scripts/headers_install.sh
-@@ -32,6 +32,7 @@ do
- 	FILE="$(basename "$i")"
- 	sed -r \
- 		-e 's/([ \t(])(__user|__force|__iomem)[ \t]/\1/g' \
-+		-e 's/__intentional_overflow\([- \t,0-9]*\)//g' \
- 		-e 's/__attribute_const__([ \t]|$)/\1/g' \
- 		-e 's@^#include <linux/compiler.h>@@' \
- 		-e 's/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g' \
-diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
-index 8fa81e8..a9ac144 100644
---- a/scripts/kallsyms.c
-+++ b/scripts/kallsyms.c
-@@ -89,7 +89,7 @@ static inline int is_arm_mapping_symbol(const char *str)
- }
- 
- static int check_symbol_range(const char *sym, unsigned long long addr,
--			      struct addr_range *ranges, int entries)
-+			      struct addr_range *ranges, size_t entries)
- {
- 	size_t i;
- 	struct addr_range *ar;
-@@ -178,7 +178,7 @@ static int read_symbol(FILE *in, struct sym_entry *s)
- }
- 
- static int symbol_in_range(struct sym_entry *s, struct addr_range *ranges,
--			   int entries)
-+			   size_t entries)
- {
- 	size_t i;
- 	struct addr_range *ar;
-diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
-index 91ca126..5f7cad6 100644
---- a/scripts/kconfig/lkc.h
-+++ b/scripts/kconfig/lkc.h
-@@ -108,7 +108,8 @@ void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
- void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
- void menu_add_option(int token, char *arg);
- void menu_finalize(struct menu *parent);
--void menu_set_type(int type);
-+enum symbol_type;
-+void menu_set_type(enum symbol_type type);
- 
- /* util.c */
- struct file *file_lookup(const char *name);
-@@ -123,7 +124,7 @@ struct gstr {
- 	* when max_width is not zero long lines in string s (if any) get
- 	* wrapped not to exceed the max_width value
- 	*/
--	int max_width;
-+	size_t max_width;
- };
- struct gstr str_new(void);
- void str_free(struct gstr *gs);
-diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
-index aed678e..1a703de 100644
---- a/scripts/kconfig/menu.c
-+++ b/scripts/kconfig/menu.c
-@@ -109,7 +109,7 @@ void menu_add_dep(struct expr *dep)
- 	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
- }
- 
--void menu_set_type(int type)
-+void menu_set_type(enum symbol_type type)
- {
- 	struct symbol *sym = current_entry->sym;
- 
-diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
-index 25cf0c2..eb178ce 100644
---- a/scripts/kconfig/symbol.c
-+++ b/scripts/kconfig/symbol.c
-@@ -956,7 +956,7 @@ const char *sym_escape_string_value(const char *in)
- 
- struct sym_match {
- 	struct symbol	*sym;
--	off_t		so, eo;
-+	regoff_t	so, eo;
- };
- 
- /* Compare matched symbols as thus:
-@@ -978,8 +978,8 @@ static int sym_rel_comp(const void *sym1, const void *sym2)
- 	 * exactly; if this is the case, we can't decide which comes first,
- 	 * and we fallback to sorting alphabetically.
- 	 */
--	exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
--	exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
-+	exact1 = (s1->eo - s1->so) == (long)strlen(s1->sym->name);
-+	exact2 = (s2->eo - s2->so) == (long)strlen(s2->sym->name);
- 	if (exact1 && !exact2)
- 		return -1;
- 	if (!exact1 && exact2)
-diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index ba6c34e..ea10bce 100755
---- a/scripts/link-vmlinux.sh
-+++ b/scripts/link-vmlinux.sh
-@@ -179,7 +179,7 @@ else
- fi;
- 
- # final build of init/
--${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
-+${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="${GCC_PLUGINS_CFLAGS}" GCC_PLUGINS_AFLAGS="${GCC_PLUGINS_AFLAGS}"
- 
- kallsymso=""
- kallsyms_vmlinux=""
-diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
-index a915507..27c1b41 100644
---- a/scripts/mod/file2alias.c
-+++ b/scripts/mod/file2alias.c
-@@ -156,7 +156,7 @@ static void device_id_check(const char *modname, const char *device_id,
- 			    unsigned long size, unsigned long id_size,
- 			    void *symval)
- {
--	int i;
-+	unsigned int i;
- 
- 	if (size % id_size || size < id_size) {
- 		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
-@@ -185,7 +185,7 @@ static void device_id_check(const char *modname, const char *device_id,
- /* USB is special because the bcdDevice can be matched against a numeric range */
- /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
- static void do_usb_entry(void *symval,
--			 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
-+			 unsigned int bcdDevice_initial, unsigned int bcdDevice_initial_digits,
- 			 unsigned char range_lo, unsigned char range_hi,
- 			 unsigned char max, struct module *mod)
- {
-@@ -295,7 +295,7 @@ static void do_usb_entry_multi(void *symval, struct module *mod)
- {
- 	unsigned int devlo, devhi;
- 	unsigned char chi, clo, max;
--	int ndigits;
-+	unsigned int ndigits;
- 
- 	DEF_FIELD(symval, usb_device_id, match_flags);
- 	DEF_FIELD(symval, usb_device_id, idVendor);
-@@ -619,7 +619,7 @@ static void do_pnp_device_entry(void *symval, unsigned long size,
- 	for (i = 0; i < count; i++) {
- 		DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
- 		char acpi_id[sizeof(*id)];
--		int j;
-+		unsigned int j;
- 
- 		buf_printf(&mod->dev_table_buf,
- 			   "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
-@@ -648,7 +648,7 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
- 
- 		for (j = 0; j < PNP_MAX_DEVICES; j++) {
- 			const char *id = (char *)(*devs)[j].id;
--			int i2, j2;
-+			unsigned int i2, j2;
- 			int dup = 0;
- 
- 			if (!id[0])
-@@ -674,7 +674,7 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
- 			/* add an individual alias for every device entry */
- 			if (!dup) {
- 				char acpi_id[PNP_ID_LEN];
--				int k;
-+				unsigned int k;
- 
- 				buf_printf(&mod->dev_table_buf,
- 					   "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
-@@ -999,7 +999,7 @@ static void dmi_ascii_filter(char *d, const char *s)
- static int do_dmi_entry(const char *filename, void *symval,
- 			char *alias)
- {
--	int i, j;
-+	unsigned int i, j;
- 	DEF_FIELD_ADDR(symval, dmi_system_id, matches);
- 	sprintf(alias, "dmi*");
- 
-diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 48958d3..d5ccb52 100644
---- a/scripts/mod/modpost.c
-+++ b/scripts/mod/modpost.c
-@@ -37,6 +37,7 @@ static int vmlinux_section_warnings = 1;
- static int warn_unresolved = 0;
- /* How a symbol is exported */
- static int sec_mismatch_count = 0;
-+static int writable_fptr_count = 0;
- static int sec_mismatch_verbose = 1;
- static int sec_mismatch_fatal = 0;
- /* ignore missing files */
-@@ -947,6 +948,7 @@ enum mismatch {
- 	ANY_EXIT_TO_ANY_INIT,
- 	EXPORT_TO_INIT_EXIT,
- 	EXTABLE_TO_NON_TEXT,
-+	DATA_TO_TEXT
- };
- 
- /**
-@@ -1073,6 +1075,12 @@ static const struct sectioncheck sectioncheck[] = {
- 	.good_tosec = {ALL_TEXT_SECTIONS , NULL},
- 	.mismatch = EXTABLE_TO_NON_TEXT,
- 	.handler = extable_mismatch_handler,
-+},
-+/* Do not reference code from writable data */
-+{
-+	.fromsec = { DATA_SECTIONS, NULL },
-+	.bad_tosec = { ALL_TEXT_SECTIONS, NULL },
-+	.mismatch = DATA_TO_TEXT
- }
- };
- 
-@@ -1222,10 +1230,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
- 			continue;
- 		if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
- 			continue;
--		if (sym->st_value == addr)
--			return sym;
- 		/* Find a symbol nearby - addr are maybe negative */
- 		d = sym->st_value - addr;
-+		if (d == 0)
-+			return sym;
- 		if (d < 0)
- 			d = addr - sym->st_value;
- 		if (d < distance) {
-@@ -1384,7 +1392,11 @@ static void report_sec_mismatch(const char *modname,
- 	char *prl_from;
- 	char *prl_to;
- 
--	sec_mismatch_count++;
-+	if (mismatch->mismatch == DATA_TO_TEXT)
-+		writable_fptr_count++;
-+	else
-+		sec_mismatch_count++;
-+
- 	if (!sec_mismatch_verbose)
- 		return;
- 
-@@ -1508,6 +1520,14 @@ static void report_sec_mismatch(const char *modname,
- 		fatal("There's a special handler for this mismatch type, "
- 		      "we should never get here.");
- 		break;
-+	case DATA_TO_TEXT:
-+#if 0
-+		fprintf(stderr,
-+		"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");
- }
-@@ -1897,7 +1917,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
- static void check_sec_ref(struct module *mod, const char *modname,
- 			  struct elf_info *elf)
- {
--	int i;
-+	unsigned int i;
- 	Elf_Shdr *sechdrs = elf->sechdrs;
- 
- 	/* Walk through all sections */
-@@ -2028,7 +2048,7 @@ void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
- 	va_end(ap);
- }
- 
--void buf_write(struct buffer *buf, const char *s, int len)
-+void buf_write(struct buffer *buf, const char *s, unsigned int len)
- {
- 	if (buf->size - buf->pos < len) {
- 		buf->size += len + SZ;
-@@ -2258,7 +2278,7 @@ static void write_if_changed(struct buffer *b, const char *fname)
- 	if (fstat(fileno(file), &st) < 0)
- 		goto close_write;
- 
--	if (st.st_size != b->pos)
-+	if (st.st_size != (off_t)b->pos)
- 		goto close_write;
- 
- 	tmp = NOFAIL(malloc(b->pos));
-@@ -2496,6 +2516,14 @@ int main(int argc, char **argv)
- 			      "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
- 		}
- 	}
-+	if (writable_fptr_count) {
-+		if (!sec_mismatch_verbose) {
-+			warn("modpost: Found %d writable function pointer(s).\n"
-+			     "To see full details build your kernel with:\n"
-+			     "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
-+			     writable_fptr_count);
-+		}
-+	}
- 
- 	return err;
- }
-diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
-index 6a5e151..f2fbaf5 100644
---- a/scripts/mod/modpost.h
-+++ b/scripts/mod/modpost.h
-@@ -98,15 +98,15 @@ void *do_nofail(void *ptr, const char *expr);
- 
- struct buffer {
- 	char *p;
--	int pos;
--	int size;
-+	unsigned int pos;
-+	unsigned int size;
- };
- 
- void __attribute__((format(printf, 2, 3)))
- buf_printf(struct buffer *buf, const char *fmt, ...);
- 
- void
--buf_write(struct buffer *buf, const char *s, int len);
-+buf_write(struct buffer *buf, const char *s, unsigned int len);
- 
- struct module {
- 	struct module *next;
-diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
-index 944418d..15291e4 100644
---- a/scripts/mod/sumversion.c
-+++ b/scripts/mod/sumversion.c
-@@ -470,7 +470,7 @@ static void write_version(const char *filename, const char *sum,
- 		goto out;
- 	}
- 
--	if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
-+	if (write(fd, sum, strlen(sum)+1) != (ssize_t)strlen(sum)+1) {
- 		warn("writing sum in %s failed: %s\n",
- 			filename, strerror(errno));
- 		goto out;
-diff --git a/scripts/module-common.lds b/scripts/module-common.lds
-index 73a2c7d..df11b31 100644
---- a/scripts/module-common.lds
-+++ b/scripts/module-common.lds
-@@ -6,6 +6,10 @@
- SECTIONS {
- 	/DISCARD/ : { *(.discard) }
- 
-+	.rodata			0: {
-+		*(.rodata) *(.rodata.*)
-+		*(.data..read_only)
-+	}
- 	__ksymtab		0 : { *(SORT(___ksymtab+*)) }
- 	__ksymtab_gpl		0 : { *(SORT(___ksymtab_gpl+*)) }
- 	__ksymtab_unused	0 : { *(SORT(___ksymtab_unused+*)) }
-diff --git a/scripts/package/Makefile b/scripts/package/Makefile
-index c2c7389..81b8117 100644
---- a/scripts/package/Makefile
-+++ b/scripts/package/Makefile
-@@ -40,7 +40,7 @@ if test "$(objtree)" != "$(srctree)"; then \
- fi ; \
- $(srctree)/scripts/setlocalversion --save-scmversion; \
- ln -sf $(srctree) $(2); \
--tar -cz $(RCS_TAR_IGNORE) -f $(2).tar.gz \
-+tar --owner=root --group=root -cz $(RCS_TAR_IGNORE) -f $(2).tar.gz \
- 	$(addprefix $(2)/,$(TAR_CONTENT) $(3)); \
- rm -f $(2) $(objtree)/.scmversion
- 
-diff --git a/scripts/package/builddeb b/scripts/package/builddeb
-index 6c3b038..54e0b5e 100755
---- a/scripts/package/builddeb
-+++ b/scripts/package/builddeb
-@@ -326,6 +326,7 @@ fi
- (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
- (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
- (cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
-+(cd $objtree; find tools/gcc -name \*.so -o -name gcc-common.h) >> "$objtree/debian/hdrobjfiles"
- destdir=$kernel_headers_dir/usr/src/linux-headers-$version
- mkdir -p "$destdir"
- (cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
-diff --git a/scripts/package/mkspec b/scripts/package/mkspec
-index fe44d68..3874acb 100755
---- a/scripts/package/mkspec
-+++ b/scripts/package/mkspec
-@@ -120,29 +120,40 @@ echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/{build,source}"
- echo "mkdir -p "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE"
- echo "EXCLUDES=\"$RCS_TAR_IGNORE --exclude .tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude=firmware --exclude .config.old --exclude .missing-syscalls.d\""
- echo "tar "'$EXCLUDES'" -cf- . | (cd "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE;tar xvf -)"
--echo 'cd $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE"
--echo "ln -sf /usr/src/kernels/$KERNELRELEASE build"
--echo "ln -sf /usr/src/kernels/$KERNELRELEASE source"
- fi
- 
- echo ""
- echo "%clean"
- echo 'rm -rf $RPM_BUILD_ROOT'
- echo ""
-+echo "%pre"
-+echo 'chmod -f 0500 /boot'
-+echo 'if [ -d /lib/modules ]; then'
-+echo 'chmod -f 0500 /lib/modules'
-+echo 'fi'
-+echo 'if [ -d /lib32/modules ]; then'
-+echo 'chmod -f 0500 /lib32/modules'
-+echo 'fi'
-+echo 'if [ -d /lib64/modules ]; then'
-+echo 'chmod -f 0500 /lib64/modules'
-+echo 'fi'
-+echo ""
-+echo "%post devel"
-+echo "ln -sf /usr/src/kernels/$KERNELRELEASE /lib/modules/$KERNELRELEASE/build"
-+echo "ln -sf /usr/src/kernels/$KERNELRELEASE /lib/modules/$KERNELRELEASE/source"
-+echo ""
- echo "%post"
--echo "if [ -x /sbin/installkernel -a -r /boot/vmlinuz-$KERNELRELEASE -a -r /boot/System.map-$KERNELRELEASE ]; then"
--echo "cp /boot/vmlinuz-$KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm"
--echo "cp /boot/System.map-$KERNELRELEASE /boot/.System.map-$KERNELRELEASE-rpm"
--echo "rm -f /boot/vmlinuz-$KERNELRELEASE /boot/System.map-$KERNELRELEASE"
--echo "/sbin/installkernel $KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm"
--echo "rm -f /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm"
-+echo "if [ -x /sbin/dracut ]; then"
-+echo '/sbin/new-kernel-pkg --dracut --mkinitrd --depmod --install --make-default '"$KERNELRELEASE"' || exit $?'
-+echo "else"
-+echo '/sbin/new-kernel-pkg --mkinitrd --depmod --install --make-default '"$KERNELRELEASE"' || exit $?'
- echo "fi"
- echo ""
- echo "%files"
--echo '%defattr (-, root, root)'
--echo "/lib/modules/$KERNELRELEASE"
-+echo '%defattr (400, root, root, 500)'
- echo "%exclude /lib/modules/$KERNELRELEASE/build"
- echo "%exclude /lib/modules/$KERNELRELEASE/source"
-+echo "/lib/modules/$KERNELRELEASE"
- echo "/lib/firmware/$KERNELRELEASE"
- echo "/boot/*"
- echo ""
-@@ -152,9 +163,11 @@ echo "/usr/include"
- echo ""
- if ! $PREBUILT; then
- echo "%files devel"
--echo '%defattr (-, root, root)'
-+echo '%defattr (400, root, root, 500)'
-+echo "%dir /lib/modules/$KERNELRELEASE"
- echo "/usr/src/kernels/$KERNELRELEASE"
--echo "/lib/modules/$KERNELRELEASE/build"
--echo "/lib/modules/$KERNELRELEASE/source"
-+echo "%attr (500, root, root) /usr/src/kernels/$KERNELRELEASE/scripts/recordmcount"
-+echo "%attr (500, root, root) /usr/src/kernels/$KERNELRELEASE/scripts/basic/fixdep"
-+echo "%attr (500, root, root) /usr/src/kernels/$KERNELRELEASE/scripts/mod/modpost"
- echo ""
- fi
-diff --git a/scripts/pnmtologo.c b/scripts/pnmtologo.c
-index 4718d78..9220d58 100644
---- a/scripts/pnmtologo.c
-+++ b/scripts/pnmtologo.c
-@@ -244,14 +244,14 @@ static void write_header(void)
-     fprintf(out, " *  Linux logo %s\n", logoname);
-     fputs(" */\n\n", out);
-     fputs("#include <linux/linux_logo.h>\n\n", out);
--    fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
-+    fprintf(out, "static unsigned char %s_data[] = {\n",
- 	    logoname);
- }
- 
- static void write_footer(void)
- {
-     fputs("\n};\n\n", out);
--    fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
-+    fprintf(out, "const struct linux_logo %s = {\n", logoname);
-     fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
-     fprintf(out, "\t.width\t\t= %d,\n", logo_width);
-     fprintf(out, "\t.height\t\t= %d,\n", logo_height);
-@@ -381,7 +381,7 @@ static void write_logo_clut224(void)
-     fputs("\n};\n\n", out);
- 
-     /* write logo clut */
--    fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
-+    fprintf(out, "static unsigned char %s_clut[] = {\n",
- 	    logoname);
-     write_hex_cnt = 0;
-     for (i = 0; i < logo_clutsize; i++) {
-diff --git a/scripts/sortextable.h b/scripts/sortextable.h
-index ba87004..3f4852c 100644
---- a/scripts/sortextable.h
-+++ b/scripts/sortextable.h
-@@ -108,9 +108,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
- 	const char *secstrtab;
- 	const char *strtab;
- 	char *extab_image;
--	int extab_index = 0;
--	int i;
--	int idx;
-+	unsigned int extab_index = 0;
-+	unsigned int i;
-+	unsigned int idx;
- 	unsigned int num_sections;
- 	unsigned int secindex_strings;
- 
-diff --git a/scripts/tags.sh b/scripts/tags.sh
-index 23ba1c6..cad2484 100755
---- a/scripts/tags.sh
-+++ b/scripts/tags.sh
-@@ -26,7 +26,7 @@ else
- fi
- 
- # ignore userspace tools
--ignore="$ignore ( -path ${tree}tools ) -prune -o"
-+ignore="$ignore ( -path \"${tree}tools/[^g]*\" ) -prune -o"
- 
- # Find all available archs
- find_all_archs()
-diff --git a/security/Kconfig b/security/Kconfig
-index e452378..4388a35 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -4,6 +4,989 @@
- 
- menu "Security options"
- 
-+menu "Grsecurity"
+diff --git a/scripts/gcc-plugins/.gitignore b/scripts/gcc-plugins/.gitignore
+new file mode 100644
+index 0000000..de92ed9
+--- /dev/null
++++ b/scripts/gcc-plugins/.gitignore
+@@ -0,0 +1 @@
++randomize_layout_seed.h
+diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
+new file mode 100644
+index 0000000..ad7ca02
+--- /dev/null
++++ b/scripts/gcc-plugins/Makefile
+@@ -0,0 +1,57 @@
++#CC := gcc
++#PLUGIN_SOURCE_FILES := pax_plugin.c
++#PLUGIN_OBJECT_FILES := $(patsubst %.c,%.o,$(PLUGIN_SOURCE_FILES))
++GCCPLUGINS_DIR := $(shell $(CC) -print-file-name=plugin)
++#CFLAGS += -I$(GCCPLUGINS_DIR)/include -fPIC -O2 -Wall -W -std=gnu99
 +
-+	config ARCH_TRACK_EXEC_LIMIT
-+	bool
++ifeq ($(PLUGINCC),$(HOSTCC))
++HOSTLIBS := hostlibs
++HOST_EXTRACFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(src) -std=gnu99 -ggdb -Wall -W
++export HOST_EXTRACFLAGS
++else
++HOSTLIBS := hostcxxlibs
++HOST_EXTRACXXFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(src) -std=gnu++98 -fno-rtti -fno-exceptions -fasynchronous-unwind-tables -ggdb -Wall -W -Wno-unused-parameter -Wno-narrowing -Wno-unused-variable
++export HOST_EXTRACXXFLAGS
++endif
 +
-+	config PAX_KERNEXEC_PLUGIN
-+	bool
++export GCCPLUGINS_DIR HOSTLIBS
 +
-+	config PAX_PER_CPU_PGD
-+	bool
++$(HOSTLIBS)-$(CONFIG_PAX_CONSTIFY_PLUGIN) := constify_plugin.so
++$(HOSTLIBS)-$(CONFIG_PAX_MEMORY_STACKLEAK) += stackleak_plugin.so
++$(HOSTLIBS)-$(CONFIG_KALLOCSTAT_PLUGIN) += kallocstat_plugin.so
++$(HOSTLIBS)-$(CONFIG_PAX_KERNEXEC_PLUGIN) += kernexec_plugin.so
++$(HOSTLIBS)-$(CONFIG_CHECKER_PLUGIN) += checker_plugin.so
++$(HOSTLIBS)-y += colorize_plugin.so
++$(HOSTLIBS)-$(CONFIG_PAX_LATENT_ENTROPY) += latent_entropy_plugin.so
++$(HOSTLIBS)-$(CONFIG_PAX_MEMORY_STRUCTLEAK) += structleak_plugin.so
++$(HOSTLIBS)-y += initify_plugin.so
++$(HOSTLIBS)-$(CONFIG_GRKERNSEC_RANDSTRUCT) += randomize_layout_plugin.so
 +
-+	config TASK_SIZE_MAX_SHIFT
-+	int
-+	depends on X86_64
-+	default 47 if !PAX_PER_CPU_PGD
-+	default 42 if PAX_PER_CPU_PGD
++subdir-$(CONFIG_PAX_SIZE_OVERFLOW) := size_overflow_plugin
++subdir- += size_overflow_plugin
 +
-+	config PAX_ENABLE_PAE
-+	bool
-+	default y if (X86_32 && (MPENTIUM4 || MK8 || MPSC || MCORE2 || MATOM))
-+	
-+	config PAX_USERCOPY_SLABS
-+	bool
++subdir-$(CONFIG_PAX_RAP) += rap_plugin
++subdir- += rap_plugin
 +
-+config GRKERNSEC
-+	bool "Grsecurity"
-+	select CRYPTO
-+	select CRYPTO_SHA256
-+	select PROC_FS
-+	select STOP_MACHINE
-+	select TTY
-+	select DEBUG_KERNEL
-+	select DEBUG_LIST
-+	select MULTIUSER
-+	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
-+	  recommended that you say Y here and read through the help
-+	  for each option so that you fully understand the features and
-+	  can evaluate their usefulness for your machine.
++always := $($(HOSTLIBS)-y)
 +
-+choice
-+	prompt "Configuration Method"
-+	depends on GRKERNSEC
-+	default GRKERNSEC_CONFIG_CUSTOM
-+	help
++constify_plugin-objs := constify_plugin.o
++stackleak_plugin-objs := stackleak_plugin.o
++kallocstat_plugin-objs := kallocstat_plugin.o
++kernexec_plugin-objs := kernexec_plugin.o
++checker_plugin-objs := checker_plugin.o
++colorize_plugin-objs := colorize_plugin.o
++latent_entropy_plugin-objs := latent_entropy_plugin.o
++structleak_plugin-objs := structleak_plugin.o
++initify_plugin-objs := initify_plugin.o
++randomize_layout_plugin-objs := randomize_layout_plugin.o
 +
-+config GRKERNSEC_CONFIG_AUTO
-+	bool "Automatic"
-+	help
-+	  If you choose this configuration method, you'll be able to answer a small
-+	  number of simple questions about how you plan to use this kernel.
-+	  The settings of grsecurity and PaX will be automatically configured for
-+	  the highest commonly-used settings within the provided constraints.
++$(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h
 +
-+	  If you require additional configuration, custom changes can still be made
-+	  from the "custom configuration" menu.
++quiet_cmd_create_randomize_layout_seed = GENSEED  $@
++      cmd_create_randomize_layout_seed = \
++	$(CONFIG_SHELL) $(srctree)/$(src)/gen-random-seed.sh $@ $(objtree)/include/generated/randomize_layout_hash.h
++$(objtree)/$(obj)/randomize_layout_seed.h: FORCE
++	$(call if_changed,create_randomize_layout_seed)
 +
-+config GRKERNSEC_CONFIG_CUSTOM
-+	bool "Custom"
-+	help
-+	  If you choose this configuration method, you'll be able to configure all
-+	  grsecurity and PaX settings manually.  Via this method, no options are
-+	  automatically enabled.
++targets += randomize_layout_seed.h randomize_layout_hash.h
+diff --git a/scripts/gcc-plugins/checker_plugin.c b/scripts/gcc-plugins/checker_plugin.c
+new file mode 100644
+index 0000000..efaf576
+--- /dev/null
++++ b/scripts/gcc-plugins/checker_plugin.c
+@@ -0,0 +1,496 @@
++/*
++ * Copyright 2011-2016 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 implement various sparse (source code checker) features
++ *
++ * TODO:
++ * - define separate __iomem, __percpu and __rcu address spaces (lots of code to patch)
++ *
++ * BUGS:
++ * - none known
++ */
 +
-+	  Take note that if menuconfig is exited with this configuration method
-+	  chosen, you will not be able to use the automatic configuration methods
-+	  without starting again with a kernel configuration with no grsecurity
-+	  or PaX options specified inside.
++#include "gcc-common.h"
 +
-+endchoice
++extern void c_register_addr_space (const char *str, addr_space_t as);
++extern enum machine_mode default_addr_space_pointer_mode (addr_space_t);
++extern enum machine_mode default_addr_space_address_mode (addr_space_t);
++extern bool default_addr_space_valid_pointer_mode(enum machine_mode mode, addr_space_t as);
++extern bool default_addr_space_legitimate_address_p(enum machine_mode mode, rtx mem, bool strict, addr_space_t as);
++extern rtx default_addr_space_legitimize_address(rtx x, rtx oldx, enum machine_mode mode, addr_space_t as);
 +
-+choice
-+	prompt "Usage Type"
-+	depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO)
-+	default GRKERNSEC_CONFIG_SERVER
-+	help
++int plugin_is_GPL_compatible;
 +
-+config GRKERNSEC_CONFIG_SERVER
-+	bool "Server"
-+	help
-+	  Choose this option if you plan to use this kernel on a server.
++static struct plugin_info checker_plugin_info = {
++	.version	= "201602181345",
++	.help		= "user\tturn on user/kernel address space checking\n"
++			  "context\tturn on locking context checking\n"
++};
 +
-+config GRKERNSEC_CONFIG_DESKTOP
-+	bool "Desktop"
-+	help
-+	  Choose this option if you plan to use this kernel on a desktop.
++#define ADDR_SPACE_KERNEL		0
++#define ADDR_SPACE_FORCE_KERNEL		1
++#define ADDR_SPACE_USER			2
++#define ADDR_SPACE_FORCE_USER		3
++#define ADDR_SPACE_IOMEM		0
++#define ADDR_SPACE_FORCE_IOMEM		0
++#define ADDR_SPACE_PERCPU		0
++#define ADDR_SPACE_FORCE_PERCPU		0
++#define ADDR_SPACE_RCU			0
++#define ADDR_SPACE_FORCE_RCU		0
 +
-+endchoice
++static enum machine_mode checker_addr_space_pointer_mode(addr_space_t addrspace)
++{
++	return default_addr_space_pointer_mode(ADDR_SPACE_GENERIC);
++}
 +
-+choice
-+	prompt "Virtualization Type"
-+	depends on (GRKERNSEC && X86 && GRKERNSEC_CONFIG_AUTO)
-+	default GRKERNSEC_CONFIG_VIRT_NONE
-+	help
++static enum machine_mode checker_addr_space_address_mode(addr_space_t addrspace)
++{
++	return default_addr_space_address_mode(ADDR_SPACE_GENERIC);
++}
 +
-+config GRKERNSEC_CONFIG_VIRT_NONE
-+	bool "None"
-+	help
-+	  Choose this option if this kernel will be run on bare metal.
++static bool checker_addr_space_valid_pointer_mode(enum machine_mode mode, addr_space_t as)
++{
++	return default_addr_space_valid_pointer_mode(mode, as);
++}
 +
-+config GRKERNSEC_CONFIG_VIRT_GUEST
-+	bool "Guest"
-+	help
-+	  Choose this option if this kernel will be run as a VM guest.
++static bool checker_addr_space_legitimate_address_p(enum machine_mode mode, rtx mem, bool strict, addr_space_t as)
++{
++	return default_addr_space_legitimate_address_p(mode, mem, strict, ADDR_SPACE_GENERIC);
++}
 +
-+config GRKERNSEC_CONFIG_VIRT_HOST
-+	bool "Host"
-+	help
-+	  Choose this option if this kernel will be run as a VM host.
++static rtx checker_addr_space_legitimize_address(rtx x, rtx oldx, enum machine_mode mode, addr_space_t as)
++{
++	return default_addr_space_legitimize_address(x, oldx, mode, as);
++}
 +
-+endchoice
++static bool checker_addr_space_subset_p(addr_space_t subset, addr_space_t superset)
++{
++	if (subset == ADDR_SPACE_FORCE_KERNEL && superset == ADDR_SPACE_KERNEL)
++		return true;
 +
-+choice
-+	prompt "Virtualization Hardware"
-+	depends on (GRKERNSEC && X86 && GRKERNSEC_CONFIG_AUTO && (GRKERNSEC_CONFIG_VIRT_GUEST || GRKERNSEC_CONFIG_VIRT_HOST))
-+	help
++	if (subset == ADDR_SPACE_FORCE_USER && superset == ADDR_SPACE_USER)
++		return true;
 +
-+config GRKERNSEC_CONFIG_VIRT_EPT
-+	bool "EPT/RVI Processor Support"
-+	depends on X86
-+	help
-+	  Choose this option if your CPU supports the EPT or RVI features of 2nd-gen
-+	  hardware virtualization.  This allows for additional kernel hardening protections
-+	  to operate without additional performance impact.
++	if (subset == ADDR_SPACE_FORCE_IOMEM && superset == ADDR_SPACE_IOMEM)
++		return true;
 +
-+	  To see if your Intel processor supports EPT, see:
-+	  http://ark.intel.com/Products/VirtualizationTechnology
-+	  (Most Core i3/5/7 support EPT)
++	if (subset == ADDR_SPACE_KERNEL && superset == ADDR_SPACE_FORCE_USER)
++		return true;
 +
-+	  To see if your AMD processor supports RVI, see:
-+	  http://support.amd.com/us/kbarticles/Pages/GPU120AMDRVICPUsHyperVWin8.aspx
++	if (subset == ADDR_SPACE_KERNEL && superset == ADDR_SPACE_FORCE_IOMEM)
++		return true;
 +
-+config GRKERNSEC_CONFIG_VIRT_SOFT
-+	bool "First-gen/No Hardware Virtualization"
-+	help
-+	  Choose this option if you use an Atom/Pentium/Core 2 processor that either doesn't
-+	  support hardware virtualization or doesn't support the EPT/RVI extensions.
++	if (subset == ADDR_SPACE_USER && superset == ADDR_SPACE_FORCE_KERNEL)
++		return true;
 +
-+endchoice
++	if (subset == ADDR_SPACE_IOMEM && superset == ADDR_SPACE_FORCE_KERNEL)
++		return true;
 +
-+choice
-+	prompt "Virtualization Software"
-+	depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO && (GRKERNSEC_CONFIG_VIRT_GUEST || GRKERNSEC_CONFIG_VIRT_HOST))
-+	help
++	return subset == superset;
++}
 +
-+config GRKERNSEC_CONFIG_VIRT_XEN
-+	bool "Xen"
-+	help
-+	  Choose this option if this kernel is running as a Xen guest or host.
++static rtx checker_addr_space_convert(rtx op, tree from_type, tree to_type)
++{
++//	addr_space_t from_as = TYPE_ADDR_SPACE(TREE_TYPE(from_type));
++//	addr_space_t to_as = TYPE_ADDR_SPACE(TREE_TYPE(to_type));
 +
-+config GRKERNSEC_CONFIG_VIRT_VMWARE
-+	bool "VMWare"
-+	help
-+	  Choose this option if this kernel is running as a VMWare guest or host.
++	return op;
++}
 +
-+config GRKERNSEC_CONFIG_VIRT_KVM
-+	bool "KVM"
-+	help
-+	  Choose this option if this kernel is running as a KVM guest or host.
++static void register_checker_address_spaces(void *event_data, void *data)
++{
++	c_register_addr_space("__kernel", ADDR_SPACE_KERNEL);
++	c_register_addr_space("__force_kernel", ADDR_SPACE_FORCE_KERNEL);
++	c_register_addr_space("__user", ADDR_SPACE_USER);
++	c_register_addr_space("__force_user", ADDR_SPACE_FORCE_USER);
++//	c_register_addr_space("__iomem", ADDR_SPACE_IOMEM);
++//	c_register_addr_space("__force_iomem", ADDR_SPACE_FORCE_IOMEM);
++//	c_register_addr_space("__percpu", ADDR_SPACE_PERCPU);
++//	c_register_addr_space("__force_percpu", ADDR_SPACE_FORCE_PERCPU);
++//	c_register_addr_space("__rcu", ADDR_SPACE_RCU);
++//	c_register_addr_space("__force_rcu", ADDR_SPACE_FORCE_RCU);
 +
-+config GRKERNSEC_CONFIG_VIRT_VIRTUALBOX
-+	bool "VirtualBox"
-+	help
-+	  Choose this option if this kernel is running as a VirtualBox guest or host.
++	targetm.addr_space.pointer_mode		= checker_addr_space_pointer_mode;
++	targetm.addr_space.address_mode		= checker_addr_space_address_mode;
++	targetm.addr_space.valid_pointer_mode	= checker_addr_space_valid_pointer_mode;
++	targetm.addr_space.legitimate_address_p	= checker_addr_space_legitimate_address_p;
++//	targetm.addr_space.legitimize_address	= checker_addr_space_legitimize_address;
++	targetm.addr_space.subset_p		= checker_addr_space_subset_p;
++	targetm.addr_space.convert		= checker_addr_space_convert;
++}
 +
-+config GRKERNSEC_CONFIG_VIRT_HYPERV
-+	bool "Hyper-V"
-+	help
-+	  Choose this option if this kernel is running as a Hyper-V guest.
++static bool split_context_attribute(tree args, tree *lock, tree *in, tree *out)
++{
++	*in = TREE_VALUE(args);
 +
-+endchoice
++	if (TREE_CODE(*in) != INTEGER_CST) {
++		*lock = *in;
++		args = TREE_CHAIN(args);
++		*in = TREE_VALUE(args);
++	} else
++		*lock = NULL_TREE;
 +
-+choice
-+	prompt "Required Priorities"
-+	depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO)
-+	default GRKERNSEC_CONFIG_PRIORITY_PERF
-+	help
++	args = TREE_CHAIN(args);
++	if (*lock && !args)
++		return false;
 +
-+config GRKERNSEC_CONFIG_PRIORITY_PERF
-+	bool "Performance"
-+	help
-+	  Choose this option if performance is of highest priority for this deployment
-+	  of grsecurity.  Features like UDEREF on a 64bit kernel, kernel stack clearing,
-+	  clearing of structures intended for userland, and freed memory sanitizing will
-+	  be disabled.
++	*out = TREE_VALUE(args);
++	return true;
++}
 +
-+config GRKERNSEC_CONFIG_PRIORITY_SECURITY
-+	bool "Security"
-+	help
-+	  Choose this option if security is of highest priority for this deployment of
-+	  grsecurity.  UDEREF, kernel stack clearing, clearing of structures intended
-+	  for userland, and freed memory sanitizing will be enabled for this kernel.
-+	  In a worst-case scenario, these features can introduce a 20% performance hit
-+	  (UDEREF on x64 contributing half of this hit).
++static tree handle_context_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
++{
++	*no_add_attrs = true;
++	tree lock, in, out;
 +
-+endchoice
++	if (TREE_CODE(*node) != FUNCTION_DECL) {
++		error("%qE attribute applies to functions only (%qD)", name, *node);
++		return NULL_TREE;
++	}
 +
-+menu "Default Special Groups"
-+depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO)
++	if (!split_context_attribute(args, &lock, &in, &out)) {
++		error("%qE attribute needs two integers after the lock expression", name);
++		return NULL_TREE;
++	}
 +
-+config GRKERNSEC_PROC_GID
-+	int "GID exempted from /proc restrictions"
-+	default 1001
-+	help
-+	  Setting this GID determines which group will be exempted from
-+	  grsecurity's /proc restrictions, allowing users of the specified
-+	  group  to view network statistics and the existence of other users'
-+	  processes on the system.  This GID may also be chosen at boot time
-+	  via "grsec_proc_gid=" on the kernel commandline.
++	if (TREE_CODE(in) != INTEGER_CST) {
++		error("the 'in' argument of the %qE attribute must be an integer (%qE)", name, in);
++		return NULL_TREE;
++	}
 +
-+config GRKERNSEC_TPE_UNTRUSTED_GID
-+        int "GID for TPE-untrusted users"
-+        depends on GRKERNSEC_CONFIG_SERVER && GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
-+        default 1005
-+        help
-+	  Setting this GID determines which group untrusted users should
-+	  be added to.  These users will be placed under grsecurity's Trusted Path
-+	  Execution mechanism, preventing them from executing their own binaries.
-+	  The users will only be able to execute binaries in directories owned and
-+	  writable only by the root user.  If the sysctl option is enabled, a sysctl
-+	  option with name "tpe_gid" is created.
++	if (TREE_CODE(out) != INTEGER_CST) {
++		error("the 'out' argument of the %qE attribute must be an integer (%qE)", name, out);
++		return NULL_TREE;
++	}
 +
-+config GRKERNSEC_TPE_TRUSTED_GID
-+        int "GID for TPE-trusted users"
-+        depends on GRKERNSEC_CONFIG_SERVER && GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
-+        default 1005
-+        help
-+          Setting this GID determines what group TPE restrictions will be
-+          *disabled* for.  If the sysctl option is enabled, a sysctl option
-+          with name "tpe_gid" is created.
++	*no_add_attrs = false;
++	return NULL_TREE;
++}
 +
-+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.
++static struct attribute_spec context_attr = {
++	.name			= "context",
++	.min_length		= 2,
++	.max_length		= 3,
++	.decl_required		= true,
++	.type_required		= false,
++	.function_type_required	= false,
++	.handler		= handle_context_attribute,
++#if BUILDING_GCC_VERSION >= 4007
++	.affects_type_identity	= true
++#endif
++};
 +
++static void register_attributes(void *event_data, void *data)
++{
++	register_attribute(&context_attr);
++}
 +
-+endmenu
++static const char context_function[] = "__context__";
++static GTY(()) tree context_function_decl;
 +
-+menu "Customize Configuration"
-+depends on GRKERNSEC
++static const char context_error[] = "__context_error__";
++static GTY(()) tree context_error_decl;
 +
-+menu "PaX"
++static void context_start_unit(void __unused *gcc_data, void __unused *user_data)
++{
++	tree fntype, attr;
 +
-+config PAX
-+	bool "Enable various PaX features"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on GRKERNSEC && (ALPHA || ARM || AVR32 || IA64 || MIPS || PARISC || PPC || SPARC || X86)
-+	help
-+	  This allows you to enable various PaX features.  PaX adds
-+	  intrusion prevention mechanisms to the kernel that reduce
-+	  the risks posed by exploitable memory corruption bugs.
++	// void __context__(void *, int);
++	fntype = build_function_type_list(void_type_node, ptr_type_node, integer_type_node, NULL_TREE);
++	context_function_decl = build_fn_decl(context_function, fntype);
 +
-+menu "PaX Control"
-+	depends on PAX
++	TREE_PUBLIC(context_function_decl) = 1;
++	TREE_USED(context_function_decl) = 1;
++	DECL_EXTERNAL(context_function_decl) = 1;
++	DECL_ARTIFICIAL(context_function_decl) = 1;
++	DECL_PRESERVE_P(context_function_decl) = 1;
++//	TREE_NOTHROW(context_function_decl) = 1;
++//	DECL_UNINLINABLE(context_function_decl) = 1;
++	DECL_ASSEMBLER_NAME(context_function_decl); // for LTO
++	lang_hooks.decls.pushdecl(context_function_decl);
 +
-+config PAX_SOFTMODE
-+	bool 'Support soft mode'
-+	help
-+	  Enabling this option will allow you to run PaX in soft mode, that
-+	  is, PaX features will not be enforced by default, only on executables
-+	  marked explicitly.  You must also enable PT_PAX_FLAGS or XATTR_PAX_FLAGS
-+	  support as they are the only way to mark executables for soft mode use.
++	// void __context_error__(const void *, int) __attribute__((error("context error")));
++	fntype = build_function_type_list(void_type_node, const_ptr_type_node, integer_type_node, NULL_TREE);
++	context_error_decl = build_fn_decl(context_error, fntype);
 +
-+	  Soft mode can be activated by using the "pax_softmode=1" kernel command
-+	  line option on boot.  Furthermore you can control various PaX features
-+	  at runtime via the entries in /proc/sys/kernel/pax.
++	TREE_PUBLIC(context_error_decl) = 1;
++	TREE_USED(context_error_decl) = 1;
++	DECL_EXTERNAL(context_error_decl) = 1;
++	DECL_ARTIFICIAL(context_error_decl) = 1;
++	DECL_PRESERVE_P(context_error_decl) = 1;
++//	TREE_NOTHROW(context_error_decl) = 1;
++//	DECL_UNINLINABLE(context_error_decl) = 1;
++	TREE_THIS_VOLATILE(context_error_decl) = 1;
++	DECL_ASSEMBLER_NAME(context_error_decl);
 +
-+config PAX_EI_PAX
-+	bool 'Use legacy ELF header marking'
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	help
-+	  Enabling this option will allow you to control PaX features on
-+	  a per executable basis via the 'chpax' utility available at
-+	  http://pax.grsecurity.net/.  The control flags will be read from
-+	  an otherwise reserved part of the ELF header.  This marking has
-+	  numerous drawbacks (no support for soft-mode, toolchain does not
-+	  know about the non-standard use of the ELF header) therefore it
-+	  has been deprecated in favour of PT_PAX_FLAGS and XATTR_PAX_FLAGS
-+	  support.
++	attr = tree_cons(NULL, build_string(14, "context error"), NULL);
++	attr = tree_cons(get_identifier("error"), attr, NULL);
++	decl_attributes(&context_error_decl, attr, 0);
++}
 +
-+	  Note that if you enable PT_PAX_FLAGS or XATTR_PAX_FLAGS marking
-+	  support as well, they will override the legacy EI_PAX marks.
++static bool context_gate(void)
++{
++	tree context_attr;
 +
-+	  If you enable none of the marking options then all applications
-+	  will run with PaX enabled on them by default.
++return true;
 +
-+config PAX_PT_PAX_FLAGS
-+	bool 'Use ELF program header marking'
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	help
-+	  Enabling this option will allow you to control PaX features on
-+	  a per executable basis via the 'paxctl' utility available at
-+	  http://pax.grsecurity.net/.  The control flags will be read from
-+	  a PaX specific ELF program header (PT_PAX_FLAGS).  This marking
-+	  has the benefits of supporting both soft mode and being fully
-+	  integrated into the toolchain (the binutils patch is available
-+	  from http://pax.grsecurity.net).
-+
-+	  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.
++	context_attr = lookup_attribute("context", DECL_ATTRIBUTES(current_function_decl));
++	return context_attr != NULL_TREE;
++}
 +
-+	  If you enable none of the marking options then all applications
-+	  will run with PaX enabled on them by default.
++static basic_block verify_context_before(gimple_stmt_iterator *gsi, tree context, tree inout, tree error)
++{
++	gimple stmt;
++	basic_block cond_bb, join_bb, true_bb;
++	edge e;
++	location_t loc;
++	const char *file;
++	int line;
++	size_t len;
++	tree filename;
 +
-+config PAX_XATTR_PAX_FLAGS
-+	bool 'Use filesystem extended attributes marking'
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	select CIFS_XATTR if CIFS
-+	select EXT2_FS_XATTR if EXT2_FS
-+	select EXT3_FS_XATTR if EXT3_FS
-+	select F2FS_FS_XATTR if F2FS_FS
-+	select JFFS2_FS_XATTR if JFFS2_FS
-+	select REISERFS_FS_XATTR if REISERFS_FS
-+	select SQUASHFS_XATTR if SQUASHFS
-+	select TMPFS_XATTR if TMPFS
-+	help
-+	  Enabling this option will allow you to control PaX features on
-+	  a per executable basis via the 'setfattr' utility.  The control
-+	  flags will be read from the user.pax.flags extended attribute of
-+	  the file.  This marking has the benefit of supporting binary-only
-+	  applications that self-check themselves (e.g., skype) and would
-+	  not tolerate chpax/paxctl changes.  The main drawback is that
-+	  extended attributes are not supported by some filesystems (e.g.,
-+	  isofs, udf, vfat) so copying files through such filesystems will
-+	  lose the extended attributes and these PaX markings.
++	stmt = gsi_stmt(*gsi);
++	if (gimple_has_location(stmt)) {
++		loc = gimple_location(stmt);
++		file = gimple_filename(stmt);
++		line = gimple_lineno(stmt);
++	} else {
++		loc = DECL_SOURCE_LOCATION(current_function_decl);
++		file = DECL_SOURCE_FILE(current_function_decl);
++		line = DECL_SOURCE_LINE(current_function_decl);
++	}
++	gcc_assert(file);
 +
-+	  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 (context != count) __context_error__(__FILE__, __LINE__);
++	stmt = gimple_build_cond(NE_EXPR, context, inout, NULL_TREE, NULL_TREE);
++	gimple_set_location(stmt, loc);
++	gsi_insert_before(gsi, stmt, GSI_NEW_STMT);
 +
-+	  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.
++	cond_bb = gsi_bb(*gsi);
++	gcc_assert(!gsi_end_p(*gsi));
++	gcc_assert(stmt == gsi_stmt(*gsi));
 +
-+	  If you enable none of the marking options then all applications
-+	  will run with PaX enabled on them by default.
++	e = split_block(cond_bb, gsi_stmt(*gsi));
++	cond_bb = e->src;
++	join_bb = e->dest;
++	e->flags = EDGE_FALSE_VALUE;
++	e->probability = REG_BR_PROB_BASE;
 +
-+choice
-+	prompt 'MAC system integration'
-+	default PAX_HAVE_ACL_FLAGS
-+	help
-+	  Mandatory Access Control systems have the option of controlling
-+	  PaX flags on a per executable basis, choose the method supported
-+	  by your particular system.
++	true_bb = create_empty_bb(EXIT_BLOCK_PTR_FOR_FN(cfun)->prev_bb);
++	make_edge(cond_bb, true_bb, EDGE_TRUE_VALUE);
++	make_edge(true_bb, join_bb, EDGE_FALLTHRU);
 +
-+	  - "none": if your MAC system does not interact with PaX,
-+	  - "direct": if your MAC system defines pax_set_initial_flags() itself,
-+	  - "hook": if your MAC system uses the pax_set_initial_flags_func callback.
++	set_immediate_dominator(CDI_DOMINATORS, true_bb, cond_bb);
++	set_immediate_dominator(CDI_DOMINATORS, join_bb, cond_bb);
 +
-+	  NOTE: this option is for developers/integrators only.
++	gcc_assert(cond_bb->loop_father == join_bb->loop_father);
++	add_bb_to_loop(true_bb, cond_bb->loop_father);
 +
-+	config PAX_NO_ACL_FLAGS
-+		bool 'none'
++	// insert call to builtin_trap or __context_error__
++	*gsi = gsi_start_bb(true_bb);
 +
-+	config PAX_HAVE_ACL_FLAGS
-+		bool 'direct'
++//	stmt = gimple_build_call(builtin_decl_implicit(BUILT_IN_TRAP), 0);
++	len = strlen(file) + 1;
++	filename = build_string(len, file);
++	TREE_TYPE(filename) = build_array_type(unsigned_char_type_node, build_index_type(size_int(len)));
++	filename = build1(ADDR_EXPR, const_ptr_type_node, filename);
++	stmt = gimple_build_call(error, 2, filename, build_int_cst(NULL_TREE, line));
++	gimple_set_location(stmt, loc);
++	gsi_insert_after(gsi, stmt, GSI_CONTINUE_LINKING);
 +
-+	config PAX_HOOK_ACL_FLAGS
-+		bool 'hook'
-+endchoice
++	*gsi = gsi_start_nondebug_bb(join_bb);
++	return join_bb;
++}
 +
-+endmenu
++static void update_context(gimple_stmt_iterator *gsi, tree context, int diff)
++{
++	gimple assign;
++	tree op;
 +
-+menu "Non-executable pages"
-+	depends on PAX
++	op = fold_build2_loc(UNKNOWN_LOCATION, PLUS_EXPR, integer_type_node, context, build_int_cst(integer_type_node, diff));
++	assign = gimple_build_assign(context, op);
++	gsi_insert_after(gsi, assign, GSI_NEW_STMT);
++	update_stmt(assign);
++}
 +
-+config PAX_NOEXEC
-+	bool "Enforce non-executable pages"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on ALPHA || (ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || IA64 || MIPS || PARISC || PPC || S390 || SPARC || X86
-+	help
-+	  By design some architectures do not allow for protecting memory
-+	  pages against execution or even if they do, Linux does not make
-+	  use of this feature.  In practice this means that if a page is
-+	  readable (such as the stack or heap) it is also executable.
++static basic_block track_context(basic_block bb, tree context)
++{
++	gimple_stmt_iterator gsi;
++	gimple assign;
 +
-+	  There is a well known exploit technique that makes use of this
-+	  fact and a common programming mistake where an attacker can
-+	  introduce code of his choice somewhere in the attacked program's
-+	  memory (typically the stack or the heap) and then execute it.
++	// adjust context according to the context information on any call stmt
++	for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
++		gimple stmt = gsi_stmt(gsi);
++		tree fndecl, context_attr;
++		tree lock, in, out;
++		int incount, outcount;
 +
-+	  If the attacked program was running with different (typically
-+	  higher) privileges than that of the attacker, then he can elevate
-+	  his own privilege level (e.g. get a root shell, write to files for
-+	  which he does not have write access to, etc).
++		if (!is_gimple_call(stmt))
++			continue;
 +
-+	  Enabling this option will let you choose from various features
-+	  that prevent the injection and execution of 'foreign' code in
-+	  a program.
++		fndecl = gimple_call_fndecl(stmt);
++		if (!fndecl)
++			continue;
 +
-+	  This will also break programs that rely on the old behaviour and
-+	  expect that dynamically allocated memory via the malloc() family
-+	  of functions is executable (which it is not).  Notable examples
-+	  are the XFree86 4.x server, the java runtime and wine.
++		if (fndecl == context_function_decl) {
++			unsigned int num_ops = gimple_num_ops(stmt);
++			int diff = tree_to_shwi(gimple_op(stmt, num_ops - 1));
 +
-+config PAX_PAGEEXEC
-+	bool "Paging based non-executable pages"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MATOM || MPENTIUM4 || MPSC || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2 || MVIAC7)
-+	select ARCH_TRACK_EXEC_LIMIT if X86_32
-+	help
-+	  This implementation is based on the paging feature of the CPU.
-+	  On i386 without hardware non-executable bit support there is a
-+	  variable but usually low performance impact, however on Intel's
-+	  P4 core based CPUs it is very high so you should not enable this
-+	  for kernels meant to be used on such CPUs.
++			gcc_assert(diff);
++			update_context(&gsi, context, diff);
++			continue;
++		}
 +
-+	  On alpha, avr32, ia64, parisc, sparc, sparc64, x86_64 and i386
-+	  with hardware non-executable bit support there is no performance
-+	  impact, on ppc the impact is negligible.
++		context_attr = lookup_attribute("context", DECL_ATTRIBUTES(fndecl));
++		if (!context_attr)
++			continue;
 +
-+	  Note that several architectures require various emulations due to
-+	  badly designed userland ABIs, this will cause a performance impact
-+	  but will disappear as soon as userland is fixed. For example, ppc
-+	  userland MUST have been built with secure-plt by a recent toolchain.
++		gcc_assert(split_context_attribute(TREE_VALUE(context_attr), &lock, &in, &out));
++		incount = tree_to_shwi(in);
++		outcount = tree_to_shwi(out);
++		bb = verify_context_before(&gsi, context, in, context_error_decl);
++		update_context(&gsi, context, outcount - incount);
++	}
 +
-+config PAX_SEGMEXEC
-+	bool "Segmentation based non-executable pages"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on PAX_NOEXEC && X86_32
-+	help
-+	  This implementation is based on the segmentation feature of the
-+	  CPU and has a very small performance impact, however applications
-+	  will be limited to a 1.5 GB address space instead of the normal
-+	  3 GB.
++	return bb;
++}
 +
-+config PAX_EMUTRAMP
-+	bool "Emulate trampolines"
-+	default y if PARISC || GRKERNSEC_CONFIG_AUTO
-+	depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || X86)
-+	help
-+	  There are some programs and libraries that for one reason or
-+	  another attempt to execute special small code snippets from
-+	  non-executable memory pages.  Most notable examples are the
-+	  signal handler return code generated by the kernel itself and
-+	  the GCC trampolines.
++static bool bb_any_loop(basic_block bb)
++{
++	return bb_loop_depth(bb) || (bb->flags & BB_IRREDUCIBLE_LOOP);
++}
 +
-+	  If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
-+	  such programs will no longer work under your kernel.
++static unsigned int context_execute(void)
++{
++	basic_block bb;
++	gimple assign;
++	gimple_stmt_iterator gsi;
++	tree context_attr, context;
++	tree lock, in, out;
 +
-+	  As a remedy you can say Y here and use the 'chpax' or 'paxctl'
-+	  utilities to enable trampoline emulation for the affected programs
-+	  yet still have the protection provided by the non-executable pages.
++	loop_optimizer_init(LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
++	gcc_assert(current_loops);
 +
-+	  On parisc you MUST enable this option and EMUSIGRT as well, otherwise
-+	  your system will not even boot.
++	calculate_dominance_info(CDI_DOMINATORS);
++	calculate_dominance_info(CDI_POST_DOMINATORS);
 +
-+	  Alternatively you can say N here and use the 'chpax' or 'paxctl'
-+	  utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
-+	  for the affected files.
++	context_attr = lookup_attribute("context", DECL_ATTRIBUTES(current_function_decl));
++	if (context_attr) {
++		gcc_assert(split_context_attribute(TREE_VALUE(context_attr), &lock, &in, &out));
++	} else {
++		in = out = integer_zero_node;
++	}
 +
-+	  NOTE: enabling this feature *may* open up a loophole in the
-+	  protection provided by non-executable pages that an attacker
-+	  could abuse.  Therefore the best solution is to not have any
-+	  files on your system that would require this option.  This can
-+	  be achieved by not using libc5 (which relies on the kernel
-+	  signal handler return code) and not using or rewriting programs
-+	  that make use of the nested function implementation of GCC.
-+	  Skilled users can just fix GCC itself so that it implements
-+	  nested function calls in a way that does not interfere with PaX.
++	// 1. create local context variable
++	context = create_tmp_var(integer_type_node, "context");
++	add_referenced_var(context);
++	mark_sym_for_renaming(context);
 +
-+config PAX_EMUSIGRT
-+	bool "Automatically emulate sigreturn trampolines"
-+	depends on PAX_EMUTRAMP && PARISC
-+	default y
-+	help
-+	  Enabling this option will have the kernel automatically detect
-+	  and emulate signal return trampolines executing on the stack
-+	  that would otherwise lead to task termination.
++	// 2. initialize local context variable
++	gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++	bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
++	if (!single_pred_p(bb)) {
++		gcc_assert(bb_any_loop(bb));
++		split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++		bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
++	}
++	gsi = gsi_start_bb(bb);
++	assign = gimple_build_assign(context, in);
++	gsi_insert_before(&gsi, assign, GSI_NEW_STMT);
++	update_stmt(assign);
 +
-+	  This solution is intended as a temporary one for users with
-+	  legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
-+	  Modula-3 runtime, etc) or executables linked to such, basically
-+	  everything that does not specify its own SA_RESTORER function in
-+	  normal executable memory like glibc 2.1+ does.
++	// 3. instrument each BB to track the local context variable
++	FOR_EACH_BB_FN(bb, cfun) {
++		bb = track_context(bb, context);
++	}
 +
-+	  On parisc you MUST enable this option, otherwise your system will
-+	  not even boot.
++	// 4. verify the local context variable against the expected state
++	if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds)) {
++		gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun)));
++		gsi = gsi_last_nondebug_bb(single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun)));
++		verify_context_before(&gsi, context, out, context_error_decl);
++	}
 +
-+	  NOTE: this feature cannot be disabled on a per executable basis
-+	  and since it *does* open up a loophole in the protection provided
-+	  by non-executable pages, the best solution is to not have any
-+	  files on your system that would require this option.
++	free_dominance_info(CDI_DOMINATORS);
++	free_dominance_info(CDI_POST_DOMINATORS);
++	loop_optimizer_finalize();
++	return 0;
++}
 +
-+config PAX_MPROTECT
-+	bool "Restrict mprotect()"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on (PAX_PAGEEXEC || PAX_SEGMEXEC)
-+	help
-+	  Enabling this option will prevent programs from
-+	   - changing the executable status of memory pages that were
-+	     not originally created as executable,
-+	   - making read-only executable pages writable again,
-+	   - creating executable pages from anonymous memory,
-+	   - making read-only-after-relocations (RELRO) data pages writable again.
++#define PASS_NAME context
++#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
++//#define TODO_FLAGS_START TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts
++#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_verify_flow | TODO_update_ssa
++#include "gcc-generate-gimple-pass.h"
 +
-+	  You should say Y here to complete the protection provided by
-+	  the enforcement of non-executable pages.
++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
++{
++	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	int i;
++	bool enable_user, enable_context;
++	struct register_pass_info context_pass_info;
 +
-+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control
-+	  this feature on a per file basis.
++	static const struct ggc_root_tab gt_ggc_r_gt_checker[] = {
++		{
++			.base = &context_function_decl,
++			.nelt = 1,
++			.stride = sizeof(context_function_decl),
++			.cb = &gt_ggc_mx_tree_node,
++			.pchw = &gt_pch_nx_tree_node
++		},
++		{
++			.base = &context_error_decl,
++			.nelt = 1,
++			.stride = sizeof(context_error_decl),
++			.cb = &gt_ggc_mx_tree_node,
++			.pchw = &gt_pch_nx_tree_node
++		},
++		LAST_GGC_ROOT_TAB
++	};
 +
-+config PAX_MPROTECT_COMPAT
-+	bool "Use legacy/compat protection demoting (read help)"
-+	depends on PAX_MPROTECT
-+	default n
-+	help
-+	  The current implementation of PAX_MPROTECT denies RWX allocations/mprotects
-+	  by sending the proper error code to the application.  For some older
-+	  userland, this can cause problems with applications that assume such
-+	  allocations will not be prevented by PaX or SELinux and other access
-+	  control systems and have no fallback mechanisms.  For modern distros,
-+	  this option should generally be set to 'N'.
-+	  
-+config PAX_ELFRELOCS
-+	bool "Allow ELF text relocations (read help)"
-+	depends on PAX_MPROTECT
-+	default n
-+	help
-+	  Non-executable pages and mprotect() restrictions are effective
-+	  in preventing the introduction of new executable code into an
-+	  attacked task's address space.  There remain only two venues
-+	  for this kind of attack: if the attacker can execute already
-+	  existing code in the attacked task then he can either have it
-+	  create and mmap() a file containing his code or have it mmap()
-+	  an already existing ELF library that does not have position
-+	  independent code in it and use mprotect() on it to make it
-+	  writable and copy his code there.  While protecting against
-+	  the former approach is beyond PaX, the latter can be prevented
-+	  by having only PIC ELF libraries on one's system (which do not
-+	  need to relocate their code).  If you are sure this is your case,
-+	  as is the case with all modern Linux distributions, then leave
-+	  this option disabled.  You should say 'n' here.
++	context_pass_info.pass				= make_context_pass();
++//	context_pass_info.reference_pass_name		= "ssa";
++	context_pass_info.reference_pass_name		= "phiprop";
++	context_pass_info.ref_pass_instance_number	= 1;
++	context_pass_info.pos_op 			= PASS_POS_INSERT_AFTER;
 +
-+config PAX_ETEXECRELOCS
-+	bool "Allow ELF ET_EXEC text relocations"
-+	depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
-+	select PAX_ELFRELOCS
-+	default y
-+	help
-+	  On some architectures there are incorrectly created applications
-+	  that require text relocations and would not work without enabling
-+	  this option.  If you are an alpha, ia64 or parisc user, you should
-+	  enable this option and disable it once you have made sure that
-+	  none of your applications need it.
++	if (!plugin_default_version_check(version, &gcc_version)) {
++		error(G_("incompatible gcc/plugin versions"));
++		return 1;
++	}
 +
-+config PAX_EMUPLT
-+	bool "Automatically emulate ELF PLT"
-+	depends on PAX_MPROTECT && (ALPHA || PARISC || SPARC)
-+	default y
-+	help
-+	  Enabling this option will have the kernel automatically detect
-+	  and emulate the Procedure Linkage Table entries in ELF files.
-+	  On some architectures such entries are in writable memory, and
-+	  become non-executable leading to task termination.  Therefore
-+	  it is mandatory that you enable this option on alpha, parisc,
-+	  sparc and sparc64, otherwise your system would not even boot.
++	register_callback(plugin_name, PLUGIN_INFO, NULL, &checker_plugin_info);
 +
-+	  NOTE: this feature *does* open up a loophole in the protection
-+	  provided by the non-executable pages, therefore the proper
-+	  solution is to modify the toolchain to produce a PLT that does
-+	  not need to be writable.
++	enable_user = false;
++	enable_context = false;
++	for (i = 0; i < argc; ++i) {
++		if (!strcmp(argv[i].key, "user")) {
++			enable_user = true;
++			continue;
++		}
++		if (!strcmp(argv[i].key, "context")) {
++			enable_context = true;
++			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
 +
-+config PAX_DLRESOLVE
-+	bool 'Emulate old glibc resolver stub'
-+	depends on PAX_EMUPLT && SPARC
-+	default n
-+	help
-+	  This option is needed if userland has an old glibc (before 2.4)
-+	  that puts a 'save' instruction into the runtime generated resolver
-+	  stub that needs special emulation.
++	if (enable_user)
++		register_callback(plugin_name, PLUGIN_PRAGMAS, register_checker_address_spaces, NULL);
++	if (enable_context) {
++		register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
++		register_callback(plugin_name, PLUGIN_START_UNIT, context_start_unit, NULL);
++		register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_checker);
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &context_pass_info);
++	}
 +
-+config PAX_KERNEXEC
-+	bool "Enforce non-executable kernel pages"
-+	default y if GRKERNSEC_CONFIG_AUTO && (!X86 || GRKERNSEC_CONFIG_VIRT_NONE || (GRKERNSEC_CONFIG_VIRT_EPT && GRKERNSEC_CONFIG_VIRT_GUEST) || (GRKERNSEC_CONFIG_VIRT_EPT && GRKERNSEC_CONFIG_VIRT_KVM))
-+	depends on (X86 || (ARM && (CPU_V6 || CPU_V6K || CPU_V7) && !(ARM_LPAE && MODULES))) && !XEN
-+	select PAX_PER_CPU_PGD if X86_64 || (X86_32 && X86_PAE)
-+	select PAX_KERNEXEC_PLUGIN if X86_64
-+	select ARM_KERNMEM_PERMS if ARM
-+	help
-+	  This is the kernel land equivalent of PAGEEXEC and MPROTECT,
-+	  that is, enabling this option will make it harder to inject
-+	  and execute 'foreign' code in kernel memory itself.
++	return 0;
++}
+diff --git a/scripts/gcc-plugins/colorize_plugin.c b/scripts/gcc-plugins/colorize_plugin.c
+new file mode 100644
+index 0000000..ffe60f6
+--- /dev/null
++++ b/scripts/gcc-plugins/colorize_plugin.c
+@@ -0,0 +1,162 @@
++/*
++ * Copyright 2012-2016 by 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 colorize diagnostic output
++ *
++ */
 +
-+	  Note that on amd64, CONFIG_EFI enabled with "efi=old_map" on
-+	  the kernel command-line will result in an RWX physical map.
++#include "gcc-common.h"
 +
-+	  Likewise, the EFI runtime services are necessarily mapped as
-+	  RWX.  If CONFIG_EFI is enabled on an EFI-capable system, it
-+	  is recommended that you boot with "noefi" on the kernel
-+	  command-line if possible to eliminate the mapping.
++int plugin_is_GPL_compatible;
 +
-+choice
-+	prompt "Return Address Instrumentation Method"
-+	default PAX_KERNEXEC_PLUGIN_METHOD_BTS
-+	depends on PAX_KERNEXEC_PLUGIN
-+	help
-+	  Select the method used to instrument function pointer dereferences.
-+	  Note that binary modules cannot be instrumented by this approach.
++static struct plugin_info colorize_plugin_info = {
++	.version	= "201602181345",
++	.help		= "color=[never|always|auto]\tdetermine when to colorize\n",
++};
 +
-+	  Note that the implementation requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.
++#define GREEN		"\033[32m\033[K"
++#define LIGHTGREEN	"\033[1;32m\033[K"
++#define YELLOW		"\033[33m\033[K"
++#define LIGHTYELLOW	"\033[1;33m\033[K"
++#define RED		"\033[31m\033[K"
++#define LIGHTRED	"\033[1;31m\033[K"
++#define BLUE		"\033[34m\033[K"
++#define LIGHTBLUE	"\033[1;34m\033[K"
++#define BRIGHT		"\033[1;m\033[K"
++#define NORMAL		"\033[m\033[K"
 +
-+	config PAX_KERNEXEC_PLUGIN_METHOD_BTS
-+		bool "bts"
-+		help
-+		  This method is compatible with binary only modules but has
-+		  a higher runtime overhead.
++static diagnostic_starter_fn old_starter;
++static diagnostic_finalizer_fn old_finalizer;
 +
-+	config PAX_KERNEXEC_PLUGIN_METHOD_OR
-+		bool "or"
-+		depends on !PARAVIRT
-+		help
-+		  This method is incompatible with binary only modules but has
-+		  a lower runtime overhead.
-+endchoice
++static void start_colorize(diagnostic_context *context, diagnostic_info *diagnostic)
++{
++	const char *color;
++	char *newprefix;
 +
-+config PAX_KERNEXEC_PLUGIN_METHOD
-+	string
-+	default "bts" if PAX_KERNEXEC_PLUGIN_METHOD_BTS
-+	default "or" if PAX_KERNEXEC_PLUGIN_METHOD_OR
-+	default ""
++	switch (diagnostic->kind) {
++	case DK_NOTE:
++		color = LIGHTBLUE;
++		break;
 +
-+config PAX_KERNEXEC_MODULE_TEXT
-+	int "Minimum amount of memory reserved for module code"
-+	default "8" if (!GRKERNSEC_CONFIG_AUTO || GRKERNSEC_CONFIG_SERVER)
-+	default "12" if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_DESKTOP)
-+	depends on PAX_KERNEXEC && X86_32
-+	help
-+	  Due to implementation details the kernel must reserve a fixed
-+	  amount of memory for runtime allocated code (such as modules)
-+	  at compile time that cannot be changed at runtime.  Here you
-+	  can specify the minimum amount in MB that will be reserved.
-+	  Due to the same implementation details this size will always
-+	  be rounded up to the next 2/4 MB boundary (depends on PAE) so
-+	  the actually available memory for runtime allocated code will
-+	  usually be more than this minimum.
++	case DK_PEDWARN:
++	case DK_WARNING:
++		color = LIGHTYELLOW;
++		break;
 +
-+	  The default 4 MB should be enough for most users but if you have
-+	  an excessive number of modules (e.g., most distribution configs
-+	  compile many drivers as modules) or use huge modules such as
-+	  nvidia's kernel driver, you will need to adjust this amount.
-+	  A good rule of thumb is to look at your currently loaded kernel
-+	  modules and add up their sizes.
++	case DK_ERROR:
++	case DK_FATAL:
++	case DK_ICE:
++	case DK_PERMERROR:
++	case DK_SORRY:
++		color = LIGHTRED;
++		break;
 +
-+endmenu
++	default:
++		color = NORMAL;
++	}
 +
-+menu "Address Space Layout Randomization"
-+	depends on PAX
++	old_starter(context, diagnostic);
++	if (-1 == asprintf(&newprefix, "%s%s" NORMAL, color, context->printer->prefix))
++		return;
++	pp_destroy_prefix(context->printer);
++	pp_set_prefix(context->printer, newprefix);
++}
 +
-+config PAX_ASLR
-+	bool "Address Space Layout Randomization"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	help
-+	  Many if not most exploit techniques rely on the knowledge of
-+	  certain addresses in the attacked program.  The following options
-+	  will allow the kernel to apply a certain amount of randomization
-+	  to specific parts of the program thereby forcing an attacker to
-+	  guess them in most cases.  Any failed guess will most likely crash
-+	  the attacked program which allows the kernel to detect such attempts
-+	  and react on them.  PaX itself provides no reaction mechanisms,
-+	  instead it is strongly encouraged that you make use of grsecurity's
-+	  (http://www.grsecurity.net/) built-in crash detection features or
-+	  develop one yourself.
++static void finalize_colorize(diagnostic_context *context, diagnostic_info *diagnostic)
++{
++	old_finalizer(context, diagnostic);
++}
 +
-+	  By saying Y here you can choose to randomize the following areas:
-+	   - top of the task's kernel stack
-+	   - top of the task's userland stack
-+	   - base address for mmap() requests that do not specify one
-+	     (this includes all libraries)
-+	   - base address of the main executable
++static void colorize_arm(void)
++{
++	old_starter = diagnostic_starter(global_dc);
++	old_finalizer = diagnostic_finalizer(global_dc);
 +
-+	  It is strongly recommended to say Y here as address space layout
-+	  randomization has negligible impact on performance yet it provides
-+	  a very effective protection.
++	diagnostic_starter(global_dc) = start_colorize;
++	diagnostic_finalizer(global_dc) = finalize_colorize;
++}
 +
-+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control
-+	  this feature on a per file basis.
++static unsigned int colorize_rearm_execute(void)
++{
++	if (diagnostic_starter(global_dc) == start_colorize)
++		return 0;
 +
-+config PAX_RANDKSTACK
-+	bool "Randomize kernel stack base"
-+	default y if GRKERNSEC_CONFIG_AUTO && !(GRKERNSEC_CONFIG_VIRT_HOST && GRKERNSEC_CONFIG_VIRT_VIRTUALBOX)
-+	depends on X86_TSC && X86
-+	help
-+	  By saying Y here the kernel will randomize every task's kernel
-+	  stack on every system call.  This will not only force an attacker
-+	  to guess it but also prevent him from making use of possible
-+	  leaked information about it.
++	colorize_arm();
++	return 0;
++}
 +
-+	  Since the kernel stack is a rather scarce resource, randomization
-+	  may cause unexpected stack overflows, therefore you should very
-+	  carefully test your system.  Note that once enabled in the kernel
-+	  configuration, this feature cannot be disabled on a per file basis.
++#define PASS_NAME colorize_rearm
++#define NO_GATE
++#include "gcc-generate-simple_ipa-pass.h"
 +
-+config PAX_RANDUSTACK
-+	bool
++static void colorize_start_unit(void *gcc_data, void *user_data)
++{
++	colorize_arm();
++}
 +
-+config PAX_RANDMMAP
-+	bool "Randomize user stack and mmap() bases"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on PAX_ASLR
-+	select PAX_RANDUSTACK
-+	help
-+	  By saying Y here the kernel will randomize every task's userland
-+	  stack and use a randomized base address for mmap() requests that
-+	  do not specify one themselves.
++static bool should_colorize(void)
++{
++#if BUILDING_GCC_VERSION >= 4009
++	return false;
++#else
++	char const *t = getenv("TERM");
 +
-+	  The stack randomization is done in two steps where the second
-+	  one may apply a big amount of shift to the top of the stack and
-+	  cause problems for programs that want to use lots of memory (more
-+	  than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
++	return t && strcmp(t, "dumb") && isatty(STDERR_FILENO);
++#endif
++}
 +
-+	  As a result of mmap randomization all dynamically loaded libraries
-+	  will appear at random addresses and therefore be harder to exploit
-+	  by a technique where an attacker attempts to execute library code
-+	  for his purposes (e.g. spawn a shell from an exploited program that
-+	  is running at an elevated privilege level).
++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
++{
++	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	int i;
++	struct register_pass_info colorize_rearm_pass_info;
++	bool colorize;
 +
-+	  Furthermore, if a program is relinked as a dynamic ELF file, its
-+	  base address will be randomized as well, completing the full
-+	  randomization of the address space layout.  Attacking such programs
-+	  becomes a guess game.  You can find an example of doing this at
-+	  http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
-+	  http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
++	colorize_rearm_pass_info.pass				= make_colorize_rearm_pass();
++	colorize_rearm_pass_info.reference_pass_name		= "*free_lang_data";
++	colorize_rearm_pass_info.ref_pass_instance_number	= 1;
++	colorize_rearm_pass_info.pos_op 			= PASS_POS_INSERT_AFTER;
 +
-+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
-+	  feature on a per file basis.
++	if (!plugin_default_version_check(version, &gcc_version)) {
++		error(G_("incompatible gcc/plugin versions"));
++		return 1;
++	}
 +
-+endmenu
++	register_callback(plugin_name, PLUGIN_INFO, NULL, &colorize_plugin_info);
 +
-+menu "Miscellaneous hardening features"
++	colorize = getenv("GCC_COLORS") ? should_colorize() : false;
 +
-+config PAX_MEMORY_SANITIZE
-+	bool "Sanitize all freed memory"
-+	default y if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_PRIORITY_SECURITY)
-+	help
-+	  By saying Y here the kernel will erase memory pages and slab objects
-+	  as soon as they are freed.  This in turn reduces the lifetime of data
-+	  stored in them, making it less likely that sensitive information such
-+	  as passwords, cryptographic secrets, etc stay in memory for too long.
++	for (i = 0; i < argc; ++i) {
++		if (!strcmp(argv[i].key, "color")) {
++			if (!argv[i].value) {
++				error(G_("no value supplied for option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++				continue;
++			}
++			if (!strcmp(argv[i].value, "always"))
++				colorize = true;
++			else if (!strcmp(argv[i].value, "never"))
++				colorize = false;
++			else if (!strcmp(argv[i].value, "auto"))
++				colorize = should_colorize();
++			else
++				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"), plugin_name, argv[i].key, argv[i].value);
++			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
 +
-+	  This is especially useful for programs whose runtime is short, long
-+	  lived processes and the kernel itself benefit from this as long as
-+	  they ensure timely freeing of memory that may hold sensitive
-+	  information.
++	if (colorize) {
++		// TODO: parse GCC_COLORS as used by gcc 4.9+
++		register_callback(plugin_name, PLUGIN_START_UNIT, &colorize_start_unit, NULL);
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &colorize_rearm_pass_info);
++	}
++	return 0;
++}
+diff --git a/scripts/gcc-plugins/constify_plugin.c b/scripts/gcc-plugins/constify_plugin.c
+new file mode 100644
+index 0000000..7142f36
+--- /dev/null
++++ b/scripts/gcc-plugins/constify_plugin.c
+@@ -0,0 +1,521 @@
++/*
++ * Copyright 2011 by Emese Revfy <re.emese@gmail.com>
++ * Copyright 2011-2016 by PaX Team <pageexec@freemail.hu>
++ * Licensed under the GPL v2, or (at your option) v3
++ *
++ * This gcc plugin constifies all structures which contain only function pointers or are explicitly marked for constification.
++ *
++ * Homepage:
++ * http://www.grsecurity.net/~ephox/const_plugin/
++ *
++ * Usage:
++ * $ gcc -I`gcc -print-file-name=plugin`/include -fPIC -shared -O2 -o constify_plugin.so constify_plugin.c
++ * $ gcc -fplugin=constify_plugin.so test.c -O2
++ */
 +
-+	  A nice side effect of the sanitization of slab objects is the
-+	  reduction of possible info leaks caused by padding bytes within the
-+	  leaky structures.  Use-after-free bugs for structures containing
-+	  pointers can also be detected as dereferencing the sanitized pointer
-+	  will generate an access violation.
++#include "gcc-common.h"
 +
-+	  The tradeoff is performance impact, on a single CPU system kernel
-+	  compilation sees a 3% slowdown, other systems and workloads may vary
-+	  and you are advised to test this feature on your expected workload
-+	  before deploying it.
++// unused C type flag in all versions 4.5-6
++#define TYPE_CONSTIFY_VISITED(TYPE) TYPE_LANG_FLAG_4(TYPE)
 +
-+	  The slab sanitization feature excludes a few slab caches per default
-+	  for performance reasons.  To extend the feature to cover those as
-+	  well, pass "pax_sanitize_slab=full" as kernel command line parameter.
++int plugin_is_GPL_compatible;
 +
-+	  To reduce the performance penalty by sanitizing pages only, albeit
-+	  limiting the effectiveness of this feature at the same time, slab
-+	  sanitization can be disabled with the kernel command line parameter
-+	  "pax_sanitize_slab=off".
++static bool enabled = true;
 +
-+	  Note that this feature does not protect data stored in live pages,
-+	  e.g., process memory swapped to disk may stay there for a long time.
++static struct plugin_info const_plugin_info = {
++	.version	= "201605212045",
++	.help		= "disable\tturn off constification\n",
++};
 +
-+config PAX_MEMORY_STACKLEAK
-+	bool "Sanitize kernel stack"
-+	default y if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_PRIORITY_SECURITY)
-+	depends on X86
-+	help
-+	  By saying Y here the kernel will erase the kernel stack before it
-+	  returns from a system call.  This in turn reduces the information
-+	  that a kernel stack leak bug can reveal.
++typedef struct {
++	bool has_fptr_field;
++	bool has_writable_field;
++	bool has_do_const_field;
++	bool has_no_const_field;
++} constify_info;
 +
-+	  Note that such a bug can still leak information that was put on
-+	  the stack by the current system call (the one eventually triggering
-+	  the bug) but traces of earlier system calls on the kernel stack
-+	  cannot leak anymore.
++static const_tree get_field_type(const_tree field)
++{
++	return strip_array_types(TREE_TYPE(field));
++}
 +
-+	  The tradeoff is performance impact: on a single CPU system kernel
-+	  compilation sees a 1% slowdown, other systems and workloads may vary
-+	  and you are advised to test this feature on your expected workload
-+	  before deploying it.
++static bool is_fptr(const_tree field)
++{
++	const_tree ptr = get_field_type(field);
 +
-+	  Note that the full feature requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.  Using
-+	  older gcc versions means that functions with large enough stack
-+	  frames may leave uninitialized memory behind that may be exposed
-+	  to a later syscall leaking the stack.
++	if (TREE_CODE(ptr) != POINTER_TYPE)
++		return false;
 +
-+config PAX_MEMORY_STRUCTLEAK
-+	bool "Forcibly initialize local variables copied to userland"
-+	default y if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_PRIORITY_SECURITY)
-+	help
-+	  By saying Y here the kernel will zero initialize some local
-+	  variables that are going to be copied to userland.  This in
-+	  turn prevents unintended information leakage from the kernel
-+	  stack should later code forget to explicitly set all parts of
-+	  the copied variable.
++	return TREE_CODE(TREE_TYPE(ptr)) == FUNCTION_TYPE;
++}
 +
-+	  The tradeoff is less performance impact than PAX_MEMORY_STACKLEAK
-+	  at a much smaller coverage.
++/*
++ * determine whether the given structure type meets the requirements for automatic constification,
++ * including the constification attributes on nested structure types
++ */
++static void constifiable(const_tree node, constify_info *cinfo)
++{
++	const_tree field;
 +
-+	  Note that the implementation requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.
++	gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
 +
-+config PAX_MEMORY_UDEREF
-+	bool "Prevent invalid userland pointer dereference"
-+	default y if GRKERNSEC_CONFIG_AUTO && !(X86_64 && GRKERNSEC_CONFIG_PRIORITY_PERF) && !(X86_64 && GRKERNSEC_CONFIG_VIRT_HOST && GRKERNSEC_CONFIG_VIRT_VIRTUALBOX) && (!X86 || GRKERNSEC_CONFIG_VIRT_NONE || GRKERNSEC_CONFIG_VIRT_EPT)
-+	depends on (X86 || (ARM && (CPU_V6 || CPU_V6K || CPU_V7) && !ARM_LPAE)) && !UML_X86 && !XEN
-+	select PAX_PER_CPU_PGD if X86_64
-+	help
-+	  By saying Y here the kernel will be prevented from dereferencing
-+	  userland pointers in contexts where the kernel expects only kernel
-+	  pointers.  This is both a useful runtime debugging feature and a
-+	  security measure that prevents exploiting a class of kernel bugs.
++	// e.g., pointer to structure fields while still constructing the structure type
++	if (TYPE_FIELDS(node) == NULL_TREE)
++		return;
 +
-+	  The tradeoff is that some virtualization solutions may experience
-+	  a huge slowdown and therefore you should not enable this feature
-+	  for kernels meant to run in such environments.  Whether a given VM
-+	  solution is affected or not is best determined by simply trying it
-+	  out, the performance impact will be obvious right on boot as this
-+	  mechanism engages from very early on.  A good rule of thumb is that
-+	  VMs running on CPUs without hardware virtualization support (i.e.,
-+	  the majority of IA-32 CPUs) will likely experience the slowdown.
++	for (field = TYPE_FIELDS(node); field; field = TREE_CHAIN(field)) {
++		const_tree type = get_field_type(field);
++		enum tree_code code = TREE_CODE(type);
 +
-+	  On X86_64 the kernel will make use of PCID support when available
-+	  (Intel's Westmere, Sandy Bridge, etc) for better security (default)
-+	  or performance impact.  Pass pax_weakuderef on the kernel command
-+	  line to choose the latter.
++		if (node == type)
++			continue;
 +
-+config PAX_REFCOUNT
-+	bool "Prevent various kernel object reference counter overflows"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on GRKERNSEC && ((ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || MIPS || PPC || SPARC64 || X86)
-+	help
-+	  By saying Y here the kernel will detect and prevent overflowing
-+	  various (but not all) kinds of object reference counters.  Such
-+	  overflows can normally occur due to bugs only and are often, if
-+	  not always, exploitable.
++		if (is_fptr(field))
++			cinfo->has_fptr_field = true;
++		else if (code == RECORD_TYPE || code == UNION_TYPE) {
++			if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type)))
++				cinfo->has_do_const_field = true;
++			else if (lookup_attribute("no_const", TYPE_ATTRIBUTES(type)))
++				cinfo->has_no_const_field = true;
++			else
++				constifiable(type, cinfo);
++		} else if (!TREE_READONLY(field))
++			cinfo->has_writable_field = true;
++	}
++}
 +
-+	  The tradeoff is that data structures protected by an overflowed
-+	  refcount will never be freed and therefore will leak memory.  Note
-+	  that this leak also happens even without this protection but in
-+	  that case the overflow can eventually trigger the freeing of the
-+	  data structure while it is still being used elsewhere, resulting
-+	  in the exploitable situation that this feature prevents.
++static bool constified(const_tree node)
++{
++	constify_info cinfo = {
++		.has_fptr_field = false,
++		.has_writable_field = false,
++		.has_do_const_field = false,
++		.has_no_const_field = false
++	};
 +
-+	  Since this has a negligible performance impact, you should enable
-+	  this feature.
++	gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
 +
-+config PAX_CONSTIFY_PLUGIN
-+	bool "Automatically constify eligible structures"
-+	default y
-+	depends on !UML && PAX_KERNEXEC
-+	help
-+	  By saying Y here the compiler will automatically constify a class
-+	  of types that contain only function pointers.  This reduces the
-+	  kernel's attack surface and also produces a better memory layout.
++	if (lookup_attribute("no_const", TYPE_ATTRIBUTES(node))) {
++//		gcc_assert(!TYPE_READONLY(node));
++		return false;
++	}
 +
-+	  Note that the implementation requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.
-+ 
-+	  Note that if some code really has to modify constified variables
-+	  then the source code will have to be patched to allow it.  Examples
-+	  can be found in PaX itself (the no_const attribute) and for some
-+	  out-of-tree modules at http://www.grsecurity.net/~paxguy1/ .
++	if (lookup_attribute("do_const", TYPE_ATTRIBUTES(node))) {
++		gcc_assert(TYPE_READONLY(node));
++		return true;
++	}
 +
-+config PAX_USERCOPY
-+	bool "Harden heap object copies between kernel and userland"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	depends on ARM || IA64 || PPC || SPARC || X86
-+	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
-+	  userland, even if only a part of the heap object is copied.
++	constifiable(node, &cinfo);
++	if ((!cinfo.has_fptr_field || cinfo.has_writable_field || cinfo.has_no_const_field) && !cinfo.has_do_const_field)
++		return false;
 +
-+	  Specifically, this checking prevents information leaking from the
-+	  kernel heap during kernel to userland copies (if the kernel heap
-+	  object is otherwise fully initialized) and prevents kernel heap
-+	  overflows during userland to kernel copies.
++	return TYPE_READONLY(node);
++}
 +
-+	  Note that the current implementation provides the strictest bounds
-+	  checks for the SLUB allocator.
++static void deconstify_tree(tree node);
 +
-+	  Enabling this option also enables per-slab cache protection against
-+	  data in a given cache being copied into/out of via userland
-+	  accessors.  Though the whitelist of regions will be reduced over
-+	  time, it notably protects important data structures like task structs.
++static void deconstify_type(tree type)
++{
++	tree field;
 +
-+	  If frame pointers are enabled on x86, this option will also restrict
-+	  copies into and out of the kernel stack to local variables within a
-+	  single frame.
++	gcc_assert(TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_TYPE);
 +
-+	  Since this has a negligible performance impact, you should enable
-+	  this feature.
++	for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) {
++		const_tree fieldtype = get_field_type(field);
 +
-+config PAX_USERCOPY_DEBUG
-+	bool
-+	depends on X86 && PAX_USERCOPY
-+	default n
++		// special case handling of simple ptr-to-same-array-type members
++		if (TREE_CODE(TREE_TYPE(field)) == POINTER_TYPE) {
++			tree ptrtype = TREE_TYPE(TREE_TYPE(field));
 +
-+config PAX_SIZE_OVERFLOW
-+	bool "Prevent various integer overflows in function size parameters"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	help
-+	  By saying Y here the kernel recomputes expressions of function
-+	  arguments marked by a size_overflow attribute with double integer
-+	  precision (DImode/TImode for 32/64 bit integer types).
++			if (TREE_TYPE(TREE_TYPE(field)) == type)
++				continue;
++			if (TREE_CODE(ptrtype) != RECORD_TYPE && TREE_CODE(ptrtype) != UNION_TYPE)
++				continue;
++			if (!constified(ptrtype))
++				continue;
++			if (TYPE_MAIN_VARIANT(ptrtype) == TYPE_MAIN_VARIANT(type)) {
++				TREE_TYPE(field) = copy_node(TREE_TYPE(field));
++				TREE_TYPE(TREE_TYPE(field)) = build_qualified_type(type, TYPE_QUALS(ptrtype) & ~TYPE_QUAL_CONST);
++			}
++			continue;
++		}
++		if (TREE_CODE(fieldtype) != RECORD_TYPE && TREE_CODE(fieldtype) != UNION_TYPE)
++			continue;
++		if (!constified(fieldtype))
++			continue;
 +
-+	  The recomputed argument is checked against TYPE_MAX and an event
-+	  is logged on overflow and the triggering process is killed.
++		deconstify_tree(field);
++		TREE_READONLY(field) = 0;
++	}
++	TYPE_READONLY(type) = 0;
++	C_TYPE_FIELDS_READONLY(type) = 0;
++	if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
++		TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
++		TYPE_ATTRIBUTES(type) = remove_attribute("do_const", TYPE_ATTRIBUTES(type));
++	}
++}
 +
-+	  Homepage: https://github.com/ephox-gcc-plugins
++static void deconstify_tree(tree node)
++{
++	tree old_type, new_type, field;
 +
-+	  Note that the implementation requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.
++	old_type = TREE_TYPE(node);
++	while (TREE_CODE(old_type) == ARRAY_TYPE && TREE_CODE(TREE_TYPE(old_type)) != ARRAY_TYPE) {
++		node = TREE_TYPE(node) = copy_node(old_type);
++		old_type = TREE_TYPE(old_type);
++	}
 +
-+config PAX_LATENT_ENTROPY
-+	bool "Generate some entropy during boot and runtime"
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	help
-+	  By saying Y here the kernel will instrument some kernel 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 and fork and irq processing.
++	gcc_assert(TREE_CODE(old_type) == RECORD_TYPE || TREE_CODE(old_type) == UNION_TYPE);
++	gcc_assert(TYPE_READONLY(old_type) && (TYPE_QUALS(old_type) & TYPE_QUAL_CONST));
 +
-+	  When pax_extra_latent_entropy is passed on the kernel command line,
-+	  entropy will be extracted from up to the first 4GB of RAM while the
-+	  runtime memory allocator is being initialized.  This costs even more
-+	  slowdown of the boot process.
++	new_type = build_qualified_type(old_type, TYPE_QUALS(old_type) & ~TYPE_QUAL_CONST);
++	TYPE_FIELDS(new_type) = copy_list(TYPE_FIELDS(new_type));
++	for (field = TYPE_FIELDS(new_type); field; field = TREE_CHAIN(field))
++		DECL_FIELD_CONTEXT(field) = new_type;
 +
-+	  Note that the implementation requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.
++	deconstify_type(new_type);
 +
-+	  Note that entropy extracted this way is not cryptographically
-+	  secure!
++	TREE_TYPE(node) = new_type;
++}
 +
-+config PAX_RAP
-+	bool "Prevent code reuse attacks"
-+	depends on X86_64
-+	default y if GRKERNSEC_CONFIG_AUTO
-+	help
-+	  By saying Y here the kernel will check indirect control transfers
-+	  in order to detect and prevent attacks that try to hijack control
-+	  flow by overwriting code pointers.
++static tree handle_no_const_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
++{
++	tree type;
++	constify_info cinfo = {
++		.has_fptr_field = false,
++		.has_writable_field = false,
++		.has_do_const_field = false,
++		.has_no_const_field = false
++	};
 +
-+	  Note that binary modules cannot be instrumented by this approach.
++	*no_add_attrs = true;
++	if (TREE_CODE(*node) == FUNCTION_DECL) {
++		error("%qE attribute does not apply to functions (%qF)", name, *node);
++		return NULL_TREE;
++	}
 +
-+	  Note that the implementation requires a gcc with plugin support,
-+	  i.e., gcc 4.5 or newer.  You may need to install the supporting
-+	  headers explicitly in addition to the normal gcc package.
++	if (TREE_CODE(*node) == PARM_DECL) {
++		error("%qE attribute does not apply to function parameters (%qD)", name, *node);
++		return NULL_TREE;
++	}
 +
-+endmenu
++	if (TREE_CODE(*node) == VAR_DECL) {
++		error("%qE attribute does not apply to variables (%qD)", name, *node);
++		return NULL_TREE;
++	}
 +
-+endmenu
++	if (TYPE_P(*node)) {
++		type = *node;
++	} else {
++		if (TREE_CODE(*node) != TYPE_DECL) {
++			error("%qE attribute does not apply to %qD (%qT)", name, *node, TREE_TYPE(*node));
++			return NULL_TREE;
++		}
++		type = TREE_TYPE(*node);
++	}
 +
-+source grsecurity/Kconfig
++	if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE) {
++		error("%qE attribute used on %qT applies to struct and union types only", name, type);
++		return NULL_TREE;
++	}
 +
-+endmenu
++	if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(type))) {
++		error("%qE attribute is already applied to the type %qT", name, type);
++		return NULL_TREE;
++	}
 +
-+endmenu
++	if (TYPE_P(*node)) {
++		if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type)))
++			error("%qE attribute used on type %qT is incompatible with 'do_const'", name, type);
++		else
++			*no_add_attrs = false;
++		return NULL_TREE;
++	}
 +
- source security/keys/Kconfig
- 
- config SECURITY_DMESG_RESTRICT
-@@ -104,7 +1087,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
--	default 32768 if ARM || (ARM64 && COMPAT)
-+	default 32768 if ALPHA || ARM || (ARM64 && COMPAT) || PARISC || SPARC32
- 	default 65536
- 	help
- 	  This is the portion of low virtual memory which should be protected
-diff --git a/security/apparmor/file.c b/security/apparmor/file.c
-index 913f377..6e392d5 100644
---- a/security/apparmor/file.c
-+++ b/security/apparmor/file.c
-@@ -348,8 +348,8 @@ static inline bool xindex_is_subset(u32 link, u32 target)
- int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
- 		 struct path *new_dir, struct dentry *new_dentry)
- {
--	struct path link = { new_dir->mnt, new_dentry };
--	struct path target = { new_dir->mnt, old_dentry };
-+	struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
-+	struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry };
- 	struct path_cond cond = {
- 		d_backing_inode(old_dentry)->i_uid,
- 		d_backing_inode(old_dentry)->i_mode
-diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
-index c28b0f2..3b9fee0 100644
---- a/security/apparmor/include/policy.h
-+++ b/security/apparmor/include/policy.h
-@@ -134,7 +134,7 @@ struct aa_namespace {
- 	struct aa_ns_acct acct;
- 	struct aa_profile *unconfined;
- 	struct list_head sub_ns;
--	atomic_t uniq_null;
-+	atomic_unchecked_t uniq_null;
- 	long uniq_id;
- 
- 	struct dentry *dents[AAFS_NS_SIZEOF];
-diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
-index dec607c..37fe357 100644
---- a/security/apparmor/lsm.c
-+++ b/security/apparmor/lsm.c
-@@ -176,7 +176,7 @@ static int common_perm_dir_dentry(int op, struct path *dir,
- 				  struct dentry *dentry, u32 mask,
- 				  struct path_cond *cond)
- {
--	struct path path = { dir->mnt, dentry };
-+	struct path path = { .mnt = dir->mnt, .dentry = dentry };
- 
- 	return common_perm(op, &path, mask, cond);
- }
-@@ -193,7 +193,7 @@ static int common_perm_dir_dentry(int op, struct path *dir,
- static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
- 				  struct dentry *dentry, u32 mask)
- {
--	struct path path = { mnt, dentry };
-+	struct path path = { .mnt = mnt, .dentry = dentry };
- 	struct path_cond cond = { d_backing_inode(dentry)->i_uid,
- 				  d_backing_inode(dentry)->i_mode
- 	};
-@@ -315,8 +315,8 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
- 
- 	profile = aa_current_profile();
- 	if (!unconfined(profile)) {
--		struct path old_path = { old_dir->mnt, old_dentry };
--		struct path new_path = { new_dir->mnt, new_dentry };
-+		struct path old_path = { .mnt = old_dir->mnt, .dentry = old_dentry };
-+		struct path new_path = { .mnt = new_dir->mnt, .dentry = new_dentry };
- 		struct path_cond cond = { d_backing_inode(old_dentry)->i_uid,
- 					  d_backing_inode(old_dentry)->i_mode
- 		};
-@@ -677,11 +677,11 @@ static const struct kernel_param_ops param_ops_aalockpolicy = {
- 	.get = param_get_aalockpolicy
- };
- 
--static int param_set_audit(const char *val, struct kernel_param *kp);
--static int param_get_audit(char *buffer, struct kernel_param *kp);
-+static int param_set_audit(const char *val, const struct kernel_param *kp);
-+static int param_get_audit(char *buffer, const struct kernel_param *kp);
- 
--static int param_set_mode(const char *val, struct kernel_param *kp);
--static int param_get_mode(char *buffer, struct kernel_param *kp);
-+static int param_set_mode(const char *val, const struct kernel_param *kp);
-+static int param_get_mode(char *buffer, const struct kernel_param *kp);
- 
- /* Flag values, also controllable via /sys/module/apparmor/parameters
-  * We define special types as we want to do additional mediation.
-@@ -791,7 +791,7 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp)
- 	return param_get_uint(buffer, kp);
- }
- 
--static int param_get_audit(char *buffer, struct kernel_param *kp)
-+static int param_get_audit(char *buffer, const struct kernel_param *kp)
- {
- 	if (!capable(CAP_MAC_ADMIN))
- 		return -EPERM;
-@@ -802,7 +802,7 @@ static int param_get_audit(char *buffer, struct kernel_param *kp)
- 	return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
- }
- 
--static int param_set_audit(const char *val, struct kernel_param *kp)
-+static int param_set_audit(const char *val, const struct kernel_param *kp)
- {
- 	int i;
- 	if (!capable(CAP_MAC_ADMIN))
-@@ -824,7 +824,7 @@ static int param_set_audit(const char *val, struct kernel_param *kp)
- 	return -EINVAL;
- }
- 
--static int param_get_mode(char *buffer, struct kernel_param *kp)
-+static int param_get_mode(char *buffer, const struct kernel_param *kp)
- {
- 	if (!capable(CAP_MAC_ADMIN))
- 		return -EPERM;
-@@ -835,7 +835,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
- 	return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
- }
- 
--static int param_set_mode(const char *val, struct kernel_param *kp)
-+static int param_set_mode(const char *val, const struct kernel_param *kp)
- {
- 	int i;
- 	if (!capable(CAP_MAC_ADMIN))
-diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
-index 705c287..81257f1 100644
---- a/security/apparmor/policy.c
-+++ b/security/apparmor/policy.c
-@@ -298,7 +298,7 @@ static struct aa_namespace *alloc_namespace(const char *prefix,
- 	/* ns and ns->unconfined share ns->unconfined refcount */
- 	ns->unconfined->ns = ns;
- 
--	atomic_set(&ns->uniq_null, 0);
-+	atomic_set_unchecked(&ns->uniq_null, 0);
- 
- 	return ns;
- 
-@@ -689,7 +689,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
- {
- 	struct aa_profile *profile = NULL;
- 	char *name;
--	int uniq = atomic_inc_return(&parent->ns->uniq_null);
-+	int uniq = atomic_inc_return_unchecked(&parent->ns->uniq_null);
- 
- 	/* freed below */
- 	name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
-diff --git a/security/commoncap.c b/security/commoncap.c
-index 48071ed..b805e0f 100644
---- a/security/commoncap.c
-+++ b/security/commoncap.c
-@@ -438,6 +438,32 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
- 	return 0;
- }
- 
-+/* returns:
-+	1 for suid privilege
-+	2 for sgid privilege
-+	3 for fscap privilege
-+*/
-+int is_privileged_binary(const struct dentry *dentry)
++	constifiable(type, &cinfo);
++	if ((cinfo.has_fptr_field && !cinfo.has_writable_field && !cinfo.has_no_const_field) || lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
++		if (enabled) {
++			if TYPE_P(*node)
++				deconstify_type(*node);
++			else
++				deconstify_tree(*node);
++		}
++		if (TYPE_P(*node))
++			TYPE_CONSTIFY_VISITED(*node) = 1;
++		else
++			TYPE_CONSTIFY_VISITED(TREE_TYPE(*node)) = 1;
++		return NULL_TREE;
++	}
++
++	if (enabled && TYPE_FIELDS(type))
++		error("%qE attribute used on type %qT that is not constified", name, type);
++	return NULL_TREE;
++}
++
++static void constify_type(tree type)
 +{
-+	struct cpu_vfs_cap_data capdata;
-+	struct inode *inode = dentry->d_inode;
++	TYPE_READONLY(type) = 1;
++	C_TYPE_FIELDS_READONLY(type) = 1;
++	TYPE_CONSTIFY_VISITED(type) = 1;
++//	TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
++//	TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("do_const"), NULL_TREE, TYPE_ATTRIBUTES(type));
++}
 +
-+	if (!inode || S_ISDIR(inode->i_mode))
-+		return 0;
++static tree handle_do_const_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
++{
++	*no_add_attrs = true;
++	if (!TYPE_P(*node)) {
++		error("%qE attribute applies to types only (%qD)", name, *node);
++		return NULL_TREE;
++	}
 +
-+	if (inode->i_mode & S_ISUID)
++	if (TREE_CODE(*node) != RECORD_TYPE && TREE_CODE(*node) != UNION_TYPE) {
++		error("%qE attribute used on %qT applies to struct and union types only", name, *node);
++		return NULL_TREE;
++	}
++
++	if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(*node))) {
++		error("%qE attribute used on %qT is already applied to the type", name, *node);
++		return NULL_TREE;
++	}
++
++	if (lookup_attribute("no_const", TYPE_ATTRIBUTES(*node))) {
++		error("%qE attribute used on %qT is incompatible with 'no_const'", name, *node);
++		return NULL_TREE;
++	}
++
++	*no_add_attrs = false;
++	return NULL_TREE;
++}
++
++static struct attribute_spec no_const_attr = {
++	.name			= "no_const",
++	.min_length		= 0,
++	.max_length		= 0,
++	.decl_required		= false,
++	.type_required		= false,
++	.function_type_required	= false,
++	.handler		= handle_no_const_attribute,
++#if BUILDING_GCC_VERSION >= 4007
++	.affects_type_identity	= true
++#endif
++};
++
++static struct attribute_spec do_const_attr = {
++	.name			= "do_const",
++	.min_length		= 0,
++	.max_length		= 0,
++	.decl_required		= false,
++	.type_required		= false,
++	.function_type_required	= false,
++	.handler		= handle_do_const_attribute,
++#if BUILDING_GCC_VERSION >= 4007
++	.affects_type_identity	= true
++#endif
++};
++
++static void register_attributes(void *event_data, void *data)
++{
++	register_attribute(&no_const_attr);
++	register_attribute(&do_const_attr);
++}
++
++static void finish_type(void *event_data, void *data)
++{
++	tree type = (tree)event_data;
++	constify_info cinfo = {
++		.has_fptr_field = false,
++		.has_writable_field = false,
++		.has_do_const_field = false,
++		.has_no_const_field = false
++	};
++
++	if (type == NULL_TREE || type == error_mark_node)
++		return;
++
++#if BUILDING_GCC_VERSION >= 5000
++	if (TREE_CODE(type) == ENUMERAL_TYPE)
++		return;
++#endif
++
++	if (TYPE_FIELDS(type) == NULL_TREE || TYPE_CONSTIFY_VISITED(type))
++		return;
++
++	constifiable(type, &cinfo);
++
++	if (lookup_attribute("no_const", TYPE_ATTRIBUTES(type))) {
++		if ((cinfo.has_fptr_field && !cinfo.has_writable_field && !cinfo.has_no_const_field) || cinfo.has_do_const_field) {
++			deconstify_type(type);
++			TYPE_CONSTIFY_VISITED(type) = 1;
++		} else
++			error("'no_const' attribute used on type %qT that is not constified", type);
++		return;
++	}
++
++	if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
++		if (!cinfo.has_writable_field && !cinfo.has_no_const_field) {
++			error("'do_const' attribute used on type %qT that is%sconstified", type, cinfo.has_fptr_field ? " " : " not ");
++			return;
++		}
++		constify_type(type);
++		return;
++	}
++
++	if (cinfo.has_fptr_field && !cinfo.has_writable_field && !cinfo.has_no_const_field) {
++		if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
++			error("'do_const' attribute used on type %qT that is constified", type);
++			return;
++		}
++		constify_type(type);
++		return;
++	}
++
++	deconstify_type(type);
++	TYPE_CONSTIFY_VISITED(type) = 1;
++}
++
++static void check_global_variables(void *event_data, void *data)
++{
++	varpool_node_ptr node;
++
++	FOR_EACH_VARIABLE(node) {
++		tree var = NODE_DECL(node);
++		tree type = TREE_TYPE(var);
++
++		if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
++			continue;
++
++		if (!TYPE_READONLY(type) || !C_TYPE_FIELDS_READONLY(type))
++			continue;
++
++		if (!TYPE_CONSTIFY_VISITED(type))
++			continue;
++
++		if (DECL_EXTERNAL(var))
++			continue;
++
++		if (DECL_INITIAL(var))
++			continue;
++
++		// this works around a gcc bug/feature where uninitialized globals
++		// are moved into the .bss section regardless of any constification
++		DECL_INITIAL(var) = build_constructor(type, NULL);
++//		inform(DECL_SOURCE_LOCATION(var), "constified variable %qE moved into .rodata", var);
++	}
++}
++
++static unsigned int check_local_variables_execute(void)
++{
++	unsigned int ret = 0;
++	tree var;
++
++	unsigned int i;
++
++	FOR_EACH_LOCAL_DECL(cfun, i, var) {
++		tree type = TREE_TYPE(var);
++
++		gcc_assert(DECL_P(var));
++		if (is_global_var(var))
++			continue;
++
++		if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
++			continue;
++
++		if (!TYPE_READONLY(type) || !C_TYPE_FIELDS_READONLY(type))
++			continue;
++
++		if (!TYPE_CONSTIFY_VISITED(type))
++			continue;
++
++		error_at(DECL_SOURCE_LOCATION(var), "constified variable %qE cannot be local", var);
++		ret = 1;
++	}
++	return ret;
++}
++
++#define PASS_NAME check_local_variables
++#define NO_GATE
++#include "gcc-generate-gimple-pass.h"
++
++static struct {
++	const char *name;
++	const char *asm_op;
++} sections[] = {
++	{".init.rodata",     "\t.section\t.init.rodata,\"a\""},
++	{".ref.rodata",      "\t.section\t.ref.rodata,\"a\""},
++	{".devinit.rodata",  "\t.section\t.devinit.rodata,\"a\""},
++	{".devexit.rodata",  "\t.section\t.devexit.rodata,\"a\""},
++	{".cpuinit.rodata",  "\t.section\t.cpuinit.rodata,\"a\""},
++	{".cpuexit.rodata",  "\t.section\t.cpuexit.rodata,\"a\""},
++	{".meminit.rodata",  "\t.section\t.meminit.rodata,\"a\""},
++	{".memexit.rodata",  "\t.section\t.memexit.rodata,\"a\""},
++	{".data..read_only", "\t.section\t.data..read_only,\"a\""},
++};
++
++static unsigned int (*old_section_type_flags)(tree decl, const char *name, int reloc);
++
++static unsigned int constify_section_type_flags(tree decl, const char *name, int reloc)
++{
++	size_t i;
++
++	for (i = 0; i < ARRAY_SIZE(sections); i++)
++		if (!strcmp(sections[i].name, name))
++			return 0;
++	return old_section_type_flags(decl, name, reloc);
++}
++
++static void constify_start_unit(void *gcc_data, void *user_data)
++{
++//	size_t i;
++
++//	for (i = 0; i < ARRAY_SIZE(sections); i++)
++//		sections[i].section = get_unnamed_section(0, output_section_asm_op, sections[i].asm_op);
++//		sections[i].section = get_section(sections[i].name, 0, NULL);
++
++	old_section_type_flags = targetm.section_type_flags;
++	targetm.section_type_flags = constify_section_type_flags;
++}
++
++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
++{
++	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	int i;
++
++	struct register_pass_info check_local_variables_pass_info;
++
++	check_local_variables_pass_info.pass				= make_check_local_variables_pass();
++	check_local_variables_pass_info.reference_pass_name		= "ssa";
++	check_local_variables_pass_info.ref_pass_instance_number	= 1;
++	check_local_variables_pass_info.pos_op				= PASS_POS_INSERT_BEFORE;
++
++	if (!plugin_default_version_check(version, &gcc_version)) {
++		error(G_("incompatible gcc/plugin versions"));
 +		return 1;
-+	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
-+		return 2;
++	}
 +
-+	if (!get_vfs_caps_from_disk(dentry, &capdata)) {
-+		if (!cap_isclear(capdata.inheritable) || !cap_isclear(capdata.permitted))
-+			return 3;
++	for (i = 0; i < argc; ++i) {
++		if (!(strcmp(argv[i].key, "disable"))) {
++			enabled = false;
++			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
++
++	if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {
++		inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);
++		enabled = false;
++	}
++
++	register_callback(plugin_name, PLUGIN_INFO, NULL, &const_plugin_info);
++	if (enabled) {
++		register_callback(plugin_name, PLUGIN_ALL_IPA_PASSES_START, check_global_variables, NULL);
++		register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &check_local_variables_pass_info);
++		register_callback(plugin_name, PLUGIN_START_UNIT, constify_start_unit, NULL);
 +	}
++	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
 +
 +	return 0;
 +}
+diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
+new file mode 100644
+index 0000000..0c0b842
+--- /dev/null
++++ b/scripts/gcc-plugins/gcc-common.h
+@@ -0,0 +1,879 @@
++#ifndef GCC_COMMON_H_INCLUDED
++#define GCC_COMMON_H_INCLUDED
 +
- /*
-  * Attempt to get the on-exec apply capability sets for an executable file from
-  * its xattrs and, if present, apply them to the proposed credentials being
-@@ -628,6 +654,9 @@ int cap_bprm_secureexec(struct linux_binprm *bprm)
- 	const struct cred *cred = current_cred();
- 	kuid_t root_uid = make_kuid(cred->user_ns, 0);
- 
-+	if (gr_acl_enable_at_secure())
-+		return 1;
++#include "bversion.h"
++#if BUILDING_GCC_VERSION >= 6000
++#include "gcc-plugin.h"
++#else
++#include "plugin.h"
++#endif
++#include "plugin-version.h"
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "line-map.h"
++#include "input.h"
++#include "tree.h"
 +
- 	if (!uid_eq(cred->uid, root_uid)) {
- 		if (bprm->cap_effective)
- 			return 1;
-diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
-index 585af61..b7d35ff 100644
---- a/security/integrity/ima/ima.h
-+++ b/security/integrity/ima/ima.h
-@@ -125,8 +125,8 @@ int ima_init_template(void);
- extern spinlock_t ima_queue_lock;
- 
- struct ima_h_table {
--	atomic_long_t len;	/* number of stored measurements in the list */
--	atomic_long_t violations;
-+	atomic_long_unchecked_t len;	/* number of stored measurements in the list */
-+	atomic_long_unchecked_t violations;
- 	struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
- };
- extern struct ima_h_table ima_htable;
-diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
-index 1d950fb..a8f4eab 100644
---- a/security/integrity/ima/ima_api.c
-+++ b/security/integrity/ima/ima_api.c
-@@ -137,7 +137,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
- 	int result;
- 
- 	/* can overflow, only indicator */
--	atomic_long_inc(&ima_htable.violations);
-+	atomic_long_inc_unchecked(&ima_htable.violations);
- 
- 	result = ima_alloc_init_template(&event_data, &entry);
- 	if (result < 0) {
-diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
-index f355231..c71f640 100644
---- a/security/integrity/ima/ima_fs.c
-+++ b/security/integrity/ima/ima_fs.c
-@@ -30,12 +30,12 @@ static DEFINE_MUTEX(ima_write_mutex);
- static int valid_policy = 1;
- #define TMPBUFLEN 12
- static ssize_t ima_show_htable_value(char __user *buf, size_t count,
--				     loff_t *ppos, atomic_long_t *val)
-+				     loff_t *ppos, atomic_long_unchecked_t *val)
- {
- 	char tmpbuf[TMPBUFLEN];
- 	ssize_t len;
- 
--	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
-+	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read_unchecked(val));
- 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
- }
- 
-diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
-index 552705d..9920f4fb 100644
---- a/security/integrity/ima/ima_queue.c
-+++ b/security/integrity/ima/ima_queue.c
-@@ -83,7 +83,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
- 	INIT_LIST_HEAD(&qe->later);
- 	list_add_tail_rcu(&qe->later, &ima_measurements);
- 
--	atomic_long_inc(&ima_htable.len);
-+	atomic_long_inc_unchecked(&ima_htable.len);
- 	key = ima_hash_key(entry->digest);
- 	hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
- 	return 0;
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index 5105c2c..a5010e6 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -90,12 +90,16 @@ extern void key_type_put(struct key_type *ktype);
- 
- extern int __key_link_begin(struct key *keyring,
- 			    const struct keyring_index_key *index_key,
--			    struct assoc_array_edit **_edit);
-+			    struct assoc_array_edit **_edit)
-+			    __acquires(&keyring->sem)
-+			    __acquires(&keyring_serialise_link_sem);
- extern int __key_link_check_live_key(struct key *keyring, struct key *key);
- extern void __key_link(struct key *key, struct assoc_array_edit **_edit);
- extern void __key_link_end(struct key *keyring,
- 			   const struct keyring_index_key *index_key,
--			   struct assoc_array_edit *edit);
-+			   struct assoc_array_edit *edit)
-+			   __releases(&keyring->sem)
-+			   __releases(&keyring_serialise_link_sem);
- 
- extern key_ref_t find_key_to_update(key_ref_t keyring_ref,
- 				    const struct keyring_index_key *index_key);
-@@ -191,7 +195,7 @@ struct request_key_auth {
- 	void			*callout_info;
- 	size_t			callout_len;
- 	pid_t			pid;
--};
-+} __randomize_layout;
- 
- extern struct key_type key_type_request_key_auth;
- extern struct key *request_key_auth_new(struct key *target,
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 09ef276..ab2894f 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -283,7 +283,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
- 
- 	atomic_set(&key->usage, 1);
- 	init_rwsem(&key->sem);
--	lockdep_set_class(&key->sem, &type->lock_class);
-+	lockdep_set_class(&key->sem, (struct lock_class_key *)&type->lock_class);
- 	key->index_key.type = type;
- 	key->user = user;
- 	key->quotalen = quotalen;
-@@ -1077,7 +1077,9 @@ int register_key_type(struct key_type *ktype)
- 	struct key_type *p;
- 	int ret;
- 
--	memset(&ktype->lock_class, 0, sizeof(ktype->lock_class));
-+	pax_open_kernel();
-+	memset((void *)&ktype->lock_class, 0, sizeof(ktype->lock_class));
-+	pax_close_kernel();
- 
- 	ret = -EEXIST;
- 	down_write(&key_types_sem);
-@@ -1089,7 +1091,7 @@ int register_key_type(struct key_type *ktype)
- 	}
- 
- 	/* store the type */
--	list_add(&ktype->link, &key_types_list);
-+	pax_list_add((struct list_head *)&ktype->link, &key_types_list);
- 
- 	pr_notice("Key type %s registered\n", ktype->name);
- 	ret = 0;
-@@ -1111,7 +1113,7 @@ EXPORT_SYMBOL(register_key_type);
- void unregister_key_type(struct key_type *ktype)
- {
- 	down_write(&key_types_sem);
--	list_del_init(&ktype->link);
-+	pax_list_del_init((struct list_head *)&ktype->link);
- 	downgrade_write(&key_types_sem);
- 	key_gc_keytype(ktype);
- 	pr_notice("Key type %s unregistered\n", ktype->name);
-@@ -1129,10 +1131,10 @@ void __init key_init(void)
- 			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
- 
- 	/* add the special key types */
--	list_add_tail(&key_type_keyring.link, &key_types_list);
--	list_add_tail(&key_type_dead.link, &key_types_list);
--	list_add_tail(&key_type_user.link, &key_types_list);
--	list_add_tail(&key_type_logon.link, &key_types_list);
-+	pax_list_add_tail((struct list_head *)&key_type_keyring.link, &key_types_list);
-+	pax_list_add_tail((struct list_head *)&key_type_dead.link, &key_types_list);
-+	pax_list_add_tail((struct list_head *)&key_type_user.link, &key_types_list);
-+	pax_list_add_tail((struct list_head *)&key_type_logon.link, &key_types_list);
- 
- 	/* record the root user tracking */
- 	rb_link_node(&root_key_user.node,
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index f931ccf..ed9cd36 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -1071,8 +1071,6 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
- int __key_link_begin(struct key *keyring,
- 		     const struct keyring_index_key *index_key,
- 		     struct assoc_array_edit **_edit)
--	__acquires(&keyring->sem)
--	__acquires(&keyring_serialise_link_sem)
- {
- 	struct assoc_array_edit *edit;
- 	int ret;
-@@ -1172,8 +1170,6 @@ void __key_link(struct key *key, struct assoc_array_edit **_edit)
- void __key_link_end(struct key *keyring,
- 		    const struct keyring_index_key *index_key,
- 		    struct assoc_array_edit *edit)
--	__releases(&keyring->sem)
--	__releases(&keyring_serialise_link_sem)
- {
- 	BUG_ON(index_key->type == NULL);
- 	kenter("%d,%s,", keyring->serial, index_key->type->name);
-diff --git a/security/min_addr.c b/security/min_addr.c
-index f728728..6457a0c 100644
---- a/security/min_addr.c
-+++ b/security/min_addr.c
-@@ -14,6 +14,7 @@ unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
-  */
- static void update_mmap_min_addr(void)
- {
-+#ifndef SPARC
- #ifdef CONFIG_LSM_MMAP_MIN_ADDR
- 	if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
- 		mmap_min_addr = dac_mmap_min_addr;
-@@ -22,6 +23,7 @@ static void update_mmap_min_addr(void)
- #else
- 	mmap_min_addr = dac_mmap_min_addr;
- #endif
-+#endif
- }
- 
- /*
-diff --git a/security/selinux/avc.c b/security/selinux/avc.c
-index e60c79d..41fb721 100644
---- a/security/selinux/avc.c
-+++ b/security/selinux/avc.c
-@@ -71,7 +71,7 @@ struct avc_xperms_node {
- struct avc_cache {
- 	struct hlist_head	slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
- 	spinlock_t		slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
--	atomic_t		lru_hint;	/* LRU hint for reclaim scan */
-+	atomic_unchecked_t	lru_hint;	/* LRU hint for reclaim scan */
- 	atomic_t		active_nodes;
- 	u32			latest_notif;	/* latest revocation notification */
- };
-@@ -183,7 +183,7 @@ void __init avc_init(void)
- 		spin_lock_init(&avc_cache.slots_lock[i]);
- 	}
- 	atomic_set(&avc_cache.active_nodes, 0);
--	atomic_set(&avc_cache.lru_hint, 0);
-+	atomic_set_unchecked(&avc_cache.lru_hint, 0);
- 
- 	avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
- 					0, SLAB_PANIC, NULL);
-@@ -521,7 +521,7 @@ static inline int avc_reclaim_node(void)
- 	spinlock_t *lock;
- 
- 	for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
--		hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
-+		hvalue = atomic_inc_return_unchecked(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
- 		head = &avc_cache.slots[hvalue];
- 		lock = &avc_cache.slots_lock[hvalue];
- 
-diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
-index 1450f85..a91e0bc 100644
---- a/security/selinux/include/xfrm.h
-+++ b/security/selinux/include/xfrm.h
-@@ -48,7 +48,7 @@ static inline void selinux_xfrm_notify_policyload(void)
- 
- 	rtnl_lock();
- 	for_each_net(net) {
--		atomic_inc(&net->xfrm.flow_cache_genid);
-+		atomic_inc_unchecked(&net->xfrm.flow_cache_genid);
- 		rt_genid_bump_all(net);
- 	}
- 	rtnl_unlock();
-diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
-index 2367b10..a0c3c51 100644
---- a/security/tomoyo/file.c
-+++ b/security/tomoyo/file.c
-@@ -692,7 +692,7 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
- {
- 	struct tomoyo_request_info r;
- 	struct tomoyo_obj_info obj = {
--		.path1 = *path,
-+		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
- 	};
- 	int error = -ENOMEM;
- 	struct tomoyo_path_info buf;
-@@ -740,7 +740,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
- 	struct tomoyo_path_info buf;
- 	struct tomoyo_request_info r;
- 	struct tomoyo_obj_info obj = {
--		.path1 = *path,
-+		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
- 	};
- 	int idx;
- 
-@@ -786,7 +786,7 @@ int tomoyo_path_perm(const u8 operation, const struct path *path, const char *ta
- {
- 	struct tomoyo_request_info r;
- 	struct tomoyo_obj_info obj = {
--		.path1 = *path,
-+		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
- 	};
- 	int error;
- 	struct tomoyo_path_info buf;
-@@ -843,7 +843,7 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path,
- {
- 	struct tomoyo_request_info r;
- 	struct tomoyo_obj_info obj = {
--		.path1 = *path,
-+		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
- 	};
- 	int error = -ENOMEM;
- 	struct tomoyo_path_info buf;
-@@ -890,8 +890,8 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
- 	struct tomoyo_path_info buf2;
- 	struct tomoyo_request_info r;
- 	struct tomoyo_obj_info obj = {
--		.path1 = *path1,
--		.path2 = *path2,
-+		.path1 = { .mnt = path1->mnt, .dentry = path1->dentry },
-+		.path2 = { .mnt = path2->mnt, .dentry = path2->dentry }
- 	};
- 	int idx;
- 
-diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
-index 390c646..f2f8db3 100644
---- a/security/tomoyo/mount.c
-+++ b/security/tomoyo/mount.c
-@@ -118,6 +118,10 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r,
- 		   type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {
- 		need_dev = -1; /* dev_name is a directory */
- 	} else {
-+		if (!capable(CAP_SYS_ADMIN)) {
-+			error = -EPERM;
-+			goto out;
-+		}
- 		fstype = get_fs_type(type);
- 		if (!fstype) {
- 			error = -ENODEV;
-diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
-index cbf3df4..22b11df 100644
---- a/security/tomoyo/tomoyo.c
-+++ b/security/tomoyo/tomoyo.c
-@@ -165,7 +165,7 @@ static int tomoyo_path_truncate(struct path *path)
-  */
- static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
- {
--	struct path path = { parent->mnt, dentry };
-+	struct path path = { .mnt = parent->mnt, .dentry = dentry };
- 	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL);
- }
- 
-@@ -181,7 +181,7 @@ static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
- static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
- 			     umode_t mode)
- {
--	struct path path = { parent->mnt, dentry };
-+	struct path path = { .mnt = parent->mnt, .dentry = dentry };
- 	return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,
- 				       mode & S_IALLUGO);
- }
-@@ -196,7 +196,7 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
-  */
- static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
- {
--	struct path path = { parent->mnt, dentry };
-+	struct path path = { .mnt = parent->mnt, .dentry = dentry };
- 	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL);
- }
- 
-@@ -212,7 +212,7 @@ static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
- static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
- 			       const char *old_name)
- {
--	struct path path = { parent->mnt, dentry };
-+	struct path path = { .mnt = parent->mnt, .dentry = dentry };
- 	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name);
- }
- 
-@@ -229,7 +229,7 @@ static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
- static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
- 			     umode_t mode, unsigned int dev)
- {
--	struct path path = { parent->mnt, dentry };
-+	struct path path = { .mnt = parent->mnt, .dentry = dentry };
- 	int type = TOMOYO_TYPE_CREATE;
- 	const unsigned int perm = mode & S_IALLUGO;
- 
-@@ -268,8 +268,8 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
- static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
- 			    struct dentry *new_dentry)
- {
--	struct path path1 = { new_dir->mnt, old_dentry };
--	struct path path2 = { new_dir->mnt, new_dentry };
-+	struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry };
-+	struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry };
- 	return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
- }
- 
-@@ -288,8 +288,8 @@ static int tomoyo_path_rename(struct path *old_parent,
- 			      struct path *new_parent,
- 			      struct dentry *new_dentry)
- {
--	struct path path1 = { old_parent->mnt, old_dentry };
--	struct path path2 = { new_parent->mnt, new_dentry };
-+	struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry };
-+	struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry };
- 	return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2);
- }
- 
-@@ -417,7 +417,7 @@ static int tomoyo_sb_mount(const char *dev_name, struct path *path,
-  */
- static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
- {
--	struct path path = { mnt, mnt->mnt_root };
-+	struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
- 	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL);
- }
- 
-diff --git a/security/yama/Kconfig b/security/yama/Kconfig
-index 90c605e..bf3a29a 100644
---- a/security/yama/Kconfig
-+++ b/security/yama/Kconfig
-@@ -1,6 +1,6 @@
- config SECURITY_YAMA
- 	bool "Yama support"
--	depends on SECURITY
-+	depends on SECURITY && !GRKERNSEC
- 	default n
- 	help
- 	  This selects Yama, which extends DAC support with additional
-diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
-index cb6ed10..fb00554 100644
---- a/security/yama/yama_lsm.c
-+++ b/security/yama/yama_lsm.c
-@@ -357,7 +357,7 @@ static struct security_hook_list yama_hooks[] = {
- static int yama_dointvec_minmax(struct ctl_table *table, int write,
- 				void __user *buffer, size_t *lenp, loff_t *ppos)
- {
--	struct ctl_table table_copy;
-+	ctl_table_no_const table_copy;
- 
- 	if (write && !capable(CAP_SYS_PTRACE))
- 		return -EPERM;
-diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
-index a04edff..6811b91 100644
---- a/sound/aoa/codecs/onyx.c
-+++ b/sound/aoa/codecs/onyx.c
-@@ -54,7 +54,7 @@ struct onyx {
- 				spdif_locked:1,
- 				analog_locked:1,
- 				original_mute:2;
--	int			open_count;
-+	local_t			open_count;
- 	struct codec_info	*codec_info;
- 
- 	/* mutex serializes concurrent access to the device
-@@ -747,7 +747,7 @@ static int onyx_open(struct codec_info_item *cii,
- 	struct onyx *onyx = cii->codec_data;
- 
- 	mutex_lock(&onyx->mutex);
--	onyx->open_count++;
-+	local_inc(&onyx->open_count);
- 	mutex_unlock(&onyx->mutex);
- 
- 	return 0;
-@@ -759,8 +759,7 @@ static int onyx_close(struct codec_info_item *cii,
- 	struct onyx *onyx = cii->codec_data;
- 
- 	mutex_lock(&onyx->mutex);
--	onyx->open_count--;
--	if (!onyx->open_count)
-+	if (local_dec_and_test(&onyx->open_count))
- 		onyx->spdif_locked = onyx->analog_locked = 0;
- 	mutex_unlock(&onyx->mutex);
- 
-diff --git a/sound/aoa/codecs/onyx.h b/sound/aoa/codecs/onyx.h
-index ffd2025..df062c9 100644
---- a/sound/aoa/codecs/onyx.h
-+++ b/sound/aoa/codecs/onyx.h
-@@ -11,6 +11,7 @@
- #include <linux/i2c.h>
- #include <asm/pmac_low_i2c.h>
- #include <asm/prom.h>
-+#include <asm/local.h>
- 
- /* PCM3052 register definitions */
- 
-diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
-index ebc9fdf..61f491e 100644
---- a/sound/core/oss/pcm_oss.c
-+++ b/sound/core/oss/pcm_oss.c
-@@ -1193,10 +1193,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
- 		if (in_kernel) {
- 			mm_segment_t fs;
- 			fs = snd_enter_user();
--			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
-+			ret = snd_pcm_lib_write(substream, (void __force_user *)ptr, frames);
- 			snd_leave_user(fs);
- 		} else {
--			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
-+			ret = snd_pcm_lib_write(substream, (void __force_user *)ptr, frames);
- 		}
- 		if (ret != -EPIPE && ret != -ESTRPIPE)
- 			break;
-@@ -1236,10 +1236,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
- 		if (in_kernel) {
- 			mm_segment_t fs;
- 			fs = snd_enter_user();
--			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
-+			ret = snd_pcm_lib_read(substream, (void __force_user *)ptr, frames);
- 			snd_leave_user(fs);
- 		} else {
--			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
-+			ret = snd_pcm_lib_read(substream, (void __force_user *)ptr, frames);
- 		}
- 		if (ret == -EPIPE) {
- 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
-@@ -1335,7 +1335,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
- 		struct snd_pcm_plugin_channel *channels;
- 		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
- 		if (!in_kernel) {
--			if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes))
-+			if (copy_from_user(runtime->oss.buffer, (const char __force_user *)buf, bytes))
- 				return -EFAULT;
- 			buf = runtime->oss.buffer;
- 		}
-@@ -1405,7 +1405,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
- 			}
- 		} else {
- 			tmp = snd_pcm_oss_write2(substream,
--						 (const char __force *)buf,
-+						 (const char __force_kernel *)buf,
- 						 runtime->oss.period_bytes, 0);
- 			if (tmp <= 0)
- 				goto err;
-@@ -1431,7 +1431,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
- 	struct snd_pcm_runtime *runtime = substream->runtime;
- 	snd_pcm_sframes_t frames, frames1;
- #ifdef CONFIG_SND_PCM_OSS_PLUGINS
--	char __user *final_dst = (char __force __user *)buf;
-+	char __user *final_dst = (char __force_user *)buf;
- 	if (runtime->oss.plugin_first) {
- 		struct snd_pcm_plugin_channel *channels;
- 		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
-@@ -1493,7 +1493,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
- 			xfer += tmp;
- 			runtime->oss.buffer_used -= tmp;
- 		} else {
--			tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
-+			tmp = snd_pcm_oss_read2(substream, (char __force_kernel *)buf,
- 						runtime->oss.period_bytes, 0);
- 			if (tmp <= 0)
- 				goto err;
-@@ -1662,7 +1662,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
- 								   size1);
- 					size1 /= runtime->channels; /* frames */
- 					fs = snd_enter_user();
--					snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
-+					snd_pcm_lib_write(substream, (void __force_user *)runtime->oss.buffer, size1);
- 					snd_leave_user(fs);
- 				}
- 			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
-diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
-index 1f64ab0..26a7233 100644
---- a/sound/core/pcm_compat.c
-+++ b/sound/core/pcm_compat.c
-@@ -31,7 +31,7 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
- 	int err;
- 
- 	fs = snd_enter_user();
--	err = snd_pcm_delay(substream, &delay);
-+	err = snd_pcm_delay(substream, (snd_pcm_sframes_t __force_user *)&delay);
- 	snd_leave_user(fs);
- 	if (err < 0)
- 		return err;
-diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
-index 3a9b66c..2b38b21 100644
---- a/sound/core/pcm_lib.c
-+++ b/sound/core/pcm_lib.c
-@@ -1867,8 +1867,9 @@ EXPORT_SYMBOL(snd_pcm_lib_ioctl);
-  * Even if more than one periods have elapsed since the last call, you
-  * have to call this only once.
-  */
--void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
-+void snd_pcm_period_elapsed(void *_substream)
- {
-+	struct snd_pcm_substream *substream = _substream;
- 	struct snd_pcm_runtime *runtime;
- 	unsigned long flags;
- 
-diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
-index 9106d8e..e7e2e3c 100644
---- a/sound/core/pcm_native.c
-+++ b/sound/core/pcm_native.c
-@@ -3014,11 +3014,11 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
- 	switch (substream->stream) {
- 	case SNDRV_PCM_STREAM_PLAYBACK:
- 		result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
--						 (void __user *)arg);
-+						 (void __force_user *)arg);
- 		break;
- 	case SNDRV_PCM_STREAM_CAPTURE:
- 		result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
--						(void __user *)arg);
-+						(void __force_user *)arg);
- 		break;
- 	default:
- 		result = -EINVAL;
-diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
-index 795437b..3650746 100644
---- a/sound/core/rawmidi.c
-+++ b/sound/core/rawmidi.c
-@@ -871,9 +871,10 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
-  *
-  * Return: The size of read data, or a negative error code on failure.
-  */
--int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
--			const unsigned char *buffer, int count)
-+int snd_rawmidi_receive(void *_substream, const void *_buffer, int count)
- {
-+	struct snd_rawmidi_substream *substream = _substream;
-+	const unsigned char *buffer = _buffer;
- 	unsigned long flags;
- 	int result = 0, count1;
- 	struct snd_rawmidi_runtime *runtime = substream->runtime;
-diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
-index b16dbef04..8eb05a4 100644
---- a/sound/core/seq/oss/seq_oss_synth.c
-+++ b/sound/core/seq/oss/seq_oss_synth.c
-@@ -653,8 +653,8 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
- 			    rec->synth_type, rec->synth_subtype,
- 			    rec->nr_voices);
- 		snd_iprintf(buf, "  capabilities : ioctl %s / load_patch %s\n",
--			    enabled_str((long)rec->oper.ioctl),
--			    enabled_str((long)rec->oper.load_patch));
-+			    enabled_str(!!rec->oper.ioctl),
-+			    enabled_str(!!rec->oper.load_patch));
- 		snd_use_lock_free(&rec->use_lock);
- 	}
- }
-diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
-index 58e79e0..19751d1 100644
---- a/sound/core/seq/seq_clientmgr.c
-+++ b/sound/core/seq/seq_clientmgr.c
-@@ -416,7 +416,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
- 	if (!client->accept_input || (fifo = client->data.user.fifo) == NULL)
- 		return -ENXIO;
- 
--	if (atomic_read(&fifo->overflow) > 0) {
-+	if (atomic_read_unchecked(&fifo->overflow) > 0) {
- 		/* buffer overflow is detected */
- 		snd_seq_fifo_clear(fifo);
- 		/* return error code */
-@@ -446,7 +446,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
- 			count -= sizeof(struct snd_seq_event);
- 			buf += sizeof(struct snd_seq_event);
- 			err = snd_seq_expand_var_event(&cell->event, count,
--						       (char __force *)buf, 0,
-+						       (char __force_kernel *)buf, 0,
- 						       sizeof(struct snd_seq_event));
- 			if (err < 0)
- 				break;
-@@ -1062,13 +1062,13 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
- 			}
- 			/* set user space pointer */
- 			event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;
--			event.data.ext.ptr = (char __force *)buf
-+			event.data.ext.ptr = (char __force_kernel *)buf
- 						+ sizeof(struct snd_seq_event);
- 			len += extlen; /* increment data length */
- 		} else {
- #ifdef CONFIG_COMPAT
- 			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
--				void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]);
-+				void *ptr = (void __force_kernel *)compat_ptr(event.data.raw32.d[1]);
- 				event.data.ext.ptr = ptr;
- 			}
- #endif
-@@ -2423,7 +2423,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
- 	if (client == NULL)
- 		return -ENXIO;
- 	fs = snd_enter_user();
--	result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg);
-+	result = snd_seq_do_ioctl(client, cmd, (void __force_user *)arg);
- 	snd_leave_user(fs);
- 	return result;
- }
-diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
-index 6517590..9905cee 100644
---- a/sound/core/seq/seq_compat.c
-+++ b/sound/core/seq/seq_compat.c
-@@ -60,7 +60,7 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
- 	data->kernel = NULL;
- 
- 	fs = snd_enter_user();
--	err = snd_seq_do_ioctl(client, cmd, data);
-+	err = snd_seq_do_ioctl(client, cmd, (void __force_user *)data);
- 	snd_leave_user(fs);
- 	if (err < 0)
- 		goto error;
-diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
-index 1d5acbe..5f55223 100644
---- a/sound/core/seq/seq_fifo.c
-+++ b/sound/core/seq/seq_fifo.c
-@@ -50,7 +50,7 @@ struct snd_seq_fifo *snd_seq_fifo_new(int poolsize)
- 	spin_lock_init(&f->lock);
- 	snd_use_lock_init(&f->use_lock);
- 	init_waitqueue_head(&f->input_sleep);
--	atomic_set(&f->overflow, 0);
-+	atomic_set_unchecked(&f->overflow, 0);
- 
- 	f->head = NULL;
- 	f->tail = NULL;
-@@ -96,7 +96,7 @@ void snd_seq_fifo_clear(struct snd_seq_fifo *f)
- 	unsigned long flags;
- 
- 	/* clear overflow flag */
--	atomic_set(&f->overflow, 0);
-+	atomic_set_unchecked(&f->overflow, 0);
- 
- 	snd_use_lock_sync(&f->use_lock);
- 	spin_lock_irqsave(&f->lock, flags);
-@@ -123,7 +123,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
- 	err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */
- 	if (err < 0) {
- 		if ((err == -ENOMEM) || (err == -EAGAIN))
--			atomic_inc(&f->overflow);
-+			atomic_inc_unchecked(&f->overflow);
- 		snd_use_lock_free(&f->use_lock);
- 		return err;
- 	}
-diff --git a/sound/core/seq/seq_fifo.h b/sound/core/seq/seq_fifo.h
-index 062c446..a4b6f4c 100644
---- a/sound/core/seq/seq_fifo.h
-+++ b/sound/core/seq/seq_fifo.h
-@@ -35,7 +35,7 @@ struct snd_seq_fifo {
- 	spinlock_t lock;
- 	snd_use_lock_t use_lock;
- 	wait_queue_head_t input_sleep;
--	atomic_t overflow;
-+	atomic_unchecked_t overflow;
- 
- };
- 
-diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
-index c850345..ec0a853 100644
---- a/sound/core/seq/seq_memory.c
-+++ b/sound/core/seq/seq_memory.c
-@@ -87,7 +87,7 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
- 
- 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
- 		char buf[32];
--		char __user *curptr = (char __force __user *)event->data.ext.ptr;
-+		char __user *curptr = (char __force_user *)event->data.ext.ptr;
- 		while (len > 0) {
- 			int size = sizeof(buf);
- 			if (len < size)
-@@ -126,15 +126,19 @@ EXPORT_SYMBOL(snd_seq_dump_var_event);
-  * expand the variable length event to linear buffer space.
-  */
- 
--static int seq_copy_in_kernel(char **bufptr, const void *src, int size)
-+static int seq_copy_in_kernel(void *_bufptr, const void *src, int size)
- {
-+	char **bufptr = (char **)_bufptr;
-+
- 	memcpy(*bufptr, src, size);
- 	*bufptr += size;
- 	return 0;
- }
- 
--static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
-+static int seq_copy_in_user(void *_bufptr, const void *src, int size)
- {
-+	char __user **bufptr = (char __user **)_bufptr;
-+
- 	if (copy_to_user(*bufptr, src, size))
- 		return -EFAULT;
- 	*bufptr += size;
-@@ -158,13 +162,13 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
- 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
- 		if (! in_kernel)
- 			return -EINVAL;
--		if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len))
-+		if (copy_from_user(buf, (void __force_user *)event->data.ext.ptr, len))
- 			return -EFAULT;
- 		return newlen;
- 	}
- 	err = snd_seq_dump_var_event(event,
--				     in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel :
--				     (snd_seq_dump_func_t)seq_copy_in_user,
-+				     in_kernel ? seq_copy_in_kernel :
-+				     seq_copy_in_user,
- 				     &buf);
- 	return err < 0 ? err : newlen;
- }
-@@ -344,7 +348,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
- 				tmp->event = src->event;
- 				src = src->next;
- 			} else if (is_usrptr) {
--				if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) {
-+				if (copy_from_user(&tmp->event, (char __force_user *)buf, size)) {
- 					err = -EFAULT;
- 					goto __error;
- 				}
-diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
-index 5dd0ee2..0208e35 100644
---- a/sound/core/seq/seq_midi.c
-+++ b/sound/core/seq/seq_midi.c
-@@ -111,8 +111,9 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
- 	}
- }
- 
--static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, int count)
-+static int dump_midi(void *_substream, const void *buf, int count)
- {
-+	struct snd_rawmidi_substream *substream = _substream;
- 	struct snd_rawmidi_runtime *runtime;
- 	int tmp;
- 
-@@ -148,7 +149,7 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,
- 			pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
- 			return 0;
- 		}
--		snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
-+		snd_seq_dump_var_event(ev, dump_midi, substream);
- 		snd_midi_event_reset_decode(msynth->parser);
- 	} else {
- 		if (msynth->parser == NULL)
-diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
-index c82ed3e..e11d039 100644
---- a/sound/core/seq/seq_virmidi.c
-+++ b/sound/core/seq/seq_virmidi.c
-@@ -90,7 +90,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
- 		if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
- 			if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
- 				continue;
--			snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream);
-+			snd_seq_dump_var_event(ev, snd_rawmidi_receive, vmidi->substream);
- 		} else {
- 			len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev);
- 			if (len > 0)
-diff --git a/sound/core/sound.c b/sound/core/sound.c
-index 175f9e4..3518d31 100644
---- a/sound/core/sound.c
-+++ b/sound/core/sound.c
-@@ -86,7 +86,7 @@ static void snd_request_other(int minor)
- 	case SNDRV_MINOR_TIMER:		str = "snd-timer";	break;
- 	default:			return;
- 	}
--	request_module(str);
-+	request_module("%s", str);
- }
- 
- #endif	/* modular kernel */
-diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
-index 2a008a9..a1efb3f 100644
---- a/sound/drivers/mts64.c
-+++ b/sound/drivers/mts64.c
-@@ -29,6 +29,7 @@
- #include <sound/initval.h>
- #include <sound/rawmidi.h>
- #include <sound/control.h>
-+#include <asm/local.h>
- 
- #define CARD_NAME "Miditerminal 4140"
- #define DRIVER_NAME "MTS64"
-@@ -67,7 +68,7 @@ struct mts64 {
- 	struct pardevice *pardev;
- 	int pardev_claimed;
- 
--	int open_count;
-+	local_t open_count;
- 	int current_midi_output_port;
- 	int current_midi_input_port;
- 	u8 mode[MTS64_NUM_INPUT_PORTS];
-@@ -687,7 +688,7 @@ static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream)
- {
- 	struct mts64 *mts = substream->rmidi->private_data;
- 
--	if (mts->open_count == 0) {
-+	if (local_read(&mts->open_count) == 0) {
- 		/* We don't need a spinlock here, because this is just called 
- 		   if the device has not been opened before. 
- 		   So there aren't any IRQs from the device */
-@@ -695,7 +696,7 @@ static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream)
- 
- 		msleep(50);
- 	}
--	++(mts->open_count);
-+	local_inc(&mts->open_count);
- 
- 	return 0;
- }
-@@ -705,8 +706,7 @@ static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream)
- 	struct mts64 *mts = substream->rmidi->private_data;
- 	unsigned long flags;
- 
--	--(mts->open_count);
--	if (mts->open_count == 0) {
-+	if (local_dec_return(&mts->open_count) == 0) {
- 		/* We need the spinlock_irqsave here because we can still
- 		   have IRQs at this point */
- 		spin_lock_irqsave(&mts->lock, flags);
-@@ -715,8 +715,8 @@ static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream)
- 
- 		msleep(500);
- 
--	} else if (mts->open_count < 0)
--		mts->open_count = 0;
-+	} else if (local_read(&mts->open_count) < 0)
-+		local_set(&mts->open_count, 0);
- 
- 	return 0;
- }
-diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
-index 89c7aa0..6d75e49 100644
---- a/sound/drivers/opl4/opl4_lib.c
-+++ b/sound/drivers/opl4/opl4_lib.c
-@@ -29,7 +29,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
- MODULE_DESCRIPTION("OPL4 driver");
- MODULE_LICENSE("GPL");
- 
--static void inline snd_opl4_wait(struct snd_opl4 *opl4)
-+static inline void snd_opl4_wait(struct snd_opl4 *opl4)
- {
- 	int timeout = 10;
- 	while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
-diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
-index 464385a..46ab3f6 100644
---- a/sound/drivers/portman2x4.c
-+++ b/sound/drivers/portman2x4.c
-@@ -48,6 +48,7 @@
- #include <sound/initval.h>
- #include <sound/rawmidi.h>
- #include <sound/control.h>
-+#include <asm/local.h>
- 
- #define CARD_NAME "Portman 2x4"
- #define DRIVER_NAME "portman"
-@@ -85,7 +86,7 @@ struct portman {
- 	struct pardevice *pardev;
- 	int pardev_claimed;
- 
--	int open_count;
-+	local_t open_count;
- 	int mode[PORTMAN_NUM_INPUT_PORTS];
- 	struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS];
- };
-diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c
-index bebddc6..f5976be 100644
---- a/sound/firewire/amdtp-am824.c
-+++ b/sound/firewire/amdtp-am824.c
-@@ -314,7 +314,7 @@ void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port,
- 	struct amdtp_am824 *p = s->protocol;
- 
- 	if (port < p->midi_ports)
--		ACCESS_ONCE(p->midi[port]) = midi;
-+		ACCESS_ONCE_RW(p->midi[port]) = midi;
- }
- EXPORT_SYMBOL_GPL(amdtp_am824_midi_trigger);
- 
-diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
-index ed29026..933d2ae 100644
---- a/sound/firewire/amdtp-stream.c
-+++ b/sound/firewire/amdtp-stream.c
-@@ -344,7 +344,7 @@ static void update_pcm_pointers(struct amdtp_stream *s,
- 	ptr = s->pcm_buffer_pointer + frames;
- 	if (ptr >= pcm->runtime->buffer_size)
- 		ptr -= pcm->runtime->buffer_size;
--	ACCESS_ONCE(s->pcm_buffer_pointer) = ptr;
-+	ACCESS_ONCE_RW(s->pcm_buffer_pointer) = ptr;
- 
- 	s->pcm_period_pointer += frames;
- 	if (s->pcm_period_pointer >= pcm->runtime->period_size) {
-@@ -811,7 +811,7 @@ EXPORT_SYMBOL(amdtp_stream_pcm_pointer);
- void amdtp_stream_update(struct amdtp_stream *s)
- {
- 	/* Precomputing. */
--	ACCESS_ONCE(s->source_node_id_field) =
-+	ACCESS_ONCE_RW(s->source_node_id_field) =
- 		(fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) &
- 								CIP_SID_MASK;
- }
-diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
-index 8775704..8fea566 100644
---- a/sound/firewire/amdtp-stream.h
-+++ b/sound/firewire/amdtp-stream.h
-@@ -215,7 +215,7 @@ static inline bool amdtp_stream_pcm_running(struct amdtp_stream *s)
- static inline void amdtp_stream_pcm_trigger(struct amdtp_stream *s,
- 					    struct snd_pcm_substream *pcm)
- {
--	ACCESS_ONCE(s->pcm) = pcm;
-+	ACCESS_ONCE_RW(s->pcm) = pcm;
- }
- 
- static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
-diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c
-index 0ac92ab..a2081aa 100644
---- a/sound/firewire/digi00x/amdtp-dot.c
-+++ b/sound/firewire/digi00x/amdtp-dot.c
-@@ -365,7 +365,7 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
- 	struct amdtp_dot *p = s->protocol;
- 
- 	if (port < p->midi_ports)
--		ACCESS_ONCE(p->midi[port]) = midi;
-+		ACCESS_ONCE_RW(p->midi[port]) = midi;
- }
- 
- static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
-diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
-index 48d6dca..a0266c23 100644
---- a/sound/firewire/isight.c
-+++ b/sound/firewire/isight.c
-@@ -96,7 +96,7 @@ static void isight_update_pointers(struct isight *isight, unsigned int count)
- 	ptr += count;
- 	if (ptr >= runtime->buffer_size)
- 		ptr -= runtime->buffer_size;
--	ACCESS_ONCE(isight->buffer_pointer) = ptr;
-+	ACCESS_ONCE_RW(isight->buffer_pointer) = ptr;
- 
- 	isight->period_counter += count;
- 	if (isight->period_counter >= runtime->period_size) {
-@@ -293,7 +293,7 @@ static int isight_hw_params(struct snd_pcm_substream *substream,
- 	if (err < 0)
- 		return err;
- 
--	ACCESS_ONCE(isight->pcm_active) = true;
-+	ACCESS_ONCE_RW(isight->pcm_active) = true;
- 
- 	return 0;
- }
-@@ -331,7 +331,7 @@ static int isight_hw_free(struct snd_pcm_substream *substream)
- {
- 	struct isight *isight = substream->private_data;
- 
--	ACCESS_ONCE(isight->pcm_active) = false;
-+	ACCESS_ONCE_RW(isight->pcm_active) = false;
- 
- 	mutex_lock(&isight->mutex);
- 	isight_stop_streaming(isight);
-@@ -424,10 +424,10 @@ static int isight_trigger(struct snd_pcm_substream *substream, int cmd)
- 
- 	switch (cmd) {
- 	case SNDRV_PCM_TRIGGER_START:
--		ACCESS_ONCE(isight->pcm_running) = true;
-+		ACCESS_ONCE_RW(isight->pcm_running) = true;
- 		break;
- 	case SNDRV_PCM_TRIGGER_STOP:
--		ACCESS_ONCE(isight->pcm_running) = false;
-+		ACCESS_ONCE_RW(isight->pcm_running) = false;
- 		break;
- 	default:
- 		return -EINVAL;
-diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c
-index bb53eb3..670cd89 100644
---- a/sound/firewire/oxfw/oxfw-scs1x.c
-+++ b/sound/firewire/oxfw/oxfw-scs1x.c
-@@ -278,9 +278,9 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
- 
- 	if (up) {
- 		scs->input_escape_count = 0;
--		ACCESS_ONCE(scs->input) = stream;
-+		ACCESS_ONCE_RW(scs->input) = stream;
- 	} else {
--		ACCESS_ONCE(scs->input) = NULL;
-+		ACCESS_ONCE_RW(scs->input) = NULL;
- 	}
- }
- 
-@@ -310,10 +310,10 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
- 		scs->output_escaped = false;
- 		scs->output_idle = false;
- 
--		ACCESS_ONCE(scs->output) = stream;
-+		ACCESS_ONCE_RW(scs->output) = stream;
- 		tasklet_schedule(&scs->tasklet);
- 	} else {
--		ACCESS_ONCE(scs->output) = NULL;
-+		ACCESS_ONCE_RW(scs->output) = NULL;
- 	}
- }
- static void midi_playback_drain(struct snd_rawmidi_substream *stream)
-diff --git a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c
-index dc91072..d85a10a 100644
---- a/sound/oss/sb_audio.c
-+++ b/sound/oss/sb_audio.c
-@@ -900,7 +900,7 @@ sb16_copy_from_user(int dev,
- 		buf16 = (signed short *)(localbuf + localoffs);
- 		while (c)
- 		{
--			locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
-+			locallen = ((unsigned)c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
- 			if (copy_from_user(lbuf8,
- 					   userbuf+useroffs + p,
- 					   locallen))
-diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
-index 213a416..aeab5c9 100644
---- a/sound/oss/swarm_cs4297a.c
-+++ b/sound/oss/swarm_cs4297a.c
-@@ -2623,7 +2623,6 @@ static int __init cs4297a_init(void)
- {
- 	struct cs4297a_state *s;
- 	u32 pwr, id;
--	mm_segment_t fs;
- 	int rval;
- 	u64 cfg;
- 	int mdio_val;
-@@ -2709,22 +2708,23 @@ static int __init cs4297a_init(void)
-         if (!rval) {
- 		char *sb1250_duart_present;
- 
-+#if 0
-+                mm_segment_t fs;
-                 fs = get_fs();
-                 set_fs(KERNEL_DS);
--#if 0
-                 val = SOUND_MASK_LINE;
-                 mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
-                 for (i = 0; i < ARRAY_SIZE(initvol); i++) {
-                         val = initvol[i].vol;
-                         mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val);
-                 }
-+                set_fs(fs);
- //                cs4297a_write_ac97(s, 0x18, 0x0808);
- #else
-                 //                cs4297a_write_ac97(s, 0x5e, 0x180);
-                 cs4297a_write_ac97(s, 0x02, 0x0808);
-                 cs4297a_write_ac97(s, 0x18, 0x0808);
- #endif
--                set_fs(fs);
- 
-                 list_add(&s->list, &cs4297a_devs);
- 
-diff --git a/sound/pci/als300.c b/sound/pci/als300.c
-index add3176..c9394d9 100644
---- a/sound/pci/als300.c
-+++ b/sound/pci/als300.c
-@@ -647,7 +647,7 @@ static int snd_als300_create(struct snd_card *card,
- 			     struct snd_als300 **rchip)
- {
- 	struct snd_als300 *chip;
--	void *irq_handler;
-+	irq_handler_t irq_handler;
- 	int err;
- 
- 	static struct snd_device_ops ops = {
-diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
-index 1677143..85aca1d 100644
---- a/sound/pci/aw2/aw2-alsa.c
-+++ b/sound/pci/aw2/aw2-alsa.c
-@@ -458,7 +458,6 @@ static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
- 
- 	/* Define Interrupt callback */
- 	snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
--						    (snd_aw2_saa7146_it_cb)
- 						    snd_pcm_period_elapsed,
- 						    (void *)substream);
- 
-@@ -487,7 +486,6 @@ static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
- 
- 	/* Define Interrupt callback */
- 	snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
--						   (snd_aw2_saa7146_it_cb)
- 						   snd_pcm_period_elapsed,
- 						   (void *)substream);
- 
-diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
-index 1d78904..d9c1056 100644
---- a/sound/pci/aw2/aw2-saa7146.c
-+++ b/sound/pci/aw2/aw2-saa7146.c
-@@ -262,7 +262,7 @@ void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
- {
- 	if (stream_number < NB_STREAM_PLAYBACK) {
- 		arr_substream_it_playback_cb[stream_number].p_it_callback =
--		    (snd_aw2_saa7146_it_cb) p_it_callback;
-+		    p_it_callback;
- 		arr_substream_it_playback_cb[stream_number].p_callback_param =
- 		    (void *)p_callback_param;
- 	}
-@@ -275,7 +275,7 @@ void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
- {
- 	if (stream_number < NB_STREAM_CAPTURE) {
- 		arr_substream_it_capture_cb[stream_number].p_it_callback =
--		    (snd_aw2_saa7146_it_cb) p_it_callback;
-+		    p_it_callback;
- 		arr_substream_it_capture_cb[stream_number].p_callback_param =
- 		    (void *)p_callback_param;
- 	}
-diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c
-index 5fcbb06..f4b85df 100644
---- a/sound/pci/ctxfi/ctamixer.c
-+++ b/sound/pci/ctxfi/ctamixer.c
-@@ -297,8 +297,9 @@ static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer)
- 	return 0;
- }
- 
--int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr)
-+int amixer_mgr_create(struct hw *hw, void **_ramixer_mgr)
- {
-+	struct amixer_mgr **ramixer_mgr = (struct amixer_mgr **)_ramixer_mgr;
- 	int err;
- 	struct amixer_mgr *amixer_mgr;
- 
-@@ -326,8 +327,10 @@ error:
- 	return err;
- }
- 
--int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)
-+int amixer_mgr_destroy(void *_amixer_mgr)
- {
-+	struct amixer_mgr *amixer_mgr = _amixer_mgr;
-+
- 	rsc_mgr_uninit(&amixer_mgr->mgr);
- 	kfree(amixer_mgr);
- 	return 0;
-@@ -452,8 +455,9 @@ static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum)
- 	return 0;
- }
- 
--int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr)
-+int sum_mgr_create(struct hw *hw, void **_rsum_mgr)
- {
-+	struct sum_mgr **rsum_mgr = (struct sum_mgr **)_rsum_mgr;
- 	int err;
- 	struct sum_mgr *sum_mgr;
- 
-@@ -481,8 +485,10 @@ error:
- 	return err;
- }
- 
--int sum_mgr_destroy(struct sum_mgr *sum_mgr)
-+int sum_mgr_destroy(void *_sum_mgr)
- {
-+	struct sum_mgr *sum_mgr = _sum_mgr;
-+
- 	rsc_mgr_uninit(&sum_mgr->mgr);
- 	kfree(sum_mgr);
- 	return 0;
-diff --git a/sound/pci/ctxfi/ctamixer.h b/sound/pci/ctxfi/ctamixer.h
-index 2de18aa..2fbd01b 100644
---- a/sound/pci/ctxfi/ctamixer.h
-+++ b/sound/pci/ctxfi/ctamixer.h
-@@ -47,8 +47,8 @@ struct sum_mgr {
- };
- 
- /* Constructor and destructor of daio resource manager */
--int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr);
--int sum_mgr_destroy(struct sum_mgr *sum_mgr);
-+int sum_mgr_create(struct hw *hw, void **rsum_mgr);
-+int sum_mgr_destroy(void *sum_mgr);
- 
- /* Define the descriptor of a amixer resource */
- struct amixer_rsc_ops;
-@@ -93,7 +93,7 @@ struct amixer_mgr {
- };
- 
- /* Constructor and destructor of amixer resource manager */
--int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr);
--int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr);
-+int amixer_mgr_create(struct hw *hw, void **ramixer_mgr);
-+int amixer_mgr_destroy(void *amixer_mgr);
- 
- #endif /* CTAMIXER_H */
-diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
-index 977a598..a787004 100644
---- a/sound/pci/ctxfi/ctatc.c
-+++ b/sound/pci/ctxfi/ctatc.c
-@@ -113,16 +113,16 @@ static struct {
- 	int (*create)(struct hw *hw, void **rmgr);
- 	int (*destroy)(void *mgr);
- } rsc_mgr_funcs[NUM_RSCTYP] = {
--	[SRC] 		= { .create 	= (create_t)src_mgr_create,
--			    .destroy 	= (destroy_t)src_mgr_destroy	},
--	[SRCIMP] 	= { .create 	= (create_t)srcimp_mgr_create,
--			    .destroy 	= (destroy_t)srcimp_mgr_destroy	},
--	[AMIXER]	= { .create	= (create_t)amixer_mgr_create,
--			    .destroy	= (destroy_t)amixer_mgr_destroy	},
--	[SUM]		= { .create	= (create_t)sum_mgr_create,
--			    .destroy	= (destroy_t)sum_mgr_destroy	},
--	[DAIO]		= { .create	= (create_t)daio_mgr_create,
--			    .destroy	= (destroy_t)daio_mgr_destroy	}
-+	[SRC] 		= { .create 	= src_mgr_create,
-+			    .destroy 	= src_mgr_destroy	},
-+	[SRCIMP] 	= { .create 	= srcimp_mgr_create,
-+			    .destroy 	= srcimp_mgr_destroy	},
-+	[AMIXER]	= { .create	= amixer_mgr_create,
-+			    .destroy	= amixer_mgr_destroy	},
-+	[SUM]		= { .create	= sum_mgr_create,
-+			    .destroy	= sum_mgr_destroy	},
-+	[DAIO]		= { .create	= daio_mgr_create,
-+			    .destroy	= daio_mgr_destroy	}
- };
- 
- static int
-diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
-index 7f089cb..6bea28e 100644
---- a/sound/pci/ctxfi/ctdaio.c
-+++ b/sound/pci/ctxfi/ctdaio.c
-@@ -687,8 +687,9 @@ static int daio_mgr_commit_write(struct daio_mgr *mgr)
- 	return 0;
- }
- 
--int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr)
-+int daio_mgr_create(struct hw *hw, void **_rdaio_mgr)
- {
-+	struct daio_mgr **rdaio_mgr = (struct daio_mgr **)_rdaio_mgr;
- 	int err, i;
- 	struct daio_mgr *daio_mgr;
- 	struct imapper *entry;
-@@ -741,8 +742,9 @@ error1:
- 	return err;
- }
- 
--int daio_mgr_destroy(struct daio_mgr *daio_mgr)
-+int daio_mgr_destroy(void *_daio_mgr)
- {
-+	struct daio_mgr *daio_mgr = _daio_mgr;
- 	unsigned long flags;
- 
- 	/* free daio input mapper list */
-diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h
-index a30be73..91b8dbd 100644
---- a/sound/pci/ctxfi/ctdaio.h
-+++ b/sound/pci/ctxfi/ctdaio.h
-@@ -119,7 +119,7 @@ struct daio_mgr {
- };
- 
- /* Constructor and destructor of daio resource manager */
--int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr);
--int daio_mgr_destroy(struct daio_mgr *daio_mgr);
-+int daio_mgr_create(struct hw *hw, void **rdaio_mgr);
-+int daio_mgr_destroy(void *daio_mgr);
- 
- #endif /* CTDAIO_H */
-diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
-index a5a72df..f86edb8 100644
---- a/sound/pci/ctxfi/ctsrc.c
-+++ b/sound/pci/ctxfi/ctsrc.c
-@@ -544,8 +544,9 @@ static int src_mgr_commit_write(struct src_mgr *mgr)
- 	return 0;
- }
- 
--int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr)
-+int src_mgr_create(struct hw *hw, void **_rsrc_mgr)
- {
-+	struct src_mgr **rsrc_mgr = (struct src_mgr **)_rsrc_mgr;
- 	int err, i;
- 	struct src_mgr *src_mgr;
- 
-@@ -584,8 +585,10 @@ error1:
- 	return err;
- }
- 
--int src_mgr_destroy(struct src_mgr *src_mgr)
-+int src_mgr_destroy(void *_src_mgr)
- {
-+	struct src_mgr *src_mgr = _src_mgr;
-+
- 	rsc_mgr_uninit(&src_mgr->mgr);
- 	kfree(src_mgr);
- 
-@@ -828,8 +831,9 @@ static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
- 	return err;
- }
- 
--int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr)
-+int srcimp_mgr_create(struct hw *hw, void **_rsrcimp_mgr)
- {
-+	struct srcimp_mgr **rsrcimp_mgr = (struct srcimp_mgr **)_rsrcimp_mgr;
- 	int err;
- 	struct srcimp_mgr *srcimp_mgr;
- 	struct imapper *entry;
-@@ -873,8 +877,9 @@ error1:
- 	return err;
- }
- 
--int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr)
-+int srcimp_mgr_destroy(void *_srcimp_mgr)
- {
-+	struct srcimp_mgr *srcimp_mgr = _srcimp_mgr;
- 	unsigned long flags;
- 
- 	/* free src input mapper list */
-diff --git a/sound/pci/ctxfi/ctsrc.h b/sound/pci/ctxfi/ctsrc.h
-index 92944a0..fc78ed4 100644
---- a/sound/pci/ctxfi/ctsrc.h
-+++ b/sound/pci/ctxfi/ctsrc.h
-@@ -143,10 +143,10 @@ struct srcimp_mgr {
- };
- 
- /* Constructor and destructor of SRC resource manager */
--int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr);
--int src_mgr_destroy(struct src_mgr *src_mgr);
-+int src_mgr_create(struct hw *hw, void **rsrc_mgr);
-+int src_mgr_destroy(void *src_mgr);
- /* Constructor and destructor of SRCIMP resource manager */
--int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrc_mgr);
--int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr);
-+int srcimp_mgr_create(struct hw *hw, void **rsrc_mgr);
-+int srcimp_mgr_destroy(void *srcimp_mgr);
- 
- #endif /* CTSRC_H */
-diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
-index 8374188..f073778 100644
---- a/sound/pci/hda/hda_codec.c
-+++ b/sound/pci/hda/hda_codec.c
-@@ -1743,7 +1743,7 @@ static int get_kctl_0dB_offset(struct hda_codec *codec,
- 		/* FIXME: set_fs() hack for obtaining user-space TLV data */
- 		mm_segment_t fs = get_fs();
- 		set_fs(get_ds());
--		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
-+		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), (unsigned int __force_user *)_tlv))
- 			tlv = _tlv;
- 		set_fs(fs);
- 	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
-diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h
-index 149d4cb..7784769 100644
---- a/sound/pci/ymfpci/ymfpci.h
-+++ b/sound/pci/ymfpci/ymfpci.h
-@@ -358,7 +358,7 @@ struct snd_ymfpci {
- 	spinlock_t reg_lock;
- 	spinlock_t voice_lock;
- 	wait_queue_head_t interrupt_sleep;
--	atomic_t interrupt_sleep_count;
-+	atomic_unchecked_t interrupt_sleep_count;
- 	struct snd_info_entry *proc_entry;
- 	const struct firmware *dsp_microcode;
- 	const struct firmware *controller_microcode;
-diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
-index 4c26076..a13f370 100644
---- a/sound/pci/ymfpci/ymfpci_main.c
-+++ b/sound/pci/ymfpci/ymfpci_main.c
-@@ -204,8 +204,8 @@ static void snd_ymfpci_hw_stop(struct snd_ymfpci *chip)
- 		if ((snd_ymfpci_readl(chip, YDSXGR_STATUS) & 2) == 0)
- 			break;
- 	}
--	if (atomic_read(&chip->interrupt_sleep_count)) {
--		atomic_set(&chip->interrupt_sleep_count, 0);
-+	if (atomic_read_unchecked(&chip->interrupt_sleep_count)) {
-+		atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
- 		wake_up(&chip->interrupt_sleep);
- 	}
-       __end:
-@@ -789,7 +789,7 @@ static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip)
- 		 	continue;
- 		init_waitqueue_entry(&wait, current);
- 		add_wait_queue(&chip->interrupt_sleep, &wait);
--		atomic_inc(&chip->interrupt_sleep_count);
-+		atomic_inc_unchecked(&chip->interrupt_sleep_count);
- 		schedule_timeout_uninterruptible(msecs_to_jiffies(50));
- 		remove_wait_queue(&chip->interrupt_sleep, &wait);
- 	}
-@@ -827,8 +827,8 @@ static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id)
- 		snd_ymfpci_writel(chip, YDSXGR_MODE, mode);
- 		spin_unlock(&chip->reg_lock);
- 
--		if (atomic_read(&chip->interrupt_sleep_count)) {
--			atomic_set(&chip->interrupt_sleep_count, 0);
-+		if (atomic_read_unchecked(&chip->interrupt_sleep_count)) {
-+			atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
- 			wake_up(&chip->interrupt_sleep);
- 		}
- 	}
-@@ -2384,7 +2384,7 @@ int snd_ymfpci_create(struct snd_card *card,
- 	spin_lock_init(&chip->reg_lock);
- 	spin_lock_init(&chip->voice_lock);
- 	init_waitqueue_head(&chip->interrupt_sleep);
--	atomic_set(&chip->interrupt_sleep_count, 0);
-+	atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
- 	chip->card = card;
- 	chip->pci = pci;
- 	chip->irq = -1;
-diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
-index d6f4abb..5d59f0c 100644
---- a/sound/soc/codecs/cx20442.c
-+++ b/sound/soc/codecs/cx20442.c
-@@ -263,6 +263,12 @@ static int v253_hangup(struct tty_struct *tty)
- 	return 0;
- }
- 
-+static int v253_hw_write(void *client, const char *buf, int count)
-+{
-+	struct tty_struct *tty = client;
-+	return tty->ops->write(client, buf, count);
-+}
-+
- /* Line discipline .receive_buf() */
- static void v253_receive(struct tty_struct *tty,
- 				const unsigned char *cp, char *fp, int count)
-@@ -280,7 +286,7 @@ static void v253_receive(struct tty_struct *tty,
- 
- 		/* Set up codec driver access to modem controls */
- 		cx20442->control_data = tty;
--		codec->hw_write = (hw_write_t)tty->ops->write;
-+		codec->hw_write = v253_hw_write;
- 		codec->component.card->pop_time = 1;
- 	}
- }
-diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c
-index 160d61a..10bfd63 100644
---- a/sound/soc/codecs/sti-sas.c
-+++ b/sound/soc/codecs/sti-sas.c
-@@ -591,11 +591,13 @@ static int sti_sas_driver_probe(struct platform_device *pdev)
- 	sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops;
- 
- 	/* Set dapms*/
--	sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
--	sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
-+	pax_open_kernel();
-+	*(const void **)&sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
-+	*(int *)&sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
- 
--	sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes;
--	sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
-+	*(const void **)&sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes;
-+	*(int *)&sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
-+	pax_close_kernel();
- 
- 	/* Store context */
- 	dev_set_drvdata(&pdev->dev, drvdata);
-diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
-index f7a6ce7..82310c8 100644
---- a/sound/soc/codecs/tlv320dac33.c
-+++ b/sound/soc/codecs/tlv320dac33.c
-@@ -1375,13 +1375,18 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
- 	return 0;
- }
- 
-+static int dac33_hw_write(void *client, const char *buf, int count)
-+{
-+	return i2c_master_send(client, buf, count);
-+}
-+
- static int dac33_soc_probe(struct snd_soc_codec *codec)
- {
- 	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
- 	int ret = 0;
- 
- 	codec->control_data = dac33->control_data;
--	codec->hw_write = (hw_write_t) i2c_master_send;
-+	codec->hw_write = dac33_hw_write;
- 	dac33->codec = codec;
- 
- 	/* Read the tlv320dac33 ID registers */
-diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
-index 35f0469..7c25cd5 100644
---- a/sound/soc/codecs/uda1380.c
-+++ b/sound/soc/codecs/uda1380.c
-@@ -687,6 +687,11 @@ static struct snd_soc_dai_driver uda1380_dai[] = {
- },
- };
- 
-+static int uda1380_hw_write(void *client, const char *buf, int count)
-+{
-+	return i2c_master_send(client, buf, count);
-+}
-+
- static int uda1380_probe(struct snd_soc_codec *codec)
- {
- 	struct uda1380_platform_data *pdata =codec->dev->platform_data;
-@@ -695,7 +700,7 @@ static int uda1380_probe(struct snd_soc_codec *codec)
- 
- 	uda1380->codec = codec;
- 
--	codec->hw_write = (hw_write_t)i2c_master_send;
-+	codec->hw_write = uda1380_hw_write;
- 	codec->control_data = uda1380->control_data;
- 
- 	if (!pdata)
-diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
-index cbb4075..edda3dd 100644
---- a/sound/soc/intel/skylake/skl-sst-dsp.h
-+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
-@@ -117,14 +117,14 @@ struct skl_dsp_fw_ops {
- 	int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, char *mod_name);
- 	int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
- 
--};
-+} __no_const;
- 
- struct skl_dsp_loader_ops {
- 	int (*alloc_dma_buf)(struct device *dev,
- 		struct snd_dma_buffer *dmab, size_t size);
- 	int (*free_dma_buf)(struct device *dev,
- 		struct snd_dma_buffer *dmab);
--};
-+} __no_const;
- 
- struct skl_load_module_info {
- 	u16 mod_id;
-diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c
-index 7e0acd8..7fe0f65 100644
---- a/sound/soc/soc-ac97.c
-+++ b/sound/soc/soc-ac97.c
-@@ -416,8 +416,10 @@ int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
- 	if (ret)
- 		return ret;
- 
--	ops->warm_reset = snd_soc_ac97_warm_reset;
--	ops->reset = snd_soc_ac97_reset;
-+	pax_open_kernel();
-+	*(void **)&ops->warm_reset = snd_soc_ac97_warm_reset;
-+	*(void **)&ops->reset = snd_soc_ac97_reset;
-+	pax_close_kernel();
- 
- 	snd_ac97_rst_cfg = cfg;
- 	return 0;
-diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c
-index 8382ffa..86af7d0 100644
---- a/sound/soc/xtensa/xtfpga-i2s.c
-+++ b/sound/soc/xtensa/xtfpga-i2s.c
-@@ -437,7 +437,7 @@ static int xtfpga_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
- 	case SNDRV_PCM_TRIGGER_START:
- 	case SNDRV_PCM_TRIGGER_RESUME:
- 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
--		ACCESS_ONCE(i2s->tx_ptr) = 0;
-+		ACCESS_ONCE_RW(i2s->tx_ptr) = 0;
- 		rcu_assign_pointer(i2s->tx_substream, substream);
- 		xtfpga_pcm_refill_fifo(i2s);
- 		break;
-diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
-index a020920..55579f6 100644
---- a/sound/synth/emux/emux_seq.c
-+++ b/sound/synth/emux/emux_seq.c
-@@ -33,13 +33,13 @@ static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *inf
-  * MIDI emulation operators
-  */
- static struct snd_midi_op emux_ops = {
--	snd_emux_note_on,
--	snd_emux_note_off,
--	snd_emux_key_press,
--	snd_emux_terminate_note,
--	snd_emux_control,
--	snd_emux_nrpn,
--	snd_emux_sysex,
-+	.note_on = snd_emux_note_on,
-+	.note_off = snd_emux_note_off,
-+	.key_press = snd_emux_key_press,
-+	.note_terminate = snd_emux_terminate_note,
-+	.control = snd_emux_control,
-+	.nrpn = snd_emux_nrpn,
-+	.sysex = snd_emux_sysex,
- };
- 
- 
-diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
-index 81b7da8..bb2676f 100644
---- a/sound/usb/line6/driver.c
-+++ b/sound/usb/line6/driver.c
-@@ -307,7 +307,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
- {
- 	struct usb_device *usbdev = line6->usbdev;
- 	int ret;
--	unsigned char len;
-+	unsigned char *plen;
- 	unsigned count;
- 
- 	if (address > 0xffff || datalen > 0xff)
-@@ -324,6 +324,10 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
- 		return ret;
- 	}
- 
-+	plen = kmalloc(1, GFP_KERNEL);
-+	if (plen == NULL)
-+		return -ENOMEM;
-+
- 	/* Wait for data length. We'll get 0xff until length arrives. */
- 	for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
- 		mdelay(LINE6_READ_WRITE_STATUS_DELAY);
-@@ -331,30 +335,35 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
- 		ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
- 				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
- 				      USB_DIR_IN,
--				      0x0012, 0x0000, &len, 1,
-+				      0x0012, 0x0000, plen, 1,
- 				      LINE6_TIMEOUT * HZ);
- 		if (ret < 0) {
- 			dev_err(line6->ifcdev,
- 				"receive length failed (error %d)\n", ret);
-+			kfree(plen);
- 			return ret;
- 		}
- 
--		if (len != 0xff)
-+		if (*plen != 0xff)
- 			break;
- 	}
- 
--	if (len == 0xff) {
-+	if (*plen == 0xff) {
- 		dev_err(line6->ifcdev, "read failed after %d retries\n",
- 			count);
-+		kfree(plen);
- 		return -EIO;
--	} else if (len != datalen) {
-+	} else if (*plen != datalen) {
- 		/* should be equal or something went wrong */
- 		dev_err(line6->ifcdev,
- 			"length mismatch (expected %d, got %d)\n",
--			(int)datalen, (int)len);
-+			(int)datalen, (int)*plen);
-+		kfree(plen);
- 		return -EIO;
- 	}
- 
-+	kfree(plen);
-+
- 	/* receive the result: */
- 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
- 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-@@ -378,7 +387,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
- {
- 	struct usb_device *usbdev = line6->usbdev;
- 	int ret;
--	unsigned char status;
-+	unsigned char *status;
- 	int count;
- 
- 	if (address > 0xffff || datalen > 0xffff)
-@@ -395,6 +404,10 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
- 		return ret;
- 	}
- 
-+	status = kmalloc(1, GFP_KERNEL);
-+	if (status == NULL)
-+		return -ENOMEM;
-+
- 	for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
- 		mdelay(LINE6_READ_WRITE_STATUS_DELAY);
- 
-@@ -403,27 +416,32 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
- 				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
- 				      USB_DIR_IN,
- 				      0x0012, 0x0000,
--				      &status, 1, LINE6_TIMEOUT * HZ);
-+				      status, 1, LINE6_TIMEOUT * HZ);
- 
- 		if (ret < 0) {
- 			dev_err(line6->ifcdev,
- 				"receiving status failed (error %d)\n", ret);
-+			kfree(status);
- 			return ret;
- 		}
- 
--		if (status != 0xff)
-+		if (*status != 0xff)
- 			break;
- 	}
- 
--	if (status == 0xff) {
-+	if (*status == 0xff) {
- 		dev_err(line6->ifcdev, "write failed after %d retries\n",
- 			count);
-+		kfree(status);
- 		return -EIO;
--	} else if (status != 0) {
-+	} else if (*status != 0) {
- 		dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
-+		kfree(status);
- 		return -EIO;
- 	}
- 
-+	kfree(status);
-+
- 	return 0;
- }
- EXPORT_SYMBOL_GPL(line6_write_data);
-diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
-index 6d4c50c..aa658c8 100644
---- a/sound/usb/line6/toneport.c
-+++ b/sound/usb/line6/toneport.c
-@@ -367,13 +367,19 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
- */
- static void toneport_setup(struct usb_line6_toneport *toneport)
- {
--	int ticks;
-+	int *ticks;
- 	struct usb_line6 *line6 = &toneport->line6;
- 	struct usb_device *usbdev = line6->usbdev;
- 
-+	ticks = kmalloc(sizeof(int), GFP_KERNEL);
-+	if (ticks == NULL)
-+		return;
-+
- 	/* sync time on device with host: */
--	ticks = (int)get_seconds();
--	line6_write_data(line6, 0x80c6, &ticks, 4);
-+	*ticks = (int)get_seconds();
-+	line6_write_data(line6, 0x80c6, ticks, sizeof(int));
-+
-+	kfree(ticks);
- 
- 	/* enable device: */
- 	toneport_send_cmd(usbdev, 0x0301, 0x0000);
-diff --git a/tools/gcc/.gitignore b/tools/gcc/.gitignore
-new file mode 100644
-index 0000000..de92ed9
---- /dev/null
-+++ b/tools/gcc/.gitignore
-@@ -0,0 +1 @@
-+randomize_layout_seed.h
-diff --git a/tools/gcc/Makefile b/tools/gcc/Makefile
-new file mode 100644
-index 0000000..f1db084
---- /dev/null
-+++ b/tools/gcc/Makefile
-@@ -0,0 +1,58 @@
-+#CC := gcc
-+#PLUGIN_SOURCE_FILES := pax_plugin.c
-+#PLUGIN_OBJECT_FILES := $(patsubst %.c,%.o,$(PLUGIN_SOURCE_FILES))
-+GCCPLUGINS_DIR := $(shell $(CC) -print-file-name=plugin)
-+#CFLAGS += -I$(GCCPLUGINS_DIR)/include -fPIC -O2 -Wall -W -std=gnu99
-+
-+ifeq ($(PLUGINCC),$(HOSTCC))
-+HOSTLIBS := hostlibs
-+HOST_EXTRACFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(src) -std=gnu99 -ggdb -Wall -W
-+export HOST_EXTRACFLAGS
-+else
-+HOSTLIBS := hostcxxlibs
-+HOST_EXTRACXXFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(src) -std=gnu++98 -fno-rtti -fno-exceptions -fasynchronous-unwind-tables -ggdb -Wall -W -Wno-unused-parameter -Wno-narrowing -Wno-unused-variable
-+export HOST_EXTRACXXFLAGS
-+endif
-+
-+export GCCPLUGINS_DIR HOSTLIBS
-+
-+$(HOSTLIBS)-$(CONFIG_PAX_CONSTIFY_PLUGIN) := constify_plugin.so
-+$(HOSTLIBS)-$(CONFIG_PAX_MEMORY_STACKLEAK) += stackleak_plugin.so
-+$(HOSTLIBS)-$(CONFIG_KALLOCSTAT_PLUGIN) += kallocstat_plugin.so
-+$(HOSTLIBS)-$(CONFIG_PAX_KERNEXEC_PLUGIN) += kernexec_plugin.so
-+$(HOSTLIBS)-$(CONFIG_CHECKER_PLUGIN) += checker_plugin.so
-+$(HOSTLIBS)-y += colorize_plugin.so
-+$(HOSTLIBS)-$(CONFIG_PAX_LATENT_ENTROPY) += latent_entropy_plugin.so
-+$(HOSTLIBS)-$(CONFIG_PAX_MEMORY_STRUCTLEAK) += structleak_plugin.so
-+$(HOSTLIBS)-y += initify_plugin.so
-+$(HOSTLIBS)-$(CONFIG_GRKERNSEC_RANDSTRUCT) += randomize_layout_plugin.so
-+
-+subdir-$(CONFIG_PAX_SIZE_OVERFLOW) := size_overflow_plugin
-+subdir- += size_overflow_plugin
-+
-+subdir-$(CONFIG_PAX_RAP) += rap_plugin
-+subdir- += rap_plugin
-+
-+always := $($(HOSTLIBS)-y)
-+
-+constify_plugin-objs := constify_plugin.o
-+stackleak_plugin-objs := stackleak_plugin.o
-+kallocstat_plugin-objs := kallocstat_plugin.o
-+kernexec_plugin-objs := kernexec_plugin.o
-+checker_plugin-objs := checker_plugin.o
-+colorize_plugin-objs := colorize_plugin.o
-+latent_entropy_plugin-objs := latent_entropy_plugin.o
-+structleak_plugin-objs := structleak_plugin.o
-+initify_plugin-objs := initify_plugin.o
-+rap_plugin-objs := rap_plugin.o sip.o
-+randomize_layout_plugin-objs := randomize_layout_plugin.o
-+
-+$(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h
-+
-+quiet_cmd_create_randomize_layout_seed = GENSEED  $@
-+      cmd_create_randomize_layout_seed = \
-+	$(CONFIG_SHELL) $(srctree)/$(src)/gen-random-seed.sh $@ $(objtree)/include/generated/randomize_layout_hash.h
-+$(objtree)/$(obj)/randomize_layout_seed.h: FORCE
-+	$(call if_changed,create_randomize_layout_seed)
-+
-+targets += randomize_layout_seed.h randomize_layout_hash.h
-diff --git a/tools/gcc/checker_plugin.c b/tools/gcc/checker_plugin.c
-new file mode 100644
-index 0000000..efaf576
---- /dev/null
-+++ b/tools/gcc/checker_plugin.c
-@@ -0,0 +1,496 @@
-+/*
-+ * Copyright 2011-2016 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 implement various sparse (source code checker) features
-+ *
-+ * TODO:
-+ * - define separate __iomem, __percpu and __rcu address spaces (lots of code to patch)
-+ *
-+ * BUGS:
-+ * - none known
-+ */
-+
-+#include "gcc-common.h"
-+
-+extern void c_register_addr_space (const char *str, addr_space_t as);
-+extern enum machine_mode default_addr_space_pointer_mode (addr_space_t);
-+extern enum machine_mode default_addr_space_address_mode (addr_space_t);
-+extern bool default_addr_space_valid_pointer_mode(enum machine_mode mode, addr_space_t as);
-+extern bool default_addr_space_legitimate_address_p(enum machine_mode mode, rtx mem, bool strict, addr_space_t as);
-+extern rtx default_addr_space_legitimize_address(rtx x, rtx oldx, enum machine_mode mode, addr_space_t as);
-+
-+int plugin_is_GPL_compatible;
-+
-+static struct plugin_info checker_plugin_info = {
-+	.version	= "201602181345",
-+	.help		= "user\tturn on user/kernel address space checking\n"
-+			  "context\tturn on locking context checking\n"
-+};
-+
-+#define ADDR_SPACE_KERNEL		0
-+#define ADDR_SPACE_FORCE_KERNEL		1
-+#define ADDR_SPACE_USER			2
-+#define ADDR_SPACE_FORCE_USER		3
-+#define ADDR_SPACE_IOMEM		0
-+#define ADDR_SPACE_FORCE_IOMEM		0
-+#define ADDR_SPACE_PERCPU		0
-+#define ADDR_SPACE_FORCE_PERCPU		0
-+#define ADDR_SPACE_RCU			0
-+#define ADDR_SPACE_FORCE_RCU		0
-+
-+static enum machine_mode checker_addr_space_pointer_mode(addr_space_t addrspace)
-+{
-+	return default_addr_space_pointer_mode(ADDR_SPACE_GENERIC);
-+}
-+
-+static enum machine_mode checker_addr_space_address_mode(addr_space_t addrspace)
-+{
-+	return default_addr_space_address_mode(ADDR_SPACE_GENERIC);
-+}
-+
-+static bool checker_addr_space_valid_pointer_mode(enum machine_mode mode, addr_space_t as)
-+{
-+	return default_addr_space_valid_pointer_mode(mode, as);
-+}
-+
-+static bool checker_addr_space_legitimate_address_p(enum machine_mode mode, rtx mem, bool strict, addr_space_t as)
-+{
-+	return default_addr_space_legitimate_address_p(mode, mem, strict, ADDR_SPACE_GENERIC);
-+}
-+
-+static rtx checker_addr_space_legitimize_address(rtx x, rtx oldx, enum machine_mode mode, addr_space_t as)
-+{
-+	return default_addr_space_legitimize_address(x, oldx, mode, as);
-+}
-+
-+static bool checker_addr_space_subset_p(addr_space_t subset, addr_space_t superset)
-+{
-+	if (subset == ADDR_SPACE_FORCE_KERNEL && superset == ADDR_SPACE_KERNEL)
-+		return true;
-+
-+	if (subset == ADDR_SPACE_FORCE_USER && superset == ADDR_SPACE_USER)
-+		return true;
-+
-+	if (subset == ADDR_SPACE_FORCE_IOMEM && superset == ADDR_SPACE_IOMEM)
-+		return true;
-+
-+	if (subset == ADDR_SPACE_KERNEL && superset == ADDR_SPACE_FORCE_USER)
-+		return true;
-+
-+	if (subset == ADDR_SPACE_KERNEL && superset == ADDR_SPACE_FORCE_IOMEM)
-+		return true;
-+
-+	if (subset == ADDR_SPACE_USER && superset == ADDR_SPACE_FORCE_KERNEL)
-+		return true;
-+
-+	if (subset == ADDR_SPACE_IOMEM && superset == ADDR_SPACE_FORCE_KERNEL)
-+		return true;
-+
-+	return subset == superset;
-+}
-+
-+static rtx checker_addr_space_convert(rtx op, tree from_type, tree to_type)
-+{
-+//	addr_space_t from_as = TYPE_ADDR_SPACE(TREE_TYPE(from_type));
-+//	addr_space_t to_as = TYPE_ADDR_SPACE(TREE_TYPE(to_type));
-+
-+	return op;
-+}
-+
-+static void register_checker_address_spaces(void *event_data, void *data)
-+{
-+	c_register_addr_space("__kernel", ADDR_SPACE_KERNEL);
-+	c_register_addr_space("__force_kernel", ADDR_SPACE_FORCE_KERNEL);
-+	c_register_addr_space("__user", ADDR_SPACE_USER);
-+	c_register_addr_space("__force_user", ADDR_SPACE_FORCE_USER);
-+//	c_register_addr_space("__iomem", ADDR_SPACE_IOMEM);
-+//	c_register_addr_space("__force_iomem", ADDR_SPACE_FORCE_IOMEM);
-+//	c_register_addr_space("__percpu", ADDR_SPACE_PERCPU);
-+//	c_register_addr_space("__force_percpu", ADDR_SPACE_FORCE_PERCPU);
-+//	c_register_addr_space("__rcu", ADDR_SPACE_RCU);
-+//	c_register_addr_space("__force_rcu", ADDR_SPACE_FORCE_RCU);
-+
-+	targetm.addr_space.pointer_mode		= checker_addr_space_pointer_mode;
-+	targetm.addr_space.address_mode		= checker_addr_space_address_mode;
-+	targetm.addr_space.valid_pointer_mode	= checker_addr_space_valid_pointer_mode;
-+	targetm.addr_space.legitimate_address_p	= checker_addr_space_legitimate_address_p;
-+//	targetm.addr_space.legitimize_address	= checker_addr_space_legitimize_address;
-+	targetm.addr_space.subset_p		= checker_addr_space_subset_p;
-+	targetm.addr_space.convert		= checker_addr_space_convert;
-+}
-+
-+static bool split_context_attribute(tree args, tree *lock, tree *in, tree *out)
-+{
-+	*in = TREE_VALUE(args);
-+
-+	if (TREE_CODE(*in) != INTEGER_CST) {
-+		*lock = *in;
-+		args = TREE_CHAIN(args);
-+		*in = TREE_VALUE(args);
-+	} else
-+		*lock = NULL_TREE;
-+
-+	args = TREE_CHAIN(args);
-+	if (*lock && !args)
-+		return false;
-+
-+	*out = TREE_VALUE(args);
-+	return true;
-+}
-+
-+static tree handle_context_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
-+{
-+	*no_add_attrs = true;
-+	tree lock, in, out;
-+
-+	if (TREE_CODE(*node) != FUNCTION_DECL) {
-+		error("%qE attribute applies to functions only (%qD)", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (!split_context_attribute(args, &lock, &in, &out)) {
-+		error("%qE attribute needs two integers after the lock expression", name);
-+		return NULL_TREE;
-+	}
-+
-+	if (TREE_CODE(in) != INTEGER_CST) {
-+		error("the 'in' argument of the %qE attribute must be an integer (%qE)", name, in);
-+		return NULL_TREE;
-+	}
-+
-+	if (TREE_CODE(out) != INTEGER_CST) {
-+		error("the 'out' argument of the %qE attribute must be an integer (%qE)", name, out);
-+		return NULL_TREE;
-+	}
-+
-+	*no_add_attrs = false;
-+	return NULL_TREE;
-+}
-+
-+static struct attribute_spec context_attr = {
-+	.name			= "context",
-+	.min_length		= 2,
-+	.max_length		= 3,
-+	.decl_required		= true,
-+	.type_required		= false,
-+	.function_type_required	= false,
-+	.handler		= handle_context_attribute,
-+#if BUILDING_GCC_VERSION >= 4007
-+	.affects_type_identity	= true
-+#endif
-+};
-+
-+static void register_attributes(void *event_data, void *data)
-+{
-+	register_attribute(&context_attr);
-+}
-+
-+static const char context_function[] = "__context__";
-+static GTY(()) tree context_function_decl;
-+
-+static const char context_error[] = "__context_error__";
-+static GTY(()) tree context_error_decl;
-+
-+static void context_start_unit(void __unused *gcc_data, void __unused *user_data)
-+{
-+	tree fntype, attr;
-+
-+	// void __context__(void *, int);
-+	fntype = build_function_type_list(void_type_node, ptr_type_node, integer_type_node, NULL_TREE);
-+	context_function_decl = build_fn_decl(context_function, fntype);
-+
-+	TREE_PUBLIC(context_function_decl) = 1;
-+	TREE_USED(context_function_decl) = 1;
-+	DECL_EXTERNAL(context_function_decl) = 1;
-+	DECL_ARTIFICIAL(context_function_decl) = 1;
-+	DECL_PRESERVE_P(context_function_decl) = 1;
-+//	TREE_NOTHROW(context_function_decl) = 1;
-+//	DECL_UNINLINABLE(context_function_decl) = 1;
-+	DECL_ASSEMBLER_NAME(context_function_decl); // for LTO
-+	lang_hooks.decls.pushdecl(context_function_decl);
-+
-+	// void __context_error__(const void *, int) __attribute__((error("context error")));
-+	fntype = build_function_type_list(void_type_node, const_ptr_type_node, integer_type_node, NULL_TREE);
-+	context_error_decl = build_fn_decl(context_error, fntype);
-+
-+	TREE_PUBLIC(context_error_decl) = 1;
-+	TREE_USED(context_error_decl) = 1;
-+	DECL_EXTERNAL(context_error_decl) = 1;
-+	DECL_ARTIFICIAL(context_error_decl) = 1;
-+	DECL_PRESERVE_P(context_error_decl) = 1;
-+//	TREE_NOTHROW(context_error_decl) = 1;
-+//	DECL_UNINLINABLE(context_error_decl) = 1;
-+	TREE_THIS_VOLATILE(context_error_decl) = 1;
-+	DECL_ASSEMBLER_NAME(context_error_decl);
-+
-+	attr = tree_cons(NULL, build_string(14, "context error"), NULL);
-+	attr = tree_cons(get_identifier("error"), attr, NULL);
-+	decl_attributes(&context_error_decl, attr, 0);
-+}
-+
-+static bool context_gate(void)
-+{
-+	tree context_attr;
-+
-+return true;
-+
-+	context_attr = lookup_attribute("context", DECL_ATTRIBUTES(current_function_decl));
-+	return context_attr != NULL_TREE;
-+}
-+
-+static basic_block verify_context_before(gimple_stmt_iterator *gsi, tree context, tree inout, tree error)
-+{
-+	gimple stmt;
-+	basic_block cond_bb, join_bb, true_bb;
-+	edge e;
-+	location_t loc;
-+	const char *file;
-+	int line;
-+	size_t len;
-+	tree filename;
-+
-+	stmt = gsi_stmt(*gsi);
-+	if (gimple_has_location(stmt)) {
-+		loc = gimple_location(stmt);
-+		file = gimple_filename(stmt);
-+		line = gimple_lineno(stmt);
-+	} else {
-+		loc = DECL_SOURCE_LOCATION(current_function_decl);
-+		file = DECL_SOURCE_FILE(current_function_decl);
-+		line = DECL_SOURCE_LINE(current_function_decl);
-+	}
-+	gcc_assert(file);
-+
-+	// if (context != count) __context_error__(__FILE__, __LINE__);
-+	stmt = gimple_build_cond(NE_EXPR, context, inout, NULL_TREE, NULL_TREE);
-+	gimple_set_location(stmt, loc);
-+	gsi_insert_before(gsi, stmt, GSI_NEW_STMT);
-+
-+	cond_bb = gsi_bb(*gsi);
-+	gcc_assert(!gsi_end_p(*gsi));
-+	gcc_assert(stmt == gsi_stmt(*gsi));
-+
-+	e = split_block(cond_bb, gsi_stmt(*gsi));
-+	cond_bb = e->src;
-+	join_bb = e->dest;
-+	e->flags = EDGE_FALSE_VALUE;
-+	e->probability = REG_BR_PROB_BASE;
-+
-+	true_bb = create_empty_bb(EXIT_BLOCK_PTR_FOR_FN(cfun)->prev_bb);
-+	make_edge(cond_bb, true_bb, EDGE_TRUE_VALUE);
-+	make_edge(true_bb, join_bb, EDGE_FALLTHRU);
-+
-+	set_immediate_dominator(CDI_DOMINATORS, true_bb, cond_bb);
-+	set_immediate_dominator(CDI_DOMINATORS, join_bb, cond_bb);
-+
-+	gcc_assert(cond_bb->loop_father == join_bb->loop_father);
-+	add_bb_to_loop(true_bb, cond_bb->loop_father);
-+
-+	// insert call to builtin_trap or __context_error__
-+	*gsi = gsi_start_bb(true_bb);
-+
-+//	stmt = gimple_build_call(builtin_decl_implicit(BUILT_IN_TRAP), 0);
-+	len = strlen(file) + 1;
-+	filename = build_string(len, file);
-+	TREE_TYPE(filename) = build_array_type(unsigned_char_type_node, build_index_type(size_int(len)));
-+	filename = build1(ADDR_EXPR, const_ptr_type_node, filename);
-+	stmt = gimple_build_call(error, 2, filename, build_int_cst(NULL_TREE, line));
-+	gimple_set_location(stmt, loc);
-+	gsi_insert_after(gsi, stmt, GSI_CONTINUE_LINKING);
-+
-+	*gsi = gsi_start_nondebug_bb(join_bb);
-+	return join_bb;
-+}
-+
-+static void update_context(gimple_stmt_iterator *gsi, tree context, int diff)
-+{
-+	gimple assign;
-+	tree op;
-+
-+	op = fold_build2_loc(UNKNOWN_LOCATION, PLUS_EXPR, integer_type_node, context, build_int_cst(integer_type_node, diff));
-+	assign = gimple_build_assign(context, op);
-+	gsi_insert_after(gsi, assign, GSI_NEW_STMT);
-+	update_stmt(assign);
-+}
-+
-+static basic_block track_context(basic_block bb, tree context)
-+{
-+	gimple_stmt_iterator gsi;
-+	gimple assign;
-+
-+	// adjust context according to the context information on any call stmt
-+	for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
-+		gimple stmt = gsi_stmt(gsi);
-+		tree fndecl, context_attr;
-+		tree lock, in, out;
-+		int incount, outcount;
-+
-+		if (!is_gimple_call(stmt))
-+			continue;
-+
-+		fndecl = gimple_call_fndecl(stmt);
-+		if (!fndecl)
-+			continue;
-+
-+		if (fndecl == context_function_decl) {
-+			unsigned int num_ops = gimple_num_ops(stmt);
-+			int diff = tree_to_shwi(gimple_op(stmt, num_ops - 1));
-+
-+			gcc_assert(diff);
-+			update_context(&gsi, context, diff);
-+			continue;
-+		}
-+
-+		context_attr = lookup_attribute("context", DECL_ATTRIBUTES(fndecl));
-+		if (!context_attr)
-+			continue;
-+
-+		gcc_assert(split_context_attribute(TREE_VALUE(context_attr), &lock, &in, &out));
-+		incount = tree_to_shwi(in);
-+		outcount = tree_to_shwi(out);
-+		bb = verify_context_before(&gsi, context, in, context_error_decl);
-+		update_context(&gsi, context, outcount - incount);
-+	}
-+
-+	return bb;
-+}
-+
-+static bool bb_any_loop(basic_block bb)
-+{
-+	return bb_loop_depth(bb) || (bb->flags & BB_IRREDUCIBLE_LOOP);
-+}
-+
-+static unsigned int context_execute(void)
-+{
-+	basic_block bb;
-+	gimple assign;
-+	gimple_stmt_iterator gsi;
-+	tree context_attr, context;
-+	tree lock, in, out;
-+
-+	loop_optimizer_init(LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
-+	gcc_assert(current_loops);
-+
-+	calculate_dominance_info(CDI_DOMINATORS);
-+	calculate_dominance_info(CDI_POST_DOMINATORS);
-+
-+	context_attr = lookup_attribute("context", DECL_ATTRIBUTES(current_function_decl));
-+	if (context_attr) {
-+		gcc_assert(split_context_attribute(TREE_VALUE(context_attr), &lock, &in, &out));
-+	} else {
-+		in = out = integer_zero_node;
-+	}
-+
-+	// 1. create local context variable
-+	context = create_tmp_var(integer_type_node, "context");
-+	add_referenced_var(context);
-+	mark_sym_for_renaming(context);
-+
-+	// 2. initialize local context variable
-+	gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+	bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+	if (!single_pred_p(bb)) {
-+		gcc_assert(bb_any_loop(bb));
-+		split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+		bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+	}
-+	gsi = gsi_start_bb(bb);
-+	assign = gimple_build_assign(context, in);
-+	gsi_insert_before(&gsi, assign, GSI_NEW_STMT);
-+	update_stmt(assign);
-+
-+	// 3. instrument each BB to track the local context variable
-+	FOR_EACH_BB_FN(bb, cfun) {
-+		bb = track_context(bb, context);
-+	}
-+
-+	// 4. verify the local context variable against the expected state
-+	if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds)) {
-+		gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun)));
-+		gsi = gsi_last_nondebug_bb(single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun)));
-+		verify_context_before(&gsi, context, out, context_error_decl);
-+	}
-+
-+	free_dominance_info(CDI_DOMINATORS);
-+	free_dominance_info(CDI_POST_DOMINATORS);
-+	loop_optimizer_finalize();
-+	return 0;
-+}
-+
-+#define PASS_NAME context
-+#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
-+//#define TODO_FLAGS_START TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts
-+#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_verify_flow | TODO_update_ssa
-+#include "gcc-generate-gimple-pass.h"
-+
-+int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
-+{
-+	const char * const plugin_name = plugin_info->base_name;
-+	const int argc = plugin_info->argc;
-+	const struct plugin_argument * const argv = plugin_info->argv;
-+	int i;
-+	bool enable_user, enable_context;
-+	struct register_pass_info context_pass_info;
-+
-+	static const struct ggc_root_tab gt_ggc_r_gt_checker[] = {
-+		{
-+			.base = &context_function_decl,
-+			.nelt = 1,
-+			.stride = sizeof(context_function_decl),
-+			.cb = &gt_ggc_mx_tree_node,
-+			.pchw = &gt_pch_nx_tree_node
-+		},
-+		{
-+			.base = &context_error_decl,
-+			.nelt = 1,
-+			.stride = sizeof(context_error_decl),
-+			.cb = &gt_ggc_mx_tree_node,
-+			.pchw = &gt_pch_nx_tree_node
-+		},
-+		LAST_GGC_ROOT_TAB
-+	};
-+
-+	context_pass_info.pass				= make_context_pass();
-+//	context_pass_info.reference_pass_name		= "ssa";
-+	context_pass_info.reference_pass_name		= "phiprop";
-+	context_pass_info.ref_pass_instance_number	= 1;
-+	context_pass_info.pos_op 			= PASS_POS_INSERT_AFTER;
-+
-+	if (!plugin_default_version_check(version, &gcc_version)) {
-+		error(G_("incompatible gcc/plugin versions"));
-+		return 1;
-+	}
-+
-+	register_callback(plugin_name, PLUGIN_INFO, NULL, &checker_plugin_info);
-+
-+	enable_user = false;
-+	enable_context = false;
-+	for (i = 0; i < argc; ++i) {
-+		if (!strcmp(argv[i].key, "user")) {
-+			enable_user = true;
-+			continue;
-+		}
-+		if (!strcmp(argv[i].key, "context")) {
-+			enable_context = true;
-+			continue;
-+		}
-+		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+	}
-+
-+	if (enable_user)
-+		register_callback(plugin_name, PLUGIN_PRAGMAS, register_checker_address_spaces, NULL);
-+	if (enable_context) {
-+		register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
-+		register_callback(plugin_name, PLUGIN_START_UNIT, context_start_unit, NULL);
-+		register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_checker);
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &context_pass_info);
-+	}
-+
-+	return 0;
-+}
-diff --git a/tools/gcc/colorize_plugin.c b/tools/gcc/colorize_plugin.c
-new file mode 100644
-index 0000000..ffe60f6
---- /dev/null
-+++ b/tools/gcc/colorize_plugin.c
-@@ -0,0 +1,162 @@
-+/*
-+ * Copyright 2012-2016 by 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 colorize diagnostic output
-+ *
-+ */
-+
-+#include "gcc-common.h"
-+
-+int plugin_is_GPL_compatible;
-+
-+static struct plugin_info colorize_plugin_info = {
-+	.version	= "201602181345",
-+	.help		= "color=[never|always|auto]\tdetermine when to colorize\n",
-+};
-+
-+#define GREEN		"\033[32m\033[K"
-+#define LIGHTGREEN	"\033[1;32m\033[K"
-+#define YELLOW		"\033[33m\033[K"
-+#define LIGHTYELLOW	"\033[1;33m\033[K"
-+#define RED		"\033[31m\033[K"
-+#define LIGHTRED	"\033[1;31m\033[K"
-+#define BLUE		"\033[34m\033[K"
-+#define LIGHTBLUE	"\033[1;34m\033[K"
-+#define BRIGHT		"\033[1;m\033[K"
-+#define NORMAL		"\033[m\033[K"
-+
-+static diagnostic_starter_fn old_starter;
-+static diagnostic_finalizer_fn old_finalizer;
-+
-+static void start_colorize(diagnostic_context *context, diagnostic_info *diagnostic)
-+{
-+	const char *color;
-+	char *newprefix;
-+
-+	switch (diagnostic->kind) {
-+	case DK_NOTE:
-+		color = LIGHTBLUE;
-+		break;
-+
-+	case DK_PEDWARN:
-+	case DK_WARNING:
-+		color = LIGHTYELLOW;
-+		break;
-+
-+	case DK_ERROR:
-+	case DK_FATAL:
-+	case DK_ICE:
-+	case DK_PERMERROR:
-+	case DK_SORRY:
-+		color = LIGHTRED;
-+		break;
-+
-+	default:
-+		color = NORMAL;
-+	}
-+
-+	old_starter(context, diagnostic);
-+	if (-1 == asprintf(&newprefix, "%s%s" NORMAL, color, context->printer->prefix))
-+		return;
-+	pp_destroy_prefix(context->printer);
-+	pp_set_prefix(context->printer, newprefix);
-+}
-+
-+static void finalize_colorize(diagnostic_context *context, diagnostic_info *diagnostic)
-+{
-+	old_finalizer(context, diagnostic);
-+}
-+
-+static void colorize_arm(void)
-+{
-+	old_starter = diagnostic_starter(global_dc);
-+	old_finalizer = diagnostic_finalizer(global_dc);
-+
-+	diagnostic_starter(global_dc) = start_colorize;
-+	diagnostic_finalizer(global_dc) = finalize_colorize;
-+}
-+
-+static unsigned int colorize_rearm_execute(void)
-+{
-+	if (diagnostic_starter(global_dc) == start_colorize)
-+		return 0;
-+
-+	colorize_arm();
-+	return 0;
-+}
-+
-+#define PASS_NAME colorize_rearm
-+#define NO_GATE
-+#include "gcc-generate-simple_ipa-pass.h"
-+
-+static void colorize_start_unit(void *gcc_data, void *user_data)
-+{
-+	colorize_arm();
-+}
-+
-+static bool should_colorize(void)
-+{
-+#if BUILDING_GCC_VERSION >= 4009
-+	return false;
-+#else
-+	char const *t = getenv("TERM");
-+
-+	return t && strcmp(t, "dumb") && isatty(STDERR_FILENO);
-+#endif
-+}
-+
-+int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
-+{
-+	const char * const plugin_name = plugin_info->base_name;
-+	const int argc = plugin_info->argc;
-+	const struct plugin_argument * const argv = plugin_info->argv;
-+	int i;
-+	struct register_pass_info colorize_rearm_pass_info;
-+	bool colorize;
-+
-+	colorize_rearm_pass_info.pass				= make_colorize_rearm_pass();
-+	colorize_rearm_pass_info.reference_pass_name		= "*free_lang_data";
-+	colorize_rearm_pass_info.ref_pass_instance_number	= 1;
-+	colorize_rearm_pass_info.pos_op 			= PASS_POS_INSERT_AFTER;
-+
-+	if (!plugin_default_version_check(version, &gcc_version)) {
-+		error(G_("incompatible gcc/plugin versions"));
-+		return 1;
-+	}
-+
-+	register_callback(plugin_name, PLUGIN_INFO, NULL, &colorize_plugin_info);
-+
-+	colorize = getenv("GCC_COLORS") ? should_colorize() : false;
-+
-+	for (i = 0; i < argc; ++i) {
-+		if (!strcmp(argv[i].key, "color")) {
-+			if (!argv[i].value) {
-+				error(G_("no value supplied for option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+				continue;
-+			}
-+			if (!strcmp(argv[i].value, "always"))
-+				colorize = true;
-+			else if (!strcmp(argv[i].value, "never"))
-+				colorize = false;
-+			else if (!strcmp(argv[i].value, "auto"))
-+				colorize = should_colorize();
-+			else
-+				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"), plugin_name, argv[i].key, argv[i].value);
-+			continue;
-+		}
-+		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+	}
-+
-+	if (colorize) {
-+		// TODO: parse GCC_COLORS as used by gcc 4.9+
-+		register_callback(plugin_name, PLUGIN_START_UNIT, &colorize_start_unit, NULL);
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &colorize_rearm_pass_info);
-+	}
-+	return 0;
-+}
-diff --git a/tools/gcc/constify_plugin.c b/tools/gcc/constify_plugin.c
-new file mode 100644
-index 0000000..b52a700
---- /dev/null
-+++ b/tools/gcc/constify_plugin.c
-@@ -0,0 +1,521 @@
-+/*
-+ * Copyright 2011 by Emese Revfy <re.emese@gmail.com>
-+ * Copyright 2011-2016 by PaX Team <pageexec@freemail.hu>
-+ * Licensed under the GPL v2, or (at your option) v3
-+ *
-+ * This gcc plugin constifies all structures which contain only function pointers or are explicitly marked for constification.
-+ *
-+ * Homepage:
-+ * http://www.grsecurity.net/~ephox/const_plugin/
-+ *
-+ * Usage:
-+ * $ gcc -I`gcc -print-file-name=plugin`/include -fPIC -shared -O2 -o constify_plugin.so constify_plugin.c
-+ * $ gcc -fplugin=constify_plugin.so test.c -O2
-+ */
-+
-+#include "gcc-common.h"
-+
-+// unused C type flag in all versions 4.5-6
-+#define TYPE_CONSTIFY_VISITED(TYPE) TYPE_LANG_FLAG_4(TYPE)
-+
-+int plugin_is_GPL_compatible;
-+
-+static bool constify = true;
-+
-+static struct plugin_info const_plugin_info = {
-+	.version	= "201602181345",
-+	.help		= "no-constify\tturn off constification\n",
-+};
-+
-+typedef struct {
-+	bool has_fptr_field;
-+	bool has_writable_field;
-+	bool has_do_const_field;
-+	bool has_no_const_field;
-+} constify_info;
-+
-+static const_tree get_field_type(const_tree field)
-+{
-+	return strip_array_types(TREE_TYPE(field));
-+}
-+
-+static bool is_fptr(const_tree field)
-+{
-+	const_tree ptr = get_field_type(field);
-+
-+	if (TREE_CODE(ptr) != POINTER_TYPE)
-+		return false;
-+
-+	return TREE_CODE(TREE_TYPE(ptr)) == FUNCTION_TYPE;
-+}
-+
-+/*
-+ * determine whether the given structure type meets the requirements for automatic constification,
-+ * including the constification attributes on nested structure types
-+ */
-+static void constifiable(const_tree node, constify_info *cinfo)
-+{
-+	const_tree field;
-+
-+	gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
-+
-+	// e.g., pointer to structure fields while still constructing the structure type
-+	if (TYPE_FIELDS(node) == NULL_TREE)
-+		return;
-+
-+	for (field = TYPE_FIELDS(node); field; field = TREE_CHAIN(field)) {
-+		const_tree type = get_field_type(field);
-+		enum tree_code code = TREE_CODE(type);
-+
-+		if (node == type)
-+			continue;
-+
-+		if (is_fptr(field))
-+			cinfo->has_fptr_field = true;
-+		else if (code == RECORD_TYPE || code == UNION_TYPE) {
-+			if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type)))
-+				cinfo->has_do_const_field = true;
-+			else if (lookup_attribute("no_const", TYPE_ATTRIBUTES(type)))
-+				cinfo->has_no_const_field = true;
-+			else
-+				constifiable(type, cinfo);
-+		} else if (!TREE_READONLY(field))
-+			cinfo->has_writable_field = true;
-+	}
-+}
-+
-+static bool constified(const_tree node)
-+{
-+	constify_info cinfo = {
-+		.has_fptr_field = false,
-+		.has_writable_field = false,
-+		.has_do_const_field = false,
-+		.has_no_const_field = false
-+	};
-+
-+	gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
-+
-+	if (lookup_attribute("no_const", TYPE_ATTRIBUTES(node))) {
-+//		gcc_assert(!TYPE_READONLY(node));
-+		return false;
-+	}
-+
-+	if (lookup_attribute("do_const", TYPE_ATTRIBUTES(node))) {
-+		gcc_assert(TYPE_READONLY(node));
-+		return true;
-+	}
-+
-+	constifiable(node, &cinfo);
-+	if ((!cinfo.has_fptr_field || cinfo.has_writable_field || cinfo.has_no_const_field) && !cinfo.has_do_const_field)
-+		return false;
-+
-+	return TYPE_READONLY(node);
-+}
-+
-+static void deconstify_tree(tree node);
-+
-+static void deconstify_type(tree type)
-+{
-+	tree field;
-+
-+	gcc_assert(TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_TYPE);
-+
-+	for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) {
-+		const_tree fieldtype = get_field_type(field);
-+
-+		// special case handling of simple ptr-to-same-array-type members
-+		if (TREE_CODE(TREE_TYPE(field)) == POINTER_TYPE) {
-+			tree ptrtype = TREE_TYPE(TREE_TYPE(field));
-+
-+			if (TREE_TYPE(TREE_TYPE(field)) == type)
-+				continue;
-+			if (TREE_CODE(ptrtype) != RECORD_TYPE && TREE_CODE(ptrtype) != UNION_TYPE)
-+				continue;
-+			if (!constified(ptrtype))
-+				continue;
-+			if (TYPE_MAIN_VARIANT(ptrtype) == TYPE_MAIN_VARIANT(type)) {
-+				TREE_TYPE(field) = copy_node(TREE_TYPE(field));
-+				TREE_TYPE(TREE_TYPE(field)) = build_qualified_type(type, TYPE_QUALS(ptrtype) & ~TYPE_QUAL_CONST);
-+			}
-+			continue;
-+		}
-+		if (TREE_CODE(fieldtype) != RECORD_TYPE && TREE_CODE(fieldtype) != UNION_TYPE)
-+			continue;
-+		if (!constified(fieldtype))
-+			continue;
-+
-+		deconstify_tree(field);
-+		TREE_READONLY(field) = 0;
-+	}
-+	TYPE_READONLY(type) = 0;
-+	C_TYPE_FIELDS_READONLY(type) = 0;
-+	if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
-+		TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
-+		TYPE_ATTRIBUTES(type) = remove_attribute("do_const", TYPE_ATTRIBUTES(type));
-+	}
-+}
-+
-+static void deconstify_tree(tree node)
-+{
-+	tree old_type, new_type, field;
-+
-+	old_type = TREE_TYPE(node);
-+	while (TREE_CODE(old_type) == ARRAY_TYPE && TREE_CODE(TREE_TYPE(old_type)) != ARRAY_TYPE) {
-+		node = TREE_TYPE(node) = copy_node(old_type);
-+		old_type = TREE_TYPE(old_type);
-+	}
-+
-+	gcc_assert(TREE_CODE(old_type) == RECORD_TYPE || TREE_CODE(old_type) == UNION_TYPE);
-+	gcc_assert(TYPE_READONLY(old_type) && (TYPE_QUALS(old_type) & TYPE_QUAL_CONST));
-+
-+	new_type = build_qualified_type(old_type, TYPE_QUALS(old_type) & ~TYPE_QUAL_CONST);
-+	TYPE_FIELDS(new_type) = copy_list(TYPE_FIELDS(new_type));
-+	for (field = TYPE_FIELDS(new_type); field; field = TREE_CHAIN(field))
-+		DECL_FIELD_CONTEXT(field) = new_type;
-+
-+	deconstify_type(new_type);
-+
-+	TREE_TYPE(node) = new_type;
-+}
-+
-+static tree handle_no_const_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
-+{
-+	tree type;
-+	constify_info cinfo = {
-+		.has_fptr_field = false,
-+		.has_writable_field = false,
-+		.has_do_const_field = false,
-+		.has_no_const_field = false
-+	};
-+
-+	*no_add_attrs = true;
-+	if (TREE_CODE(*node) == FUNCTION_DECL) {
-+		error("%qE attribute does not apply to functions (%qF)", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (TREE_CODE(*node) == PARM_DECL) {
-+		error("%qE attribute does not apply to function parameters (%qD)", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (TREE_CODE(*node) == VAR_DECL) {
-+		error("%qE attribute does not apply to variables (%qD)", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (TYPE_P(*node)) {
-+		type = *node;
-+	} else {
-+		if (TREE_CODE(*node) != TYPE_DECL) {
-+			error("%qE attribute does not apply to %qD (%qT)", name, *node, TREE_TYPE(*node));
-+			return NULL_TREE;
-+		}
-+		type = TREE_TYPE(*node);
-+	}
-+
-+	if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE) {
-+		error("%qE attribute used on %qT applies to struct and union types only", name, type);
-+		return NULL_TREE;
-+	}
-+
-+	if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(type))) {
-+		error("%qE attribute is already applied to the type %qT", name, type);
-+		return NULL_TREE;
-+	}
-+
-+	if (TYPE_P(*node)) {
-+		if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type)))
-+			error("%qE attribute used on type %qT is incompatible with 'do_const'", name, type);
-+		else
-+			*no_add_attrs = false;
-+		return NULL_TREE;
-+	}
-+
-+	constifiable(type, &cinfo);
-+	if ((cinfo.has_fptr_field && !cinfo.has_writable_field && !cinfo.has_no_const_field) || lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
-+		if (constify) {
-+			if TYPE_P(*node)
-+				deconstify_type(*node);
-+			else
-+				deconstify_tree(*node);
-+		}
-+		if (TYPE_P(*node))
-+			TYPE_CONSTIFY_VISITED(*node) = 1;
-+		else
-+			TYPE_CONSTIFY_VISITED(TREE_TYPE(*node)) = 1;
-+		return NULL_TREE;
-+	}
-+
-+	if (constify && TYPE_FIELDS(type))
-+		error("%qE attribute used on type %qT that is not constified", name, type);
-+	return NULL_TREE;
-+}
-+
-+static void constify_type(tree type)
-+{
-+	TYPE_READONLY(type) = 1;
-+	C_TYPE_FIELDS_READONLY(type) = 1;
-+	TYPE_CONSTIFY_VISITED(type) = 1;
-+//	TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
-+//	TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("do_const"), NULL_TREE, TYPE_ATTRIBUTES(type));
-+}
-+
-+static tree handle_do_const_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
-+{
-+	*no_add_attrs = true;
-+	if (!TYPE_P(*node)) {
-+		error("%qE attribute applies to types only (%qD)", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (TREE_CODE(*node) != RECORD_TYPE && TREE_CODE(*node) != UNION_TYPE) {
-+		error("%qE attribute used on %qT applies to struct and union types only", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(*node))) {
-+		error("%qE attribute used on %qT is already applied to the type", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	if (lookup_attribute("no_const", TYPE_ATTRIBUTES(*node))) {
-+		error("%qE attribute used on %qT is incompatible with 'no_const'", name, *node);
-+		return NULL_TREE;
-+	}
-+
-+	*no_add_attrs = false;
-+	return NULL_TREE;
-+}
-+
-+static struct attribute_spec no_const_attr = {
-+	.name			= "no_const",
-+	.min_length		= 0,
-+	.max_length		= 0,
-+	.decl_required		= false,
-+	.type_required		= false,
-+	.function_type_required	= false,
-+	.handler		= handle_no_const_attribute,
-+#if BUILDING_GCC_VERSION >= 4007
-+	.affects_type_identity	= true
-+#endif
-+};
-+
-+static struct attribute_spec do_const_attr = {
-+	.name			= "do_const",
-+	.min_length		= 0,
-+	.max_length		= 0,
-+	.decl_required		= false,
-+	.type_required		= false,
-+	.function_type_required	= false,
-+	.handler		= handle_do_const_attribute,
-+#if BUILDING_GCC_VERSION >= 4007
-+	.affects_type_identity	= true
-+#endif
-+};
-+
-+static void register_attributes(void *event_data, void *data)
-+{
-+	register_attribute(&no_const_attr);
-+	register_attribute(&do_const_attr);
-+}
-+
-+static void finish_type(void *event_data, void *data)
-+{
-+	tree type = (tree)event_data;
-+	constify_info cinfo = {
-+		.has_fptr_field = false,
-+		.has_writable_field = false,
-+		.has_do_const_field = false,
-+		.has_no_const_field = false
-+	};
-+
-+	if (type == NULL_TREE || type == error_mark_node)
-+		return;
-+
-+#if BUILDING_GCC_VERSION >= 5000
-+	if (TREE_CODE(type) == ENUMERAL_TYPE)
-+		return;
-+#endif
-+
-+	if (TYPE_FIELDS(type) == NULL_TREE || TYPE_CONSTIFY_VISITED(type))
-+		return;
-+
-+	constifiable(type, &cinfo);
-+
-+	if (lookup_attribute("no_const", TYPE_ATTRIBUTES(type))) {
-+		if ((cinfo.has_fptr_field && !cinfo.has_writable_field && !cinfo.has_no_const_field) || cinfo.has_do_const_field) {
-+			deconstify_type(type);
-+			TYPE_CONSTIFY_VISITED(type) = 1;
-+		} else
-+			error("'no_const' attribute used on type %qT that is not constified", type);
-+		return;
-+	}
-+
-+	if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
-+		if (!cinfo.has_writable_field && !cinfo.has_no_const_field) {
-+			error("'do_const' attribute used on type %qT that is%sconstified", type, cinfo.has_fptr_field ? " " : " not ");
-+			return;
-+		}
-+		constify_type(type);
-+		return;
-+	}
-+
-+	if (cinfo.has_fptr_field && !cinfo.has_writable_field && !cinfo.has_no_const_field) {
-+		if (lookup_attribute("do_const", TYPE_ATTRIBUTES(type))) {
-+			error("'do_const' attribute used on type %qT that is constified", type);
-+			return;
-+		}
-+		constify_type(type);
-+		return;
-+	}
-+
-+	deconstify_type(type);
-+	TYPE_CONSTIFY_VISITED(type) = 1;
-+}
-+
-+static void check_global_variables(void *event_data, void *data)
-+{
-+	varpool_node_ptr node;
-+
-+	FOR_EACH_VARIABLE(node) {
-+		tree var = NODE_DECL(node);
-+		tree type = TREE_TYPE(var);
-+
-+		if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
-+			continue;
-+
-+		if (!TYPE_READONLY(type) || !C_TYPE_FIELDS_READONLY(type))
-+			continue;
-+
-+		if (!TYPE_CONSTIFY_VISITED(type))
-+			continue;
-+
-+		if (DECL_EXTERNAL(var))
-+			continue;
-+
-+		if (DECL_INITIAL(var))
-+			continue;
-+
-+		// this works around a gcc bug/feature where uninitialized globals
-+		// are moved into the .bss section regardless of any constification
-+		DECL_INITIAL(var) = build_constructor(type, NULL);
-+//		inform(DECL_SOURCE_LOCATION(var), "constified variable %qE moved into .rodata", var);
-+	}
-+}
-+
-+static unsigned int check_local_variables_execute(void)
-+{
-+	unsigned int ret = 0;
-+	tree var;
-+
-+	unsigned int i;
-+
-+	FOR_EACH_LOCAL_DECL(cfun, i, var) {
-+		tree type = TREE_TYPE(var);
-+
-+		gcc_assert(DECL_P(var));
-+		if (is_global_var(var))
-+			continue;
-+
-+		if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
-+			continue;
-+
-+		if (!TYPE_READONLY(type) || !C_TYPE_FIELDS_READONLY(type))
-+			continue;
-+
-+		if (!TYPE_CONSTIFY_VISITED(type))
-+			continue;
-+
-+		error_at(DECL_SOURCE_LOCATION(var), "constified variable %qE cannot be local", var);
-+		ret = 1;
-+	}
-+	return ret;
-+}
-+
-+#define PASS_NAME check_local_variables
-+#define NO_GATE
-+#include "gcc-generate-gimple-pass.h"
-+
-+static struct {
-+	const char *name;
-+	const char *asm_op;
-+} sections[] = {
-+	{".init.rodata",     "\t.section\t.init.rodata,\"a\""},
-+	{".ref.rodata",      "\t.section\t.ref.rodata,\"a\""},
-+	{".devinit.rodata",  "\t.section\t.devinit.rodata,\"a\""},
-+	{".devexit.rodata",  "\t.section\t.devexit.rodata,\"a\""},
-+	{".cpuinit.rodata",  "\t.section\t.cpuinit.rodata,\"a\""},
-+	{".cpuexit.rodata",  "\t.section\t.cpuexit.rodata,\"a\""},
-+	{".meminit.rodata",  "\t.section\t.meminit.rodata,\"a\""},
-+	{".memexit.rodata",  "\t.section\t.memexit.rodata,\"a\""},
-+	{".data..read_only", "\t.section\t.data..read_only,\"a\""},
-+};
-+
-+static unsigned int (*old_section_type_flags)(tree decl, const char *name, int reloc);
-+
-+static unsigned int constify_section_type_flags(tree decl, const char *name, int reloc)
-+{
-+	size_t i;
-+
-+	for (i = 0; i < ARRAY_SIZE(sections); i++)
-+		if (!strcmp(sections[i].name, name))
-+			return 0;
-+	return old_section_type_flags(decl, name, reloc);
-+}
-+
-+static void constify_start_unit(void *gcc_data, void *user_data)
-+{
-+//	size_t i;
-+
-+//	for (i = 0; i < ARRAY_SIZE(sections); i++)
-+//		sections[i].section = get_unnamed_section(0, output_section_asm_op, sections[i].asm_op);
-+//		sections[i].section = get_section(sections[i].name, 0, NULL);
-+
-+	old_section_type_flags = targetm.section_type_flags;
-+	targetm.section_type_flags = constify_section_type_flags;
-+}
-+
-+int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
-+{
-+	const char * const plugin_name = plugin_info->base_name;
-+	const int argc = plugin_info->argc;
-+	const struct plugin_argument * const argv = plugin_info->argv;
-+	int i;
-+
-+	struct register_pass_info check_local_variables_pass_info;
-+
-+	check_local_variables_pass_info.pass				= make_check_local_variables_pass();
-+	check_local_variables_pass_info.reference_pass_name		= "ssa";
-+	check_local_variables_pass_info.ref_pass_instance_number	= 1;
-+	check_local_variables_pass_info.pos_op				= PASS_POS_INSERT_BEFORE;
-+
-+	if (!plugin_default_version_check(version, &gcc_version)) {
-+		error(G_("incompatible gcc/plugin versions"));
-+		return 1;
-+	}
-+
-+	for (i = 0; i < argc; ++i) {
-+		if (!(strcmp(argv[i].key, "no-constify"))) {
-+			constify = false;
-+			continue;
-+		}
-+		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+	}
-+
-+	if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {
-+		inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);
-+		constify = false;
-+	}
-+
-+	register_callback(plugin_name, PLUGIN_INFO, NULL, &const_plugin_info);
-+	if (constify) {
-+		register_callback(plugin_name, PLUGIN_ALL_IPA_PASSES_START, check_global_variables, NULL);
-+		register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &check_local_variables_pass_info);
-+		register_callback(plugin_name, PLUGIN_START_UNIT, constify_start_unit, NULL);
-+	}
-+	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
-+
-+	return 0;
-+}
-diff --git a/tools/gcc/gcc-common.h b/tools/gcc/gcc-common.h
-new file mode 100644
-index 0000000..0c0b842
---- /dev/null
-+++ b/tools/gcc/gcc-common.h
-@@ -0,0 +1,879 @@
-+#ifndef GCC_COMMON_H_INCLUDED
-+#define GCC_COMMON_H_INCLUDED
-+
-+#include "bversion.h"
-+#if BUILDING_GCC_VERSION >= 6000
-+#include "gcc-plugin.h"
-+#else
-+#include "plugin.h"
-+#endif
-+#include "plugin-version.h"
-+#include "config.h"
-+#include "system.h"
-+#include "coretypes.h"
-+#include "tm.h"
-+#include "line-map.h"
-+#include "input.h"
-+#include "tree.h"
-+
-+#include "tree-inline.h"
-+#include "version.h"
-+#include "rtl.h"
-+#include "tm_p.h"
-+#include "flags.h"
-+//#include "insn-attr.h"
-+//#include "insn-config.h"
-+//#include "insn-flags.h"
-+#include "hard-reg-set.h"
-+//#include "recog.h"
-+#include "output.h"
-+#include "except.h"
-+#include "function.h"
-+#include "toplev.h"
-+//#include "expr.h"
-+#include "basic-block.h"
-+#include "intl.h"
-+#include "ggc.h"
-+//#include "regs.h"
-+#include "timevar.h"
-+
-+#include "params.h"
-+
-+#if BUILDING_GCC_VERSION <= 4009
-+#include "pointer-set.h"
-+#else
-+#include "hash-map.h"
++#include "tree-inline.h"
++#include "version.h"
++#include "rtl.h"
++#include "tm_p.h"
++#include "flags.h"
++//#include "insn-attr.h"
++//#include "insn-config.h"
++//#include "insn-flags.h"
++#include "hard-reg-set.h"
++//#include "recog.h"
++#include "output.h"
++#include "except.h"
++#include "function.h"
++#include "toplev.h"
++//#include "expr.h"
++#include "basic-block.h"
++#include "intl.h"
++#include "ggc.h"
++//#include "regs.h"
++#include "timevar.h"
++
++#include "params.h"
++
++#if BUILDING_GCC_VERSION <= 4009
++#include "pointer-set.h"
++#else
++#include "hash-map.h"
 +#endif
 +
 +#include "emit-rtl.h"
@@ -166240,11 +163512,11 @@ index 0000000..0c0b842
 +#endif
 +
 +#endif
-diff --git a/tools/gcc/gcc-generate-gimple-pass.h b/tools/gcc/gcc-generate-gimple-pass.h
+diff --git a/scripts/gcc-plugins/gcc-generate-gimple-pass.h b/scripts/gcc-plugins/gcc-generate-gimple-pass.h
 new file mode 100644
 index 0000000..0b081fe
 --- /dev/null
-+++ b/tools/gcc/gcc-generate-gimple-pass.h
++++ b/scripts/gcc-plugins/gcc-generate-gimple-pass.h
 @@ -0,0 +1,175 @@
 +/*
 + * Generator for GIMPLE pass related boilerplate code/data
@@ -166421,11 +163693,11 @@ index 0000000..0b081fe
 +#undef __PASS_NAME_PASS_DATA
 +
 +#endif /* PASS_NAME */
-diff --git a/tools/gcc/gcc-generate-ipa-pass.h b/tools/gcc/gcc-generate-ipa-pass.h
+diff --git a/scripts/gcc-plugins/gcc-generate-ipa-pass.h b/scripts/gcc-plugins/gcc-generate-ipa-pass.h
 new file mode 100644
 index 0000000..9bd926e
 --- /dev/null
-+++ b/tools/gcc/gcc-generate-ipa-pass.h
++++ b/scripts/gcc-plugins/gcc-generate-ipa-pass.h
 @@ -0,0 +1,289 @@
 +/*
 + * Generator for IPA pass related boilerplate code/data
@@ -166716,11 +163988,11 @@ index 0000000..9bd926e
 +#undef __WRITE_SUMMARY
 +
 +#endif /* PASS_NAME */
-diff --git a/tools/gcc/gcc-generate-rtl-pass.h b/tools/gcc/gcc-generate-rtl-pass.h
+diff --git a/scripts/gcc-plugins/gcc-generate-rtl-pass.h b/scripts/gcc-plugins/gcc-generate-rtl-pass.h
 new file mode 100644
 index 0000000..1dc67a5
 --- /dev/null
-+++ b/tools/gcc/gcc-generate-rtl-pass.h
++++ b/scripts/gcc-plugins/gcc-generate-rtl-pass.h
 @@ -0,0 +1,175 @@
 +/*
 + * Generator for RTL pass related boilerplate code/data
@@ -166897,11 +164169,11 @@ index 0000000..1dc67a5
 +#undef __PASS_NAME_PASS_DATA
 +
 +#endif /* PASS_NAME */
-diff --git a/tools/gcc/gcc-generate-simple_ipa-pass.h b/tools/gcc/gcc-generate-simple_ipa-pass.h
+diff --git a/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h b/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h
 new file mode 100644
 index 0000000..a27e2b3
 --- /dev/null
-+++ b/tools/gcc/gcc-generate-simple_ipa-pass.h
++++ b/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h
 @@ -0,0 +1,175 @@
 +/*
 + * Generator for SIMPLE_IPA pass related boilerplate code/data
@@ -167078,11 +164350,11 @@ index 0000000..a27e2b3
 +#undef __PASS_NAME_PASS_DATA
 +
 +#endif /* PASS_NAME */
-diff --git a/tools/gcc/gen-random-seed.sh b/tools/gcc/gen-random-seed.sh
+diff --git a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh
 new file mode 100644
 index 0000000..7514850
 --- /dev/null
-+++ b/tools/gcc/gen-random-seed.sh
++++ b/scripts/gcc-plugins/gen-random-seed.sh
 @@ -0,0 +1,8 @@
 +#!/bin/sh
 +
@@ -167092,11 +164364,11 @@ index 0000000..7514850
 +	HASH=`echo -n "$SEED" | sha256sum | cut -d" " -f1 | tr -d ' \n'`
 +	echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2"
 +fi
-diff --git a/tools/gcc/initify_plugin.c b/tools/gcc/initify_plugin.c
+diff --git a/scripts/gcc-plugins/initify_plugin.c b/scripts/gcc-plugins/initify_plugin.c
 new file mode 100644
 index 0000000..bf3eb6c
 --- /dev/null
-+++ b/tools/gcc/initify_plugin.c
++++ b/scripts/gcc-plugins/initify_plugin.c
 @@ -0,0 +1,536 @@
 +/*
 + * Copyright 2015-2016 by Emese Revfy <re.emese@gmail.com>
@@ -167634,11 +164906,11 @@ index 0000000..bf3eb6c
 +
 +	return 0;
 +}
-diff --git a/tools/gcc/kallocstat_plugin.c b/tools/gcc/kallocstat_plugin.c
+diff --git a/scripts/gcc-plugins/kallocstat_plugin.c b/scripts/gcc-plugins/kallocstat_plugin.c
 new file mode 100644
 index 0000000..30ecc9a
 --- /dev/null
-+++ b/tools/gcc/kallocstat_plugin.c
++++ b/scripts/gcc-plugins/kallocstat_plugin.c
 @@ -0,0 +1,135 @@
 +/*
 + * Copyright 2011-2016 by the PaX Team <pageexec@freemail.hu>
@@ -167775,11 +165047,11 @@ index 0000000..30ecc9a
 +
 +	return 0;
 +}
-diff --git a/tools/gcc/kernexec_plugin.c b/tools/gcc/kernexec_plugin.c
+diff --git a/scripts/gcc-plugins/kernexec_plugin.c b/scripts/gcc-plugins/kernexec_plugin.c
 new file mode 100644
 index 0000000..e31e92f
 --- /dev/null
-+++ b/tools/gcc/kernexec_plugin.c
++++ b/scripts/gcc-plugins/kernexec_plugin.c
 @@ -0,0 +1,407 @@
 +/*
 + * Copyright 2011-2016 by the PaX Team <pageexec@freemail.hu>
@@ -168188,12 +165460,12 @@ index 0000000..e31e92f
 +
 +	return 0;
 +}
-diff --git a/tools/gcc/latent_entropy_plugin.c b/tools/gcc/latent_entropy_plugin.c
+diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c
 new file mode 100644
-index 0000000..50d373c
+index 0000000..f08a221
 --- /dev/null
-+++ b/tools/gcc/latent_entropy_plugin.c
-@@ -0,0 +1,422 @@
++++ b/scripts/gcc-plugins/latent_entropy_plugin.c
+@@ -0,0 +1,438 @@
 +/*
 + * Copyright 2012-2016 by the PaX Team <pageexec@freemail.hu>
 + * Licensed under the GPL v2
@@ -168219,11 +165491,13 @@ index 0000000..50d373c
 +
 +int plugin_is_GPL_compatible;
 +
++static bool enabled = true;
++
 +static GTY(()) tree latent_entropy_decl;
 +
 +static struct plugin_info latent_entropy_plugin_info = {
-+	.version	= "201604022010",
-+	.help		= NULL
++	.version	= "201605212030",
++	.help		= "disable\tturn off latent entropy instrumentation\n",
 +};
 +
 +static unsigned HOST_WIDE_INT seed;
@@ -168586,6 +165860,10 @@ index 0000000..50d373c
 +int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
 +{
 +	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	int i;
++
 +	struct register_pass_info latent_entropy_pass_info;
 +
 +	latent_entropy_pass_info.pass				= make_latent_entropy_pass();
@@ -168608,19 +165886,29 @@ index 0000000..50d373c
 +		return 1;
 +	}
 +
++	for (i = 0; i < argc; ++i) {
++		if (!(strcmp(argv[i].key, "disable"))) {
++			enabled = false;
++			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
++
 +	register_callback(plugin_name, PLUGIN_INFO, NULL, &latent_entropy_plugin_info);
-+	register_callback(plugin_name, PLUGIN_START_UNIT, &latent_entropy_start_unit, NULL);
-+	register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_latent_entropy);
-+	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &latent_entropy_pass_info);
++	if (enabled) {
++		register_callback(plugin_name, PLUGIN_START_UNIT, &latent_entropy_start_unit, NULL);
++		register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_latent_entropy);
++		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/randomize_layout_plugin.c b/tools/gcc/randomize_layout_plugin.c
+diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
 new file mode 100644
 index 0000000..a716d7a
 --- /dev/null
-+++ b/tools/gcc/randomize_layout_plugin.c
++++ b/scripts/gcc-plugins/randomize_layout_plugin.c
 @@ -0,0 +1,940 @@
 +/*
 + * Copyright 2014-2016 by Open Source Security, Inc., Brad Spengler <spender@grsecurity.net>
@@ -169562,21 +166850,21 @@ index 0000000..a716d7a
 +
 +	return 0;
 +}
-diff --git a/tools/gcc/rap_plugin/Makefile b/tools/gcc/rap_plugin/Makefile
+diff --git a/scripts/gcc-plugins/rap_plugin/Makefile b/scripts/gcc-plugins/rap_plugin/Makefile
 new file mode 100644
 index 0000000..8171be8
 --- /dev/null
-+++ b/tools/gcc/rap_plugin/Makefile
++++ b/scripts/gcc-plugins/rap_plugin/Makefile
 @@ -0,0 +1,4 @@
 +$(HOSTLIBS)-$(CONFIG_PAX_RAP) += rap_plugin.so
 +always := $($(HOSTLIBS)-y)
 +
 +rap_plugin-objs := $(patsubst $(srctree)/$(src)/%.c,%.o,$(wildcard $(srctree)/$(src)/*.c))
-diff --git a/tools/gcc/rap_plugin/rap.h b/tools/gcc/rap_plugin/rap.h
+diff --git a/scripts/gcc-plugins/rap_plugin/rap.h b/scripts/gcc-plugins/rap_plugin/rap.h
 new file mode 100644
 index 0000000..f6a284d
 --- /dev/null
-+++ b/tools/gcc/rap_plugin/rap.h
++++ b/scripts/gcc-plugins/rap_plugin/rap.h
 @@ -0,0 +1,36 @@
 +#ifndef RAP_H_INCLUDED
 +#define RAP_H_INCLUDED
@@ -169614,11 +166902,11 @@ index 0000000..f6a284d
 +#endif
 +
 +#endif
-diff --git a/tools/gcc/rap_plugin/rap_fptr_pass.c b/tools/gcc/rap_plugin/rap_fptr_pass.c
+diff --git a/scripts/gcc-plugins/rap_plugin/rap_fptr_pass.c b/scripts/gcc-plugins/rap_plugin/rap_fptr_pass.c
 new file mode 100644
 index 0000000..2f53f14
 --- /dev/null
-+++ b/tools/gcc/rap_plugin/rap_fptr_pass.c
++++ b/scripts/gcc-plugins/rap_plugin/rap_fptr_pass.c
 @@ -0,0 +1,220 @@
 +/*
 + * Copyright 2012-2016 by PaX Team <pageexec@freemail.hu>
@@ -169840,11 +167128,11 @@ index 0000000..2f53f14
 +#define PASS_NAME rap_fptr
 +#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_remove_unused_locals | TODO_update_ssa | TODO_cleanup_cfg | TODO_rebuild_cgraph_edges | TODO_verify_flow
 +#include "gcc-generate-gimple-pass.h"
-diff --git a/tools/gcc/rap_plugin/rap_hash.c b/tools/gcc/rap_plugin/rap_hash.c
+diff --git a/scripts/gcc-plugins/rap_plugin/rap_hash.c b/scripts/gcc-plugins/rap_plugin/rap_hash.c
 new file mode 100644
 index 0000000..7c59f38
 --- /dev/null
-+++ b/tools/gcc/rap_plugin/rap_hash.c
++++ b/scripts/gcc-plugins/rap_plugin/rap_hash.c
 @@ -0,0 +1,382 @@
 +/*
 + * Copyright 2012-2016 by PaX Team <pageexec@freemail.hu>
@@ -170228,11 +167516,11 @@ index 0000000..7c59f38
 +		gcc_assert(rap_imprecise_hashes[uid].hash);
 +	}
 +}
-diff --git a/tools/gcc/rap_plugin/rap_plugin.c b/tools/gcc/rap_plugin/rap_plugin.c
+diff --git a/scripts/gcc-plugins/rap_plugin/rap_plugin.c b/scripts/gcc-plugins/rap_plugin/rap_plugin.c
 new file mode 100644
 index 0000000..bca74dc
 --- /dev/null
-+++ b/tools/gcc/rap_plugin/rap_plugin.c
++++ b/scripts/gcc-plugins/rap_plugin/rap_plugin.c
 @@ -0,0 +1,511 @@
 +/*
 + * Copyright 2012-2016 by PaX Team <pageexec@freemail.hu>
@@ -170745,11 +168033,11 @@ index 0000000..bca74dc
 +
 +	return 0;
 +}
-diff --git a/tools/gcc/rap_plugin/sip.c b/tools/gcc/rap_plugin/sip.c
+diff --git a/scripts/gcc-plugins/rap_plugin/sip.c b/scripts/gcc-plugins/rap_plugin/sip.c
 new file mode 100644
 index 0000000..65bc1cd
 --- /dev/null
-+++ b/tools/gcc/rap_plugin/sip.c
++++ b/scripts/gcc-plugins/rap_plugin/sip.c
 @@ -0,0 +1,96 @@
 +// SipHash-2-4 adapted by the PaX Team from the public domain version written by
 +//   Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
@@ -170847,20 +168135,20 @@ index 0000000..65bc1cd
 +	b = v0 ^ v1 ^ v2 ^ v3;
 +	U64TO8_LE(out, b);
 +}
-diff --git a/tools/gcc/size_overflow_plugin/.gitignore b/tools/gcc/size_overflow_plugin/.gitignore
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/.gitignore b/scripts/gcc-plugins/size_overflow_plugin/.gitignore
 new file mode 100644
 index 0000000..c4b24b9
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/.gitignore
++++ b/scripts/gcc-plugins/size_overflow_plugin/.gitignore
 @@ -0,0 +1,3 @@
 +disable_size_overflow_hash.h
 +size_overflow_hash.h
 +size_overflow_hash_aux.h
-diff --git a/tools/gcc/size_overflow_plugin/Makefile b/tools/gcc/size_overflow_plugin/Makefile
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/Makefile b/scripts/gcc-plugins/size_overflow_plugin/Makefile
 new file mode 100644
 index 0000000..f74d85a
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/Makefile
++++ b/scripts/gcc-plugins/size_overflow_plugin/Makefile
 @@ -0,0 +1,28 @@
 +HOST_EXTRACXXFLAGS += $(call hostcc-option, -fno-ipa-icf)
 +
@@ -170890,11 +168178,11 @@ index 0000000..f74d85a
 +	$(call if_changed,build_disable_size_overflow_hash)
 +
 +targets += size_overflow_hash.h size_overflow_hash_aux.h disable_size_overflow_hash.h
-diff --git a/tools/gcc/size_overflow_plugin/disable_size_overflow_hash.data b/tools/gcc/size_overflow_plugin/disable_size_overflow_hash.data
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/disable_size_overflow_hash.data b/scripts/gcc-plugins/size_overflow_plugin/disable_size_overflow_hash.data
 new file mode 100644
 index 0000000..2a420f3
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/disable_size_overflow_hash.data
++++ b/scripts/gcc-plugins/size_overflow_plugin/disable_size_overflow_hash.data
 @@ -0,0 +1,12444 @@
 +disable_so_interrupt_pnode_gru_message_queue_desc_4 interrupt_pnode gru_message_queue_desc 0 4 NULL
 +disable_so_bch_btree_insert_fndecl_12 bch_btree_insert fndecl 0 12 NULL
@@ -183340,11 +180628,11 @@ index 0000000..2a420f3
 +enable_so_inofree_iagctl_5194 inofree iagctl 0 5194 NULL
 +enable_so_inofreefwd_iag_4921 inofreefwd iag 0 4921 NULL
 +enable_so_iagnum_iag_23227 iagnum iag 0 23227 NULL
-diff --git a/tools/gcc/size_overflow_plugin/generate_size_overflow_hash.sh b/tools/gcc/size_overflow_plugin/generate_size_overflow_hash.sh
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/generate_size_overflow_hash.sh b/scripts/gcc-plugins/size_overflow_plugin/generate_size_overflow_hash.sh
 new file mode 100644
 index 0000000..be9724d
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/generate_size_overflow_hash.sh
++++ b/scripts/gcc-plugins/size_overflow_plugin/generate_size_overflow_hash.sh
 @@ -0,0 +1,103 @@
 +#!/bin/bash
 +
@@ -183449,11 +180737,11 @@ index 0000000..be9724d
 +create_array_elements
 +
 +exit 0
-diff --git a/tools/gcc/size_overflow_plugin/insert_size_overflow_asm.c b/tools/gcc/size_overflow_plugin/insert_size_overflow_asm.c
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/insert_size_overflow_asm.c b/scripts/gcc-plugins/size_overflow_plugin/insert_size_overflow_asm.c
 new file mode 100644
 index 0000000..ee987da
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/insert_size_overflow_asm.c
++++ b/scripts/gcc-plugins/size_overflow_plugin/insert_size_overflow_asm.c
 @@ -0,0 +1,369 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
@@ -183824,11 +181112,11 @@ index 0000000..ee987da
 +#define TODO_FLAGS_FINISH TODO_dump_func | TODO_verify_ssa | TODO_verify_stmts | TODO_remove_unused_locals | TODO_update_ssa_no_phi | TODO_cleanup_cfg | TODO_ggc_collect | TODO_verify_flow
 +
 +#include "gcc-generate-gimple-pass.h"
-diff --git a/tools/gcc/size_overflow_plugin/intentional_overflow.c b/tools/gcc/size_overflow_plugin/intentional_overflow.c
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/intentional_overflow.c b/scripts/gcc-plugins/size_overflow_plugin/intentional_overflow.c
 new file mode 100644
-index 0000000..6fcc436
+index 0000000..f29aac6
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/intentional_overflow.c
++++ b/scripts/gcc-plugins/size_overflow_plugin/intentional_overflow.c
 @@ -0,0 +1,1166 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
@@ -184963,7 +182251,7 @@ index 0000000..6fcc436
 +{
 +	const_tree rhs, lhs_type, rhs_type;
 +	const_tree def_rhs1, def_rhs2;
-+	gimple def_stmt;
++	const_gimple def_stmt;
 +	gimple def_def_stmt = NULL;
 +
 +	if (!gimple_assign_cast_p(stmt))
@@ -184996,11 +182284,11 @@ index 0000000..6fcc436
 +	// _36 = (signed short) _35;
 +	return def_def_stmt && gimple_assign_cast_p(def_def_stmt);
 +}
-diff --git a/tools/gcc/size_overflow_plugin/remove_unnecessary_dup.c b/tools/gcc/size_overflow_plugin/remove_unnecessary_dup.c
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/remove_unnecessary_dup.c b/scripts/gcc-plugins/size_overflow_plugin/remove_unnecessary_dup.c
 new file mode 100644
 index 0000000..c910983
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/remove_unnecessary_dup.c
++++ b/scripts/gcc-plugins/size_overflow_plugin/remove_unnecessary_dup.c
 @@ -0,0 +1,137 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
@@ -185139,11 +182427,11 @@ index 0000000..c910983
 +	}
 +}
 +
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow.h b/tools/gcc/size_overflow_plugin/size_overflow.h
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow.h b/scripts/gcc-plugins/size_overflow_plugin/size_overflow.h
 new file mode 100644
 index 0000000..4bd2e7f
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow.h
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow.h
 @@ -0,0 +1,331 @@
 +#ifndef SIZE_OVERFLOW_H
 +#define SIZE_OVERFLOW_H
@@ -185476,11 +182764,11 @@ index 0000000..4bd2e7f
 +extern const char * __unused print_intentional_mark_name(enum intentional_mark mark);
 +
 +#endif
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_debug.c b/tools/gcc/size_overflow_plugin/size_overflow_debug.c
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_debug.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_debug.c
 new file mode 100644
 index 0000000..4098952
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_debug.c
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_debug.c
 @@ -0,0 +1,194 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
@@ -185676,11 +182964,11 @@ index 0000000..4098952
 +
 +	gcc_unreachable();
 +}
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_hash.data b/tools/gcc/size_overflow_plugin/size_overflow_hash.data
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data
 new file mode 100644
 index 0000000..cbb8a80
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_hash.data
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash.data
 @@ -0,0 +1,21645 @@
 +enable_so_recv_ctrl_pipe_us_data_0 recv_ctrl_pipe us_data 0 0 NULL
 +enable_so___earlyonly_bootmem_alloc_fndecl_3 __earlyonly_bootmem_alloc fndecl 2-3-4 3 NULL
@@ -207327,11 +204615,11 @@ index 0000000..cbb8a80
 +enable_so_write_page_nocow_fndecl_65527 write_page_nocow fndecl 2 65527 NULL
 +enable_so_size_mei_msg_data_65529 size mei_msg_data 0 65529 NULL
 +enable_so_connector_write_fndecl_65534 connector_write fndecl 3 65534 NULL
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_hash_aux.data b/tools/gcc/size_overflow_plugin/size_overflow_hash_aux.data
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash_aux.data b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash_aux.data
 new file mode 100644
 index 0000000..17bc0d8
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_hash_aux.data
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_hash_aux.data
 @@ -0,0 +1,92 @@
 +enable_so_spa_set_aux_vdevs_fndecl_746 spa_set_aux_vdevs fndecl 3 746 NULL
 +enable_so_zfs_lookup_fndecl_2144 zfs_lookup fndecl 0 2144 NULL
@@ -207425,11 +204713,11 @@ index 0000000..17bc0d8
 +enable_so_proc_copyin_string_fndecl_62019 proc_copyin_string fndecl 4 62019 NULL
 +enable_so_random_get_pseudo_bytes_fndecl_64611 random_get_pseudo_bytes fndecl 2 64611 NULL
 +enable_so_zpios_read_fndecl_64734 zpios_read fndecl 3 64734 NULL
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_ipa.c b/tools/gcc/size_overflow_plugin/size_overflow_ipa.c
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_ipa.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_ipa.c
 new file mode 100644
 index 0000000..0a679f8
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_ipa.c
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_ipa.c
 @@ -0,0 +1,1163 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
@@ -207445,1161 +204733,2326 @@ index 0000000..0a679f8
 + * with double integer precision (DImode/TImode for 32/64 bit integer types).
 + * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
 + *
-+ * Usage:
-+ * $ make
-+ * $ make run
++ * Usage:
++ * $ make
++ * $ make run
++ */
++
++#include "size_overflow.h"
++#include <libgen.h>
++
++static void walk_use_def_next_functions(struct walk_use_def_data *use_def_data, tree lhs);
++
++next_interesting_function_t global_next_interesting_function[GLOBAL_NIFN_LEN];
++static bool global_changed;
++#define PRINT_DATA_FLOW true
++#define NO_PRINT_DATA_FLOW false
++
++static struct cgraph_node_hook_list *function_insertion_hook_holder;
++static struct cgraph_2node_hook_list *node_duplication_hook_holder;
++
++struct cgraph_node *get_cnode(const_tree fndecl)
++{
++	gcc_assert(TREE_CODE(fndecl) == FUNCTION_DECL);
++#if BUILDING_GCC_VERSION <= 4005
++	return cgraph_get_node(CONST_CAST_TREE(fndecl));
++#else
++	return cgraph_get_node(fndecl);
++#endif
++}
++
++static bool compare_next_interesting_functions(next_interesting_function_t cur_node, const char *decl_name, const char *context, unsigned int num)
++{
++	// Ignore num without a value
++	if (num != NONE_ARGNUM && cur_node->num != num)
++		return false;
++	if (strcmp(cur_node->context, context))
++		return false;
++	return !strcmp(cur_node->decl_name, decl_name);
++}
++
++// Return the context of vardecl. If it is in a file scope then the context is vardecl_filebasename
++static const char* get_vardecl_context(const_tree decl)
++{
++	expanded_location xloc;
++	char *buf, *path;
++	const char *bname;
++	int len;
++
++	xloc = expand_location(DECL_SOURCE_LOCATION(decl));
++	gcc_assert(xloc.file);
++	path = xstrdup(xloc.file);
++	bname = basename(path);
++
++	len = asprintf(&buf, "vardecl_%s", bname);
++	gcc_assert(len > 0);
++	return buf;
++}
++
++// Return the type name for a function pointer (or "fielddecl" if the type has no name), otherwise either "vardecl" or "fndecl"
++const char* get_decl_context(const_tree decl)
++{
++	switch (TREE_CODE(decl)) {
++	case FUNCTION_DECL:
++		return "fndecl";
++		// TODO: Ignore anonymous types for now
++	case FIELD_DECL:
++		return get_type_name_from_field(decl);
++	case VAR_DECL:
++		if (TREE_PUBLIC(decl) || DECL_EXTERNAL(decl))
++			return "vardecl";
++		if (TREE_STATIC(decl) && !TREE_PUBLIC(decl))
++			return get_vardecl_context(decl);
++		// ignore local variable
++		if (!TREE_STATIC(decl) && !DECL_EXTERNAL(decl))
++			return NULL;
++	default:
++		debug_tree(decl);
++		gcc_unreachable();
++	}
++}
++
++// Find the function with the specified argument in the list
++next_interesting_function_t get_global_next_interesting_function_entry(struct fn_raw_data *raw_data)
++{
++	next_interesting_function_t cur_node, head;
++
++	head = global_next_interesting_function[raw_data->hash];
++	for (cur_node = head; cur_node; cur_node = cur_node->next) {
++		if (raw_data->marked != ASM_STMT_SO_MARK && cur_node->marked == ASM_STMT_SO_MARK)
++			continue;
++		if (compare_next_interesting_functions(cur_node, raw_data->decl_str, raw_data->context, raw_data->num))
++			return cur_node;
++	}
++	return NULL;
++}
++
++next_interesting_function_t get_global_next_interesting_function_entry_with_hash(struct fn_raw_data *raw_data)
++{
++	raw_data->hash = get_decl_hash(raw_data->decl, raw_data->decl_str);
++	if (raw_data->hash == NO_HASH)
++		return NULL;
++
++	raw_data->context = get_decl_context(raw_data->decl);
++	if (!raw_data->context)
++		return NULL;
++	return get_global_next_interesting_function_entry(raw_data);
++}
++
++next_interesting_function_t create_new_next_interesting_entry(struct fn_raw_data *raw_data, next_interesting_function_t orig_next_node)
++{
++	next_interesting_function_t new_node;
++
++	new_node = (next_interesting_function_t)xmalloc(sizeof(*new_node));
++	new_node->decl_name = xstrdup(raw_data->decl_str);
++
++	gcc_assert(raw_data->context);
++	new_node->context = xstrdup(raw_data->context);
++	new_node->hash = raw_data->hash;
++	new_node->num = raw_data->num;
++	new_node->next = NULL;
++	new_node->children = NULL;
++	new_node->marked = raw_data->marked;
++	new_node->orig_next_node = orig_next_node;
++	return new_node;
++}
++
++// Ignore these functions to not explode coverage (+strncmp+fndecl+3+35130+)
++static bool temporary_skip_these_functions(struct fn_raw_data *raw_data)
++{
++	if (raw_data->hash == 35130 && !strcmp(raw_data->decl_str, "strncmp"))
++		return true;
++	if (raw_data->hash == 46193 && !strcmp(raw_data->decl_str, "strnlen"))
++		return true;
++	if (raw_data->hash == 43267 && !strcmp(raw_data->decl_str, "strncpy"))
++		return true;
++	if (raw_data->hash == 10300 && !strcmp(raw_data->decl_str, "strncpy_from_user"))
++		return true;
++	if (raw_data->hash == 26117 && !strcmp(raw_data->decl_str, "memchr"))
++		return true;
++	if (raw_data->hash == 16203 && !strcmp(raw_data->decl_str, "memchr_inv"))
++		return true;
++	if (raw_data->hash == 24269 && !strcmp(raw_data->decl_str, "memcmp"))
++		return true;
++	if (raw_data->hash == 60390 && !strcmp(raw_data->decl_str, "memcpy"))
++		return true;
++	if (raw_data->hash == 25040 && !strcmp(raw_data->decl_str, "memmove"))
++		return true;
++	if (raw_data->hash == 29763 && !strcmp(raw_data->decl_str, "memset"))
++		return true;
++	return false;
++}
++
++// Create the main data structure
++next_interesting_function_t create_new_next_interesting_decl(struct fn_raw_data *raw_data, next_interesting_function_t orig_next_node)
++{
++	enum tree_code decl_code = TREE_CODE(raw_data->decl);
++
++	gcc_assert(decl_code == FIELD_DECL || decl_code == FUNCTION_DECL || decl_code == VAR_DECL);
++
++	if (is_vararg(raw_data->decl, raw_data->num))
++		return NULL;
++
++	raw_data->hash = get_decl_hash(raw_data->decl, raw_data->decl_str);
++	if (raw_data->hash == NO_HASH)
++		return NULL;
++	if (get_size_overflow_hash_entry_tree(raw_data->decl, raw_data->num, DISABLE_SIZE_OVERFLOW))
++		return NULL;
++	if (temporary_skip_these_functions(raw_data))
++		return NULL;
++
++	gcc_assert(raw_data->num <= MAX_PARAM);
++	// Clones must have an orig_next_node
++	gcc_assert(!made_by_compiler(raw_data->decl) || orig_next_node);
++
++	raw_data->context = get_decl_context(raw_data->decl);
++	if (!raw_data->context)
++		return NULL;
++	return create_new_next_interesting_entry(raw_data, orig_next_node);
++}
++
++void add_to_global_next_interesting_function(next_interesting_function_t new_entry)
++{
++	next_interesting_function_t cur_global_head, cur_global, cur_global_end = NULL;
++
++	// new_entry is appended to the end of a list
++	new_entry->next = NULL;
++
++	cur_global_head = global_next_interesting_function[new_entry->hash];
++	if (!cur_global_head) {
++		global_next_interesting_function[new_entry->hash] = new_entry;
++		return;
++	}
++
++
++	for (cur_global = cur_global_head; cur_global; cur_global = cur_global->next) {
++		if (!cur_global->next)
++			cur_global_end = cur_global;
++
++		if (compare_next_interesting_functions(cur_global, new_entry->decl_name, new_entry->context, new_entry->num))
++			return;
++	}
++
++	gcc_assert(cur_global_end);
++	cur_global_end->next = new_entry;
++}
++
++/* If the interesting function is a clone then find or create its original next_interesting_function_t node
++ * and add it to global_next_interesting_function
++ */
++static next_interesting_function_t create_orig_next_node_for_a_clone(struct fn_raw_data *clone_raw_data)
++{
++	struct fn_raw_data orig_raw_data;
++	next_interesting_function_t orig_next_node;
++	enum tree_code decl_code;
++
++	orig_raw_data.decl = get_orig_fndecl(clone_raw_data->decl);
++
++	if (DECL_BUILT_IN(orig_raw_data.decl) || DECL_BUILT_IN_CLASS(orig_raw_data.decl) == BUILT_IN_NORMAL)
++		return NULL;
++
++	if (made_by_compiler(orig_raw_data.decl))
++		return NULL;
++
++	decl_code = TREE_CODE(orig_raw_data.decl);
++	if (decl_code == FIELD_DECL || decl_code == VAR_DECL)
++		orig_raw_data.num = clone_raw_data->num;
++	else
++		orig_raw_data.num = get_correct_argnum(clone_raw_data->decl, orig_raw_data.decl, clone_raw_data->num);
++
++	// Skip over ISRA.162 parm decls
++	if (orig_raw_data.num == CANNOT_FIND_ARG)
++		return NULL;
++
++	orig_raw_data.decl_str = get_orig_decl_name(orig_raw_data.decl);
++	orig_raw_data.marked = NO_SO_MARK;
++	orig_next_node = get_global_next_interesting_function_entry_with_hash(&orig_raw_data);
++	if (orig_next_node)
++		return orig_next_node;
++
++	orig_raw_data.marked = clone_raw_data->marked;
++	orig_next_node = create_new_next_interesting_decl(&orig_raw_data, NULL);
++	if (!orig_next_node)
++		return NULL;
++
++	add_to_global_next_interesting_function(orig_next_node);
++	return orig_next_node;
++}
++
++// Find or create the next_interesting_function_t node for decl and num
++next_interesting_function_t get_and_create_next_node_from_global_next_nodes(struct fn_raw_data *raw_data, next_interesting_function_t orig_next_node)
++{
++	next_interesting_function_t cur_next_cnode;
++
++	if (DECL_NAME(raw_data->decl) == NULL_TREE)
++		return NULL;
++	raw_data->decl_str = DECL_NAME_POINTER(raw_data->decl);
++
++	cur_next_cnode = get_global_next_interesting_function_entry_with_hash(raw_data);
++	if (cur_next_cnode)
++		goto out;
++
++	if (!orig_next_node && made_by_compiler(raw_data->decl)) {
++		orig_next_node = create_orig_next_node_for_a_clone(raw_data);
++		if (!orig_next_node)
++			return NULL;
++	}
++
++	cur_next_cnode = create_new_next_interesting_decl(raw_data, orig_next_node);
++	if (!cur_next_cnode)
++		return NULL;
++
++	add_to_global_next_interesting_function(cur_next_cnode);
++out:
++	if (cur_next_cnode->marked != raw_data->marked && cur_next_cnode->marked != NO_SO_MARK)
++		return cur_next_cnode;
++
++	if (raw_data->marked != NO_SO_MARK && cur_next_cnode->marked == NO_SO_MARK)
++		cur_next_cnode->marked = raw_data->marked;
++
++	return cur_next_cnode;
++}
++
++static bool has_next_interesting_function_chain_node(next_interesting_function_t next_cnodes_head, struct fn_raw_data *raw_data)
++{
++	next_interesting_function_t cur_node;
++
++	raw_data->decl_str = DECL_NAME_POINTER(raw_data->decl);
++	raw_data->context = get_decl_context(raw_data->decl);
++	// Ignore function if there is no context
++	if (!raw_data->context)
++		return true;
++
++	for (cur_node = next_cnodes_head; cur_node; cur_node = cur_node->next) {
++		if (compare_next_interesting_functions(cur_node, raw_data->decl_str, raw_data->context, raw_data->num))
++			return true;
++	}
++	return false;
++}
++
++static void handle_function(struct walk_use_def_data *use_def_data, tree fndecl, const_tree arg)
++{
++	struct fn_raw_data raw_data;
++	next_interesting_function_t orig_next_node, new_node;
++
++	gcc_assert(fndecl != NULL_TREE);
++
++	// ignore builtins to not explode coverage (e.g., memcpy)
++	if (DECL_BUILT_IN(fndecl) || DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_NORMAL)
++		return;
++
++	if (get_intentional_attr_type(fndecl) == MARK_TURN_OFF)
++		return;
++
++	raw_data.decl = fndecl;
++	raw_data.decl_str = DECL_NAME_POINTER(fndecl);
++	raw_data.marked = NO_SO_MARK;
++
++	// convert arg into its position
++	if (arg == NULL_TREE)
++		raw_data.num = 0;
++	else
++		raw_data.num = find_arg_number_tree(arg, raw_data.decl);
++	if (raw_data.num == CANNOT_FIND_ARG)
++		return;
++
++	if (has_next_interesting_function_chain_node(use_def_data->next_cnodes_head, &raw_data))
++		return;
++
++	if (made_by_compiler(raw_data.decl)) {
++		orig_next_node = create_orig_next_node_for_a_clone(&raw_data);
++		if (!orig_next_node)
++			return;
++	} else
++		orig_next_node = NULL;
++
++	new_node = create_new_next_interesting_decl(&raw_data, orig_next_node);
++	if (!new_node)
++		return;
++	new_node->next = use_def_data->next_cnodes_head;
++	use_def_data->next_cnodes_head = new_node;
++}
++
++static void walk_use_def_next_functions_phi(struct walk_use_def_data *use_def_data, const_tree result)
++{
++	gphi *phi = as_a_gphi(get_def_stmt(result));
++	unsigned int i, n = gimple_phi_num_args(phi);
++
++	pointer_set_insert(use_def_data->visited, phi);
++	for (i = 0; i < n; i++) {
++		tree arg = gimple_phi_arg_def(phi, i);
++
++		walk_use_def_next_functions(use_def_data, arg);
++	}
++}
++
++static void walk_use_def_next_functions_binary(struct walk_use_def_data *use_def_data, const_tree lhs)
++{
++	gassign *def_stmt = as_a_gassign(get_def_stmt(lhs));
++	tree rhs1, rhs2;
++
++	rhs1 = gimple_assign_rhs1(def_stmt);
++	rhs2 = gimple_assign_rhs2(def_stmt);
++
++	walk_use_def_next_functions(use_def_data, rhs1);
++	walk_use_def_next_functions(use_def_data, rhs2);
++}
++
++static void walk_use_def_next_functions_unary(struct walk_use_def_data *use_def_data, const gassign *stmt)
++{
++	tree rhs1 = gimple_assign_rhs1(stmt);
++
++	walk_use_def_next_functions(use_def_data, rhs1);
++}
++
++void __attribute__((weak)) handle_function_ptr_ret(struct walk_use_def_data *use_def_data __unused, const_tree fn_ptr __unused)
++{
++}
++
++static void create_and_append_new_next_interesting_field_var_decl(struct walk_use_def_data *use_def_data, struct fn_raw_data *raw_data)
++{
++	next_interesting_function_t new_node;
++
++	if (raw_data->decl == NULL_TREE)
++		return;
++
++	if (DECL_NAME(raw_data->decl) == NULL_TREE)
++		return;
++
++	raw_data->decl_str = DECL_NAME_POINTER(raw_data->decl);
++	raw_data->num = 0;
++	raw_data->marked = NO_SO_MARK;
++
++	new_node = create_new_next_interesting_decl(raw_data, NULL);
++	if (!new_node)
++		return;
++	new_node->next = use_def_data->next_cnodes_head;
++	use_def_data->next_cnodes_head = new_node;
++}
++
++static void handle_struct_fields(struct walk_use_def_data *use_def_data, const_tree node)
++{
++	struct fn_raw_data raw_data;
++
++	switch (TREE_CODE(node)) {
++	case ARRAY_REF:
++#if BUILDING_GCC_VERSION >= 4006
++	case MEM_REF:
++#endif
++	case INDIRECT_REF:
++	case COMPONENT_REF:
++		raw_data.decl = get_ref_field(node);
++		break;
++	// TODO
++	case BIT_FIELD_REF:
++	case VIEW_CONVERT_EXPR:
++	case REALPART_EXPR:
++	case IMAGPART_EXPR:
++		return;
++	default:
++		debug_tree(node);
++		gcc_unreachable();
++	}
++
++	if (get_intentional_attr_type(raw_data.decl) == MARK_TURN_OFF)
++		return;
++
++	create_and_append_new_next_interesting_field_var_decl(use_def_data, &raw_data);
++}
++
++static void handle_vardecl(struct walk_use_def_data *use_def_data, tree node)
++{
++	struct fn_raw_data raw_data;
++
++	raw_data.decl = node;
++	create_and_append_new_next_interesting_field_var_decl(use_def_data, &raw_data);
++}
++
++/* Find all functions that influence lhs
++ *
++ * Encountered functions are added to the children vector (next_interesting_function_t).
 + */
++static void walk_use_def_next_functions(struct walk_use_def_data *use_def_data, tree lhs)
++{
++	enum tree_code code;
++	const_gimple def_stmt;
 +
-+#include "size_overflow.h"
-+#include <libgen.h>
++	if (skip_types(lhs))
++		return;
 +
-+static void walk_use_def_next_functions(struct walk_use_def_data *use_def_data, tree lhs);
++	if (VAR_P(lhs)) {
++		handle_vardecl(use_def_data, lhs);
++		return;
++	}
 +
-+next_interesting_function_t global_next_interesting_function[GLOBAL_NIFN_LEN];
-+static bool global_changed;
-+#define PRINT_DATA_FLOW true
-+#define NO_PRINT_DATA_FLOW false
++	code = TREE_CODE(lhs);
++	if (code == PARM_DECL) {
++		handle_function(use_def_data, current_function_decl, lhs);
++		return;
++	}
 +
-+static struct cgraph_node_hook_list *function_insertion_hook_holder;
-+static struct cgraph_2node_hook_list *node_duplication_hook_holder;
++	if (TREE_CODE_CLASS(code) == tcc_reference) {
++		handle_struct_fields(use_def_data, lhs);
++		return;
++	}
 +
-+struct cgraph_node *get_cnode(const_tree fndecl)
++	if (code != SSA_NAME)
++		return;
++
++	def_stmt = get_def_stmt(lhs);
++	if (!def_stmt)
++		return;
++
++	if (pointer_set_insert(use_def_data->visited, def_stmt))
++		return;
++
++	switch (gimple_code(def_stmt)) {
++	case GIMPLE_NOP:
++		walk_use_def_next_functions(use_def_data, SSA_NAME_VAR(lhs));
++		return;
++	case GIMPLE_ASM:
++		if (!is_size_overflow_asm(def_stmt))
++			return;
++		walk_use_def_next_functions(use_def_data, get_size_overflow_asm_input(as_a_const_gasm(def_stmt)));
++		return;
++	case GIMPLE_CALL: {
++		tree fndecl = gimple_call_fndecl(def_stmt);
++
++		if (fndecl != NULL_TREE) {
++			handle_function(use_def_data, fndecl, NULL_TREE);
++			return;
++		}
++		fndecl = gimple_call_fn(def_stmt);
++		handle_function_ptr_ret(use_def_data, fndecl);
++		return;
++	}
++	case GIMPLE_PHI:
++		walk_use_def_next_functions_phi(use_def_data, lhs);
++		return;
++	case GIMPLE_ASSIGN:
++		switch (gimple_num_ops(def_stmt)) {
++		case 2:
++			walk_use_def_next_functions_unary(use_def_data, as_a_const_gassign(def_stmt));
++			return;
++		case 3:
++			walk_use_def_next_functions_binary(use_def_data, lhs);
++			return;
++		}
++	default:
++		debug_gimple_stmt((gimple)def_stmt);
++		error("%s: unknown gimple code", __func__);
++		gcc_unreachable();
++	}
++}
++
++// Start the search for next_interesting_function_t children based on the (next_interesting_function_t) parent node
++static next_interesting_function_t search_next_functions(tree node, next_interesting_function_t parent)
 +{
-+	gcc_assert(TREE_CODE(fndecl) == FUNCTION_DECL);
-+#if BUILDING_GCC_VERSION <= 4005
-+	return cgraph_get_node(CONST_CAST_TREE(fndecl));
++	struct walk_use_def_data use_def_data;
++
++	use_def_data.parent = parent;
++	use_def_data.next_cnodes_head = NULL;
++	use_def_data.visited = pointer_set_create();
++
++	walk_use_def_next_functions(&use_def_data, node);
++
++	pointer_set_destroy(use_def_data.visited);
++	return use_def_data.next_cnodes_head;
++}
++
++// True if child already exists in the next_interesting_function_t children vector
++bool has_next_interesting_function_vec(next_interesting_function_t target, next_interesting_function_t next_node)
++{
++	unsigned int i;
++	next_interesting_function_t cur;
++
++	gcc_assert(next_node);
++	// handle recursion
++	if (!strcmp(target->decl_name, next_node->decl_name) && target->num == next_node->num)
++		return true;
++
++#if BUILDING_GCC_VERSION <= 4007
++	if (VEC_empty(next_interesting_function_t, target->children))
++		return false;
++	FOR_EACH_VEC_ELT(next_interesting_function_t, target->children, i, cur) {
 +#else
-+	return cgraph_get_node(fndecl);
++	FOR_EACH_VEC_SAFE_ELT(target->children, i, cur) {
 +#endif
++		if (compare_next_interesting_functions(cur, next_node->decl_name, next_node->context, next_node->num))
++			return true;
++	}
++	return false;
 +}
 +
-+static bool compare_next_interesting_functions(next_interesting_function_t cur_node, const char *decl_name, const char *context, unsigned int num)
++void push_child(next_interesting_function_t parent, next_interesting_function_t child)
 +{
-+	// Ignore num without a value
-+	if (num != NONE_ARGNUM && cur_node->num != num)
-+		return false;
-+	if (strcmp(cur_node->context, context))
-+		return false;
-+	return !strcmp(cur_node->decl_name, decl_name);
++	if (!has_next_interesting_function_vec(parent, child)) {
++#if BUILDING_GCC_VERSION <= 4007
++		VEC_safe_push(next_interesting_function_t, heap, parent->children, child);
++#else
++		vec_safe_push(parent->children, child);
++#endif
++	}
 +}
 +
-+// Return the context of vardecl. If it is in a file scope then the context is vardecl_filebasename
-+static const char* get_vardecl_context(const_tree decl)
++void __attribute__((weak)) check_local_variables(next_interesting_function_t next_node __unused) {}
++
++// Add children to parent and global_next_interesting_function
++static void collect_data_for_execute(next_interesting_function_t parent, next_interesting_function_t children)
 +{
-+	expanded_location xloc;
-+	char *buf, *path;
-+	const char *bname;
-+	int len;
++	next_interesting_function_t cur = children;
 +
-+	xloc = expand_location(DECL_SOURCE_LOCATION(decl));
-+	gcc_assert(xloc.file);
-+	path = xstrdup(xloc.file);
-+	bname = basename(path);
++	gcc_assert(parent);
 +
-+	len = asprintf(&buf, "vardecl_%s", bname);
-+	gcc_assert(len > 0);
-+	return buf;
++	while (cur) {
++		struct fn_raw_data child_raw_data;
++		next_interesting_function_t next, child;
++
++		next = cur->next;
++
++		child_raw_data.decl_str = cur->decl_name;
++		child_raw_data.context = cur->context;
++		child_raw_data.hash = cur->hash;
++		child_raw_data.num = cur->num;
++		child_raw_data.marked = NO_SO_MARK;
++		child = get_global_next_interesting_function_entry(&child_raw_data);
++		if (!child) {
++			add_to_global_next_interesting_function(cur);
++			child = cur;
++		}
++
++		check_local_variables(child);
++
++		push_child(parent, child);
++
++		cur = next;
++	}
++
++	check_local_variables(parent);
 +}
 +
-+// Return the type name for a function pointer (or "fielddecl" if the type has no name), otherwise either "vardecl" or "fndecl"
-+const char* get_decl_context(const_tree decl)
++next_interesting_function_t __attribute__((weak)) get_and_create_next_node_from_global_next_nodes_fnptr(const_tree fn_ptr __unused, struct fn_raw_data *raw_data __unused)
 +{
-+	switch (TREE_CODE(decl)) {
-+	case FUNCTION_DECL:
-+		return "fndecl";
-+		// TODO: Ignore anonymous types for now
-+	case FIELD_DECL:
-+		return get_type_name_from_field(decl);
-+	case VAR_DECL:
-+		if (TREE_PUBLIC(decl) || DECL_EXTERNAL(decl))
-+			return "vardecl";
-+		if (TREE_STATIC(decl) && !TREE_PUBLIC(decl))
-+			return get_vardecl_context(decl);
-+		// ignore local variable
-+		if (!TREE_STATIC(decl) && !DECL_EXTERNAL(decl))
++	return NULL;
++}
++
++static next_interesting_function_t create_parent_next_cnode(const_gimple stmt, unsigned int num)
++{
++	struct fn_raw_data raw_data;
++
++	raw_data.num = num;
++	raw_data.marked = NO_SO_MARK;
++
++	switch (gimple_code(stmt)) {
++	case GIMPLE_ASM:
++		raw_data.decl = current_function_decl;
++		raw_data.marked = ASM_STMT_SO_MARK;
++		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
++	case GIMPLE_CALL:
++		raw_data.decl = gimple_call_fndecl(stmt);
++		if (raw_data.decl != NULL_TREE)
++			return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
++		raw_data.decl = gimple_call_fn(stmt);
++		return get_and_create_next_node_from_global_next_nodes_fnptr(raw_data.decl, &raw_data);
++	case GIMPLE_RETURN:
++		raw_data.decl = current_function_decl;
++		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
++	case GIMPLE_ASSIGN: {
++		tree lhs = gimple_assign_lhs(stmt);
++
++		if (VAR_P(lhs))
++			raw_data.decl = lhs;
++		else
++			raw_data.decl = get_ref_field(lhs);
++		if (raw_data.decl == NULL_TREE)
 +			return NULL;
++		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
++	}
 +	default:
-+		debug_tree(decl);
++		debug_gimple_stmt((gimple)stmt);
 +		gcc_unreachable();
 +	}
 +}
 +
-+// Find the function with the specified argument in the list
-+next_interesting_function_t get_global_next_interesting_function_entry(struct fn_raw_data *raw_data)
++// Handle potential next_interesting_function_t parent if its argument has an integer type
++static void collect_all_possible_size_overflow_fns(const_gimple stmt, tree start_var, unsigned int num)
 +{
-+	next_interesting_function_t cur_node, head;
++	next_interesting_function_t children_next_cnode, parent_next_cnode;
 +
-+	head = global_next_interesting_function[raw_data->hash];
-+	for (cur_node = head; cur_node; cur_node = cur_node->next) {
-+		if (raw_data->marked != ASM_STMT_SO_MARK && cur_node->marked == ASM_STMT_SO_MARK)
++	// skip void return values
++	if (start_var == NULL_TREE)
++		return;
++
++	if (skip_types(start_var))
++		return;
++
++	// handle intentional MARK_TURN_OFF
++	if (check_intentional_size_overflow_asm_and_attribute(start_var) == MARK_TURN_OFF)
++		return;
++
++	parent_next_cnode = create_parent_next_cnode(stmt, num);
++	if (!parent_next_cnode)
++		return;
++
++	children_next_cnode = search_next_functions(start_var, parent_next_cnode);
++	collect_data_for_execute(parent_next_cnode, children_next_cnode);
++}
++
++static void collect_all_possible_size_overflow_fields_and_vars(const gassign *assign)
++{
++	tree start_var, decl, lhs = gimple_assign_lhs(assign);
++
++	if (VAR_P(lhs))
++		decl = lhs;
++	else
++		decl = get_ref_field(lhs);
++	if (decl == NULL_TREE)
++		return;
++
++	if (get_intentional_attr_type(decl) == MARK_TURN_OFF)
++		return;
++
++	start_var = gimple_assign_rhs1(assign);
++	collect_all_possible_size_overflow_fns(assign, start_var, 0);
++
++	start_var = gimple_assign_rhs2(assign);
++	collect_all_possible_size_overflow_fns(assign, start_var, 0);
++
++#if BUILDING_GCC_VERSION >= 4006
++	start_var = gimple_assign_rhs3(assign);
++	collect_all_possible_size_overflow_fns(assign, start_var, 0);
++#endif
++}
++
++// Find potential next_interesting_function_t parents
++static void handle_cgraph_node(struct cgraph_node *node)
++{
++	basic_block bb;
++	tree cur_fndecl = NODE_DECL(node);
++
++	set_current_function_decl(cur_fndecl);
++
++	FOR_EACH_BB_FN(bb, cfun) {
++		gimple_stmt_iterator gsi;
++
++		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
++			tree start_var;
++			gimple stmt = gsi_stmt(gsi);
++
++			switch (gimple_code(stmt)) {
++			case GIMPLE_RETURN: {
++				const greturn *return_stmt = as_a_const_greturn(stmt);
++
++				start_var = gimple_return_retval(return_stmt);
++				collect_all_possible_size_overflow_fns(return_stmt, start_var, 0);
++				break;
++			}
++			case GIMPLE_ASM: {
++				const gasm *asm_stmt = as_a_const_gasm(stmt);
++
++				if (!is_size_overflow_insert_check_asm(asm_stmt))
++					break;
++				start_var = get_size_overflow_asm_input(asm_stmt);
++				collect_all_possible_size_overflow_fns(asm_stmt, start_var, 0);
++				break;
++			}
++			case GIMPLE_CALL: {
++				unsigned int i, len;
++				const gcall *call = as_a_const_gcall(stmt);
++				tree fndecl = gimple_call_fndecl(call);
++
++				if (fndecl != NULL_TREE && (DECL_BUILT_IN(fndecl) || DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_NORMAL))
++					break;
++
++				len = gimple_call_num_args(call);
++				for (i = 0; i < len; i++) {
++					start_var = gimple_call_arg(call, i);
++					collect_all_possible_size_overflow_fns(call, start_var, i + 1);
++				}
++				break;
++			}
++			case GIMPLE_ASSIGN:
++				collect_all_possible_size_overflow_fields_and_vars(as_a_const_gassign(stmt));
++				break;
++			default:
++				break;
++			}
++		}
++	}
++
++	unset_current_function_decl();
++}
++
++/* Collect all potentially interesting function parameters and return values of integer types
++ * and store their data flow dependencies
++ */
++static void size_overflow_generate_summary(void)
++{
++	struct cgraph_node *node;
++
++	size_overflow_register_hooks();
++
++	FOR_EACH_FUNCTION(node) {
++		if (is_valid_cgraph_node(node))
++			handle_cgraph_node(node);
++	}
++}
++
++static void size_overflow_function_insertion_hook(struct cgraph_node *node __unused, void *data __unused)
++{
++	debug_cgraph_node(node);
++	gcc_unreachable();
++}
++
++/* Handle dst if src is in the global_next_interesting_function list.
++ * If src is a clone then dst inherits the orig_next_node of src otherwise
++ * src will become the orig_next_node of dst.
++ */
++static void size_overflow_node_duplication_hook(struct cgraph_node *src, struct cgraph_node *dst, void *data __unused)
++{
++	next_interesting_function_t head, cur;
++	struct fn_raw_data src_raw_data;
++
++	src_raw_data.decl = NODE_DECL(src);
++	src_raw_data.decl_str = DECL_NAME_POINTER(src_raw_data.decl);
++	src_raw_data.context = get_decl_context(src_raw_data.decl);
++	if (!src_raw_data.context)
++		return;
++
++	src_raw_data.num = NONE_ARGNUM;
++	src_raw_data.marked = NO_SO_MARK;
++
++	head = get_global_next_interesting_function_entry_with_hash(&src_raw_data);
++	if (!head)
++		return;
++
++	for (cur = head; cur; cur = cur->next) {
++		struct fn_raw_data dst_raw_data;
++		next_interesting_function_t orig_next_node, next_node;
++
++		if (!compare_next_interesting_functions(cur, src_raw_data.decl_str, src_raw_data.context, src_raw_data.num))
 +			continue;
-+		if (compare_next_interesting_functions(cur_node, raw_data->decl_str, raw_data->context, raw_data->num))
-+			return cur_node;
++
++		dst_raw_data.decl = NODE_DECL(dst);
++		dst_raw_data.decl_str = cgraph_node_name(dst);
++		dst_raw_data.marked = cur->marked;
++
++		if (!made_by_compiler(dst_raw_data.decl))
++			break;
++
++		// For clones use the original node instead
++		if (cur->orig_next_node)
++			orig_next_node = cur->orig_next_node;
++		else
++			orig_next_node = cur;
++
++		dst_raw_data.num = get_correct_argnum_fndecl(src_raw_data.decl, dst_raw_data.decl, cur->num);
++		if (dst_raw_data.num == CANNOT_FIND_ARG)
++			continue;
++
++		next_node = create_new_next_interesting_decl(&dst_raw_data, orig_next_node);
++		if (next_node)
++			add_to_global_next_interesting_function(next_node);
 +	}
-+	return NULL;
 +}
 +
-+next_interesting_function_t get_global_next_interesting_function_entry_with_hash(struct fn_raw_data *raw_data)
++void size_overflow_register_hooks(void)
 +{
-+	raw_data->hash = get_decl_hash(raw_data->decl, raw_data->decl_str);
-+	if (raw_data->hash == NO_HASH)
-+		return NULL;
++	static bool init_p = false;
 +
-+	raw_data->context = get_decl_context(raw_data->decl);
-+	if (!raw_data->context)
-+		return NULL;
-+	return get_global_next_interesting_function_entry(raw_data);
++	if (init_p)
++		return;
++	init_p = true;
++
++	function_insertion_hook_holder = cgraph_add_function_insertion_hook(&size_overflow_function_insertion_hook, NULL);
++	node_duplication_hook_holder = cgraph_add_node_duplication_hook(&size_overflow_node_duplication_hook, NULL);
 +}
 +
-+next_interesting_function_t create_new_next_interesting_entry(struct fn_raw_data *raw_data, next_interesting_function_t orig_next_node)
++static void set_yes_so_mark(next_interesting_function_t next_node)
 +{
-+	next_interesting_function_t new_node;
++	if (next_node->marked == NO_SO_MARK) {
++		next_node->marked = YES_SO_MARK;
++		global_changed = true;
++	}
++	// Mark the orig decl as well if it's a clone
++	if (next_node->orig_next_node && next_node->orig_next_node->marked == NO_SO_MARK) {
++		next_node->orig_next_node->marked = YES_SO_MARK;
++		global_changed = true;
++	}
++}
 +
-+	new_node = (next_interesting_function_t)xmalloc(sizeof(*new_node));
-+	new_node->decl_name = xstrdup(raw_data->decl_str);
++// Determine whether node or orig node is part of a tracked data flow
++static bool marked_fn(next_interesting_function_t next_node)
++{
++	bool is_marked_fn, is_marked_orig = false;
 +
-+	gcc_assert(raw_data->context);
-+	new_node->context = xstrdup(raw_data->context);
-+	new_node->hash = raw_data->hash;
-+	new_node->num = raw_data->num;
-+	new_node->next = NULL;
-+	new_node->children = NULL;
-+	new_node->marked = raw_data->marked;
-+	new_node->orig_next_node = orig_next_node;
-+	return new_node;
++	is_marked_fn = next_node->marked != NO_SO_MARK;
++
++	if (next_node->orig_next_node)
++		is_marked_orig = next_node->orig_next_node->marked != NO_SO_MARK;
++
++	return is_marked_fn || is_marked_orig;
 +}
 +
-+// Ignore these functions to not explode coverage (+strncmp+fndecl+3+35130+)
-+static bool temporary_skip_these_functions(struct fn_raw_data *raw_data)
++// Determine whether node or orig node is in the hash table already
++static bool already_in_the_hashtable(next_interesting_function_t next_node)
 +{
-+	if (raw_data->hash == 35130 && !strcmp(raw_data->decl_str, "strncmp"))
-+		return true;
-+	if (raw_data->hash == 46193 && !strcmp(raw_data->decl_str, "strnlen"))
-+		return true;
-+	if (raw_data->hash == 43267 && !strcmp(raw_data->decl_str, "strncpy"))
-+		return true;
-+	if (raw_data->hash == 10300 && !strcmp(raw_data->decl_str, "strncpy_from_user"))
-+		return true;
-+	if (raw_data->hash == 26117 && !strcmp(raw_data->decl_str, "memchr"))
-+		return true;
-+	if (raw_data->hash == 16203 && !strcmp(raw_data->decl_str, "memchr_inv"))
-+		return true;
-+	if (raw_data->hash == 24269 && !strcmp(raw_data->decl_str, "memcmp"))
-+		return true;
-+	if (raw_data->hash == 60390 && !strcmp(raw_data->decl_str, "memcpy"))
-+		return true;
-+	if (raw_data->hash == 25040 && !strcmp(raw_data->decl_str, "memmove"))
-+		return true;
-+	if (raw_data->hash == 29763 && !strcmp(raw_data->decl_str, "memset"))
-+		return true;
-+	return false;
++	if (next_node->orig_next_node)
++		next_node = next_node->orig_next_node;
++	return get_size_overflow_hash_entry(next_node->hash, next_node->decl_name, next_node->context, next_node->num) != NULL;
 +}
 +
-+// Create the main data structure
-+next_interesting_function_t create_new_next_interesting_decl(struct fn_raw_data *raw_data, next_interesting_function_t orig_next_node)
++// Propagate the size_overflow marks up the use-def chains
++static bool has_marked_child(next_interesting_function_t next_node)
 +{
-+	enum tree_code decl_code = TREE_CODE(raw_data->decl);
++	bool ret = false;
++	unsigned int i;
++	next_interesting_function_t child;
 +
-+	gcc_assert(decl_code == FIELD_DECL || decl_code == FUNCTION_DECL || decl_code == VAR_DECL);
++#if BUILDING_GCC_VERSION <= 4007
++	if (VEC_empty(next_interesting_function_t, next_node->children))
++		return false;
++	FOR_EACH_VEC_ELT(next_interesting_function_t, next_node->children, i, child) {
++#else
++	FOR_EACH_VEC_SAFE_ELT(next_node->children, i, child) {
++#endif
++		if (marked_fn(child) || already_in_the_hashtable(child))
++			ret = true;
++	}
 +
-+	if (is_vararg(raw_data->decl, raw_data->num))
-+		return NULL;
++	return ret;
++}
 +
-+	raw_data->hash = get_decl_hash(raw_data->decl, raw_data->decl_str);
-+	if (raw_data->hash == NO_HASH)
-+		return NULL;
-+	if (get_size_overflow_hash_entry_tree(raw_data->decl, raw_data->num, DISABLE_SIZE_OVERFLOW))
-+		return NULL;
-+	if (temporary_skip_these_functions(raw_data))
-+		return NULL;
++/* Set YES_SO_MARK on the function, its orig node and children if:
++ *      * the function or its orig node or one of its children is in the hash table already
++ *      * the function's orig node is marked with YES_SO_MARK or ASM_STMT_SO_MARK
++ *      * one of the children is marked with YES_SO_MARK or ASM_STMT_SO_MARK
++ */
++static bool set_fn_so_mark(next_interesting_function_t next_node)
++{
++	bool so_fn, so_hashtable, so_child;
 +
-+	gcc_assert(raw_data->num <= MAX_PARAM);
-+	// Clones must have an orig_next_node
-+	gcc_assert(!made_by_compiler(raw_data->decl) || orig_next_node);
++	so_hashtable = already_in_the_hashtable(next_node);
++	so_fn = marked_fn(next_node);
++	so_child = has_marked_child(next_node);
 +
-+	raw_data->context = get_decl_context(raw_data->decl);
-+	if (!raw_data->context)
++	if (!so_fn && !so_hashtable && !so_child)
++		return false;
++	set_yes_so_mark(next_node);
++	return true;
++}
++
++// Determine if any of the function pointer targets have data flow between the return value and one of the arguments
++static next_interesting_function_t get_same_not_ret_child(next_interesting_function_t parent)
++{
++	unsigned int i;
++	next_interesting_function_t child;
++
++#if BUILDING_GCC_VERSION <= 4007
++	if (VEC_empty(next_interesting_function_t, parent->children))
 +		return NULL;
-+	return create_new_next_interesting_entry(raw_data, orig_next_node);
++	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
++#else
++	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
++#endif
++		if (child->num == 0)
++			continue;
++		if (strcmp(parent->decl_name, child->decl_name))
++			continue;
++		if (!strcmp(child->context, "fndecl"))
++			return child;
++	}
++	return NULL;
 +}
 +
-+void add_to_global_next_interesting_function(next_interesting_function_t new_entry)
++/* Trace a return value of function pointer type back to an argument via a concrete function
++   fnptr 0 && fn 0 && (fn 0 -> fn 2) => fnptr 2 */
++static void search_missing_fptr_arg(next_interesting_function_t parent)
 +{
-+	next_interesting_function_t cur_global_head, cur_global, cur_global_end = NULL;
++	next_interesting_function_t child;
++	unsigned int i;
++#if BUILDING_GCC_VERSION <= 4007
++	VEC(next_interesting_function_t, heap) *new_children = NULL;
++#else
++	vec<next_interesting_function_t, va_heap, vl_embed> *new_children = NULL;
++#endif
 +
-+	// new_entry is appended to the end of a list
-+	new_entry->next = NULL;
++	if (parent->num != 0)
++		return;
++	if (!strcmp(parent->context, "fndecl"))
++		return;
++	if (!strncmp(parent->context, "vardecl", sizeof("vardecl") - 1))
++		return;
 +
-+	cur_global_head = global_next_interesting_function[new_entry->hash];
-+	if (!cur_global_head) {
-+		global_next_interesting_function[new_entry->hash] = new_entry;
++	// fnptr 0 && fn 0
++#if BUILDING_GCC_VERSION <= 4007
++	if (VEC_empty(next_interesting_function_t, parent->children))
 +		return;
++	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
++#else
++	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
++#endif
++		next_interesting_function_t cur_next_node, tracked_fn;
++
++		if (child->num != 0)
++			continue;
++		// (fn 0 -> fn 2)
++		tracked_fn = get_same_not_ret_child(child);
++		if (!tracked_fn)
++			continue;
++
++		// fn 2 => fnptr 2
++		for (cur_next_node = global_next_interesting_function[parent->hash]; cur_next_node; cur_next_node = cur_next_node->next) {
++			if (cur_next_node->num != tracked_fn->num)
++				continue;
++
++			if (strcmp(parent->decl_name, cur_next_node->decl_name))
++				continue;
++
++			if (!has_next_interesting_function_vec(parent, cur_next_node)) {
++#if BUILDING_GCC_VERSION <= 4007
++				VEC_safe_push(next_interesting_function_t, heap, new_children, cur_next_node);
++#else
++				vec_safe_push(new_children, cur_next_node);
++#endif
++			}
++		}
 +	}
 +
++#if BUILDING_GCC_VERSION == 4005
++	if (VEC_empty(next_interesting_function_t, new_children))
++		return;
++	FOR_EACH_VEC_ELT(next_interesting_function_t, new_children, i, child)
++		VEC_safe_push(next_interesting_function_t, heap, parent->children, child);
++#elif BUILDING_GCC_VERSION <= 4007
++	VEC_safe_splice(next_interesting_function_t, heap, parent->children, new_children);
++#else
++	vec_safe_splice(parent->children, new_children);
++#endif
++}
++
++static void walk_so_marked_fns(next_interesting_function_set *visited, next_interesting_function_t parent, bool debug)
++{
++	unsigned int i;
++	next_interesting_function_t child;
 +
-+	for (cur_global = cur_global_head; cur_global; cur_global = cur_global->next) {
-+		if (!cur_global->next)
-+			cur_global_end = cur_global;
++	gcc_assert(parent);
++	if (!set_fn_so_mark(parent))
++		return;
 +
-+		if (compare_next_interesting_functions(cur_global, new_entry->decl_name, new_entry->context, new_entry->num))
-+			return;
++#if BUILDING_GCC_VERSION <= 4007
++	if (VEC_empty(next_interesting_function_t, parent->children))
++		return;
++	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
++#else
++	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
++#endif
++		set_yes_so_mark(child);
++
++		if (in_lto_p && debug == PRINT_DATA_FLOW) {
++			fprintf(stderr, " PARENT: decl: %s-%u context: %s %p\n", parent->decl_name, parent->num, parent->context, parent);
++			fprintf(stderr, " \tCHILD: decl: %s-%u context: %s %p\n", child->decl_name, child->num, child->context, child);
++		}
++
++		if (!pointer_set_insert(visited, child))
++			walk_so_marked_fns(visited, child, debug);
 +	}
++}
 +
-+	gcc_assert(cur_global_end);
-+	cur_global_end->next = new_entry;
++// Do a depth-first recursive dump of the next_interesting_function_t children vector
++static void print_missing_functions(next_interesting_function_set *visited, next_interesting_function_t parent)
++{
++	unsigned int i;
++	next_interesting_function_t child;
++
++	gcc_assert(parent);
++	gcc_assert(parent->marked != NO_SO_MARK);
++	print_missing_function(parent);
++
++#if BUILDING_GCC_VERSION <= 4007
++	if (VEC_empty(next_interesting_function_t, parent->children))
++		return;
++	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
++#else
++	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
++#endif
++		gcc_assert(child->marked != NO_SO_MARK);
++		if (!pointer_set_insert(visited, child))
++			print_missing_functions(visited, child);
++	}
 +}
 +
-+/* If the interesting function is a clone then find or create its original next_interesting_function_t node
-+ * and add it to global_next_interesting_function
++// Set YES_SO_MARK on functions that will be emitted into the hash table
++static void search_so_marked_fns(bool debug)
++{
++
++	unsigned int i;
++	next_interesting_function_set *visited;
++	next_interesting_function_t cur_global;
++
++	visited = next_interesting_function_pointer_set_create();
++	for (i = 0; i < GLOBAL_NIFN_LEN; i++) {
++		for (cur_global = global_next_interesting_function[i]; cur_global; cur_global = cur_global->next) {
++			if (cur_global->marked == NO_SO_MARK || pointer_set_insert(visited, cur_global))
++				continue;
++
++			if  (in_lto_p && debug == PRINT_DATA_FLOW)
++				fprintf(stderr, "Data flow: decl: %s-%u context: %s %p\n", cur_global->decl_name, cur_global->num, cur_global->context, cur_global);
++
++			walk_so_marked_fns(visited, cur_global, debug);
++
++			if  (in_lto_p && debug == PRINT_DATA_FLOW)
++				fprintf(stderr, "\n");
++		}
++	}
++	pointer_set_destroy(visited);
++}
++
++// Print functions missing from the hash table
++static void print_so_marked_fns(void)
++{
++	unsigned int i;
++	next_interesting_function_set *visited;
++	next_interesting_function_t cur_global;
++
++	visited = next_interesting_function_pointer_set_create();
++	for (i = 0; i < GLOBAL_NIFN_LEN; i++) {
++		for (cur_global = global_next_interesting_function[i]; cur_global; cur_global = cur_global->next) {
++			if (cur_global->marked != NO_SO_MARK && !pointer_set_insert(visited, cur_global))
++				print_missing_functions(visited, cur_global);
++		}
++	}
++	pointer_set_destroy(visited);
++}
++
++void __attribute__((weak)) check_global_variables(next_interesting_function_t cur_global __unused) {}
++
++// Print all missing interesting functions
++static unsigned int size_overflow_execute(void)
++{
++	unsigned int i;
++	next_interesting_function_t cur_global;
++
++	if (flag_lto && !in_lto_p)
++		return 0;
++
++	// Collect vardecls and funtions reachable by function pointers
++	for (i = 0; i < GLOBAL_NIFN_LEN; i++) {
++		for (cur_global = global_next_interesting_function[i]; cur_global; cur_global = cur_global->next) {
++			check_global_variables(cur_global);
++			search_missing_fptr_arg(cur_global);
++		}
++	}
++
++	search_so_marked_fns(PRINT_DATA_FLOW);
++	while (global_changed) {
++		global_changed = false;
++		search_so_marked_fns(NO_PRINT_DATA_FLOW);
++	}
++
++	print_so_marked_fns();
++
++	if (in_lto_p) {
++		fprintf(stderr, "%s: SIZE_OVERFLOW EXECUTE\n", __func__);
++		print_global_next_interesting_functions();
++	}
++
++	return 0;
++}
++
++// Omit the IPA/LTO callbacks until https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61311 gets fixed (license concerns)
++#if BUILDING_GCC_VERSION >= 4008
++void __attribute__((weak)) size_overflow_write_summary(void) {}
++void __attribute__((weak)) size_overflow_write_optimization_summary(void) {}
++#elif BUILDING_GCC_VERSION >= 4006
++void __attribute__((weak)) size_overflow_write_summary(cgraph_node_set set __unused, varpool_node_set vset __unused) {}
++void __attribute__((weak)) size_overflow_write_optimization_summary(cgraph_node_set set __unused, varpool_node_set vset __unused) {}
++#else
++void __attribute__((weak)) size_overflow_write_summary(cgraph_node_set set __unused) {}
++void __attribute__((weak)) size_overflow_write_optimization_summary(cgraph_node_set set __unused) {}
++#endif
++
++void __attribute__((weak)) size_overflow_read_summary(void);
++void __attribute__((weak)) size_overflow_read_optimization_summary(void);
++
++#define PASS_NAME size_overflow
++
++#define NO_STMT_FIXUP
++#define NO_VARIABLE_TRANSFORM
++#define NO_GATE
++
++#include "gcc-generate-ipa-pass.h"
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_misc.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_misc.c
+new file mode 100644
+index 0000000..7f459ed
+--- /dev/null
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_misc.c
+@@ -0,0 +1,505 @@
++/*
++ * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
++ * Licensed under the GPL v2, or (at your option) v3
++ *
++ * Homepage:
++ * https://github.com/ephox-gcc-plugins/size_overflow
++ *
++ * Documentation:
++ * http://forums.grsecurity.net/viewtopic.php?f=7&t=3043
++ *
++ * This plugin recomputes expressions of function arguments marked by a size_overflow attribute
++ * with double integer precision (DImode/TImode for 32/64 bit integer types).
++ * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
++ *
++ * Usage:
++ * $ make
++ * $ make run
 + */
-+static next_interesting_function_t create_orig_next_node_for_a_clone(struct fn_raw_data *clone_raw_data)
++
++#include "size_overflow.h"
++
++bool is_vararg(const_tree fn, unsigned int num)
 +{
-+	struct fn_raw_data orig_raw_data;
-+	next_interesting_function_t orig_next_node;
-+	enum tree_code decl_code;
++	tree arg_list;
 +
-+	orig_raw_data.decl = get_orig_fndecl(clone_raw_data->decl);
++	if (num == 0)
++		return false;
++	if (fn == NULL_TREE)
++		return false;
++	if (TREE_CODE(fn) != FUNCTION_DECL)
++		return false;
 +
-+	if (DECL_BUILT_IN(orig_raw_data.decl) || DECL_BUILT_IN_CLASS(orig_raw_data.decl) == BUILT_IN_NORMAL)
-+		return NULL;
++	arg_list = TYPE_ARG_TYPES(TREE_TYPE(fn));
++	if (arg_list == NULL_TREE)
++		return false;
 +
-+	if (made_by_compiler(orig_raw_data.decl))
-+		return NULL;
++	if (tree_last(arg_list) == void_list_node)
++		return false;
 +
-+	decl_code = TREE_CODE(orig_raw_data.decl);
-+	if (decl_code == FIELD_DECL || decl_code == VAR_DECL)
-+		orig_raw_data.num = clone_raw_data->num;
-+	else
-+		orig_raw_data.num = get_correct_argnum(clone_raw_data->decl, orig_raw_data.decl, clone_raw_data->num);
++	return num >= (unsigned int)list_length(arg_list);
++}
 +
-+	// Skip over ISRA.162 parm decls
-+	if (orig_raw_data.num == CANNOT_FIND_ARG)
-+		return NULL;
++// Extract the field decl from memory references
++tree get_ref_field(const_tree ref)
++{
++	tree field;
 +
-+	orig_raw_data.decl_str = get_orig_decl_name(orig_raw_data.decl);
-+	orig_raw_data.marked = NO_SO_MARK;
-+	orig_next_node = get_global_next_interesting_function_entry_with_hash(&orig_raw_data);
-+	if (orig_next_node)
-+		return orig_next_node;
++	// TODO: handle nested memory references
++	switch (TREE_CODE(ref)) {
++	case ARRAY_REF:
++		return NULL_TREE;
++#if BUILDING_GCC_VERSION >= 4006
++	case MEM_REF:
++#endif
++	case INDIRECT_REF:
++		field = TREE_OPERAND(ref, 0);
++		break;
++	case COMPONENT_REF:
++		field = TREE_OPERAND(ref, 1);
++		break;
++	default:
++		return NULL_TREE;
++	}
 +
-+	orig_raw_data.marked = clone_raw_data->marked;
-+	orig_next_node = create_new_next_interesting_decl(&orig_raw_data, NULL);
-+	if (!orig_next_node)
-+		return NULL;
++	// TODO
++	if (TREE_CODE(field) == SSA_NAME)
++		return NULL_TREE;
++	// TODO
++	if (TREE_CODE(field) != FIELD_DECL)
++		return NULL_TREE;
++	// TODO
++	if (TREE_CODE(field) == ADDR_EXPR)
++		return NULL_TREE;
 +
-+	add_to_global_next_interesting_function(orig_next_node);
-+	return orig_next_node;
++	return field;
 +}
 +
-+// Find or create the next_interesting_function_t node for decl and num
-+next_interesting_function_t get_and_create_next_node_from_global_next_nodes(struct fn_raw_data *raw_data, next_interesting_function_t orig_next_node)
++const char *get_type_name_from_field(const_tree field_decl)
 +{
-+	next_interesting_function_t cur_next_cnode;
++	const_tree context, type_name;
 +
-+	if (DECL_NAME(raw_data->decl) == NULL_TREE)
++	if (TREE_CODE(field_decl) != FIELD_DECL)
 +		return NULL;
-+	raw_data->decl_str = DECL_NAME_POINTER(raw_data->decl);
 +
-+	cur_next_cnode = get_global_next_interesting_function_entry_with_hash(raw_data);
-+	if (cur_next_cnode)
-+		goto out;
++	context = DECL_CONTEXT(field_decl);
++	// TODO
++	if (TREE_CODE(context) != RECORD_TYPE)
++		return NULL;
++	gcc_assert(TREE_CODE(context) == RECORD_TYPE);
++	type_name = TYPE_NAME(TYPE_MAIN_VARIANT(context));
++	if (type_name == NULL_TREE)
++		return NULL;
 +
-+	if (!orig_next_node && made_by_compiler(raw_data->decl)) {
-+		orig_next_node = create_orig_next_node_for_a_clone(raw_data);
-+		if (!orig_next_node)
-+			return NULL;
++	if (TREE_CODE(type_name) == IDENTIFIER_NODE)
++		return IDENTIFIER_POINTER(type_name);
++	else if (TREE_CODE(type_name) == TYPE_DECL)
++		return DECL_NAME_POINTER(type_name);
++
++	debug_tree(field_decl);
++	debug_tree(type_name);
++	gcc_unreachable();
++}
++
++// Was the function created by the compiler itself?
++bool made_by_compiler(const_tree decl)
++{
++	enum tree_code decl_code;
++	struct cgraph_node *node;
++
++	if (FUNCTION_PTR_P(decl))
++		return false;
++	decl_code = TREE_CODE(decl);
++	if (decl_code == VAR_DECL || decl_code == FIELD_DECL)
++		return false;
++
++	gcc_assert(decl_code == FUNCTION_DECL);
++	if (DECL_ABSTRACT_ORIGIN(decl) != NULL_TREE && DECL_ABSTRACT_ORIGIN(decl) != decl)
++		return true;
++	if (DECL_ARTIFICIAL(decl))
++		return true;
++
++	node = get_cnode(decl);
++	if (!node)
++		return false;
++	return node->clone_of != NULL;
++}
++
++bool skip_types(const_tree var)
++{
++	const_tree type;
++
++	type = TREE_TYPE(var);
++	if (type == NULL_TREE)
++		return true;
++
++	switch (TREE_CODE(type)) {
++		case INTEGER_TYPE:
++		case ENUMERAL_TYPE:
++			return false;
++		default:
++			return true;
 +	}
++}
 +
-+	cur_next_cnode = create_new_next_interesting_decl(raw_data, orig_next_node);
-+	if (!cur_next_cnode)
++gimple get_fnptr_def_stmt(const_tree fn_ptr)
++{
++	gimple def_stmt;
++
++	gcc_assert(fn_ptr != NULL_TREE);
++	gcc_assert(FUNCTION_PTR_P(fn_ptr));
++
++	if (is_gimple_constant(fn_ptr))
 +		return NULL;
 +
-+	add_to_global_next_interesting_function(cur_next_cnode);
-+out:
-+	if (cur_next_cnode->marked != raw_data->marked && cur_next_cnode->marked != NO_SO_MARK)
-+		return cur_next_cnode;
++	def_stmt = get_def_stmt(fn_ptr);
++	gcc_assert(def_stmt);
++	return def_stmt;
++}
 +
-+	if (raw_data->marked != NO_SO_MARK && cur_next_cnode->marked == NO_SO_MARK)
-+		cur_next_cnode->marked = raw_data->marked;
++gimple get_def_stmt(const_tree node)
++{
++	gcc_assert(node != NULL_TREE);
 +
-+	return cur_next_cnode;
++	if (TREE_CODE(node) != SSA_NAME)
++		return NULL;
++	return SSA_NAME_DEF_STMT(node);
 +}
 +
-+static bool has_next_interesting_function_chain_node(next_interesting_function_t next_cnodes_head, struct fn_raw_data *raw_data)
++tree create_new_var(tree type)
 +{
-+	next_interesting_function_t cur_node;
-+
-+	raw_data->decl_str = DECL_NAME_POINTER(raw_data->decl);
-+	raw_data->context = get_decl_context(raw_data->decl);
-+	// Ignore function if there is no context
-+	if (!raw_data->context)
-+		return true;
++	tree new_var = create_tmp_var(type, "cicus");
 +
-+	for (cur_node = next_cnodes_head; cur_node; cur_node = cur_node->next) {
-+		if (compare_next_interesting_functions(cur_node, raw_data->decl_str, raw_data->context, raw_data->num))
-+			return true;
-+	}
-+	return false;
++	add_referenced_var(new_var);
++	return new_var;
 +}
 +
-+static void handle_function(struct walk_use_def_data *use_def_data, tree fndecl, const_tree arg)
++static bool skip_cast(tree dst_type, const_tree rhs, bool force)
 +{
-+	struct fn_raw_data raw_data;
-+	next_interesting_function_t orig_next_node, new_node;
++	const_gimple def_stmt = get_def_stmt(rhs);
 +
-+	gcc_assert(fndecl != NULL_TREE);
++	if (force)
++		return false;
 +
-+	// ignore builtins to not explode coverage (e.g., memcpy)
-+	if (DECL_BUILT_IN(fndecl) || DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_NORMAL)
-+		return;
++	if (is_gimple_constant(rhs))
++		return false;
 +
-+	if (get_intentional_attr_type(fndecl) == MARK_TURN_OFF)
-+		return;
++	if (!def_stmt || gimple_code(def_stmt) == GIMPLE_NOP)
++		return false;
 +
-+	raw_data.decl = fndecl;
-+	raw_data.decl_str = DECL_NAME_POINTER(fndecl);
-+	raw_data.marked = NO_SO_MARK;
++	if (!types_compatible_p(dst_type, TREE_TYPE(rhs)))
++		return false;
 +
-+	// convert arg into its position
-+	if (arg == NULL_TREE)
-+		raw_data.num = 0;
-+	else
-+		raw_data.num = find_arg_number_tree(arg, raw_data.decl);
-+	if (raw_data.num == CANNOT_FIND_ARG)
-+		return;
++	// DI type can be on 32 bit (from create_assign) but overflow type stays DI
++	if (LONG_TYPE_SIZE == GET_MODE_BITSIZE(SImode))
++		return false;
 +
-+	if (has_next_interesting_function_chain_node(use_def_data->next_cnodes_head, &raw_data))
-+		return;
++	return true;
++}
 +
-+	if (made_by_compiler(raw_data.decl)) {
-+		orig_next_node = create_orig_next_node_for_a_clone(&raw_data);
-+		if (!orig_next_node)
-+			return;
-+	} else
-+		orig_next_node = NULL;
++tree cast_a_tree(tree type, tree var)
++{
++	gcc_assert(type != NULL_TREE);
++	gcc_assert(var != NULL_TREE);
++	gcc_assert(fold_convertible_p(type, var));
 +
-+	new_node = create_new_next_interesting_decl(&raw_data, orig_next_node);
-+	if (!new_node)
-+		return;
-+	new_node->next = use_def_data->next_cnodes_head;
-+	use_def_data->next_cnodes_head = new_node;
++	return fold_convert(type, var);
 +}
 +
-+static void walk_use_def_next_functions_phi(struct walk_use_def_data *use_def_data, const_tree result)
++gimple build_cast_stmt(struct visited *visited, tree dst_type, tree rhs, tree lhs, gimple_stmt_iterator *gsi, bool before, bool force)
 +{
-+	gphi *phi = as_a_gphi(get_def_stmt(result));
-+	unsigned int i, n = gimple_phi_num_args(phi);
++	gassign *assign;
++	gimple def_stmt;
 +
-+	pointer_set_insert(use_def_data->visited, phi);
-+	for (i = 0; i < n; i++) {
-+		tree arg = gimple_phi_arg_def(phi, i);
++	gcc_assert(dst_type != NULL_TREE && rhs != NULL_TREE);
++	gcc_assert(!is_gimple_constant(rhs));
++	if (gsi_end_p(*gsi) && before == AFTER_STMT)
++		gcc_unreachable();
 +
-+		walk_use_def_next_functions(use_def_data, arg);
++	def_stmt = get_def_stmt(rhs);
++	if (def_stmt && gimple_code(def_stmt) != GIMPLE_NOP && skip_cast(dst_type, rhs, force) && pointer_set_contains(visited->my_stmts, def_stmt))
++		return def_stmt;
++
++	if (lhs == CREATE_NEW_VAR)
++		lhs = create_new_var(dst_type);
++
++	assign = gimple_build_assign(lhs, cast_a_tree(dst_type, rhs));
++
++	if (!gsi_end_p(*gsi)) {
++		location_t loc = gimple_location(gsi_stmt(*gsi));
++		gimple_set_location(assign, loc);
 +	}
++
++	gimple_assign_set_lhs(assign, make_ssa_name(lhs, assign));
++
++	if (before)
++		gsi_insert_before(gsi, assign, GSI_NEW_STMT);
++	else
++		gsi_insert_after(gsi, assign, GSI_NEW_STMT);
++	update_stmt(assign);
++	return assign;
 +}
 +
-+static void walk_use_def_next_functions_binary(struct walk_use_def_data *use_def_data, const_tree lhs)
++bool is_size_overflow_type(const_tree var)
 +{
-+	gassign *def_stmt = as_a_gassign(get_def_stmt(lhs));
-+	tree rhs1, rhs2;
++	const char *name;
++	const_tree type_name, type;
 +
-+	rhs1 = gimple_assign_rhs1(def_stmt);
-+	rhs2 = gimple_assign_rhs2(def_stmt);
++	if (var == NULL_TREE)
++		return false;
 +
-+	walk_use_def_next_functions(use_def_data, rhs1);
-+	walk_use_def_next_functions(use_def_data, rhs2);
-+}
++	type = TREE_TYPE(var);
++	type_name = TYPE_NAME(type);
++	if (type_name == NULL_TREE)
++		return false;
 +
-+static void walk_use_def_next_functions_unary(struct walk_use_def_data *use_def_data, const gassign *stmt)
-+{
-+	tree rhs1 = gimple_assign_rhs1(stmt);
++	if (DECL_P(type_name))
++		name = DECL_NAME_POINTER(type_name);
++	else
++		name = IDENTIFIER_POINTER(type_name);
 +
-+	walk_use_def_next_functions(use_def_data, rhs1);
++	if (!strncmp(name, "size_overflow_type", 18))
++		return true;
++	return false;
 +}
 +
-+void __attribute__((weak)) handle_function_ptr_ret(struct walk_use_def_data *use_def_data __unused, const_tree fn_ptr __unused)
++// Determine if a cloned function has all the original arguments
++static bool unchanged_arglist(struct cgraph_node *new_node, struct cgraph_node *old_node)
 +{
++	const_tree new_decl_list, old_decl_list;
++
++	if (new_node->clone_of && new_node->clone.tree_map)
++		return !new_node->clone.args_to_skip;
++
++	new_decl_list = DECL_ARGUMENTS(NODE_DECL(new_node));
++	old_decl_list = DECL_ARGUMENTS(NODE_DECL(old_node));
++	if (new_decl_list != NULL_TREE && old_decl_list != NULL_TREE)
++		gcc_assert(list_length(new_decl_list) == list_length(old_decl_list));
++
++	return true;
 +}
 +
-+static void create_and_append_new_next_interesting_field_var_decl(struct walk_use_def_data *use_def_data, struct fn_raw_data *raw_data)
++unsigned int get_correct_argnum_fndecl(const_tree fndecl, const_tree correct_argnum_of_fndecl, unsigned int num)
 +{
-+	next_interesting_function_t new_node;
-+
-+	if (raw_data->decl == NULL_TREE)
-+		return;
++	unsigned int new_num;
++	const_tree fndecl_arg;
++	tree fndecl_arglist = DECL_ARGUMENTS(fndecl);
++	const_tree arg, target_fndecl_arglist;
 +
-+	if (DECL_NAME(raw_data->decl) == NULL_TREE)
-+		return;
++	if (num == 0)
++		return num;
 +
-+	raw_data->decl_str = DECL_NAME_POINTER(raw_data->decl);
-+	raw_data->num = 0;
-+	raw_data->marked = NO_SO_MARK;
++	if (fndecl == correct_argnum_of_fndecl && !DECL_ARTIFICIAL(fndecl))
++		return num;
++	else if (fndecl == correct_argnum_of_fndecl && DECL_ARTIFICIAL(fndecl))
++		return CANNOT_FIND_ARG;
 +
-+	new_node = create_new_next_interesting_decl(raw_data, NULL);
-+	if (!new_node)
-+		return;
-+	new_node->next = use_def_data->next_cnodes_head;
-+	use_def_data->next_cnodes_head = new_node;
-+}
++	target_fndecl_arglist = DECL_ARGUMENTS(correct_argnum_of_fndecl);
++	if (fndecl_arglist == NULL_TREE || target_fndecl_arglist == NULL_TREE)
++		return CANNOT_FIND_ARG;
 +
-+static void handle_struct_fields(struct walk_use_def_data *use_def_data, const_tree node)
-+{
-+	struct fn_raw_data raw_data;
++	fndecl_arg = chain_index(num - 1, fndecl_arglist);
++	if (fndecl_arg == NULL_TREE)
++		return CANNOT_FIND_ARG;
 +
-+	switch (TREE_CODE(node)) {
-+	case ARRAY_REF:
-+#if BUILDING_GCC_VERSION >= 4006
-+	case MEM_REF:
-+#endif
-+	case INDIRECT_REF:
-+	case COMPONENT_REF:
-+		raw_data.decl = get_ref_field(node);
-+		break;
-+	// TODO
-+	case BIT_FIELD_REF:
-+	case VIEW_CONVERT_EXPR:
-+	case REALPART_EXPR:
-+	case IMAGPART_EXPR:
-+		return;
-+	default:
-+		debug_tree(node);
-+		gcc_unreachable();
++	for (arg = target_fndecl_arglist, new_num = 1; arg; arg = TREE_CHAIN(arg), new_num++) {
++		if (arg == fndecl_arg || !strcmp(DECL_NAME_POINTER(arg), DECL_NAME_POINTER(fndecl_arg)))
++			return new_num;
 +	}
 +
-+	if (get_intentional_attr_type(raw_data.decl) == MARK_TURN_OFF)
-+		return;
-+
-+	create_and_append_new_next_interesting_field_var_decl(use_def_data, &raw_data);
++	return CANNOT_FIND_ARG;
 +}
 +
-+static void handle_vardecl(struct walk_use_def_data *use_def_data, tree node)
++// Find the specified argument in the originally cloned function
++static unsigned int clone_argnum_on_orig(struct cgraph_node *new_node, struct cgraph_node *old_node, unsigned int clone_argnum)
 +{
-+	struct fn_raw_data raw_data;
++	bitmap args_to_skip;
++	unsigned int i, new_argnum = clone_argnum;
 +
-+	raw_data.decl = node;
-+	create_and_append_new_next_interesting_field_var_decl(use_def_data, &raw_data);
++	if (unchanged_arglist(new_node, old_node))
++		return clone_argnum;
++
++	gcc_assert(new_node->clone_of && new_node->clone.tree_map);
++	args_to_skip = new_node->clone.args_to_skip;
++	for (i = 0; i < clone_argnum; i++) {
++		if (bitmap_bit_p(args_to_skip, i))
++			new_argnum++;
++	}
++	return new_argnum;
 +}
 +
-+/* Find all functions that influence lhs
-+ *
-+ * Encountered functions are added to the children vector (next_interesting_function_t).
-+ */
-+static void walk_use_def_next_functions(struct walk_use_def_data *use_def_data, tree lhs)
++// Find the specified argument in the clone
++static unsigned int orig_argnum_on_clone(struct cgraph_node *new_node, struct cgraph_node *old_node, unsigned int orig_argnum)
 +{
-+	enum tree_code code;
-+	const_gimple def_stmt;
++	bitmap args_to_skip;
++	unsigned int i, new_argnum = orig_argnum;
 +
-+	if (skip_types(lhs))
-+		return;
++	if (unchanged_arglist(new_node, old_node))
++		return orig_argnum;
 +
-+	if (VAR_P(lhs)) {
-+		handle_vardecl(use_def_data, lhs);
-+		return;
-+	}
++	gcc_assert(new_node->clone_of && new_node->clone.tree_map);
++	args_to_skip = new_node->clone.args_to_skip;
++	if (bitmap_bit_p(args_to_skip, orig_argnum - 1))
++		// XXX torolni kellene a nodeot
++		return CANNOT_FIND_ARG;
 +
-+	code = TREE_CODE(lhs);
-+	if (code == PARM_DECL) {
-+		handle_function(use_def_data, current_function_decl, lhs);
-+		return;
++	for (i = 0; i < orig_argnum; i++) {
++		if (bitmap_bit_p(args_to_skip, i))
++			new_argnum--;
 +	}
++	return new_argnum;
++}
 +
-+	if (TREE_CODE_CLASS(code) == tcc_reference) {
-+		handle_struct_fields(use_def_data, lhs);
-+		return;
-+	}
++// Associate the argument between a clone and a cloned function
++static unsigned int get_correct_argnum_cnode(struct cgraph_node *node, struct cgraph_node *correct_argnum_of_node, unsigned int argnum)
++{
++	bool node_clone, correct_argnum_of_node_clone;
++	const_tree correct_argnum_of_node_decl, node_decl;
 +
-+	if (code != SSA_NAME)
-+		return;
++	if (node == correct_argnum_of_node)
++		return argnum;
++	if (argnum == 0)
++		return argnum;
 +
-+	def_stmt = get_def_stmt(lhs);
-+	if (!def_stmt)
-+		return;
++	correct_argnum_of_node_decl = NODE_DECL(correct_argnum_of_node);
++	gcc_assert(correct_argnum_of_node_decl != NULL_TREE);
++	gcc_assert(correct_argnum_of_node && !DECL_ARTIFICIAL(correct_argnum_of_node_decl));
 +
-+	if (pointer_set_insert(use_def_data->visited, def_stmt))
-+		return;
++	if (node) {
++		node_decl = NODE_DECL(node);
++		gcc_assert(!DECL_ARTIFICIAL(node_decl));
++		node_clone = made_by_compiler(node_decl);
++	} else {
++		node_decl = NULL_TREE;
++		node_clone = false;
++	}
 +
-+	switch (gimple_code(def_stmt)) {
-+	case GIMPLE_NOP:
-+		walk_use_def_next_functions(use_def_data, SSA_NAME_VAR(lhs));
-+		return;
-+	case GIMPLE_ASM:
-+		if (!is_size_overflow_asm(def_stmt))
-+			return;
-+		walk_use_def_next_functions(use_def_data, get_size_overflow_asm_input(as_a_const_gasm(def_stmt)));
-+		return;
-+	case GIMPLE_CALL: {
-+		tree fndecl = gimple_call_fndecl(def_stmt);
++	if (correct_argnum_of_node_decl == node_decl)
++		return argnum;
 +
-+		if (fndecl != NULL_TREE) {
-+			handle_function(use_def_data, fndecl, NULL_TREE);
-+			return;
-+		}
-+		fndecl = gimple_call_fn(def_stmt);
-+		handle_function_ptr_ret(use_def_data, fndecl);
-+		return;
-+	}
-+	case GIMPLE_PHI:
-+		walk_use_def_next_functions_phi(use_def_data, lhs);
-+		return;
-+	case GIMPLE_ASSIGN:
-+		switch (gimple_num_ops(def_stmt)) {
-+		case 2:
-+			walk_use_def_next_functions_unary(use_def_data, as_a_const_gassign(def_stmt));
-+			return;
-+		case 3:
-+			walk_use_def_next_functions_binary(use_def_data, lhs);
-+			return;
-+		}
-+	default:
-+		debug_gimple_stmt((gimple)def_stmt);
-+		error("%s: unknown gimple code", __func__);
-+		gcc_unreachable();
++	correct_argnum_of_node_clone = made_by_compiler(correct_argnum_of_node_decl);
++	// the original decl is lost if both nodes are clones
++	if (node_clone && correct_argnum_of_node_clone) {
++		gcc_assert(unchanged_arglist(node, correct_argnum_of_node));
++		return argnum;
 +	}
++
++	if (node_clone && !correct_argnum_of_node_clone)
++		return clone_argnum_on_orig(correct_argnum_of_node, node, argnum);
++	else if (!node_clone && correct_argnum_of_node_clone)
++		return orig_argnum_on_clone(correct_argnum_of_node, node, argnum);
++
++	if (node)
++		debug_tree(NODE_DECL(node));
++	debug_tree(correct_argnum_of_node_decl);
++	gcc_unreachable();
 +}
 +
-+// Start the search for next_interesting_function_t children based on the (next_interesting_function_t) parent node
-+static next_interesting_function_t search_next_functions(tree node, next_interesting_function_t parent)
++unsigned int get_correct_argnum(const_tree decl, const_tree correct_argnum_of_decl, unsigned int argnum)
 +{
-+	struct walk_use_def_data use_def_data;
++	struct cgraph_node *node, *correct_argnum_of_node;
 +
-+	use_def_data.parent = parent;
-+	use_def_data.next_cnodes_head = NULL;
-+	use_def_data.visited = pointer_set_create();
++	gcc_assert(decl != NULL_TREE);
++	gcc_assert(correct_argnum_of_decl != NULL_TREE);
 +
-+	walk_use_def_next_functions(&use_def_data, node);
++	correct_argnum_of_node = get_cnode(correct_argnum_of_decl);
++	if (!correct_argnum_of_node || DECL_ARTIFICIAL(decl) || DECL_ARTIFICIAL(correct_argnum_of_decl))
++		return get_correct_argnum_fndecl(decl, correct_argnum_of_decl, argnum);
 +
-+	pointer_set_destroy(use_def_data.visited);
-+	return use_def_data.next_cnodes_head;
++	node = get_cnode(decl);
++	return get_correct_argnum_cnode(node, correct_argnum_of_node, argnum);
 +}
 +
-+// True if child already exists in the next_interesting_function_t children vector
-+bool has_next_interesting_function_vec(next_interesting_function_t target, next_interesting_function_t next_node)
++// Find the original cloned function
++tree get_orig_fndecl(const_tree clone_fndecl)
 +{
-+	unsigned int i;
-+	next_interesting_function_t cur;
++	struct cgraph_node *node;
 +
-+	gcc_assert(next_node);
-+	// handle recursion
-+	if (!strcmp(target->decl_name, next_node->decl_name) && target->num == next_node->num)
-+		return true;
++	gcc_assert(TREE_CODE(clone_fndecl) == FUNCTION_DECL);
 +
-+#if BUILDING_GCC_VERSION <= 4007
-+	if (VEC_empty(next_interesting_function_t, target->children))
-+		return false;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, target->children, i, cur) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(target->children, i, cur) {
-+#endif
-+		if (compare_next_interesting_functions(cur, next_node->decl_name, next_node->context, next_node->num))
-+			return true;
-+	}
-+	return false;
++	if (DECL_ABSTRACT_ORIGIN(clone_fndecl))
++		return CONST_CAST_TREE(DECL_ABSTRACT_ORIGIN(clone_fndecl));
++	node = get_cnode(clone_fndecl);
++	if (!node)
++		return CONST_CAST_TREE(clone_fndecl);
++
++	while (node->clone_of)
++		node = node->clone_of;
++	if (!made_by_compiler(NODE_DECL(node)))
++		return NODE_DECL(node);
++	// Return the cloned decl because it is needed for the transform callback
++	return CONST_CAST_TREE(clone_fndecl);
 +}
 +
-+void push_child(next_interesting_function_t parent, next_interesting_function_t child)
++static tree get_interesting_fndecl_from_stmt(const gcall *stmt)
 +{
-+	if (!has_next_interesting_function_vec(parent, child)) {
-+#if BUILDING_GCC_VERSION <= 4007
-+		VEC_safe_push(next_interesting_function_t, heap, parent->children, child);
-+#else
-+		vec_safe_push(parent->children, child);
-+#endif
-+	}
++	if (gimple_call_num_args(stmt) == 0)
++		return NULL_TREE;
++	return gimple_call_fndecl(stmt);
 +}
 +
-+void __attribute__((weak)) check_local_variables(next_interesting_function_t next_node __unused) {}
-+
-+// Add children to parent and global_next_interesting_function
-+static void collect_data_for_execute(next_interesting_function_t parent, next_interesting_function_t children)
++tree get_interesting_orig_fndecl_from_stmt(const gcall *stmt)
 +{
-+	next_interesting_function_t cur = children;
-+
-+	gcc_assert(parent);
-+
-+	while (cur) {
-+		struct fn_raw_data child_raw_data;
-+		next_interesting_function_t next, child;
-+
-+		next = cur->next;
++	tree fndecl;
 +
-+		child_raw_data.decl_str = cur->decl_name;
-+		child_raw_data.context = cur->context;
-+		child_raw_data.hash = cur->hash;
-+		child_raw_data.num = cur->num;
-+		child_raw_data.marked = NO_SO_MARK;
-+		child = get_global_next_interesting_function_entry(&child_raw_data);
-+		if (!child) {
-+			add_to_global_next_interesting_function(cur);
-+			child = cur;
-+		}
++	fndecl = get_interesting_fndecl_from_stmt(stmt);
++	if (fndecl == NULL_TREE)
++		return NULL_TREE;
++	return get_orig_fndecl(fndecl);
++}
 +
-+		check_local_variables(child);
++void set_dominance_info(void)
++{
++	calculate_dominance_info(CDI_DOMINATORS);
++	calculate_dominance_info(CDI_POST_DOMINATORS);
++}
 +
-+		push_child(parent, child);
++void unset_dominance_info(void)
++{
++	free_dominance_info(CDI_DOMINATORS);
++	free_dominance_info(CDI_POST_DOMINATORS);
++}
 +
-+		cur = next;
-+	}
++void set_current_function_decl(tree fndecl)
++{
++	gcc_assert(fndecl != NULL_TREE);
 +
-+	check_local_variables(parent);
++	push_cfun(DECL_STRUCT_FUNCTION(fndecl));
++#if BUILDING_GCC_VERSION <= 4007
++	current_function_decl = fndecl;
++#endif
++	set_dominance_info();
 +}
 +
-+next_interesting_function_t __attribute__((weak)) get_and_create_next_node_from_global_next_nodes_fnptr(const_tree fn_ptr __unused, struct fn_raw_data *raw_data __unused)
++void unset_current_function_decl(void)
 +{
-+	return NULL;
++	unset_dominance_info();
++#if BUILDING_GCC_VERSION <= 4007
++	current_function_decl = NULL_TREE;
++#endif
++	pop_cfun();
 +}
 +
-+static next_interesting_function_t create_parent_next_cnode(const_gimple stmt, unsigned int num)
++bool is_valid_cgraph_node(struct cgraph_node *node)
 +{
-+	struct fn_raw_data raw_data;
-+
-+	raw_data.num = num;
-+	raw_data.marked = NO_SO_MARK;
++	if (cgraph_function_body_availability(node) == AVAIL_NOT_AVAILABLE)
++		return false;
++	if (node->thunk.thunk_p || node->alias)
++		return false;
++	return true;
++}
 +
++tree get_lhs(const_gimple stmt)
++{
 +	switch (gimple_code(stmt)) {
-+	case GIMPLE_ASM:
-+		raw_data.decl = current_function_decl;
-+		raw_data.marked = ASM_STMT_SO_MARK;
-+		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
++	case GIMPLE_ASSIGN:
 +	case GIMPLE_CALL:
-+		raw_data.decl = gimple_call_fndecl(stmt);
-+		if (raw_data.decl != NULL_TREE)
-+			return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
-+		raw_data.decl = gimple_call_fn(stmt);
-+		return get_and_create_next_node_from_global_next_nodes_fnptr(raw_data.decl, &raw_data);
-+	case GIMPLE_RETURN:
-+		raw_data.decl = current_function_decl;
-+		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
-+	case GIMPLE_ASSIGN: {
-+		tree lhs = gimple_assign_lhs(stmt);
-+
-+		if (VAR_P(lhs))
-+			raw_data.decl = lhs;
-+		else
-+			raw_data.decl = get_ref_field(lhs);
-+		if (raw_data.decl == NULL_TREE)
-+			return NULL;
-+		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
-+	}
++		return gimple_get_lhs(stmt);
++	case GIMPLE_PHI:
++		return gimple_phi_result(stmt);
 +	default:
 +		debug_gimple_stmt((gimple)stmt);
 +		gcc_unreachable();
 +	}
 +}
 +
-+// Handle potential next_interesting_function_t parent if its argument has an integer type
-+static void collect_all_possible_size_overflow_fns(const_gimple stmt, tree start_var, unsigned int num)
-+{
-+	next_interesting_function_t children_next_cnode, parent_next_cnode;
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin.c
+new file mode 100644
+index 0000000..3f8f032
+--- /dev/null
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin.c
+@@ -0,0 +1,290 @@
++/*
++ * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
++ * Licensed under the GPL v2, or (at your option) v3
++ *
++ * Homepage:
++ * https://github.com/ephox-gcc-plugins/size_overflow
++ *
++ * Documentation:
++ * http://forums.grsecurity.net/viewtopic.php?f=7&t=3043
++ *
++ * This plugin recomputes expressions of function arguments marked by a size_overflow attribute
++ * with double integer precision (DImode/TImode for 32/64 bit integer types).
++ * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
++ *
++ * Usage:
++ * $ make
++ * $ make run
++ */
 +
-+	// skip void return values
-+	if (start_var == NULL_TREE)
-+		return;
++#include "size_overflow.h"
 +
-+	if (skip_types(start_var))
-+		return;
++int plugin_is_GPL_compatible;
 +
-+	// handle intentional MARK_TURN_OFF
-+	if (check_intentional_size_overflow_asm_and_attribute(start_var) == MARK_TURN_OFF)
-+		return;
++tree report_size_overflow_decl;
 +
-+	parent_next_cnode = create_parent_next_cnode(stmt, num);
-+	if (!parent_next_cnode)
-+		return;
++tree size_overflow_type_HI;
++tree size_overflow_type_SI;
++tree size_overflow_type_DI;
++tree size_overflow_type_TI;
 +
-+	children_next_cnode = search_next_functions(start_var, parent_next_cnode);
-+	collect_data_for_execute(parent_next_cnode, children_next_cnode);
-+}
++static struct plugin_info size_overflow_plugin_info = {
++	.version	= "20160521",
++	.help		= "no-size-overflow\tturn off size overflow checking\n",
++};
 +
-+static void collect_all_possible_size_overflow_fields_and_vars(const gassign *assign)
++static tree handle_size_overflow_attribute(tree *node, tree __unused name, tree args, int __unused flags, bool *no_add_attrs)
 +{
-+	tree start_var, decl, lhs = gimple_assign_lhs(assign);
-+
-+	if (VAR_P(lhs))
-+		decl = lhs;
-+	else
-+		decl = get_ref_field(lhs);
-+	if (decl == NULL_TREE)
-+		return;
++	unsigned int arg_count;
++	enum tree_code code = TREE_CODE(*node);
 +
-+	if (get_intentional_attr_type(decl) == MARK_TURN_OFF)
-+		return;
++	switch (code) {
++	case FUNCTION_DECL:
++		arg_count = type_num_arguments(TREE_TYPE(*node));
++		break;
++	case FUNCTION_TYPE:
++	case METHOD_TYPE:
++		arg_count = type_num_arguments(*node);
++		break;
++	default:
++		*no_add_attrs = true;
++		debug_tree(*node);
++		error("%s: %qE attribute only applies to functions", __func__, name);
++		return NULL_TREE;
++	}
 +
-+	start_var = gimple_assign_rhs1(assign);
-+	collect_all_possible_size_overflow_fns(assign, start_var, 0);
++	for (; args; args = TREE_CHAIN(args)) {
++		int cur_val;
++		tree position = TREE_VALUE(args);
 +
-+	start_var = gimple_assign_rhs2(assign);
-+	collect_all_possible_size_overflow_fns(assign, start_var, 0);
++		if (TREE_CODE(position) != INTEGER_CST) {
++			error("%s: parameter isn't an integer", __func__);
++			debug_tree(args);
++			*no_add_attrs = true;
++			return NULL_TREE;
++		}
 +
-+#if BUILDING_GCC_VERSION >= 4006
-+	start_var = gimple_assign_rhs3(assign);
-+	collect_all_possible_size_overflow_fns(assign, start_var, 0);
-+#endif
++		cur_val = tree_to_shwi(position);
++		if (cur_val < 0 || arg_count < (unsigned int)cur_val) {
++			error("%s: parameter %d is outside range.", __func__, cur_val);
++			*no_add_attrs = true;
++			return NULL_TREE;
++		}
++	}
++	return NULL_TREE;
 +}
 +
-+// Find potential next_interesting_function_t parents
-+static void handle_cgraph_node(struct cgraph_node *node)
++static tree handle_intentional_overflow_attribute(tree *node, tree __unused name, tree args, int __unused flags, bool *no_add_attrs)
 +{
-+	basic_block bb;
-+	tree cur_fndecl = NODE_DECL(node);
-+
-+	set_current_function_decl(cur_fndecl);
-+
-+	FOR_EACH_BB_FN(bb, cfun) {
-+		gimple_stmt_iterator gsi;
-+
-+		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
-+			tree start_var;
-+			gimple stmt = gsi_stmt(gsi);
++	unsigned int arg_count;
++	HOST_WIDE_INT s_first_arg;
++	enum tree_code code = TREE_CODE(*node);
 +
-+			switch (gimple_code(stmt)) {
-+			case GIMPLE_RETURN: {
-+				const greturn *return_stmt = as_a_const_greturn(stmt);
++	switch (code) {
++	case FUNCTION_DECL:
++		arg_count = type_num_arguments(TREE_TYPE(*node));
++		break;
++	case FUNCTION_TYPE:
++	case METHOD_TYPE:
++		arg_count = type_num_arguments(*node);
++		break;
++	case VAR_DECL:
++	case FIELD_DECL:
++		return NULL_TREE;
++	default:
++		*no_add_attrs = true;
++		debug_tree(*node);
++		error("%qE attribute only applies to functions, fields or vars", name);
++		return NULL_TREE;
++	}
 +
-+				start_var = gimple_return_retval(return_stmt);
-+				collect_all_possible_size_overflow_fns(return_stmt, start_var, 0);
-+				break;
-+			}
-+			case GIMPLE_ASM: {
-+				const gasm *asm_stmt = as_a_const_gasm(stmt);
++	s_first_arg = tree_to_shwi(TREE_VALUE(args));
++	if (s_first_arg == -1)
++		return NULL_TREE;
++	if (s_first_arg < -1)
++		error("%s: parameter %d is outside range.", __func__, (int)s_first_arg);
 +
-+				if (!is_size_overflow_insert_check_asm(asm_stmt))
-+					break;
-+				start_var = get_size_overflow_asm_input(asm_stmt);
-+				collect_all_possible_size_overflow_fns(asm_stmt, start_var, 0);
-+				break;
-+			}
-+			case GIMPLE_CALL: {
-+				unsigned int i, len;
-+				const gcall *call = as_a_const_gcall(stmt);
-+				tree fndecl = gimple_call_fndecl(call);
++	for (; args; args = TREE_CHAIN(args)) {
++		unsigned int cur_val;
 +
-+				if (fndecl != NULL_TREE && (DECL_BUILT_IN(fndecl) || DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_NORMAL))
-+					break;
++		if (TREE_CODE(TREE_VALUE(args)) != INTEGER_CST) {
++			error("%s: parameter isn't an integer", __func__);
++			debug_tree(args);
++			*no_add_attrs = true;
++			return NULL_TREE;
++		}
 +
-+				len = gimple_call_num_args(call);
-+				for (i = 0; i < len; i++) {
-+					start_var = gimple_call_arg(call, i);
-+					collect_all_possible_size_overflow_fns(call, start_var, i + 1);
-+				}
-+				break;
-+			}
-+			case GIMPLE_ASSIGN:
-+				collect_all_possible_size_overflow_fields_and_vars(as_a_const_gassign(stmt));
-+				break;
-+			default:
-+				break;
-+			}
++		cur_val = (unsigned int)tree_to_uhwi(TREE_VALUE(args));
++		if (cur_val > arg_count ) {
++			error("%s: parameter %u is outside range. (arg_count: %u)", __func__, cur_val, arg_count);
++			*no_add_attrs = true;
++			return NULL_TREE;
 +		}
 +	}
-+
-+	unset_current_function_decl();
++	return NULL_TREE;
 +}
 +
-+/* Collect all potentially interesting function parameters and return values of integer types
-+ * and store their data flow dependencies
-+ */
-+static void size_overflow_generate_summary(void)
++static struct attribute_spec size_overflow_attr = {
++	.name				= "size_overflow",
++	.min_length			= 1,
++	.max_length			= -1,
++	.decl_required			= true,
++	.type_required			= false,
++	.function_type_required		= false,
++	.handler			= handle_size_overflow_attribute,
++#if BUILDING_GCC_VERSION >= 4007
++	.affects_type_identity		= false
++#endif
++};
++
++static struct attribute_spec intentional_overflow_attr = {
++	.name				= "intentional_overflow",
++	.min_length			= 1,
++	.max_length			= -1,
++	.decl_required			= true,
++	.type_required			= false,
++	.function_type_required		= false,
++	.handler			= handle_intentional_overflow_attribute,
++#if BUILDING_GCC_VERSION >= 4007
++	.affects_type_identity		= false
++#endif
++};
++
++static void register_attributes(void __unused *event_data, void __unused *data)
 +{
-+	struct cgraph_node *node;
++	register_attribute(&size_overflow_attr);
++	register_attribute(&intentional_overflow_attr);
++}
 +
-+	size_overflow_register_hooks();
++static tree create_typedef(tree type, const char* ident)
++{
++	tree new_type, decl;
 +
-+	FOR_EACH_FUNCTION(node) {
-+		if (is_valid_cgraph_node(node))
-+			handle_cgraph_node(node);
-+	}
++	new_type = build_variant_type_copy(type);
++	decl = build_decl(BUILTINS_LOCATION, TYPE_DECL, get_identifier(ident), new_type);
++	DECL_ORIGINAL_TYPE(decl) = type;
++	TYPE_NAME(new_type) = decl;
++	return new_type;
 +}
 +
-+static void size_overflow_function_insertion_hook(struct cgraph_node *node __unused, void *data __unused)
++// Create the noreturn report_size_overflow() function decl.
++static void size_overflow_start_unit(void __unused *gcc_data, void __unused *user_data)
 +{
-+	debug_cgraph_node(node);
-+	gcc_unreachable();
++	tree const_char_ptr_type_node;
++	tree fntype;
++
++	const_char_ptr_type_node = build_pointer_type(build_type_variant(char_type_node, 1, 0));
++
++	size_overflow_type_HI = create_typedef(intHI_type_node, "size_overflow_type_HI");
++	size_overflow_type_SI = create_typedef(intSI_type_node, "size_overflow_type_SI");
++	size_overflow_type_DI = create_typedef(intDI_type_node, "size_overflow_type_DI");
++	size_overflow_type_TI = create_typedef(intTI_type_node, "size_overflow_type_TI");
++
++	// void report_size_overflow(const char *loc_file, unsigned int loc_line, const char *current_func, const char *ssa_var)
++	fntype = build_function_type_list(void_type_node,
++					  const_char_ptr_type_node,
++					  unsigned_type_node,
++					  const_char_ptr_type_node,
++					  const_char_ptr_type_node,
++					  NULL_TREE);
++	report_size_overflow_decl = build_fn_decl("report_size_overflow", fntype);
++
++	DECL_ASSEMBLER_NAME(report_size_overflow_decl);
++	TREE_PUBLIC(report_size_overflow_decl) = 1;
++	DECL_EXTERNAL(report_size_overflow_decl) = 1;
++	DECL_ARTIFICIAL(report_size_overflow_decl) = 1;
++//	TREE_THIS_VOLATILE(report_size_overflow_decl) = 1;
++// !!!
++	DECL_PRESERVE_P(report_size_overflow_decl) = 1;
++	DECL_UNINLINABLE(report_size_overflow_decl) = 1;
++	TREE_USED(report_size_overflow_decl) = 1;
++	TREE_NOTHROW(report_size_overflow_decl) = 1;
 +}
 +
-+/* Handle dst if src is in the global_next_interesting_function list.
-+ * If src is a clone then dst inherits the orig_next_node of src otherwise
-+ * src will become the orig_next_node of dst.
-+ */
-+static void size_overflow_node_duplication_hook(struct cgraph_node *src, struct cgraph_node *dst, void *data __unused)
++static bool disable_ubsan_si_overflow_gate(void)
 +{
-+	next_interesting_function_t head, cur;
-+	struct fn_raw_data src_raw_data;
++#if BUILDING_GCC_VERSION >= 4009
++	flag_sanitize &= ~SANITIZE_SI_OVERFLOW;
++#endif
++	return true;
++}
 +
-+	src_raw_data.decl = NODE_DECL(src);
-+	src_raw_data.decl_str = DECL_NAME_POINTER(src_raw_data.decl);
-+	src_raw_data.context = get_decl_context(src_raw_data.decl);
-+	if (!src_raw_data.context)
-+		return;
++#define PASS_NAME disable_ubsan_si_overflow
 +
-+	src_raw_data.num = NONE_ARGNUM;
-+	src_raw_data.marked = NO_SO_MARK;
++#define NO_EXECUTE
 +
-+	head = get_global_next_interesting_function_entry_with_hash(&src_raw_data);
-+	if (!head)
-+		return;
++#include "gcc-generate-gimple-pass.h"
 +
-+	for (cur = head; cur; cur = cur->next) {
-+		struct fn_raw_data dst_raw_data;
-+		next_interesting_function_t orig_next_node, next_node;
++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
++{
++	int i;
++	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	bool enable = true;
++	struct register_pass_info insert_size_overflow_asm_pass_info;
++	struct register_pass_info size_overflow_pass_info;
++#if BUILDING_GCC_VERSION >= 4009
++	struct register_pass_info disable_ubsan_si_overflow_pass_info;
++#endif
 +
-+		if (!compare_next_interesting_functions(cur, src_raw_data.decl_str, src_raw_data.context, src_raw_data.num))
-+			continue;
++	static const struct ggc_root_tab gt_ggc_r_gt_size_overflow[] = {
++		{
++			.base = &report_size_overflow_decl,
++			.nelt = 1,
++			.stride = sizeof(report_size_overflow_decl),
++			.cb = &gt_ggc_mx_tree_node,
++			.pchw = &gt_pch_nx_tree_node
++		},
++		LAST_GGC_ROOT_TAB
++	};
 +
-+		dst_raw_data.decl = NODE_DECL(dst);
-+		dst_raw_data.decl_str = cgraph_node_name(dst);
-+		dst_raw_data.marked = cur->marked;
++	insert_size_overflow_asm_pass_info.pass				= make_insert_size_overflow_asm_pass();
++	insert_size_overflow_asm_pass_info.reference_pass_name		= "ssa";
++	insert_size_overflow_asm_pass_info.ref_pass_instance_number	= 1;
++	insert_size_overflow_asm_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
 +
-+		if (!made_by_compiler(dst_raw_data.decl))
-+			break;
++	size_overflow_pass_info.pass			= make_size_overflow_pass();
++	size_overflow_pass_info.reference_pass_name	= "inline";
++	size_overflow_pass_info.ref_pass_instance_number	= 1;
++	size_overflow_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
 +
-+		// For clones use the original node instead
-+		if (cur->orig_next_node)
-+			orig_next_node = cur->orig_next_node;
-+		else
-+			orig_next_node = cur;
++	if (!plugin_default_version_check(version, &gcc_version)) {
++		error(G_("incompatible gcc/plugin versions"));
++		return 1;
++	}
 +
-+		dst_raw_data.num = get_correct_argnum_fndecl(src_raw_data.decl, dst_raw_data.decl, cur->num);
-+		if (dst_raw_data.num == CANNOT_FIND_ARG)
++	for (i = 0; i < argc; ++i) {
++		if (!strcmp(argv[i].key, "no-size-overflow")) {
++			enable = false;
 +			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
 +
-+		next_node = create_new_next_interesting_decl(&dst_raw_data, orig_next_node);
-+		if (next_node)
-+			add_to_global_next_interesting_function(next_node);
++	register_callback(plugin_name, PLUGIN_INFO, NULL, &size_overflow_plugin_info);
++	if (enable) {
++#if BUILDING_GCC_VERSION >= 4009
++		if (flag_sanitize & SANITIZE_SI_OVERFLOW) {
++			error(G_("ubsan SANITIZE_SI_OVERFLOW option is unsupported"));
++			return 1;
++		}
++#endif
++		register_callback(plugin_name, PLUGIN_START_UNIT, &size_overflow_start_unit, NULL);
++		register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_size_overflow);
++#if BUILDING_GCC_VERSION >= 4009
++		flag_sanitize |= SANITIZE_SI_OVERFLOW;
++		disable_ubsan_si_overflow_pass_info.pass			= make_disable_ubsan_si_overflow_pass();
++		disable_ubsan_si_overflow_pass_info.reference_pass_name		= "ubsan";
++		disable_ubsan_si_overflow_pass_info.ref_pass_instance_number	= 1;
++		disable_ubsan_si_overflow_pass_info.pos_op			= PASS_POS_REPLACE;
++
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &disable_ubsan_si_overflow_pass_info);
++#endif
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &insert_size_overflow_asm_pass_info);
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &size_overflow_pass_info);
 +	}
++	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
++
++	return 0;
 +}
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin_hash.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin_hash.c
+new file mode 100644
+index 0000000..87af656
+--- /dev/null
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_plugin_hash.c
+@@ -0,0 +1,352 @@
++/*
++ * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
++ * Licensed under the GPL v2, or (at your option) v3
++ *
++ * Homepage:
++ * https://github.com/ephox-gcc-plugins/size_overflow
++ *
++ * Documentation:
++ * http://forums.grsecurity.net/viewtopic.php?f=7&t=3043
++ *
++ * This plugin recomputes expressions of function arguments marked by a size_overflow attribute
++ * with double integer precision (DImode/TImode for 32/64 bit integer types).
++ * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
++ *
++ * Usage:
++ * $ make
++ * $ make run
++ */
 +
-+void size_overflow_register_hooks(void)
-+{
-+	static bool init_p = false;
++#include "size_overflow.h"
 +
-+	if (init_p)
-+		return;
-+	init_p = true;
++#include "size_overflow_hash.h"
++#include "disable_size_overflow_hash.h"
++#include "size_overflow_hash_aux.h"
 +
-+	function_insertion_hook_holder = cgraph_add_function_insertion_hook(&size_overflow_function_insertion_hook, NULL);
-+	node_duplication_hook_holder = cgraph_add_node_duplication_hook(&size_overflow_node_duplication_hook, NULL);
++static const_tree get_function_type(const_tree decl)
++{
++	if (FUNCTION_PTR_P(decl))
++		return TREE_TYPE(TREE_TYPE(decl));
++	gcc_assert(TREE_CODE(decl) == FUNCTION_DECL);
++	return TREE_TYPE(decl);
 +}
 +
-+static void set_yes_so_mark(next_interesting_function_t next_node)
++static unsigned char get_tree_code(const_tree type)
 +{
-+	if (next_node->marked == NO_SO_MARK) {
-+		next_node->marked = YES_SO_MARK;
-+		global_changed = true;
++	switch (TREE_CODE(type)) {
++	case ARRAY_TYPE:
++		return 0;
++	case BOOLEAN_TYPE:
++		return 1;
++	case ENUMERAL_TYPE:
++		return 2;
++	case FUNCTION_TYPE:
++		return 3;
++	case INTEGER_TYPE:
++		return 4;
++	case POINTER_TYPE:
++		return 5;
++	case RECORD_TYPE:
++		return 6;
++	case UNION_TYPE:
++		return 7;
++	case VOID_TYPE:
++		return 8;
++	case REAL_TYPE:
++		return 9;
++	case VECTOR_TYPE:
++		return 10;
++	case REFERENCE_TYPE:
++		return 11;
++	case OFFSET_TYPE:
++		return 12;
++	case COMPLEX_TYPE:
++		return 13;
++	default:
++		debug_tree(type);
++		gcc_unreachable();
 +	}
-+	// Mark the orig decl as well if it's a clone
-+	if (next_node->orig_next_node && next_node->orig_next_node->marked == NO_SO_MARK) {
-+		next_node->orig_next_node->marked = YES_SO_MARK;
-+		global_changed = true;
++}
++
++// http://www.team5150.com/~andrew/noncryptohashzoo2~/CrapWow.html
++static unsigned int CrapWow(const char *key, unsigned int len, unsigned int seed)
++{
++#define cwfold( a, b, lo, hi ) { p = (unsigned int)(a) * (unsigned long long)(b); lo ^= (unsigned int)p; hi ^= (unsigned int)(p >> 32); }
++#define cwmixa( in ) { cwfold( in, m, k, h ); }
++#define cwmixb( in ) { cwfold( in, n, h, k ); }
++
++	unsigned int m = 0x57559429;
++	unsigned int n = 0x5052acdb;
++	const unsigned int *key4 = (const unsigned int *)key;
++	unsigned int h = len;
++	unsigned int k = len + seed + n;
++	unsigned long long p;
++
++	while (len >= 8) {
++		cwmixb(key4[0]) cwmixa(key4[1]) key4 += 2;
++		len -= 8;
++	}
++	if (len >= 4) {
++		cwmixb(key4[0]) key4 += 1;
++		len -= 4;
 +	}
++	if (len)
++		cwmixa(key4[0] & ((1 << (len * 8)) - 1 ));
++	cwmixb(h ^ (k + n));
++	return k ^ h;
++
++#undef cwfold
++#undef cwmixa
++#undef cwmixb
 +}
 +
-+// Determine whether node or orig node is part of a tracked data flow
-+static bool marked_fn(next_interesting_function_t next_node)
++static void set_hash(struct decl_hash *decl_hash_data)
 +{
-+	bool is_marked_fn, is_marked_orig = false;
-+
-+	is_marked_fn = next_node->marked != NO_SO_MARK;
-+
-+	if (next_node->orig_next_node)
-+		is_marked_orig = next_node->orig_next_node->marked != NO_SO_MARK;
++	unsigned int fn, type, codes, seed = 0;
 +
-+	return is_marked_fn || is_marked_orig;
++	fn = CrapWow(decl_hash_data->fn_name, strlen(decl_hash_data->fn_name), seed) & 0xffff;
++	codes = CrapWow((const char*)decl_hash_data->tree_codes, decl_hash_data->tree_codes_len, seed) & 0xffff;
++	type = CrapWow(decl_hash_data->context, strlen(decl_hash_data->context), 0) & 0xffff;
++	decl_hash_data->hash = type ^ fn ^ codes;
 +}
 +
-+// Determine whether node or orig node is in the hash table already
-+static bool already_in_the_hashtable(next_interesting_function_t next_node)
++static void set_decl_type_codes(const_tree type, struct decl_hash *decl_hash_data)
 +{
-+	if (next_node->orig_next_node)
-+		next_node = next_node->orig_next_node;
-+	return get_size_overflow_hash_entry(next_node->hash, next_node->decl_name, next_node->context, next_node->num) != NULL;
++	gcc_assert(type != NULL_TREE);
++	gcc_assert(TREE_CODE_CLASS(TREE_CODE(type)) == tcc_type);
++
++	while (type && decl_hash_data->tree_codes_len < CODES_LIMIT) {
++		decl_hash_data->tree_codes[decl_hash_data->tree_codes_len] = get_tree_code(type);
++		decl_hash_data->tree_codes_len++;
++		type = TREE_TYPE(type);
++	}
 +}
 +
-+// Propagate the size_overflow marks up the use-def chains
-+static bool has_marked_child(next_interesting_function_t next_node)
++static void set_result_codes(const_tree node, struct decl_hash *decl_hash_data)
 +{
-+	bool ret = false;
-+	unsigned int i;
-+	next_interesting_function_t child;
++	const_tree result;
 +
-+#if BUILDING_GCC_VERSION <= 4007
-+	if (VEC_empty(next_interesting_function_t, next_node->children))
-+		return false;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, next_node->children, i, child) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(next_node->children, i, child) {
-+#endif
-+		if (marked_fn(child) || already_in_the_hashtable(child))
-+			ret = true;
++	gcc_assert(node != NULL_TREE);
++
++	if (DECL_P(node)) {
++		result = DECL_RESULT(node);
++		if (result != NULL_TREE)
++			return set_decl_type_codes(TREE_TYPE(result), decl_hash_data);
++		return set_result_codes(TREE_TYPE(node), decl_hash_data);
 +	}
 +
-+	return ret;
++	gcc_assert(TYPE_P(node));
++
++	if (TREE_CODE(node) == FUNCTION_TYPE)
++		return set_result_codes(TREE_TYPE(node), decl_hash_data);
++
++	return set_decl_type_codes(node, decl_hash_data);
 +}
 +
-+/* Set YES_SO_MARK on the function, its orig node and children if:
-+ *      * the function or its orig node or one of its children is in the hash table already
-+ *      * the function's orig node is marked with YES_SO_MARK or ASM_STMT_SO_MARK
-+ *      * one of the children is marked with YES_SO_MARK or ASM_STMT_SO_MARK
-+ */
-+static bool set_fn_so_mark(next_interesting_function_t next_node)
++static void set_decl_codes(struct decl_hash *decl_hash_data)
 +{
-+	bool so_fn, so_hashtable, so_child;
++	const_tree arg, type;
++	enum tree_code code;
 +
-+	so_hashtable = already_in_the_hashtable(next_node);
-+	so_fn = marked_fn(next_node);
-+	so_child = has_marked_child(next_node);
++	if (TREE_CODE(decl_hash_data->decl) == VAR_DECL || TREE_CODE(decl_hash_data->decl) == FIELD_DECL) {
++		set_decl_type_codes(TREE_TYPE(decl_hash_data->decl), decl_hash_data);
++		return;
++	}
 +
-+	if (!so_fn && !so_hashtable && !so_child)
-+		return false;
-+	set_yes_so_mark(next_node);
-+	return true;
++	type = get_function_type(decl_hash_data->decl);
++	code = TREE_CODE(type);
++	gcc_assert(code == FUNCTION_TYPE || code == METHOD_TYPE);
++
++	if (FUNCTION_PTR_P(decl_hash_data->decl))
++		set_result_codes(type, decl_hash_data);
++	else
++		set_result_codes(decl_hash_data->decl, decl_hash_data);
++
++	for (arg = TYPE_ARG_TYPES(type); arg != NULL_TREE && decl_hash_data->tree_codes_len < CODES_LIMIT; arg = TREE_CHAIN(arg))
++		set_decl_type_codes(TREE_VALUE(arg), decl_hash_data);
 +}
 +
-+// Determine if any of the function pointer targets have data flow between the return value and one of the arguments
-+static next_interesting_function_t get_same_not_ret_child(next_interesting_function_t parent)
++static const struct size_overflow_hash *get_proper_hash_chain(const struct size_overflow_hash *entry, const char *func_name, const char *context)
 +{
-+	unsigned int i;
-+	next_interesting_function_t child;
-+
-+#if BUILDING_GCC_VERSION <= 4007
-+	if (VEC_empty(next_interesting_function_t, parent->children))
-+		return NULL;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
-+#endif
-+		if (child->num == 0)
-+			continue;
-+		if (strcmp(parent->decl_name, child->decl_name))
++	for (; entry; entry = entry->next) {
++		if (strcmp(entry->name, func_name))
 +			continue;
-+		if (!strcmp(child->context, "fndecl"))
-+			return child;
++		if (!strcmp(entry->context, context))
++			return entry;
 +	}
 +	return NULL;
 +}
 +
-+/* Trace a return value of function pointer type back to an argument via a concrete function
-+   fnptr 0 && fn 0 && (fn 0 -> fn 2) => fnptr 2 */
-+static void search_missing_fptr_arg(next_interesting_function_t parent)
++unsigned int get_decl_hash(const_tree decl, const char *decl_name)
 +{
-+	next_interesting_function_t child;
-+	unsigned int i;
-+#if BUILDING_GCC_VERSION <= 4007
-+	VEC(next_interesting_function_t, heap) *new_children = NULL;
-+#else
-+	vec<next_interesting_function_t, va_heap, vl_embed> *new_children = NULL;
-+#endif
-+
-+	if (parent->num != 0)
-+		return;
-+	if (!strcmp(parent->context, "fndecl"))
-+		return;
-+	if (!strncmp(parent->context, "vardecl", sizeof("vardecl") - 1))
-+		return;
-+
-+	// fnptr 0 && fn 0
-+#if BUILDING_GCC_VERSION <= 4007
-+	if (VEC_empty(next_interesting_function_t, parent->children))
-+		return;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
-+#endif
-+		next_interesting_function_t cur_next_node, tracked_fn;
-+
-+		if (child->num != 0)
-+			continue;
-+		// (fn 0 -> fn 2)
-+		tracked_fn = get_same_not_ret_child(child);
-+		if (!tracked_fn)
-+			continue;
++	struct decl_hash decl_hash_data;
++	enum tree_code code = TREE_CODE(decl);
 +
-+		// fn 2 => fnptr 2
-+		for (cur_next_node = global_next_interesting_function[parent->hash]; cur_next_node; cur_next_node = cur_next_node->next) {
-+			if (cur_next_node->num != tracked_fn->num)
-+				continue;
++	gcc_assert(code == FIELD_DECL || code == FUNCTION_DECL || code == VAR_DECL);
 +
-+			if (strcmp(parent->decl_name, cur_next_node->decl_name))
-+				continue;
++	// skip builtins __builtin_constant_p
++	if (code == FUNCTION_DECL && (DECL_BUILT_IN(decl) || DECL_BUILT_IN_CLASS(decl) == BUILT_IN_NORMAL))
++		return NO_HASH;
 +
-+			if (!has_next_interesting_function_vec(parent, cur_next_node)) {
-+#if BUILDING_GCC_VERSION <= 4007
-+				VEC_safe_push(next_interesting_function_t, heap, new_children, cur_next_node);
-+#else
-+				vec_safe_push(new_children, cur_next_node);
-+#endif
-+			}
-+		}
-+	}
++	decl_hash_data.fn_name = decl_name;
++	decl_hash_data.decl = decl;
++	decl_hash_data.context = get_decl_context(decl);
++	if (!decl_hash_data.context)
++		return NO_HASH;
++	decl_hash_data.tree_codes_len = 0;
 +
-+#if BUILDING_GCC_VERSION == 4005
-+	if (VEC_empty(next_interesting_function_t, new_children))
-+		return;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, new_children, i, child)
-+		VEC_safe_push(next_interesting_function_t, heap, parent->children, child);
-+#elif BUILDING_GCC_VERSION <= 4007
-+	VEC_safe_splice(next_interesting_function_t, heap, parent->children, new_children);
-+#else
-+	vec_safe_splice(parent->children, new_children);
-+#endif
++	set_decl_codes(&decl_hash_data);
++	gcc_assert(decl_hash_data.tree_codes_len != 0);
++	set_hash(&decl_hash_data);
++	return decl_hash_data.hash;
 +}
 +
-+static void walk_so_marked_fns(next_interesting_function_set *visited, next_interesting_function_t parent, bool debug)
++const char *get_orig_decl_name(const_tree decl)
 +{
-+	unsigned int i;
-+	next_interesting_function_t child;
++	const char *name;
++	unsigned int len;
++	const void *end;
++	const_tree orig_decl;
 +
-+	gcc_assert(parent);
-+	if (!set_fn_so_mark(parent))
-+		return;
++	if (TREE_CODE(decl) == FUNCTION_DECL)
++		orig_decl = DECL_ORIGIN(decl);
++	else
++		orig_decl = decl;
 +
-+#if BUILDING_GCC_VERSION <= 4007
-+	if (VEC_empty(next_interesting_function_t, parent->children))
-+		return;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
-+#endif
-+		set_yes_so_mark(child);
++	len = DECL_NAME_LENGTH(orig_decl);
++	name = DECL_NAME_POINTER(orig_decl);
 +
-+		if (in_lto_p && debug == PRINT_DATA_FLOW) {
-+			fprintf(stderr, " PARENT: decl: %s-%u context: %s %p\n", parent->decl_name, parent->num, parent->context, parent);
-+			fprintf(stderr, " \tCHILD: decl: %s-%u context: %s %p\n", child->decl_name, child->num, child->context, child);
-+		}
++	/* Sometimes gcc loses the original cgraph node leaving only clones behind.
++	 * In such cases we will extract the name from the clone and use it in the hash table
++	 * without checking the parameter number on the original (unavailable) decl.
++	 */
 +
-+		if (!pointer_set_insert(visited, child))
-+			walk_so_marked_fns(visited, child, debug);
++	if (made_by_compiler(orig_decl)) {
++		end = memchr(name, '.', len);
++		if (!end)
++			return xstrndup(name, len);
++		len = (long)end - (long)name;
++		gcc_assert(len > 0);
 +	}
++
++	return xstrndup(name, len);
 +}
 +
-+// Do a depth-first recursive dump of the next_interesting_function_t children vector
-+static void print_missing_functions(next_interesting_function_set *visited, next_interesting_function_t parent)
++const struct size_overflow_hash *get_disable_size_overflow_hash_entry(unsigned int hash, const char *decl_name, const char *context, unsigned int argnum)
 +{
-+	unsigned int i;
-+	next_interesting_function_t child;
-+
-+	gcc_assert(parent);
-+	gcc_assert(parent->marked != NO_SO_MARK);
-+	print_missing_function(parent);
++	const struct size_overflow_hash *entry, *entry_node;
 +
-+#if BUILDING_GCC_VERSION <= 4007
-+	if (VEC_empty(next_interesting_function_t, parent->children))
-+		return;
-+	FOR_EACH_VEC_ELT(next_interesting_function_t, parent->children, i, child) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(parent->children, i, child) {
-+#endif
-+		gcc_assert(child->marked != NO_SO_MARK);
-+		if (!pointer_set_insert(visited, child))
-+			print_missing_functions(visited, child);
-+	}
++	entry = disable_size_overflow_hash[hash];
++	entry_node = get_proper_hash_chain(entry, decl_name, context);
++	if (entry_node && entry_node->param & (1U << argnum))
++		return entry_node;
++	return NULL;
 +}
 +
-+// Set YES_SO_MARK on functions that will be emitted into the hash table
-+static void search_so_marked_fns(bool debug)
++const struct size_overflow_hash *get_size_overflow_hash_entry(unsigned int hash, const char *decl_name, const char *context, unsigned int argnum)
 +{
++	const struct size_overflow_hash *entry, *entry_node;
 +
-+	unsigned int i;
-+	next_interesting_function_set *visited;
-+	next_interesting_function_t cur_global;
-+
-+	visited = next_interesting_function_pointer_set_create();
-+	for (i = 0; i < GLOBAL_NIFN_LEN; i++) {
-+		for (cur_global = global_next_interesting_function[i]; cur_global; cur_global = cur_global->next) {
-+			if (cur_global->marked == NO_SO_MARK || pointer_set_insert(visited, cur_global))
-+				continue;
-+
-+			if  (in_lto_p && debug == PRINT_DATA_FLOW)
-+				fprintf(stderr, "Data flow: decl: %s-%u context: %s %p\n", cur_global->decl_name, cur_global->num, cur_global->context, cur_global);
-+
-+			walk_so_marked_fns(visited, cur_global, debug);
++	entry = size_overflow_hash[hash];
++	entry_node = get_proper_hash_chain(entry, decl_name, context);
++	if (entry_node && entry_node->param & (1U << argnum))
++		return entry_node;
 +
-+			if  (in_lto_p && debug == PRINT_DATA_FLOW)
-+				fprintf(stderr, "\n");
-+		}
-+	}
-+	pointer_set_destroy(visited);
++	entry = size_overflow_hash_aux[hash];
++	entry_node = get_proper_hash_chain(entry, decl_name, context);
++	if (entry_node && entry_node->param & (1U << argnum))
++		return entry_node;
++	return NULL;
 +}
 +
-+// Print functions missing from the hash table
-+static void print_so_marked_fns(void)
++const struct size_overflow_hash *get_size_overflow_hash_entry_tree(const_tree fndecl, unsigned int argnum, bool hash_table)
 +{
-+	unsigned int i;
-+	next_interesting_function_set *visited;
-+	next_interesting_function_t cur_global;
++	const_tree orig_decl;
++	unsigned int orig_argnum, hash;
++	const char *decl_name, *context;
 +
-+	visited = next_interesting_function_pointer_set_create();
-+	for (i = 0; i < GLOBAL_NIFN_LEN; i++) {
-+		for (cur_global = global_next_interesting_function[i]; cur_global; cur_global = cur_global->next) {
-+			if (cur_global->marked != NO_SO_MARK && !pointer_set_insert(visited, cur_global))
-+				print_missing_functions(visited, cur_global);
-+		}
++	if (made_by_compiler(fndecl)) {
++		orig_decl = get_orig_fndecl(fndecl);
++		orig_argnum = get_correct_argnum(fndecl, orig_decl, argnum);
++	} else {
++		orig_decl = fndecl;
++		orig_argnum = argnum;
 +	}
-+	pointer_set_destroy(visited);
-+}
 +
-+void __attribute__((weak)) check_global_variables(next_interesting_function_t cur_global __unused) {}
++	if (orig_argnum == CANNOT_FIND_ARG)
++		return NULL;
 +
-+// Print all missing interesting functions
-+static unsigned int size_overflow_execute(void)
-+{
-+	unsigned int i;
-+	next_interesting_function_t cur_global;
++	decl_name = get_orig_decl_name(orig_decl);
++	hash = get_decl_hash(orig_decl, decl_name);
++	if (hash == NO_HASH)
++		return NULL;
 +
-+	if (flag_lto && !in_lto_p)
-+		return 0;
++	context = get_decl_context(orig_decl);
++	if (!context)
++		return NULL;
 +
-+	// Collect vardecls and funtions reachable by function pointers
-+	for (i = 0; i < GLOBAL_NIFN_LEN; i++) {
-+		for (cur_global = global_next_interesting_function[i]; cur_global; cur_global = cur_global->next) {
-+			check_global_variables(cur_global);
-+			search_missing_fptr_arg(cur_global);
-+		}
-+	}
++	if (hash_table == SIZE_OVERFLOW)
++		return get_size_overflow_hash_entry(hash, decl_name, context, orig_argnum);
++	return get_disable_size_overflow_hash_entry(hash, decl_name, context, orig_argnum);
++}
 +
-+	search_so_marked_fns(PRINT_DATA_FLOW);
-+	while (global_changed) {
-+		global_changed = false;
-+		search_so_marked_fns(NO_PRINT_DATA_FLOW);
-+	}
++unsigned int find_arg_number_tree(const_tree arg, const_tree func)
++{
++	tree var;
++	unsigned int argnum = 1;
 +
-+	print_so_marked_fns();
++	if (DECL_ARGUMENTS(func) == NULL_TREE)
++		return CANNOT_FIND_ARG;
 +
-+	if (in_lto_p) {
-+		fprintf(stderr, "%s: SIZE_OVERFLOW EXECUTE\n", __func__);
-+		print_global_next_interesting_functions();
++	if (TREE_CODE(arg) == SSA_NAME)
++		arg = SSA_NAME_VAR(arg);
++
++	for (var = DECL_ARGUMENTS(func); var; var = TREE_CHAIN(var), argnum++) {
++		if (!operand_equal_p(arg, var, 0) && strcmp(DECL_NAME_POINTER(var), DECL_NAME_POINTER(arg)))
++			continue;
++		if (!skip_types(var))
++			return argnum;
 +	}
 +
-+	return 0;
++	return CANNOT_FIND_ARG;
 +}
 +
-+// Omit the IPA/LTO callbacks until https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61311 gets fixed (license concerns)
-+#if BUILDING_GCC_VERSION >= 4008
-+void __attribute__((weak)) size_overflow_write_summary(void) {}
-+void __attribute__((weak)) size_overflow_write_optimization_summary(void) {}
-+#elif BUILDING_GCC_VERSION >= 4006
-+void __attribute__((weak)) size_overflow_write_summary(cgraph_node_set set __unused, varpool_node_set vset __unused) {}
-+void __attribute__((weak)) size_overflow_write_optimization_summary(cgraph_node_set set __unused, varpool_node_set vset __unused) {}
-+#else
-+void __attribute__((weak)) size_overflow_write_summary(cgraph_node_set set __unused) {}
-+void __attribute__((weak)) size_overflow_write_optimization_summary(cgraph_node_set set __unused) {}
-+#endif
++const_tree get_attribute(const char* attr_name, const_tree decl)
++{
++	const_tree attr = lookup_attribute(attr_name, DECL_ATTRIBUTES(decl));
++	if (attr && TREE_VALUE(attr))
++		return attr;
++	return NULL_TREE;
++}
 +
-+void __attribute__((weak)) size_overflow_read_summary(void);
-+void __attribute__((weak)) size_overflow_read_optimization_summary(void);
++/* Check if the function has a size_overflow attribute or it is in the size_overflow hash table.
++ * If the function is missing everywhere then print the missing message into stderr.
++ */
++void print_missing_function(next_interesting_function_t node)
++{
++	unsigned int argnum, hash;
++	const struct size_overflow_hash *entry;
++	const char *decl_name;
 +
-+#define PASS_NAME size_overflow
++	if (node->marked == ASM_STMT_SO_MARK)
++		return;
 +
-+#define NO_STMT_FIXUP
-+#define NO_VARIABLE_TRANSFORM
-+#define NO_GATE
++	if (node->orig_next_node) {
++		hash = node->orig_next_node->hash;
++		decl_name = node->orig_next_node->decl_name;
++		argnum = node->orig_next_node->num;
++		gcc_assert(!strcmp(node->context, node->orig_next_node->context));
++	} else {
++		hash = node->hash;
++		decl_name = node->decl_name;
++		argnum = node->num;
++	}
 +
-+#include "gcc-generate-ipa-pass.h"
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_misc.c b/tools/gcc/size_overflow_plugin/size_overflow_misc.c
++	entry = get_size_overflow_hash_entry(hash, decl_name, node->context, argnum);
++	if (entry)
++		return;
++
++	// inform() would be too slow
++	fprintf(stderr, "Function %s is missing from the size_overflow hash table +%s+%s+%u+%u+\n", decl_name, decl_name, node->context, argnum, hash);
++}
++
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform.c
 new file mode 100644
-index 0000000..7f459ed
+index 0000000..eebcf4c
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_misc.c
-@@ -0,0 +1,505 @@
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform.c
+@@ -0,0 +1,743 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
 + * Licensed under the GPL v2, or (at your option) v3
@@ -208621,496 +207074,734 @@ index 0000000..7f459ed
 +
 +#include "size_overflow.h"
 +
-+bool is_vararg(const_tree fn, unsigned int num)
++static tree cast_to_orig_type(struct visited *visited, gimple stmt, const_tree orig_node, tree new_node)
 +{
-+	tree arg_list;
++	gimple def_stmt;
++	const_gimple assign;
++	tree result, orig_type = TREE_TYPE(orig_node);
++	gimple_stmt_iterator gsi;
 +
-+	if (num == 0)
-+		return false;
-+	if (fn == NULL_TREE)
-+		return false;
-+	if (TREE_CODE(fn) != FUNCTION_DECL)
-+		return false;
++	if (gimple_code(stmt) != GIMPLE_PHI) {
++		gsi = gsi_for_stmt(stmt);
++		assign = build_cast_stmt(visited, orig_type, new_node, CREATE_NEW_VAR, &gsi, BEFORE_STMT, false);
++		return get_lhs(assign);
++	}
 +
-+	arg_list = TYPE_ARG_TYPES(TREE_TYPE(fn));
-+	if (arg_list == NULL_TREE)
-+		return false;
++	def_stmt = get_def_stmt(new_node);
++	if (gimple_code(def_stmt) == GIMPLE_PHI)
++		gsi = gsi_after_labels(gimple_bb(def_stmt));
++	else
++		gsi = gsi_for_stmt(def_stmt);
 +
-+	if (tree_last(arg_list) == void_list_node)
-+		return false;
++	result = gimple_phi_result(stmt);
++	assign = build_cast_stmt(visited, orig_type, new_node, SSA_NAME_VAR(result), &gsi, AFTER_STMT, false);
++	return get_lhs(assign);
++}
 +
-+	return num >= (unsigned int)list_length(arg_list);
++static void change_size_overflow_asm_input(gasm *stmt, tree new_input)
++{
++	tree list;
++
++	gcc_assert(is_size_overflow_insert_check_asm(stmt));
++
++	list = build_tree_list(NULL_TREE, build_string(3, "rm"));
++	list = chainon(NULL_TREE, build_tree_list(list, new_input));
++	gimple_asm_set_input_op(stmt, 0, list);
 +}
 +
-+// Extract the field decl from memory references
-+tree get_ref_field(const_tree ref)
++static void change_field_write_rhs(gassign *assign, const_tree orig_rhs, tree new_rhs)
 +{
-+	tree field;
++	const_tree rhs1, rhs2, rhs3 = NULL_TREE;
++
++	rhs1 = gimple_assign_rhs1(assign);
++	if (rhs1 == orig_rhs) {
++		gimple_assign_set_rhs1(assign, new_rhs);
++		return;
++	}
++
++	rhs2 = gimple_assign_rhs2(assign);
++	if (rhs2 == orig_rhs) {
++		gimple_assign_set_rhs2(assign, new_rhs);
++		return;
++	}
 +
-+	// TODO: handle nested memory references
-+	switch (TREE_CODE(ref)) {
-+	case ARRAY_REF:
-+		return NULL_TREE;
 +#if BUILDING_GCC_VERSION >= 4006
-+	case MEM_REF:
++	rhs3 = gimple_assign_rhs3(assign);
++	if (rhs3 == orig_rhs) {
++		gimple_assign_set_rhs3(assign, new_rhs);
++		return;
++	}
 +#endif
-+	case INDIRECT_REF:
-+		field = TREE_OPERAND(ref, 0);
++
++	debug_gimple_stmt(assign);
++	fprintf(stderr, "orig_rhs:\n");
++	debug_tree(orig_rhs);
++	fprintf(stderr, "rhs1:\n");
++	debug_tree(rhs1);
++	fprintf(stderr, "rhs2:\n");
++	debug_tree(rhs2);
++	fprintf(stderr, "rhs3:\n");
++	debug_tree(rhs3);
++	gcc_unreachable();
++}
++
++static void change_phi_arg(gphi *phi, tree new_node, unsigned int num)
++{
++	unsigned int i;
++	location_t loc = gimple_location(phi);
++
++	for (i = 0; i < gimple_phi_num_args(phi); i++) {
++		if (i == num)
++			add_phi_arg(phi, new_node, gimple_phi_arg_edge(phi, i), loc);
++	}
++}
++
++static void change_orig_node(struct visited *visited, gimple stmt, const_tree orig_node, tree new_node, unsigned int num)
++{
++	tree cast_lhs = cast_to_orig_type(visited, stmt, orig_node, new_node);
++
++	switch (gimple_code(stmt)) {
++	case GIMPLE_RETURN:
++		gimple_return_set_retval(as_a_greturn(stmt), cast_lhs);
 +		break;
-+	case COMPONENT_REF:
-+		field = TREE_OPERAND(ref, 1);
++	case GIMPLE_CALL:
++		gimple_call_set_arg(as_a_gcall(stmt), num - 1, cast_lhs);
++		break;
++	case GIMPLE_ASM:
++		change_size_overflow_asm_input(as_a_gasm(stmt), cast_lhs);
++		break;
++	case GIMPLE_ASSIGN:
++		change_field_write_rhs(as_a_gassign(stmt), orig_node, cast_lhs);
++		break;
++	case GIMPLE_PHI:
++		change_phi_arg(as_a_gphi(stmt), cast_lhs, num);
 +		break;
 +	default:
-+		return NULL_TREE;
++		debug_gimple_stmt(stmt);
++		gcc_unreachable();
 +	}
 +
-+	// TODO
-+	if (TREE_CODE(field) == SSA_NAME)
-+		return NULL_TREE;
-+	// TODO
-+	if (TREE_CODE(field) != FIELD_DECL)
-+		return NULL_TREE;
-+	// TODO
-+	if (TREE_CODE(field) == ADDR_EXPR)
-+		return NULL_TREE;
++	update_stmt(stmt);
++}
 +
-+	return field;
++// e.g., 3.8.2, 64, arch/x86/ia32/ia32_signal.c copy_siginfo_from_user32(): compat_ptr() u32 max
++static bool skip_asm_cast(const_tree arg)
++{
++	gimple def_stmt = get_def_stmt(arg);
++
++	if (!def_stmt || !gimple_assign_cast_p(def_stmt))
++		return false;
++
++	def_stmt = get_def_stmt(gimple_assign_rhs1(def_stmt));
++	if (is_size_overflow_asm(def_stmt))
++		return false;
++	return def_stmt && gimple_code(def_stmt) == GIMPLE_ASM;
 +}
 +
-+const char *get_type_name_from_field(const_tree field_decl)
++static interesting_stmts_t create_interesting_stmts(interesting_stmts_t head, next_interesting_function_t next_node, tree orig_node, gimple first_stmt, unsigned int num)
 +{
-+	const_tree context, type_name;
++	interesting_stmts_t new_node;
 +
-+	if (TREE_CODE(field_decl) != FIELD_DECL)
-+		return NULL;
++	new_node = (interesting_stmts_t )xmalloc(sizeof(*new_node));
++	new_node->first_stmt = first_stmt;
++	new_node->num = num;
++	new_node->orig_node = orig_node;
++	new_node->next = head;
++	new_node->next_node = next_node;
++	return new_node;
++}
 +
-+	context = DECL_CONTEXT(field_decl);
-+	// TODO
-+	if (TREE_CODE(context) != RECORD_TYPE)
-+		return NULL;
-+	gcc_assert(TREE_CODE(context) == RECORD_TYPE);
-+	type_name = TYPE_NAME(TYPE_MAIN_VARIANT(context));
-+	if (type_name == NULL_TREE)
-+		return NULL;
++static void free_interesting_stmts(interesting_stmts_t head)
++{
++	while (head) {
++		interesting_stmts_t cur = head->next;
++		free(head);
++		head = cur;
++	}
++}
 +
-+	if (TREE_CODE(type_name) == IDENTIFIER_NODE)
-+		return IDENTIFIER_POINTER(type_name);
-+	else if (TREE_CODE(type_name) == TYPE_DECL)
-+		return DECL_NAME_POINTER(type_name);
++/* This function calls the main recursion function (expand) that duplicates the stmts. Before that it checks the intentional_overflow attribute,
++ * it decides whether the duplication is necessary or not. After expand() it changes the orig node to the duplicated node
++ * in the original stmt (first stmt) and it inserts the overflow check for the arg of the callee or for the return value.
++ */
++static interesting_stmts_t search_interesting_stmt(interesting_stmts_t head, next_interesting_function_t next_node, gimple first_stmt, tree orig_node, unsigned int num)
++{
++	enum tree_code orig_code;
 +
-+	debug_tree(field_decl);
-+	debug_tree(type_name);
-+	gcc_unreachable();
++	gcc_assert(orig_node != NULL_TREE);
++
++	if (is_gimple_constant(orig_node))
++		return head;
++
++	orig_code = TREE_CODE(orig_node);
++	gcc_assert(orig_code != FIELD_DECL && orig_code != FUNCTION_DECL);
++
++	if (skip_types(orig_node))
++		return head;
++
++	// find a defining marked caller argument or struct field for arg
++	if (check_intentional_size_overflow_asm_and_attribute(orig_node) != MARK_NO)
++		return head;
++
++	if (skip_asm_cast(orig_node))
++		return head;
++
++	return create_interesting_stmts(head, next_node, orig_node, first_stmt, num);
 +}
 +
-+// Was the function created by the compiler itself?
-+bool made_by_compiler(const_tree decl)
++static bool is_signed_error_code_const(const_tree node)
 +{
-+	enum tree_code decl_code;
-+	struct cgraph_node *node;
++	HOST_WIDE_INT constant = tree_to_shwi(node);
 +
-+	if (FUNCTION_PTR_P(decl))
-+		return false;
-+	decl_code = TREE_CODE(decl);
-+	if (decl_code == VAR_DECL || decl_code == FIELD_DECL)
-+		return false;
++	return constant >= -4095 && constant <= -1;
++}
 +
-+	gcc_assert(decl_code == FUNCTION_DECL);
-+	if (DECL_ABSTRACT_ORIGIN(decl) != NULL_TREE && DECL_ABSTRACT_ORIGIN(decl) != decl)
-+		return true;
-+	if (DECL_ARTIFICIAL(decl))
++static bool is_unsigned_error_code_const(const_tree node)
++{
++	unsigned HOST_WIDE_INT constant = tree_to_uhwi(node);
++
++	// ulong -4095
++	if (constant >= 0xfffffffffffff001)
 +		return true;
++	// uint -4095
++	return constant >= 0xfffff001;
++}
 +
-+	node = get_cnode(decl);
-+	if (!node)
++static bool is_error_code_const(const_tree node)
++{
++	enum machine_mode mode;
++
++	if (!is_gimple_constant(node))
 +		return false;
-+	return node->clone_of != NULL;
++	mode = TYPE_MODE(TREE_TYPE(node));
++	if (mode != SImode && mode != DImode)
++		return false;
++
++	if (!TYPE_UNSIGNED(TREE_TYPE(node)) && is_signed_error_code_const(node))
++		return true;
++	return TYPE_UNSIGNED(TREE_TYPE(node)) && is_unsigned_error_code_const(node);
 +}
 +
-+bool skip_types(const_tree var)
++static bool has_error_code(gphi *phi)
 +{
-+	const_tree type;
++	unsigned int i, len = gimple_phi_num_args(phi);
 +
-+	type = TREE_TYPE(var);
-+	if (type == NULL_TREE)
-+		return true;
++	for (i = 0; i < len; i++) {
++		const_tree arg = gimple_phi_arg_def(phi, i);
 +
-+	switch (TREE_CODE(type)) {
-+		case INTEGER_TYPE:
-+		case ENUMERAL_TYPE:
-+			return false;
-+		default:
++		if (is_error_code_const(arg))
 +			return true;
 +	}
++
++	return false;
 +}
 +
-+gimple get_fnptr_def_stmt(const_tree fn_ptr)
++static interesting_stmts_t search_interesting_rets(interesting_stmts_t head, next_interesting_function_t next_node_ret, greturn *ret)
 +{
-+	gimple def_stmt;
++	tree first_node;
 +
-+	gcc_assert(fn_ptr != NULL_TREE);
-+	gcc_assert(FUNCTION_PTR_P(fn_ptr));
++	if (!next_node_ret || next_node_ret->marked == ASM_STMT_SO_MARK)
++		return head;
 +
-+	if (is_gimple_constant(fn_ptr))
-+		return NULL;
++	first_node = gimple_return_retval(ret);
++	if (first_node == NULL_TREE)
++		return head;
 +
-+	def_stmt = get_def_stmt(fn_ptr);
-+	gcc_assert(def_stmt);
-+	return def_stmt;
++	return search_interesting_stmt(head, next_node_ret, ret, first_node, 0);
 +}
 +
-+gimple get_def_stmt(const_tree node)
++static void handle_binary_assign(interesting_stmts_t expand_from, gassign *assign, tree rhs)
 +{
-+	gcc_assert(node != NULL_TREE);
++	tree new_node;
++	gimple def_orig_node;
 +
-+	if (TREE_CODE(node) != SSA_NAME)
-+		return NULL;
-+	return SSA_NAME_DEF_STMT(node);
++	new_node = expand(expand_from, rhs);
++	if (new_node == NULL_TREE)
++		return;
++
++	def_orig_node = get_def_stmt(rhs);
++	if (pointer_set_contains(expand_from->visited->no_cast_check, def_orig_node))
++		return;
++	change_orig_node(expand_from->visited, assign, rhs, new_node, 0);
++	check_size_overflow(expand_from, assign, TREE_TYPE(new_node), new_node, rhs, BEFORE_STMT);
 +}
 +
-+tree create_new_var(tree type)
++static bool search_error_codes(gimple_set *visited_error_codes, interesting_stmts_t expand_from, tree lhs, bool error_code)
 +{
-+	tree new_var = create_tmp_var(type, "cicus");
++	gimple def_stmt;
 +
-+	add_referenced_var(new_var);
-+	return new_var;
++	def_stmt = get_def_stmt(lhs);
++	if (!def_stmt || gimple_code(def_stmt) == GIMPLE_NOP)
++		return error_code;
++
++	if (pointer_set_insert(visited_error_codes, def_stmt))
++		return error_code;
++
++	if (is_gimple_constant(lhs))
++		return error_code;
++	if (skip_types(lhs))
++		return is_error_code_const(lhs);
++
++	switch (gimple_code(def_stmt)) {
++	case GIMPLE_CALL:
++	case GIMPLE_ASM:
++		return error_code;
++	case GIMPLE_ASSIGN: {
++		tree rhs1, rhs2;
++		gassign *assign = as_a_gassign(def_stmt);
++
++		switch (gimple_num_ops(assign)) {
++		case 2:
++			return search_error_codes(visited_error_codes, expand_from, gimple_assign_rhs1(def_stmt), error_code);
++		case 3:
++			if (!error_code)
++				return error_code;
++
++			/* Run stmt duplication from the binary assignment ops (rhs1 and rhs2)
++			 * so that size_overflow checking skips the lhs of the last binary assignment
++			 * before the error code PHI.
++			 */
++			rhs1 = gimple_assign_rhs1(assign);
++			handle_binary_assign(expand_from, assign, rhs1);
++			rhs2 = gimple_assign_rhs2(assign);
++			handle_binary_assign(expand_from, assign, rhs2);
++			return error_code;
++		}
++		gcc_unreachable();
++	}
++	case GIMPLE_PHI: {
++		unsigned int i;
++
++		error_code = has_error_code(as_a_gphi(def_stmt));
++		for (i = 0; i < gimple_phi_num_args(def_stmt); i++) {
++			error_code = search_error_codes(visited_error_codes, expand_from, gimple_phi_arg_def(def_stmt, i), error_code);
++		}
++		return error_code;
++	}
++	default:
++		debug_gimple_stmt(def_stmt);
++		error("%s: unknown gimple code", __func__);
++		gcc_unreachable();
++	}
 +}
 +
-+static bool skip_cast(tree dst_type, const_tree rhs, bool force)
++static bool handle_error_codes(interesting_stmts_t expand_from)
 +{
-+	const_gimple def_stmt = get_def_stmt(rhs);
++	bool error_code;
++	gimple_set *visited_error_codes;
 +
-+	if (force)
++	// expand the data flow from a return stmt
++	if (expand_from->next_node->num != 0 || strcmp(expand_from->next_node->context, "fndecl"))
 +		return false;
 +
-+	if (is_gimple_constant(rhs))
-+		return false;
++	visited_error_codes = pointer_set_create();
++	error_code = search_error_codes(visited_error_codes, expand_from, expand_from->orig_node, false);
++	pointer_set_destroy(visited_error_codes);
 +
-+	if (!def_stmt || gimple_code(def_stmt) == GIMPLE_NOP)
-+		return false;
++	return error_code;
++}
 +
-+	if (!types_compatible_p(dst_type, TREE_TYPE(rhs)))
-+		return false;
++static void handle_interesting_stmt(struct visited *visited, interesting_stmts_t head)
++{
++	interesting_stmts_t cur;
 +
-+	// DI type can be on 32 bit (from create_assign) but overflow type stays DI
-+	if (LONG_TYPE_SIZE == GET_MODE_BITSIZE(SImode))
-+		return false;
++	for (cur = head; cur; cur = cur->next) {
++		tree new_node;
++		gimple orig_def_stmt;
 +
-+	return true;
++		cur->visited = visited;
++		if (handle_error_codes(cur))
++			continue;
++
++		new_node = expand(cur, cur->orig_node);
++		if (new_node == NULL_TREE)
++			continue;
++
++		orig_def_stmt = get_def_stmt(cur->orig_node);
++		if (pointer_set_contains(visited->no_cast_check, orig_def_stmt))
++			continue;
++		change_orig_node(visited, cur->first_stmt, cur->orig_node, new_node, cur->num);
++		check_size_overflow(cur, cur->first_stmt, TREE_TYPE(new_node), new_node, cur->orig_node, BEFORE_STMT);
++	}
 +}
 +
-+tree cast_a_tree(tree type, tree var)
++static next_interesting_function_t get_interesting_function_next_node(tree decl, unsigned int num)
 +{
-+	gcc_assert(type != NULL_TREE);
-+	gcc_assert(var != NULL_TREE);
-+	gcc_assert(fold_convertible_p(type, var));
++	next_interesting_function_t next_node;
++	const struct size_overflow_hash *so_hash;
++	struct fn_raw_data raw_data;
 +
-+	return fold_convert(type, var);
++	raw_data.decl = decl;
++	raw_data.decl_str = DECL_NAME_POINTER(decl);
++	raw_data.num = num;
++	raw_data.marked = YES_SO_MARK;
++
++	next_node = get_global_next_interesting_function_entry_with_hash(&raw_data);
++	if (next_node && next_node->marked != NO_SO_MARK)
++		return next_node;
++
++	so_hash = get_size_overflow_hash_entry_tree(raw_data.decl, raw_data.num, SIZE_OVERFLOW);
++	if (so_hash)
++		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
++	return NULL;
 +}
 +
-+gimple build_cast_stmt(struct visited *visited, tree dst_type, tree rhs, tree lhs, gimple_stmt_iterator *gsi, bool before, bool force)
++tree handle_fnptr_assign(const_gimple stmt)
 +{
-+	gassign *assign;
-+	gimple def_stmt;
++	tree field, rhs, op0;
++	const_tree op0_type;
++	enum tree_code rhs_code;
 +
-+	gcc_assert(dst_type != NULL_TREE && rhs != NULL_TREE);
-+	gcc_assert(!is_gimple_constant(rhs));
-+	if (gsi_end_p(*gsi) && before == AFTER_STMT)
-+		gcc_unreachable();
++	// TODO skip binary assignments for now (fs/sync.c _591 = __bpf_call_base + _590;)
++	if (gimple_num_ops(stmt) != 2)
++		return NULL_TREE;
 +
-+	def_stmt = get_def_stmt(rhs);
-+	if (def_stmt && gimple_code(def_stmt) != GIMPLE_NOP && skip_cast(dst_type, rhs, force) && pointer_set_contains(visited->my_stmts, def_stmt))
-+		return def_stmt;
++	gcc_assert(gimple_num_ops(stmt) == 2);
++	// TODO skip asm_stmt for now
++	if (gimple_code(stmt) == GIMPLE_ASM)
++		return NULL_TREE;
++	rhs = gimple_assign_rhs1(stmt);
++	if (is_gimple_constant(rhs))
++		return NULL_TREE;
 +
-+	if (lhs == CREATE_NEW_VAR)
-+		lhs = create_new_var(dst_type);
++	rhs_code = TREE_CODE(rhs);
++	if (rhs_code == VAR_DECL)
++		return rhs;
 +
-+	assign = gimple_build_assign(lhs, cast_a_tree(dst_type, rhs));
++	switch (rhs_code) {
++	case ADDR_EXPR:
++		op0 = TREE_OPERAND(rhs, 0);
++		gcc_assert(TREE_CODE(op0) == FUNCTION_DECL);
++		return op0;
++	case COMPONENT_REF:
++		break;
++	// TODO skip array_ref for now
++	case ARRAY_REF:
++		return NULL_TREE;
++	// TODO skip ssa_name because it can lead to parm_decl
++	case SSA_NAME:
++		return NULL_TREE;
++	// TODO skip mem_ref and indirect_ref for now
++#if BUILDING_GCC_VERSION >= 4006
++	case MEM_REF:
++#endif
++	case INDIRECT_REF:
++		return NULL_TREE;
++	default:
++		debug_tree(rhs);
++		debug_gimple_stmt((gimple)stmt);
++		gcc_unreachable();
++	}
 +
-+	if (!gsi_end_p(*gsi)) {
-+		location_t loc = gimple_location(gsi_stmt(*gsi));
-+		gimple_set_location(assign, loc);
++	op0 = TREE_OPERAND(rhs, 0);
++	switch (TREE_CODE(op0)) {
++	// TODO skip array_ref and parm_decl for now
++	case ARRAY_REF:
++	case PARM_DECL:
++		return NULL_TREE;
++	case COMPONENT_REF:
++#if BUILDING_GCC_VERSION >= 4006
++	case MEM_REF:
++#endif
++	case INDIRECT_REF:
++	case VAR_DECL:
++		break;
++	default:
++		debug_tree(op0);
++		gcc_unreachable();
 +	}
 +
-+	gimple_assign_set_lhs(assign, make_ssa_name(lhs, assign));
++	op0_type = TREE_TYPE(op0);
++	// TODO skip unions for now
++	if (TREE_CODE(op0_type) == UNION_TYPE)
++		return NULL_TREE;
++	gcc_assert(TREE_CODE(op0_type) == RECORD_TYPE);
 +
-+	if (before)
-+		gsi_insert_before(gsi, assign, GSI_NEW_STMT);
-+	else
-+		gsi_insert_after(gsi, assign, GSI_NEW_STMT);
-+	update_stmt(assign);
-+	return assign;
++	field = TREE_OPERAND(rhs, 1);
++	gcc_assert(TREE_CODE(field) == FIELD_DECL);
++	return field;
 +}
 +
-+bool is_size_overflow_type(const_tree var)
++static tree get_fn_or_fnptr_decl(const gcall *call_stmt)
 +{
-+	const char *name;
-+	const_tree type_name, type;
-+
-+	if (var == NULL_TREE)
-+		return false;
++	const_tree fnptr;
++	const_gimple def_stmt;
++	tree decl = gimple_call_fndecl(call_stmt);
 +
-+	type = TREE_TYPE(var);
-+	type_name = TYPE_NAME(type);
-+	if (type_name == NULL_TREE)
-+		return false;
++	if (decl != NULL_TREE)
++		return decl;
 +
-+	if (DECL_P(type_name))
-+		name = DECL_NAME_POINTER(type_name);
-+	else
-+		name = IDENTIFIER_POINTER(type_name);
++	fnptr = gimple_call_fn(call_stmt);
++	if (fnptr == NULL_TREE)
++		return NULL_TREE;
 +
-+	if (!strncmp(name, "size_overflow_type", 18))
-+		return true;
-+	return false;
++	// !!! assertot kell irni 0-ra, mert csak az lehet ott
++	if (is_gimple_constant(fnptr))
++		return NULL_TREE;
++	def_stmt = get_fnptr_def_stmt(fnptr);
++	return handle_fnptr_assign(def_stmt);
 +}
 +
-+// Determine if a cloned function has all the original arguments
-+static bool unchanged_arglist(struct cgraph_node *new_node, struct cgraph_node *old_node)
++// Start stmt duplication on marked function parameters
++static interesting_stmts_t search_interesting_calls(interesting_stmts_t head, gcall *call_stmt)
 +{
-+	const_tree new_decl_list, old_decl_list;
++	tree decl;
++	unsigned int i, len;
 +
-+	if (new_node->clone_of && new_node->clone.tree_map)
-+		return !new_node->clone.args_to_skip;
++	len = gimple_call_num_args(call_stmt);
++	if (len == 0)
++		return head;
 +
-+	new_decl_list = DECL_ARGUMENTS(NODE_DECL(new_node));
-+	old_decl_list = DECL_ARGUMENTS(NODE_DECL(old_node));
-+	if (new_decl_list != NULL_TREE && old_decl_list != NULL_TREE)
-+		gcc_assert(list_length(new_decl_list) == list_length(old_decl_list));
++	decl = get_fn_or_fnptr_decl(call_stmt);
++	if (decl == NULL_TREE)
++		return head;
 +
-+	return true;
++	for (i = 0; i < len; i++) {
++		tree arg;
++		next_interesting_function_t next_node;
++
++		arg = gimple_call_arg(call_stmt, i);
++		if (is_gimple_constant(arg))
++			continue;
++		if (skip_types(arg))
++			continue;
++		next_node = get_interesting_function_next_node(decl, i + 1);
++		if (next_node)
++			head = search_interesting_stmt(head, next_node, call_stmt, arg, i + 1);
++	}
++
++	return head;
 +}
 +
-+unsigned int get_correct_argnum_fndecl(const_tree fndecl, const_tree correct_argnum_of_fndecl, unsigned int num)
++// Find assignements to structure fields and vardecls
++static interesting_stmts_t search_interesting_structs_vardecls(interesting_stmts_t head, gassign *assign)
 +{
-+	unsigned int new_num;
-+	const_tree fndecl_arg;
-+	tree fndecl_arglist = DECL_ARGUMENTS(fndecl);
-+	const_tree arg, target_fndecl_arglist;
-+
-+	if (num == 0)
-+		return num;
++	enum intentional_mark mark;
++	next_interesting_function_t next_node;
++	tree rhs1, rhs2, lhs, decl;
++#if BUILDING_GCC_VERSION >= 4006
++	tree rhs3;
++#endif
 +
-+	if (fndecl == correct_argnum_of_fndecl && !DECL_ARTIFICIAL(fndecl))
-+		return num;
-+	else if (fndecl == correct_argnum_of_fndecl && DECL_ARTIFICIAL(fndecl))
-+		return CANNOT_FIND_ARG;
++	lhs = gimple_assign_lhs(assign);
 +
-+	target_fndecl_arglist = DECL_ARGUMENTS(correct_argnum_of_fndecl);
-+	if (fndecl_arglist == NULL_TREE || target_fndecl_arglist == NULL_TREE)
-+		return CANNOT_FIND_ARG;
++	if (VAR_P(lhs))
++		decl = lhs;
++	else
++		decl = get_ref_field(lhs);
++	if (decl == NULL_TREE)
++		return head;
++	if (DECL_NAME(decl) == NULL_TREE)
++		return head;
 +
-+	fndecl_arg = chain_index(num - 1, fndecl_arglist);
-+	if (fndecl_arg == NULL_TREE)
-+		return CANNOT_FIND_ARG;
++	if (is_bitfield_unnamed_cast(decl, assign))
++		return head;
 +
-+	for (arg = target_fndecl_arglist, new_num = 1; arg; arg = TREE_CHAIN(arg), new_num++) {
-+		if (arg == fndecl_arg || !strcmp(DECL_NAME_POINTER(arg), DECL_NAME_POINTER(fndecl_arg)))
-+			return new_num;
-+	}
++	next_node = get_interesting_function_next_node(decl, 0);
++	if (!next_node)
++		return head;
 +
-+	return CANNOT_FIND_ARG;
-+}
++	mark = get_intentional_attr_type(decl);
++	if (mark != MARK_NO)
++		return head;
 +
-+// Find the specified argument in the originally cloned function
-+static unsigned int clone_argnum_on_orig(struct cgraph_node *new_node, struct cgraph_node *old_node, unsigned int clone_argnum)
-+{
-+	bitmap args_to_skip;
-+	unsigned int i, new_argnum = clone_argnum;
++	rhs1 = gimple_assign_rhs1(assign);
++	head = search_interesting_stmt(head, next_node, assign, rhs1, 0);
 +
-+	if (unchanged_arglist(new_node, old_node))
-+		return clone_argnum;
++	rhs2 = gimple_assign_rhs2(assign);
++	if (rhs2)
++		head = search_interesting_stmt(head, next_node, assign, rhs2, 0);
 +
-+	gcc_assert(new_node->clone_of && new_node->clone.tree_map);
-+	args_to_skip = new_node->clone.args_to_skip;
-+	for (i = 0; i < clone_argnum; i++) {
-+		if (bitmap_bit_p(args_to_skip, i))
-+			new_argnum++;
-+	}
-+	return new_argnum;
++#if BUILDING_GCC_VERSION >= 4006
++	rhs3 = gimple_assign_rhs3(assign);
++	if (rhs3)
++		head = search_interesting_stmt(head, next_node, assign, rhs3, 0);
++#endif
++	return head;
 +}
 +
-+// Find the specified argument in the clone
-+static unsigned int orig_argnum_on_clone(struct cgraph_node *new_node, struct cgraph_node *old_node, unsigned int orig_argnum)
++static next_interesting_function_t create_so_asm_next_interesting_function_node(const gasm *stmt)
 +{
-+	bitmap args_to_skip;
-+	unsigned int i, new_argnum = orig_argnum;
++	next_interesting_function_t next_node;
++	struct fn_raw_data raw_data;
 +
-+	if (unchanged_arglist(new_node, old_node))
-+		return orig_argnum;
++	raw_data.decl = NULL_TREE;
++	raw_data.decl_str = gimple_asm_string(stmt);
++	raw_data.context = "attr";
++	raw_data.hash = 0;
++	raw_data.num = 0;
++	raw_data.marked = ASM_STMT_SO_MARK;
 +
-+	gcc_assert(new_node->clone_of && new_node->clone.tree_map);
-+	args_to_skip = new_node->clone.args_to_skip;
-+	if (bitmap_bit_p(args_to_skip, orig_argnum - 1))
-+		// XXX torolni kellene a nodeot
-+		return CANNOT_FIND_ARG;
++	next_node = get_global_next_interesting_function_entry(&raw_data);
++	if (next_node)
++		return next_node;
++	next_node = create_new_next_interesting_entry(&raw_data, NULL);
++	gcc_assert(next_node);
 +
-+	for (i = 0; i < orig_argnum; i++) {
-+		if (bitmap_bit_p(args_to_skip, i))
-+			new_argnum--;
-+	}
-+	return new_argnum;
++	add_to_global_next_interesting_function(next_node);
++	return next_node;
 +}
 +
-+// Associate the argument between a clone and a cloned function
-+static unsigned int get_correct_argnum_cnode(struct cgraph_node *node, struct cgraph_node *correct_argnum_of_node, unsigned int argnum)
++// Collect interesting stmts for duplication
++static void search_interesting_stmts(struct visited *visited)
 +{
-+	bool node_clone, correct_argnum_of_node_clone;
-+	const_tree correct_argnum_of_node_decl, node_decl;
++	basic_block bb;
++	next_interesting_function_t next_node_ret;
++	interesting_stmts_t head = NULL;
 +
-+	if (node == correct_argnum_of_node)
-+		return argnum;
-+	if (argnum == 0)
-+		return argnum;
++	next_node_ret = get_interesting_function_next_node(current_function_decl, 0);
 +
-+	correct_argnum_of_node_decl = NODE_DECL(correct_argnum_of_node);
-+	gcc_assert(correct_argnum_of_node_decl != NULL_TREE);
-+	gcc_assert(correct_argnum_of_node && !DECL_ARTIFICIAL(correct_argnum_of_node_decl));
++	FOR_EACH_BB_FN(bb, cfun) {
++		gimple_stmt_iterator gsi;
 +
-+	if (node) {
-+		node_decl = NODE_DECL(node);
-+		gcc_assert(!DECL_ARTIFICIAL(node_decl));
-+		node_clone = made_by_compiler(node_decl);
-+	} else {
-+		node_decl = NULL_TREE;
-+		node_clone = false;
-+	}
++		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
++			gimple stmt = gsi_stmt(gsi);
 +
-+	if (correct_argnum_of_node_decl == node_decl)
-+		return argnum;
++			switch (gimple_code(stmt)) {
++			case GIMPLE_ASM: {
++				tree first_node;
++				next_interesting_function_t next_node;
++				const gasm *asm_stmt = as_a_gasm(stmt);
 +
-+	correct_argnum_of_node_clone = made_by_compiler(correct_argnum_of_node_decl);
-+	// the original decl is lost if both nodes are clones
-+	if (node_clone && correct_argnum_of_node_clone) {
-+		gcc_assert(unchanged_arglist(node, correct_argnum_of_node));
-+		return argnum;
++				if (!is_size_overflow_insert_check_asm(asm_stmt))
++					continue;
++				next_node = create_so_asm_next_interesting_function_node(asm_stmt);
++				first_node = get_size_overflow_asm_input(asm_stmt);
++				head = search_interesting_stmt(head, next_node, stmt, first_node, 0);
++				break;
++			}
++			case GIMPLE_RETURN:
++				head = search_interesting_rets(head, next_node_ret, as_a_greturn(stmt));
++				break;
++			case GIMPLE_CALL:
++				head = search_interesting_calls(head, as_a_gcall(stmt));
++				break;
++			case GIMPLE_ASSIGN:
++				/* !!! TODO LTO modeban nincs duplikalas a globalis valtozora, mert a tree mergek
++				 * utan mar nem lehet megkulonboztetni attol a globalis valtozotol, aminek a scopeja csak a file
++				 * igy a context nem vardecl lesz, hanem vardecl_filenev. De execute-ban kiirja, ha hianyzik a hash tablabol
++				 * IPA-ban van duplikalas.
++				 */
++				head = search_interesting_structs_vardecls(head, as_a_gassign(stmt));
++				break;
++			default:
++				break;
++			}
++		}
 +	}
 +
-+	if (node_clone && !correct_argnum_of_node_clone)
-+		return clone_argnum_on_orig(correct_argnum_of_node, node, argnum);
-+	else if (!node_clone && correct_argnum_of_node_clone)
-+		return orig_argnum_on_clone(correct_argnum_of_node, node, argnum);
-+
-+	if (node)
-+		debug_tree(NODE_DECL(node));
-+	debug_tree(correct_argnum_of_node_decl);
-+	gcc_unreachable();
++	handle_interesting_stmt(visited, head);
++	free_interesting_stmts(head);
 +}
 +
-+unsigned int get_correct_argnum(const_tree decl, const_tree correct_argnum_of_decl, unsigned int argnum)
++static struct visited *create_visited(void)
 +{
-+	struct cgraph_node *node, *correct_argnum_of_node;
++	struct visited *new_node;
 +
-+	gcc_assert(decl != NULL_TREE);
-+	gcc_assert(correct_argnum_of_decl != NULL_TREE);
++	new_node = (struct visited *)xmalloc(sizeof(*new_node));
++	new_node->stmts = pointer_set_create();
++	new_node->my_stmts = pointer_set_create();
++	new_node->skip_expr_casts = pointer_set_create();
++	new_node->no_cast_check = pointer_set_create();
++	return new_node;
++}
 +
-+	correct_argnum_of_node = get_cnode(correct_argnum_of_decl);
-+	if (!correct_argnum_of_node || DECL_ARTIFICIAL(decl) || DECL_ARTIFICIAL(correct_argnum_of_decl))
-+		return get_correct_argnum_fndecl(decl, correct_argnum_of_decl, argnum);
++static void free_visited(struct visited *visited)
++{
++	pointer_set_destroy(visited->stmts);
++	pointer_set_destroy(visited->my_stmts);
++	pointer_set_destroy(visited->skip_expr_casts);
++	pointer_set_destroy(visited->no_cast_check);
 +
-+	node = get_cnode(decl);
-+	return get_correct_argnum_cnode(node, correct_argnum_of_node, argnum);
++	free(visited);
 +}
 +
-+// Find the original cloned function
-+tree get_orig_fndecl(const_tree clone_fndecl)
++// Remove the size_overflow asm stmt and create an assignment from the input and output of the asm
++static void replace_size_overflow_asm_with_assign(gasm *asm_stmt, tree lhs, tree rhs)
 +{
-+	struct cgraph_node *node;
++	gassign *assign;
++	gimple_stmt_iterator gsi;
 +
-+	gcc_assert(TREE_CODE(clone_fndecl) == FUNCTION_DECL);
++	// already removed
++	if (gimple_bb(asm_stmt) == NULL)
++		return;
++	gsi = gsi_for_stmt(asm_stmt);
 +
-+	if (DECL_ABSTRACT_ORIGIN(clone_fndecl))
-+		return CONST_CAST_TREE(DECL_ABSTRACT_ORIGIN(clone_fndecl));
-+	node = get_cnode(clone_fndecl);
-+	if (!node)
-+		return CONST_CAST_TREE(clone_fndecl);
++	assign = gimple_build_assign(lhs, rhs);
++	gsi_insert_before(&gsi, assign, GSI_SAME_STMT);
++	SSA_NAME_DEF_STMT(lhs) = assign;
 +
-+	while (node->clone_of)
-+		node = node->clone_of;
-+	if (!made_by_compiler(NODE_DECL(node)))
-+		return NODE_DECL(node);
-+	// Return the cloned decl because it is needed for the transform callback
-+	return CONST_CAST_TREE(clone_fndecl);
++	gsi_remove(&gsi, true);
 +}
 +
-+static tree get_interesting_fndecl_from_stmt(const gcall *stmt)
++// Replace our asm stmts with assignments (they are no longer needed and may interfere with later optimizations)
++static void remove_size_overflow_asm(gimple stmt)
 +{
-+	if (gimple_call_num_args(stmt) == 0)
-+		return NULL_TREE;
-+	return gimple_call_fndecl(stmt);
-+}
++	gimple_stmt_iterator gsi;
++	tree input, output;
 +
-+tree get_interesting_orig_fndecl_from_stmt(const gcall *stmt)
-+{
-+	tree fndecl;
++	if (!is_size_overflow_asm(stmt))
++		return;
 +
-+	fndecl = get_interesting_fndecl_from_stmt(stmt);
-+	if (fndecl == NULL_TREE)
-+		return NULL_TREE;
-+	return get_orig_fndecl(fndecl);
-+}
++	if (gimple_asm_noutputs(as_a_gasm(stmt)) == 0) {
++		gsi = gsi_for_stmt(stmt);
 +
-+void set_dominance_info(void)
-+{
-+	calculate_dominance_info(CDI_DOMINATORS);
-+	calculate_dominance_info(CDI_POST_DOMINATORS);
++		ipa_remove_stmt_references(cgraph_get_node(current_function_decl), stmt);
++		gsi_remove(&gsi, true);
++		return;
++	}
++
++	input = gimple_asm_input_op(as_a_gasm(stmt), 0);
++	output = gimple_asm_output_op(as_a_gasm(stmt), 0);
++	replace_size_overflow_asm_with_assign(as_a_gasm(stmt), TREE_VALUE(output), TREE_VALUE(input));
 +}
 +
-+void unset_dominance_info(void)
++static void remove_all_size_overflow_asm(void)
 +{
-+	free_dominance_info(CDI_DOMINATORS);
-+	free_dominance_info(CDI_POST_DOMINATORS);
++	basic_block bb;
++
++	FOR_EACH_BB_FN(bb, cfun) {
++		gimple_stmt_iterator si;
++
++		for (si = gsi_start_bb(bb); !gsi_end_p(si); gsi_next(&si))
++			remove_size_overflow_asm(gsi_stmt(si));
++	}
 +}
 +
-+void set_current_function_decl(tree fndecl)
++unsigned int size_overflow_function_transform(struct cgraph_node *node __unused)
 +{
-+	gcc_assert(fndecl != NULL_TREE);
++	struct visited *visited;
 +
-+	push_cfun(DECL_STRUCT_FUNCTION(fndecl));
-+#if BUILDING_GCC_VERSION <= 4007
-+	current_function_decl = fndecl;
++#if BUILDING_GCC_VERSION >= 4008
++	if (dump_file) {
++		fprintf(dump_file, "BEFORE TRANSFORM -------------------------\n");
++		size_overflow_dump_function(dump_file, node);
++	}
 +#endif
++	visited = create_visited();
 +	set_dominance_info();
-+}
 +
-+void unset_current_function_decl(void)
-+{
-+	unset_dominance_info();
-+#if BUILDING_GCC_VERSION <= 4007
-+	current_function_decl = NULL_TREE;
-+#endif
-+	pop_cfun();
-+}
++	search_interesting_stmts(visited);
 +
-+bool is_valid_cgraph_node(struct cgraph_node *node)
-+{
-+	if (cgraph_function_body_availability(node) == AVAIL_NOT_AVAILABLE)
-+		return false;
-+	if (node->thunk.thunk_p || node->alias)
-+		return false;
-+	return true;
-+}
++	remove_all_size_overflow_asm();
 +
-+tree get_lhs(const_gimple stmt)
-+{
-+	switch (gimple_code(stmt)) {
-+	case GIMPLE_ASSIGN:
-+	case GIMPLE_CALL:
-+		return gimple_get_lhs(stmt);
-+	case GIMPLE_PHI:
-+		return gimple_phi_result(stmt);
-+	default:
-+		debug_gimple_stmt((gimple)stmt);
-+		gcc_unreachable();
++	unset_dominance_info();
++	free_visited(visited);
++
++#if BUILDING_GCC_VERSION >= 4008
++	if (dump_file) {
++		fprintf(dump_file, "AFTER TRANSFORM -------------------------\n");
++		size_overflow_dump_function(dump_file, node);
 +	}
++#endif
++	return TODO_dump_func | TODO_verify_stmts | TODO_remove_unused_locals | TODO_update_ssa_no_phi | TODO_ggc_collect | TODO_verify_flow;
 +}
-+
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_plugin.c b/tools/gcc/size_overflow_plugin/size_overflow_plugin.c
+diff --git a/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform_core.c b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform_core.c
 new file mode 100644
-index 0000000..3f8f032
+index 0000000..062204a
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_plugin.c
-@@ -0,0 +1,290 @@
++++ b/scripts/gcc-plugins/size_overflow_plugin/size_overflow_transform_core.c
+@@ -0,0 +1,1025 @@
 +/*
 + * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
 + * Licensed under the GPL v2, or (at your option) v3
@@ -209132,3014 +207823,5055 @@ index 0000000..3f8f032
 +
 +#include "size_overflow.h"
 +
-+int plugin_is_GPL_compatible;
++#define MIN_CHECK true
++#define MAX_CHECK false
 +
-+tree report_size_overflow_decl;
++unsigned int call_count = 0;
 +
-+tree size_overflow_type_HI;
-+tree size_overflow_type_SI;
-+tree size_overflow_type_DI;
-+tree size_overflow_type_TI;
++tree get_size_overflow_type(struct visited *visited, const_gimple stmt, const_tree node)
++{
++	const_tree type;
++	tree new_type;
 +
-+static struct plugin_info size_overflow_plugin_info = {
-+	.version	= "20160521",
-+	.help		= "no-size-overflow\tturn off size overflow checking\n",
-+};
++	gcc_assert(node != NULL_TREE);
 +
-+static tree handle_size_overflow_attribute(tree *node, tree __unused name, tree args, int __unused flags, bool *no_add_attrs)
-+{
-+	unsigned int arg_count;
-+	enum tree_code code = TREE_CODE(*node);
++	type = TREE_TYPE(node);
 +
-+	switch (code) {
-+	case FUNCTION_DECL:
-+		arg_count = type_num_arguments(TREE_TYPE(*node));
++	if (pointer_set_contains(visited->my_stmts, stmt))
++		return TREE_TYPE(node);
++
++	switch (TYPE_MODE(type)) {
++	case QImode:
++	case HImode:
++		new_type = size_overflow_type_SI;
 +		break;
-+	case FUNCTION_TYPE:
-+	case METHOD_TYPE:
-+		arg_count = type_num_arguments(*node);
++	case SImode:
++		new_type = size_overflow_type_DI;
++		break;
++	case DImode:
++		if (LONG_TYPE_SIZE == GET_MODE_BITSIZE(SImode))
++			new_type = TYPE_UNSIGNED(type) ? unsigned_intDI_type_node : intDI_type_node;
++		else
++			new_type = size_overflow_type_TI;
++		break;
++	case TImode:
++		gcc_assert(!TYPE_UNSIGNED(type));
++		new_type = size_overflow_type_TI;
 +		break;
 +	default:
-+		*no_add_attrs = true;
-+		debug_tree(*node);
-+		error("%s: %qE attribute only applies to functions", __func__, name);
-+		return NULL_TREE;
++		debug_tree(node);
++		error("%s: unsupported gcc configuration (%qE).", __func__, current_function_decl);
++		gcc_unreachable();
 +	}
 +
-+	for (; args; args = TREE_CHAIN(args)) {
-+		int cur_val;
-+		tree position = TREE_VALUE(args);
++	if (TYPE_QUALS(type) != 0)
++		return build_qualified_type(new_type, TYPE_QUALS(type));
++	return new_type;
++}
 +
-+		if (TREE_CODE(position) != INTEGER_CST) {
-+			error("%s: parameter isn't an integer", __func__);
-+			debug_tree(args);
-+			*no_add_attrs = true;
-+			return NULL_TREE;
-+		}
++tree cast_to_new_size_overflow_type(struct visited *visited, gimple stmt, tree rhs, tree size_overflow_type, bool before)
++{
++	gimple_stmt_iterator gsi;
++	gimple new_stmt;
 +
-+		cur_val = tree_to_shwi(position);
-+		if (cur_val < 0 || arg_count < (unsigned int)cur_val) {
-+			error("%s: parameter %d is outside range.", __func__, cur_val);
-+			*no_add_attrs = true;
-+			return NULL_TREE;
-+		}
-+	}
-+	return NULL_TREE;
++	if (rhs == NULL_TREE)
++		return NULL_TREE;
++
++	gsi = gsi_for_stmt(stmt);
++	new_stmt = build_cast_stmt(visited, size_overflow_type, rhs, CREATE_NEW_VAR, &gsi, before, false);
++	if (gimple_assign_cast_p(new_stmt))
++		gimple_assign_set_rhs_code(new_stmt, CONVERT_EXPR);
++	pointer_set_insert(visited->my_stmts, new_stmt);
++
++	return get_lhs(new_stmt);
 +}
 +
-+static tree handle_intentional_overflow_attribute(tree *node, tree __unused name, tree args, int __unused flags, bool *no_add_attrs)
++tree create_assign(struct visited *visited, gimple oldstmt, tree rhs1, bool before)
 +{
-+	unsigned int arg_count;
-+	HOST_WIDE_INT s_first_arg;
-+	enum tree_code code = TREE_CODE(*node);
++	tree lhs, dst_type;
++	gimple_stmt_iterator gsi;
 +
-+	switch (code) {
-+	case FUNCTION_DECL:
-+		arg_count = type_num_arguments(TREE_TYPE(*node));
++	if (rhs1 == NULL_TREE) {
++		debug_gimple_stmt(oldstmt);
++		error("%s: rhs1 is NULL_TREE", __func__);
++		gcc_unreachable();
++	}
++
++	switch (gimple_code(oldstmt)) {
++	case GIMPLE_ASM:
++		lhs = rhs1;
 +		break;
-+	case FUNCTION_TYPE:
-+	case METHOD_TYPE:
-+		arg_count = type_num_arguments(*node);
++	case GIMPLE_CALL:
++	case GIMPLE_ASSIGN:
++		lhs = gimple_get_lhs(oldstmt);
 +		break;
-+	case VAR_DECL:
-+	case FIELD_DECL:
-+		return NULL_TREE;
 +	default:
-+		*no_add_attrs = true;
-+		debug_tree(*node);
-+		error("%qE attribute only applies to functions, fields or vars", name);
-+		return NULL_TREE;
++		debug_gimple_stmt(oldstmt);
++		gcc_unreachable();
 +	}
 +
-+	s_first_arg = tree_to_shwi(TREE_VALUE(args));
-+	if (s_first_arg == -1)
-+		return NULL_TREE;
-+	if (s_first_arg < -1)
-+		error("%s: parameter %d is outside range.", __func__, (int)s_first_arg);
-+
-+	for (; args; args = TREE_CHAIN(args)) {
-+		unsigned int cur_val;
-+
-+		if (TREE_CODE(TREE_VALUE(args)) != INTEGER_CST) {
-+			error("%s: parameter isn't an integer", __func__);
-+			debug_tree(args);
-+			*no_add_attrs = true;
-+			return NULL_TREE;
-+		}
++	gsi = gsi_for_stmt(oldstmt);
++	pointer_set_insert(visited->stmts, oldstmt);
++	if (lookup_stmt_eh_lp(oldstmt) != 0) {
++		basic_block next_bb, cur_bb;
++		const_edge e;
 +
-+		cur_val = (unsigned int)tree_to_uhwi(TREE_VALUE(args));
-+		if (cur_val > arg_count ) {
-+			error("%s: parameter %u is outside range. (arg_count: %u)", __func__, cur_val, arg_count);
-+			*no_add_attrs = true;
-+			return NULL_TREE;
-+		}
-+	}
-+	return NULL_TREE;
-+}
++		gcc_assert(before == false);
++		gcc_assert(stmt_can_throw_internal(oldstmt));
++		gcc_assert(gimple_code(oldstmt) == GIMPLE_CALL);
++		gcc_assert(!gsi_end_p(gsi));
 +
-+static struct attribute_spec size_overflow_attr = {
-+	.name				= "size_overflow",
-+	.min_length			= 1,
-+	.max_length			= -1,
-+	.decl_required			= true,
-+	.type_required			= false,
-+	.function_type_required		= false,
-+	.handler			= handle_size_overflow_attribute,
-+#if BUILDING_GCC_VERSION >= 4007
-+	.affects_type_identity		= false
-+#endif
-+};
++		cur_bb = gimple_bb(oldstmt);
++		next_bb = cur_bb->next_bb;
++		e = find_edge(cur_bb, next_bb);
++		gcc_assert(e != NULL);
++		gcc_assert(e->flags & EDGE_FALLTHRU);
 +
-+static struct attribute_spec intentional_overflow_attr = {
-+	.name				= "intentional_overflow",
-+	.min_length			= 1,
-+	.max_length			= -1,
-+	.decl_required			= true,
-+	.type_required			= false,
-+	.function_type_required		= false,
-+	.handler			= handle_intentional_overflow_attribute,
-+#if BUILDING_GCC_VERSION >= 4007
-+	.affects_type_identity		= false
-+#endif
-+};
++		gsi = gsi_after_labels(next_bb);
++		gcc_assert(!gsi_end_p(gsi));
 +
-+static void register_attributes(void __unused *event_data, void __unused *data)
-+{
-+	register_attribute(&size_overflow_attr);
-+	register_attribute(&intentional_overflow_attr);
-+}
++		before = true;
++		oldstmt = gsi_stmt(gsi);
++	}
 +
-+static tree create_typedef(tree type, const char* ident)
-+{
-+	tree new_type, decl;
++	if (is_gimple_constant(rhs1) && TREE_CODE_CLASS(gimple_assign_rhs_code(oldstmt)) == tcc_comparison)
++		dst_type = get_size_overflow_type(visited, oldstmt, rhs1);
++	else
++		dst_type = get_size_overflow_type(visited, oldstmt, lhs);
 +
-+	new_type = build_variant_type_copy(type);
-+	decl = build_decl(BUILTINS_LOCATION, TYPE_DECL, get_identifier(ident), new_type);
-+	DECL_ORIGINAL_TYPE(decl) = type;
-+	TYPE_NAME(new_type) = decl;
-+	return new_type;
++	if (is_gimple_constant(rhs1))
++		return cast_a_tree(dst_type, rhs1);
++	return cast_to_new_size_overflow_type(visited, oldstmt, rhs1, dst_type, before);
 +}
 +
-+// Create the noreturn report_size_overflow() function decl.
-+static void size_overflow_start_unit(void __unused *gcc_data, void __unused *user_data)
++tree dup_assign(struct visited *visited, gassign *oldstmt, const_tree node, tree rhs1, tree rhs2, tree __unused rhs3)
 +{
-+	tree const_char_ptr_type_node;
-+	tree fntype;
-+
-+	const_char_ptr_type_node = build_pointer_type(build_type_variant(char_type_node, 1, 0));
++	gassign *stmt;
++	gimple_stmt_iterator gsi;
++	tree size_overflow_type, new_var, lhs = gimple_assign_lhs(oldstmt);
 +
-+	size_overflow_type_HI = create_typedef(intHI_type_node, "size_overflow_type_HI");
-+	size_overflow_type_SI = create_typedef(intSI_type_node, "size_overflow_type_SI");
-+	size_overflow_type_DI = create_typedef(intDI_type_node, "size_overflow_type_DI");
-+	size_overflow_type_TI = create_typedef(intTI_type_node, "size_overflow_type_TI");
++	if (pointer_set_contains(visited->my_stmts, oldstmt))
++		return lhs;
 +
-+	// void report_size_overflow(const char *loc_file, unsigned int loc_line, const char *current_func, const char *ssa_var)
-+	fntype = build_function_type_list(void_type_node,
-+					  const_char_ptr_type_node,
-+					  unsigned_type_node,
-+					  const_char_ptr_type_node,
-+					  const_char_ptr_type_node,
-+					  NULL_TREE);
-+	report_size_overflow_decl = build_fn_decl("report_size_overflow", fntype);
++	if (gimple_num_ops(oldstmt) != 4 && rhs1 == NULL_TREE) {
++		rhs1 = gimple_assign_rhs1(oldstmt);
++		rhs1 = create_assign(visited, oldstmt, rhs1, BEFORE_STMT);
++	}
++	if (gimple_num_ops(oldstmt) == 3 && rhs2 == NULL_TREE) {
++		rhs2 = gimple_assign_rhs2(oldstmt);
++		rhs2 = create_assign(visited, oldstmt, rhs2, BEFORE_STMT);
++	}
 +
-+	DECL_ASSEMBLER_NAME(report_size_overflow_decl);
-+	TREE_PUBLIC(report_size_overflow_decl) = 1;
-+	DECL_EXTERNAL(report_size_overflow_decl) = 1;
-+	DECL_ARTIFICIAL(report_size_overflow_decl) = 1;
-+//	TREE_THIS_VOLATILE(report_size_overflow_decl) = 1;
-+// !!!
-+	DECL_PRESERVE_P(report_size_overflow_decl) = 1;
-+	DECL_UNINLINABLE(report_size_overflow_decl) = 1;
-+	TREE_USED(report_size_overflow_decl) = 1;
-+	TREE_NOTHROW(report_size_overflow_decl) = 1;
-+}
++	stmt = as_a_gassign(gimple_copy(oldstmt));
++	gimple_set_location(stmt, gimple_location(oldstmt));
++	pointer_set_insert(visited->my_stmts, stmt);
 +
-+static bool disable_ubsan_si_overflow_gate(void)
-+{
-+#if BUILDING_GCC_VERSION >= 4009
-+	flag_sanitize &= ~SANITIZE_SI_OVERFLOW;
-+#endif
-+	return true;
-+}
++	if (gimple_assign_rhs_code(oldstmt) == WIDEN_MULT_EXPR)
++		gimple_assign_set_rhs_code(stmt, MULT_EXPR);
 +
-+#define PASS_NAME disable_ubsan_si_overflow
++	size_overflow_type = get_size_overflow_type(visited, oldstmt, node);
 +
-+#define NO_EXECUTE
++	new_var = create_new_var(size_overflow_type);
++	new_var = make_ssa_name(new_var, stmt);
++	gimple_assign_set_lhs(stmt, new_var);
 +
-+#include "gcc-generate-gimple-pass.h"
++	if (rhs1 != NULL_TREE)
++		gimple_assign_set_rhs1(stmt, rhs1);
 +
-+int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
-+{
-+	int i;
-+	const char * const plugin_name = plugin_info->base_name;
-+	const int argc = plugin_info->argc;
-+	const struct plugin_argument * const argv = plugin_info->argv;
-+	bool enable = true;
-+	struct register_pass_info insert_size_overflow_asm_pass_info;
-+	struct register_pass_info size_overflow_pass_info;
-+#if BUILDING_GCC_VERSION >= 4009
-+	struct register_pass_info disable_ubsan_si_overflow_pass_info;
++	if (rhs2 != NULL_TREE)
++		gimple_assign_set_rhs2(stmt, rhs2);
++#if BUILDING_GCC_VERSION >= 4006
++	if (rhs3 != NULL_TREE)
++		gimple_assign_set_rhs3(stmt, rhs3);
 +#endif
++	gimple_set_vuse(stmt, gimple_vuse(oldstmt));
++	gimple_set_vdef(stmt, gimple_vdef(oldstmt));
 +
-+	static const struct ggc_root_tab gt_ggc_r_gt_size_overflow[] = {
-+		{
-+			.base = &report_size_overflow_decl,
-+			.nelt = 1,
-+			.stride = sizeof(report_size_overflow_decl),
-+			.cb = &gt_ggc_mx_tree_node,
-+			.pchw = &gt_pch_nx_tree_node
-+		},
-+		LAST_GGC_ROOT_TAB
-+	};
++	gsi = gsi_for_stmt(oldstmt);
++	gsi_insert_after(&gsi, stmt, GSI_SAME_STMT);
++	update_stmt(stmt);
++	pointer_set_insert(visited->stmts, oldstmt);
++	return gimple_assign_lhs(stmt);
++}
 +
-+	insert_size_overflow_asm_pass_info.pass				= make_insert_size_overflow_asm_pass();
-+	insert_size_overflow_asm_pass_info.reference_pass_name		= "ssa";
-+	insert_size_overflow_asm_pass_info.ref_pass_instance_number	= 1;
-+	insert_size_overflow_asm_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
++static tree cast_parm_decl(struct visited *visited, tree phi_ssa_name, tree arg, tree size_overflow_type, basic_block bb)
++{
++	const_gimple assign;
++	gimple_stmt_iterator gsi;
++	basic_block first_bb;
 +
-+	size_overflow_pass_info.pass			= make_size_overflow_pass();
-+	size_overflow_pass_info.reference_pass_name	= "inline";
-+	size_overflow_pass_info.ref_pass_instance_number	= 1;
-+	size_overflow_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
++	gcc_assert(SSA_NAME_IS_DEFAULT_DEF(arg));
 +
-+	if (!plugin_default_version_check(version, &gcc_version)) {
-+		error(G_("incompatible gcc/plugin versions"));
-+		return 1;
++	if (bb->index == 0) {
++		first_bb = split_block_after_labels(ENTRY_BLOCK_PTR_FOR_FN(cfun))->dest;
++		gcc_assert(dom_info_available_p(CDI_DOMINATORS));
++		set_immediate_dominator(CDI_DOMINATORS, first_bb, ENTRY_BLOCK_PTR_FOR_FN(cfun));
++		bb = first_bb;
 +	}
 +
-+	for (i = 0; i < argc; ++i) {
-+		if (!strcmp(argv[i].key, "no-size-overflow")) {
-+			enable = false;
-+			continue;
-+		}
-+		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+	}
++	gsi = gsi_after_labels(bb);
++	assign = build_cast_stmt(visited, size_overflow_type, arg, phi_ssa_name, &gsi, BEFORE_STMT, false);
++	pointer_set_insert(visited->my_stmts, assign);
++	return get_lhs(assign);
++}
 +
-+	register_callback(plugin_name, PLUGIN_INFO, NULL, &size_overflow_plugin_info);
-+	if (enable) {
-+#if BUILDING_GCC_VERSION >= 4009
-+		if (flag_sanitize & SANITIZE_SI_OVERFLOW) {
-+			error(G_("ubsan SANITIZE_SI_OVERFLOW option is unsupported"));
-+			return 1;
-+		}
-+#endif
-+		register_callback(plugin_name, PLUGIN_START_UNIT, &size_overflow_start_unit, NULL);
-+		register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_size_overflow);
-+#if BUILDING_GCC_VERSION >= 4009
-+		flag_sanitize |= SANITIZE_SI_OVERFLOW;
-+		disable_ubsan_si_overflow_pass_info.pass			= make_disable_ubsan_si_overflow_pass();
-+		disable_ubsan_si_overflow_pass_info.reference_pass_name		= "ubsan";
-+		disable_ubsan_si_overflow_pass_info.ref_pass_instance_number	= 1;
-+		disable_ubsan_si_overflow_pass_info.pos_op			= PASS_POS_REPLACE;
++static tree use_phi_ssa_name(struct visited *visited, tree ssa_name_var, tree new_arg)
++{
++	gimple_stmt_iterator gsi;
++	const_gimple assign;
++	gimple def_stmt = get_def_stmt(new_arg);
 +
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &disable_ubsan_si_overflow_pass_info);
-+#endif
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &insert_size_overflow_asm_pass_info);
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &size_overflow_pass_info);
++	if (gimple_code(def_stmt) == GIMPLE_PHI) {
++		gsi = gsi_after_labels(gimple_bb(def_stmt));
++		assign = build_cast_stmt(visited, TREE_TYPE(new_arg), new_arg, ssa_name_var, &gsi, BEFORE_STMT, true);
++	} else {
++		gsi = gsi_for_stmt(def_stmt);
++		assign = build_cast_stmt(visited, TREE_TYPE(new_arg), new_arg, ssa_name_var, &gsi, AFTER_STMT, true);
 +	}
-+	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
 +
-+	return 0;
++	pointer_set_insert(visited->my_stmts, assign);
++	return get_lhs(assign);
 +}
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_plugin_hash.c b/tools/gcc/size_overflow_plugin/size_overflow_plugin_hash.c
-new file mode 100644
-index 0000000..87af656
---- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_plugin_hash.c
-@@ -0,0 +1,352 @@
-+/*
-+ * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
-+ * Licensed under the GPL v2, or (at your option) v3
-+ *
-+ * Homepage:
-+ * https://github.com/ephox-gcc-plugins/size_overflow
-+ *
-+ * Documentation:
-+ * http://forums.grsecurity.net/viewtopic.php?f=7&t=3043
-+ *
-+ * This plugin recomputes expressions of function arguments marked by a size_overflow attribute
-+ * with double integer precision (DImode/TImode for 32/64 bit integer types).
-+ * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
-+ *
-+ * Usage:
-+ * $ make
-+ * $ make run
-+ */
 +
-+#include "size_overflow.h"
++static tree cast_visited_phi_arg(struct visited *visited, tree ssa_name_var, tree arg, tree size_overflow_type)
++{
++	basic_block bb;
++	gimple_stmt_iterator gsi;
++	const_gimple def_stmt;
++	const_gimple assign;
 +
-+#include "size_overflow_hash.h"
-+#include "disable_size_overflow_hash.h"
-+#include "size_overflow_hash_aux.h"
++	def_stmt = get_def_stmt(arg);
++	bb = gimple_bb(def_stmt);
++	gcc_assert(bb->index != 0);
++	gsi = gsi_after_labels(bb);
 +
-+static const_tree get_function_type(const_tree decl)
-+{
-+	if (FUNCTION_PTR_P(decl))
-+		return TREE_TYPE(TREE_TYPE(decl));
-+	gcc_assert(TREE_CODE(decl) == FUNCTION_DECL);
-+	return TREE_TYPE(decl);
++	assign = build_cast_stmt(visited, size_overflow_type, arg, ssa_name_var, &gsi, BEFORE_STMT, false);
++	pointer_set_insert(visited->my_stmts, assign);
++	return get_lhs(assign);
 +}
 +
-+static unsigned char get_tree_code(const_tree type)
++static tree create_new_phi_arg(struct visited *visited, tree ssa_name_var, tree new_arg, gphi *oldstmt, unsigned int i)
 +{
-+	switch (TREE_CODE(type)) {
-+	case ARRAY_TYPE:
-+		return 0;
-+	case BOOLEAN_TYPE:
-+		return 1;
-+	case ENUMERAL_TYPE:
-+		return 2;
-+	case FUNCTION_TYPE:
-+		return 3;
-+	case INTEGER_TYPE:
-+		return 4;
-+	case POINTER_TYPE:
-+		return 5;
-+	case RECORD_TYPE:
-+		return 6;
-+	case UNION_TYPE:
-+		return 7;
-+	case VOID_TYPE:
-+		return 8;
-+	case REAL_TYPE:
-+		return 9;
-+	case VECTOR_TYPE:
-+		return 10;
-+	case REFERENCE_TYPE:
-+		return 11;
-+	case OFFSET_TYPE:
-+		return 12;
-+	case COMPLEX_TYPE:
-+		return 13;
-+	default:
-+		debug_tree(type);
-+		gcc_unreachable();
-+	}
-+}
++	tree size_overflow_type;
++	tree arg;
++	const_gimple def_stmt;
 +
-+// http://www.team5150.com/~andrew/noncryptohashzoo2~/CrapWow.html
-+static unsigned int CrapWow(const char *key, unsigned int len, unsigned int seed)
-+{
-+#define cwfold( a, b, lo, hi ) { p = (unsigned int)(a) * (unsigned long long)(b); lo ^= (unsigned int)p; hi ^= (unsigned int)(p >> 32); }
-+#define cwmixa( in ) { cwfold( in, m, k, h ); }
-+#define cwmixb( in ) { cwfold( in, n, h, k ); }
++	if (new_arg != NULL_TREE && is_gimple_constant(new_arg))
++		return new_arg;
 +
-+	unsigned int m = 0x57559429;
-+	unsigned int n = 0x5052acdb;
-+	const unsigned int *key4 = (const unsigned int *)key;
-+	unsigned int h = len;
-+	unsigned int k = len + seed + n;
-+	unsigned long long p;
++	arg = gimple_phi_arg_def(oldstmt, i);
++	def_stmt = get_def_stmt(arg);
++	gcc_assert(def_stmt != NULL);
++	size_overflow_type = get_size_overflow_type(visited, oldstmt, arg);
 +
-+	while (len >= 8) {
-+		cwmixb(key4[0]) cwmixa(key4[1]) key4 += 2;
-+		len -= 8;
-+	}
-+	if (len >= 4) {
-+		cwmixb(key4[0]) key4 += 1;
-+		len -= 4;
++	switch (gimple_code(def_stmt)) {
++	case GIMPLE_PHI:
++		return cast_visited_phi_arg(visited, ssa_name_var, arg, size_overflow_type);
++	case GIMPLE_NOP: {
++		basic_block bb;
++
++		bb = gimple_phi_arg_edge(oldstmt, i)->src;
++		return cast_parm_decl(visited, ssa_name_var, arg, size_overflow_type, bb);
 +	}
-+	if (len)
-+		cwmixa(key4[0] & ((1 << (len * 8)) - 1 ));
-+	cwmixb(h ^ (k + n));
-+	return k ^ h;
++	case GIMPLE_ASM: {
++		gimple_stmt_iterator gsi;
++		const_gimple assign;
++		gimple stmt = get_def_stmt(arg);
 +
-+#undef cwfold
-+#undef cwmixa
-+#undef cwmixb
++		gsi = gsi_for_stmt(stmt);
++		assign = build_cast_stmt(visited, size_overflow_type, arg, ssa_name_var, &gsi, AFTER_STMT, false);
++		pointer_set_insert(visited->my_stmts, assign);
++		return get_lhs(assign);
++	}
++	default:
++		gcc_assert(new_arg != NULL_TREE);
++		gcc_assert(types_compatible_p(TREE_TYPE(new_arg), size_overflow_type));
++		return use_phi_ssa_name(visited, ssa_name_var, new_arg);
++	}
 +}
 +
-+static void set_hash(struct decl_hash *decl_hash_data)
++static gphi *overflow_create_phi_node(struct visited *visited, gphi *oldstmt, tree result)
 +{
-+	unsigned int fn, type, codes, seed = 0;
++	basic_block bb;
++	gphi *phi;
++	gimple_seq seq;
++	gimple_stmt_iterator gsi = gsi_for_stmt(oldstmt);
 +
-+	fn = CrapWow(decl_hash_data->fn_name, strlen(decl_hash_data->fn_name), seed) & 0xffff;
-+	codes = CrapWow((const char*)decl_hash_data->tree_codes, decl_hash_data->tree_codes_len, seed) & 0xffff;
-+	type = CrapWow(decl_hash_data->context, strlen(decl_hash_data->context), 0) & 0xffff;
-+	decl_hash_data->hash = type ^ fn ^ codes;
-+}
++	bb = gsi_bb(gsi);
 +
-+static void set_decl_type_codes(const_tree type, struct decl_hash *decl_hash_data)
-+{
-+	gcc_assert(type != NULL_TREE);
-+	gcc_assert(TREE_CODE_CLASS(TREE_CODE(type)) == tcc_type);
++	if (result == NULL_TREE) {
++		tree old_result = gimple_phi_result(oldstmt);
++		tree size_overflow_type = get_size_overflow_type(visited, oldstmt, old_result);
 +
-+	while (type && decl_hash_data->tree_codes_len < CODES_LIMIT) {
-+		decl_hash_data->tree_codes[decl_hash_data->tree_codes_len] = get_tree_code(type);
-+		decl_hash_data->tree_codes_len++;
-+		type = TREE_TYPE(type);
++		result = create_new_var(size_overflow_type);
 +	}
++
++	phi = as_a_gphi(create_phi_node(result, bb));
++	gimple_phi_set_result(phi, make_ssa_name(result, phi));
++	seq = phi_nodes(bb);
++	gsi = gsi_last(seq);
++	gsi_remove(&gsi, false);
++
++	gsi = gsi_for_stmt(oldstmt);
++	gsi_insert_after(&gsi, phi, GSI_NEW_STMT);
++	gimple_set_bb(phi, bb);
++	return phi;
 +}
 +
-+static void set_result_codes(const_tree node, struct decl_hash *decl_hash_data)
++#if BUILDING_GCC_VERSION <= 4007
++static tree create_new_phi_node(struct visited *visited, VEC(tree, heap) **args, tree ssa_name_var, gimple oldstmt)
++#else
++static tree create_new_phi_node(struct visited *visited, vec<tree, va_heap, vl_embed> *&args, tree ssa_name_var, gphi *oldstmt)
++#endif
 +{
-+	const_tree result;
-+
-+	gcc_assert(node != NULL_TREE);
++	gphi *new_phi;
++	unsigned int i;
++	tree arg, result;
++	location_t loc = gimple_location(oldstmt);
 +
-+	if (DECL_P(node)) {
-+		result = DECL_RESULT(node);
-+		if (result != NULL_TREE)
-+			return set_decl_type_codes(TREE_TYPE(result), decl_hash_data);
-+		return set_result_codes(TREE_TYPE(node), decl_hash_data);
-+	}
++#if BUILDING_GCC_VERSION <= 4007
++	gcc_assert(!VEC_empty(tree, *args));
++#else
++	gcc_assert(!args->is_empty());
++#endif
 +
-+	gcc_assert(TYPE_P(node));
++	new_phi = overflow_create_phi_node(visited, oldstmt, ssa_name_var);
++	result = gimple_phi_result(new_phi);
++	ssa_name_var = SSA_NAME_VAR(result);
 +
-+	if (TREE_CODE(node) == FUNCTION_TYPE)
-+		return set_result_codes(TREE_TYPE(node), decl_hash_data);
++#if BUILDING_GCC_VERSION <= 4007
++	FOR_EACH_VEC_ELT(tree, *args, i, arg) {
++#else
++	FOR_EACH_VEC_SAFE_ELT(args, i, arg) {
++#endif
++		arg = create_new_phi_arg(visited, ssa_name_var, arg, oldstmt, i);
++		add_phi_arg(new_phi, arg, gimple_phi_arg_edge(oldstmt, i), loc);
++	}
 +
-+	return set_decl_type_codes(node, decl_hash_data);
++#if BUILDING_GCC_VERSION <= 4007
++	VEC_free(tree, heap, *args);
++#else
++	vec_free(args);
++#endif
++	update_stmt(new_phi);
++	pointer_set_insert(visited->my_stmts, new_phi);
++	return result;
 +}
 +
-+static void set_decl_codes(struct decl_hash *decl_hash_data)
++static tree handle_phi(interesting_stmts_t expand_from, tree orig_result)
 +{
-+	const_tree arg, type;
-+	enum tree_code code;
++#if BUILDING_GCC_VERSION <= 4007
++	VEC(tree, heap) *args = NULL;
++#else
++	vec<tree, va_heap, vl_embed> *args = NULL;
++#endif
++	unsigned int i, len;
++	tree ssa_name_var = NULL_TREE;
++	gphi *oldstmt = as_a_gphi(get_def_stmt(orig_result));
 +
-+	if (TREE_CODE(decl_hash_data->decl) == VAR_DECL || TREE_CODE(decl_hash_data->decl) == FIELD_DECL) {
-+		set_decl_type_codes(TREE_TYPE(decl_hash_data->decl), decl_hash_data);
-+		return;
-+	}
++	len = gimple_phi_num_args(oldstmt);
++	pointer_set_insert(expand_from->visited->stmts, oldstmt);
++	for (i = 0; i < len; i++) {
++		tree arg, new_arg;
 +
-+	type = get_function_type(decl_hash_data->decl);
-+	code = TREE_CODE(type);
-+	gcc_assert(code == FUNCTION_TYPE || code == METHOD_TYPE);
++		arg = gimple_phi_arg_def(oldstmt, i);
++		new_arg = expand(expand_from, arg);
 +
-+	if (FUNCTION_PTR_P(decl_hash_data->decl))
-+		set_result_codes(type, decl_hash_data);
-+	else
-+		set_result_codes(decl_hash_data->decl, decl_hash_data);
++		if (ssa_name_var == NULL_TREE && new_arg != NULL_TREE)
++			ssa_name_var = SSA_NAME_VAR(new_arg);
 +
-+	for (arg = TYPE_ARG_TYPES(type); arg != NULL_TREE && decl_hash_data->tree_codes_len < CODES_LIMIT; arg = TREE_CHAIN(arg))
-+		set_decl_type_codes(TREE_VALUE(arg), decl_hash_data);
-+}
++		if (is_gimple_constant(arg)) {
++			tree size_overflow_type = get_size_overflow_type(expand_from->visited, oldstmt, arg);
 +
-+static const struct size_overflow_hash *get_proper_hash_chain(const struct size_overflow_hash *entry, const char *func_name, const char *context)
-+{
-+	for (; entry; entry = entry->next) {
-+		if (strcmp(entry->name, func_name))
-+			continue;
-+		if (!strcmp(entry->context, context))
-+			return entry;
++			new_arg = cast_a_tree(size_overflow_type, arg);
++		}
++
++#if BUILDING_GCC_VERSION <= 4007
++		VEC_safe_push(tree, heap, args, new_arg);
++#else
++		vec_safe_push(args, new_arg);
++#endif
 +	}
-+	return NULL;
++
++#if BUILDING_GCC_VERSION <= 4007
++	return create_new_phi_node(expand_from->visited, &args, ssa_name_var, oldstmt);
++#else
++	return create_new_phi_node(expand_from->visited, args, ssa_name_var, oldstmt);
++#endif
 +}
 +
-+unsigned int get_decl_hash(const_tree decl, const char *decl_name)
++static tree create_cast_assign(struct visited *visited, gassign *stmt)
 +{
-+	struct decl_hash decl_hash_data;
-+	enum tree_code code = TREE_CODE(decl);
-+
-+	gcc_assert(code == FIELD_DECL || code == FUNCTION_DECL || code == VAR_DECL);
-+
-+	// skip builtins __builtin_constant_p
-+	if (code == FUNCTION_DECL && (DECL_BUILT_IN(decl) || DECL_BUILT_IN_CLASS(decl) == BUILT_IN_NORMAL))
-+		return NO_HASH;
++	tree rhs1 = gimple_assign_rhs1(stmt);
++	tree lhs = gimple_assign_lhs(stmt);
++	const_tree rhs1_type = TREE_TYPE(rhs1);
++	const_tree lhs_type = TREE_TYPE(lhs);
 +
-+	decl_hash_data.fn_name = decl_name;
-+	decl_hash_data.decl = decl;
-+	decl_hash_data.context = get_decl_context(decl);
-+	if (!decl_hash_data.context)
-+		return NO_HASH;
-+	decl_hash_data.tree_codes_len = 0;
++	if (TYPE_UNSIGNED(rhs1_type) == TYPE_UNSIGNED(lhs_type))
++		return create_assign(visited, stmt, lhs, AFTER_STMT);
 +
-+	set_decl_codes(&decl_hash_data);
-+	gcc_assert(decl_hash_data.tree_codes_len != 0);
-+	set_hash(&decl_hash_data);
-+	return decl_hash_data.hash;
++	return create_assign(visited, stmt, rhs1, AFTER_STMT);
 +}
 +
-+const char *get_orig_decl_name(const_tree decl)
++static bool skip_lhs_cast_check(struct visited *visited, const gassign *stmt)
 +{
-+	const char *name;
-+	unsigned int len;
-+	const void *end;
-+	const_tree orig_decl;
-+
-+	if (TREE_CODE(decl) == FUNCTION_DECL)
-+		orig_decl = DECL_ORIGIN(decl);
-+	else
-+		orig_decl = decl;
-+
-+	len = DECL_NAME_LENGTH(orig_decl);
-+	name = DECL_NAME_POINTER(orig_decl);
++	const_tree rhs = gimple_assign_rhs1(stmt);
++	const_gimple def_stmt = get_def_stmt(rhs);
 +
-+	/* Sometimes gcc loses the original cgraph node leaving only clones behind.
-+	 * In such cases we will extract the name from the clone and use it in the hash table
-+	 * without checking the parameter number on the original (unavailable) decl.
-+	 */
++	// 3.8.2 kernel/futex_compat.c compat_exit_robust_list(): get_user() 64 ulong -> int (compat_long_t), int max
++	if (gimple_code(def_stmt) == GIMPLE_ASM)
++		return true;
 +
-+	if (made_by_compiler(orig_decl)) {
-+		end = memchr(name, '.', len);
-+		if (!end)
-+			return xstrndup(name, len);
-+		len = (long)end - (long)name;
-+		gcc_assert(len > 0);
++	if (is_const_plus_unsigned_signed_truncation(rhs)) {
++		pointer_set_insert(visited->no_cast_check, stmt);
++		return true;
 +	}
 +
-+	return xstrndup(name, len);
++	return false;
 +}
 +
-+const struct size_overflow_hash *get_disable_size_overflow_hash_entry(unsigned int hash, const char *decl_name, const char *context, unsigned int argnum)
++static tree create_string_param(tree string)
 +{
-+	const struct size_overflow_hash *entry, *entry_node;
++	tree i_type, a_type;
++	const int length = TREE_STRING_LENGTH(string);
 +
-+	entry = disable_size_overflow_hash[hash];
-+	entry_node = get_proper_hash_chain(entry, decl_name, context);
-+	if (entry_node && entry_node->param & (1U << argnum))
-+		return entry_node;
-+	return NULL;
++	gcc_assert(length > 0);
++
++	i_type = build_index_type(build_int_cst(NULL_TREE, length - 1));
++	a_type = build_array_type(char_type_node, i_type);
++
++	TREE_TYPE(string) = a_type;
++	TREE_CONSTANT(string) = 1;
++	TREE_READONLY(string) = 1;
++
++	return build1(ADDR_EXPR, ptr_type_node, string);
 +}
 +
-+const struct size_overflow_hash *get_size_overflow_hash_entry(unsigned int hash, const char *decl_name, const char *context, unsigned int argnum)
++static void insert_cond(basic_block cond_bb, tree arg, enum tree_code cond_code, tree type_value)
 +{
-+	const struct size_overflow_hash *entry, *entry_node;
-+
-+	entry = size_overflow_hash[hash];
-+	entry_node = get_proper_hash_chain(entry, decl_name, context);
-+	if (entry_node && entry_node->param & (1U << argnum))
-+		return entry_node;
++	gcond *cond_stmt;
++	gimple_stmt_iterator gsi = gsi_last_bb(cond_bb);
 +
-+	entry = size_overflow_hash_aux[hash];
-+	entry_node = get_proper_hash_chain(entry, decl_name, context);
-+	if (entry_node && entry_node->param & (1U << argnum))
-+		return entry_node;
-+	return NULL;
++	cond_stmt = gimple_build_cond(cond_code, arg, type_value, NULL_TREE, NULL_TREE);
++	gsi_insert_after(&gsi, cond_stmt, GSI_CONTINUE_LINKING);
++	update_stmt(cond_stmt);
 +}
 +
-+const struct size_overflow_hash *get_size_overflow_hash_entry_tree(const_tree fndecl, unsigned int argnum, bool hash_table)
++static void insert_cond_result(interesting_stmts_t expand_from, basic_block bb_true, const_gimple stmt, const_tree arg, bool min)
 +{
-+	const_tree orig_decl;
-+	unsigned int orig_argnum, hash;
-+	const char *decl_name, *context;
++	gcall *func_stmt;
++	const_gimple def_stmt;
++	const_tree loc_line;
++	tree loc_file, ssa_name, current_func;
++	expanded_location xloc;
++	char *ssa_name_buf;
++	int len;
++	struct cgraph_edge *edge;
++	struct cgraph_node *report_node;
++	int frequency;
++	gimple_stmt_iterator gsi = gsi_start_bb(bb_true);
 +
-+	if (made_by_compiler(fndecl)) {
-+		orig_decl = get_orig_fndecl(fndecl);
-+		orig_argnum = get_correct_argnum(fndecl, orig_decl, argnum);
-+	} else {
-+		orig_decl = fndecl;
-+		orig_argnum = argnum;
-+	}
++	def_stmt = get_def_stmt(arg);
++	if (gimple_has_location(def_stmt))
++		xloc = expand_location(gimple_location(def_stmt));
++	else if (gimple_has_location(stmt))
++		xloc = expand_location(gimple_location(stmt));
++	else
++		xloc = expand_location(DECL_SOURCE_LOCATION(current_function_decl));
 +
-+	if (orig_argnum == CANNOT_FIND_ARG)
-+		return NULL;
++	loc_line = build_int_cstu(unsigned_type_node, xloc.line);
 +
-+	decl_name = get_orig_decl_name(orig_decl);
-+	hash = get_decl_hash(orig_decl, decl_name);
-+	if (hash == NO_HASH)
-+		return NULL;
++	loc_file = build_string(strlen(xloc.file) + 1, xloc.file);
++	loc_file = create_string_param(loc_file);
 +
-+	context = get_decl_context(orig_decl);
-+	if (!context)
-+		return NULL;
++	current_func = build_string(DECL_NAME_LENGTH(current_function_decl) + 1, DECL_NAME_POINTER(current_function_decl));
++	current_func = create_string_param(current_func);
 +
-+	if (hash_table == SIZE_OVERFLOW)
-+		return get_size_overflow_hash_entry(hash, decl_name, context, orig_argnum);
-+	return get_disable_size_overflow_hash_entry(hash, decl_name, context, orig_argnum);
++	gcc_assert(DECL_NAME(SSA_NAME_VAR(arg)) != NULL);
++	call_count++;
++	len = asprintf(&ssa_name_buf, "%s_%u %s, count: %u, decl: %s; num: %u; context: %s;\n", DECL_NAME_POINTER(SSA_NAME_VAR(arg)), SSA_NAME_VERSION(arg), min ? "min" : "max", call_count, expand_from->next_node->decl_name, expand_from->next_node->num, expand_from->next_node->context);
++	gcc_assert(len > 0);
++	ssa_name = build_string(len + 1, ssa_name_buf);
++	free(ssa_name_buf);
++	ssa_name = create_string_param(ssa_name);
++
++	// void report_size_overflow(const char *file, unsigned int line, const char *func, const char *ssa_name)
++	func_stmt = as_a_gcall(gimple_build_call(report_size_overflow_decl, 4, loc_file, loc_line, current_func, ssa_name));
++	gsi_insert_after(&gsi, func_stmt, GSI_CONTINUE_LINKING);
++
++	report_node = cgraph_get_create_node(report_size_overflow_decl);
++	gcc_assert(report_node);
++	frequency = compute_call_stmt_bb_frequency(current_function_decl, bb_true);
++
++	edge = cgraph_create_edge(get_cnode(current_function_decl), report_node, func_stmt, bb_true->count, frequency, bb_true->loop_depth);
++	gcc_assert(edge != NULL);
 +}
 +
-+unsigned int find_arg_number_tree(const_tree arg, const_tree func)
++static void insert_check_size_overflow(interesting_stmts_t expand_from, gimple stmt, enum tree_code cond_code, tree arg, tree type_value, bool before, bool min)
 +{
-+	tree var;
-+	unsigned int argnum = 1;
++	basic_block cond_bb, join_bb, bb_true;
++	edge e;
++	gimple_stmt_iterator gsi = gsi_for_stmt(stmt);
 +
-+	if (DECL_ARGUMENTS(func) == NULL_TREE)
-+		return CANNOT_FIND_ARG;
++	cond_bb = gimple_bb(stmt);
++	if (before)
++		gsi_prev(&gsi);
++	if (gsi_end_p(gsi))
++		e = split_block_after_labels(cond_bb);
++	else
++		e = split_block(cond_bb, gsi_stmt(gsi));
++	cond_bb = e->src;
++	join_bb = e->dest;
++	e->flags = EDGE_FALSE_VALUE;
++	e->probability = REG_BR_PROB_BASE;
 +
-+	if (TREE_CODE(arg) == SSA_NAME)
-+		arg = SSA_NAME_VAR(arg);
++	bb_true = create_empty_bb(cond_bb);
++	make_edge(cond_bb, bb_true, EDGE_TRUE_VALUE);
++	make_edge(cond_bb, join_bb, EDGE_FALSE_VALUE);
++	make_edge(bb_true, join_bb, EDGE_FALLTHRU);
 +
-+	for (var = DECL_ARGUMENTS(func); var; var = TREE_CHAIN(var), argnum++) {
-+		if (!operand_equal_p(arg, var, 0) && strcmp(DECL_NAME_POINTER(var), DECL_NAME_POINTER(arg)))
-+			continue;
-+		if (!skip_types(var))
-+			return argnum;
++	gcc_assert(dom_info_available_p(CDI_DOMINATORS));
++	set_immediate_dominator(CDI_DOMINATORS, bb_true, cond_bb);
++	set_immediate_dominator(CDI_DOMINATORS, join_bb, cond_bb);
++
++	if (current_loops != NULL) {
++		gcc_assert(cond_bb->loop_father == join_bb->loop_father);
++		add_bb_to_loop(bb_true, cond_bb->loop_father);
 +	}
 +
-+	return CANNOT_FIND_ARG;
-+}
++	insert_cond(cond_bb, arg, cond_code, type_value);
++	insert_cond_result(expand_from, bb_true, stmt, arg, min);
 +
-+const_tree get_attribute(const char* attr_name, const_tree decl)
-+{
-+	const_tree attr = lookup_attribute(attr_name, DECL_ATTRIBUTES(decl));
-+	if (attr && TREE_VALUE(attr))
-+		return attr;
-+	return NULL_TREE;
++//	print_the_code_insertions(stmt);
 +}
 +
-+/* Check if the function has a size_overflow attribute or it is in the size_overflow hash table.
-+ * If the function is missing everywhere then print the missing message into stderr.
-+ */
-+void print_missing_function(next_interesting_function_t node)
++void check_size_overflow(interesting_stmts_t expand_from, gimple stmt, tree size_overflow_type, tree cast_rhs, tree rhs, bool before)
 +{
-+	unsigned int argnum, hash;
-+	const struct size_overflow_hash *entry;
-+	const char *decl_name;
++	const_tree rhs_type = TREE_TYPE(rhs);
++	tree cast_rhs_type, type_max_type, type_min_type, type_max, type_min;
 +
-+	if (node->marked == ASM_STMT_SO_MARK)
++	if (pointer_set_contains(expand_from->visited->no_cast_check, stmt))
 +		return;
 +
-+	if (node->orig_next_node) {
-+		hash = node->orig_next_node->hash;
-+		decl_name = node->orig_next_node->decl_name;
-+		argnum = node->orig_next_node->num;
-+		gcc_assert(!strcmp(node->context, node->orig_next_node->context));
-+	} else {
-+		hash = node->hash;
-+		decl_name = node->decl_name;
-+		argnum = node->num;
-+	}
++	gcc_assert(rhs_type != NULL_TREE);
++	if (TREE_CODE(rhs_type) == POINTER_TYPE)
++		return;
 +
-+	entry = get_size_overflow_hash_entry(hash, decl_name, node->context, argnum);
-+	if (entry)
++	gcc_assert(TREE_CODE(rhs_type) == INTEGER_TYPE || TREE_CODE(rhs_type) == ENUMERAL_TYPE);
++
++	if (is_gimple_assign(stmt) && neg_short_add_intentional_overflow(as_a_gassign(stmt)))
 +		return;
 +
-+	// inform() would be too slow
-+	fprintf(stderr, "Function %s is missing from the size_overflow hash table +%s+%s+%u+%u+\n", decl_name, decl_name, node->context, argnum, hash);
-+}
++	type_max = cast_a_tree(size_overflow_type, TYPE_MAX_VALUE(rhs_type));
++	// typemax (-1) < typemin (0)
++	if (TREE_OVERFLOW(type_max))
++		return;
 +
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_transform.c b/tools/gcc/size_overflow_plugin/size_overflow_transform.c
-new file mode 100644
-index 0000000..eebcf4c
---- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_transform.c
-@@ -0,0 +1,743 @@
-+/*
-+ * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
-+ * Licensed under the GPL v2, or (at your option) v3
-+ *
-+ * Homepage:
-+ * https://github.com/ephox-gcc-plugins/size_overflow
-+ *
-+ * Documentation:
-+ * http://forums.grsecurity.net/viewtopic.php?f=7&t=3043
-+ *
-+ * This plugin recomputes expressions of function arguments marked by a size_overflow attribute
-+ * with double integer precision (DImode/TImode for 32/64 bit integer types).
-+ * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
-+ *
-+ * Usage:
-+ * $ make
-+ * $ make run
-+ */
++	type_min = cast_a_tree(size_overflow_type, TYPE_MIN_VALUE(rhs_type));
 +
-+#include "size_overflow.h"
++	cast_rhs_type = TREE_TYPE(cast_rhs);
++	type_max_type = TREE_TYPE(type_max);
++	gcc_assert(types_compatible_p(cast_rhs_type, type_max_type));
 +
-+static tree cast_to_orig_type(struct visited *visited, gimple stmt, const_tree orig_node, tree new_node)
++	insert_check_size_overflow(expand_from, stmt, GT_EXPR, cast_rhs, type_max, before, MAX_CHECK);
++
++	// special case: get_size_overflow_type(), 32, u64->s
++	if (LONG_TYPE_SIZE == GET_MODE_BITSIZE(SImode) && TYPE_UNSIGNED(size_overflow_type) && !TYPE_UNSIGNED(rhs_type))
++		return;
++
++	type_min_type = TREE_TYPE(type_min);
++	gcc_assert(types_compatible_p(type_max_type, type_min_type));
++	insert_check_size_overflow(expand_from, stmt, LT_EXPR, cast_rhs, type_min, before, MIN_CHECK);
++}
++
++static tree get_my_stmt_lhs(struct visited *visited, gimple stmt)
 +{
-+	gimple def_stmt;
-+	const_gimple assign;
-+	tree result, orig_type = TREE_TYPE(orig_node);
 +	gimple_stmt_iterator gsi;
++	gimple next_stmt = NULL;
 +
-+	if (gimple_code(stmt) != GIMPLE_PHI) {
-+		gsi = gsi_for_stmt(stmt);
-+		assign = build_cast_stmt(visited, orig_type, new_node, CREATE_NEW_VAR, &gsi, BEFORE_STMT, false);
-+		return get_lhs(assign);
-+	}
++	gsi = gsi_for_stmt(stmt);
 +
-+	def_stmt = get_def_stmt(new_node);
-+	if (gimple_code(def_stmt) == GIMPLE_PHI)
-+		gsi = gsi_after_labels(gimple_bb(def_stmt));
-+	else
-+		gsi = gsi_for_stmt(def_stmt);
++	do {
++		gsi_next(&gsi);
++		next_stmt = gsi_stmt(gsi);
 +
-+	result = gimple_phi_result(stmt);
-+	assign = build_cast_stmt(visited, orig_type, new_node, SSA_NAME_VAR(result), &gsi, AFTER_STMT, false);
-+	return get_lhs(assign);
-+}
++		if (gimple_code(stmt) == GIMPLE_PHI && !pointer_set_contains(visited->my_stmts, next_stmt))
++			return NULL_TREE;
 +
-+static void change_size_overflow_asm_input(gasm *stmt, tree new_input)
-+{
-+	tree list;
++		if (pointer_set_contains(visited->my_stmts, next_stmt) && !pointer_set_contains(visited->skip_expr_casts, next_stmt))
++			break;
 +
-+	gcc_assert(is_size_overflow_insert_check_asm(stmt));
++		gcc_assert(pointer_set_contains(visited->my_stmts, next_stmt));
++	} while (!gsi_end_p(gsi));
 +
-+	list = build_tree_list(NULL_TREE, build_string(3, "rm"));
-+	list = chainon(NULL_TREE, build_tree_list(list, new_input));
-+	gimple_asm_set_input_op(stmt, 0, list);
++	gcc_assert(next_stmt);
++	return get_lhs(next_stmt);
 +}
 +
-+static void change_field_write_rhs(gassign *assign, const_tree orig_rhs, tree new_rhs)
++/* When the result of the negation is cast to a signed type then move
++ * the size_overflow cast check before negation.
++ * ssa:
++ * unsigned _588
++ * _588 = _587 >> 12;
++ * _589 = -_588;
++ * _590 = (long int) _589;
++ */
++static bool handle_unsigned_neg_or_bit_not(interesting_stmts_t expand_from, const gassign *stmt)
 +{
-+	const_tree rhs1, rhs2, rhs3 = NULL_TREE;
++	gimple def_neg_stmt, neg_stmt;
++	tree lhs, new_neg_rhs;
++	const_tree rhs, neg_rhs;
++	enum tree_code rhs_code;
 +
-+	rhs1 = gimple_assign_rhs1(assign);
-+	if (rhs1 == orig_rhs) {
-+		gimple_assign_set_rhs1(assign, new_rhs);
-+		return;
-+	}
++	rhs = gimple_assign_rhs1(stmt);
++	lhs = gimple_assign_lhs(stmt);
++	if (TYPE_UNSIGNED(TREE_TYPE(lhs)) || !TYPE_UNSIGNED(TREE_TYPE(rhs)))
++		return false;
 +
-+	rhs2 = gimple_assign_rhs2(assign);
-+	if (rhs2 == orig_rhs) {
-+		gimple_assign_set_rhs2(assign, new_rhs);
-+		return;
-+	}
++	neg_stmt = get_def_stmt(rhs);
++	if (!neg_stmt || !is_gimple_assign(neg_stmt))
++		return false;
 +
-+#if BUILDING_GCC_VERSION >= 4006
-+	rhs3 = gimple_assign_rhs3(assign);
-+	if (rhs3 == orig_rhs) {
-+		gimple_assign_set_rhs3(assign, new_rhs);
-+		return;
-+	}
-+#endif
++	rhs_code = gimple_assign_rhs_code(neg_stmt);
++	if (rhs_code != BIT_NOT_EXPR && rhs_code != NEGATE_EXPR)
++		return false;
 +
-+	debug_gimple_stmt(assign);
-+	fprintf(stderr, "orig_rhs:\n");
-+	debug_tree(orig_rhs);
-+	fprintf(stderr, "rhs1:\n");
-+	debug_tree(rhs1);
-+	fprintf(stderr, "rhs2:\n");
-+	debug_tree(rhs2);
-+	fprintf(stderr, "rhs3:\n");
-+	debug_tree(rhs3);
-+	gcc_unreachable();
++	neg_rhs = gimple_assign_rhs1(neg_stmt);
++	def_neg_stmt = get_def_stmt(neg_rhs);
++	if (!def_neg_stmt)
++		return false;
++
++	new_neg_rhs = get_my_stmt_lhs(expand_from->visited, def_neg_stmt);
++	check_size_overflow(expand_from, neg_stmt, TREE_TYPE(new_neg_rhs), new_neg_rhs, lhs, BEFORE_STMT);
++	pointer_set_insert(expand_from->visited->no_cast_check, stmt);
++	return true;
 +}
 +
-+static void change_phi_arg(gphi *phi, tree new_node, unsigned int num)
++static tree create_cast_overflow_check(interesting_stmts_t expand_from, tree new_rhs1, gassign *stmt)
 +{
-+	unsigned int i;
-+	location_t loc = gimple_location(phi);
++	bool cast_lhs, cast_rhs;
++	tree lhs = gimple_assign_lhs(stmt);
++	tree rhs = gimple_assign_rhs1(stmt);
++	const_tree lhs_type = TREE_TYPE(lhs);
++	const_tree rhs_type = TREE_TYPE(rhs);
++	enum machine_mode lhs_mode = TYPE_MODE(lhs_type);
++	enum machine_mode rhs_mode = TYPE_MODE(rhs_type);
++	unsigned int lhs_size = GET_MODE_BITSIZE(lhs_mode);
++	unsigned int rhs_size = GET_MODE_BITSIZE(rhs_mode);
 +
-+	for (i = 0; i < gimple_phi_num_args(phi); i++) {
-+		if (i == num)
-+			add_phi_arg(phi, new_node, gimple_phi_arg_edge(phi, i), loc);
++	static bool check_lhs[3][4] = {
++		// ss    su     us     uu
++		{ false, true,  true,  false }, // lhs > rhs
++		{ false, false, false, false }, // lhs = rhs
++		{ true,  true,  true,  true  }, // lhs < rhs
++	};
++
++	static bool check_rhs[3][4] = {
++		// ss    su     us     uu
++		{ true,  false, true,  true  }, // lhs > rhs
++		{ true,  false, true,  true  }, // lhs = rhs
++		{ true,  false, true,  true  }, // lhs < rhs
++	};
++
++	if (handle_unsigned_neg_or_bit_not(expand_from, stmt))
++		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
++
++	// skip lhs check on HI -> QI cast
++	if (rhs_mode == HImode && lhs_mode == QImode) {
++		pointer_set_insert(expand_from->visited->no_cast_check, stmt);
++		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
 +	}
-+}
 +
-+static void change_orig_node(struct visited *visited, gimple stmt, const_tree orig_node, tree new_node, unsigned int num)
-+{
-+	tree cast_lhs = cast_to_orig_type(visited, stmt, orig_node, new_node);
++	// skip lhs check on signed SI -> HI cast or signed SI -> QI cast
++	if (rhs_mode == SImode && !TYPE_UNSIGNED(rhs_type) && (lhs_mode == HImode || lhs_mode == QImode))
++		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
 +
-+	switch (gimple_code(stmt)) {
-+	case GIMPLE_RETURN:
-+		gimple_return_set_retval(as_a_greturn(stmt), cast_lhs);
-+		break;
-+	case GIMPLE_CALL:
-+		gimple_call_set_arg(as_a_gcall(stmt), num - 1, cast_lhs);
-+		break;
-+	case GIMPLE_ASM:
-+		change_size_overflow_asm_input(as_a_gasm(stmt), cast_lhs);
-+		break;
-+	case GIMPLE_ASSIGN:
-+		change_field_write_rhs(as_a_gassign(stmt), orig_node, cast_lhs);
-+		break;
-+	case GIMPLE_PHI:
-+		change_phi_arg(as_a_gphi(stmt), cast_lhs, num);
-+		break;
-+	default:
-+		debug_gimple_stmt(stmt);
-+		gcc_unreachable();
++	if (lhs_size > rhs_size) {
++		cast_lhs = check_lhs[0][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
++		cast_rhs = check_rhs[0][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
++	} else if (lhs_size == rhs_size) {
++		cast_lhs = check_lhs[1][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
++		cast_rhs = check_rhs[1][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
++	} else {
++		cast_lhs = check_lhs[2][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
++		cast_rhs = check_rhs[2][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
 +	}
 +
-+	update_stmt(stmt);
-+}
++	if (!cast_lhs && !cast_rhs)
++		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
 +
-+// e.g., 3.8.2, 64, arch/x86/ia32/ia32_signal.c copy_siginfo_from_user32(): compat_ptr() u32 max
-+static bool skip_asm_cast(const_tree arg)
-+{
-+	gimple def_stmt = get_def_stmt(arg);
++	if (cast_lhs && !skip_lhs_cast_check(expand_from->visited, stmt))
++		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs1), new_rhs1, lhs, BEFORE_STMT);
 +
-+	if (!def_stmt || !gimple_assign_cast_p(def_stmt))
-+		return false;
++	if (cast_rhs)
++		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs1), new_rhs1, rhs, BEFORE_STMT);
 +
-+	def_stmt = get_def_stmt(gimple_assign_rhs1(def_stmt));
-+	if (is_size_overflow_asm(def_stmt))
-+		return false;
-+	return def_stmt && gimple_code(def_stmt) == GIMPLE_ASM;
++	return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
 +}
 +
-+static interesting_stmts_t create_interesting_stmts(interesting_stmts_t head, next_interesting_function_t next_node, tree orig_node, gimple first_stmt, unsigned int num)
++static tree handle_unary_rhs(interesting_stmts_t expand_from, gassign *stmt)
 +{
-+	interesting_stmts_t new_node;
++	enum tree_code rhs_code;
++	tree rhs1, new_rhs1, lhs = gimple_assign_lhs(stmt);
 +
-+	new_node = (interesting_stmts_t )xmalloc(sizeof(*new_node));
-+	new_node->first_stmt = first_stmt;
-+	new_node->num = num;
-+	new_node->orig_node = orig_node;
-+	new_node->next = head;
-+	new_node->next_node = next_node;
-+	return new_node;
-+}
++	if (pointer_set_contains(expand_from->visited->my_stmts, stmt))
++		return lhs;
 +
-+static void free_interesting_stmts(interesting_stmts_t head)
-+{
-+	while (head) {
-+		interesting_stmts_t cur = head->next;
-+		free(head);
-+		head = cur;
-+	}
-+}
++	rhs1 = gimple_assign_rhs1(stmt);
++	if (TREE_CODE(TREE_TYPE(rhs1)) == POINTER_TYPE)
++		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
 +
-+/* This function calls the main recursion function (expand) that duplicates the stmts. Before that it checks the intentional_overflow attribute,
-+ * it decides whether the duplication is necessary or not. After expand() it changes the orig node to the duplicated node
-+ * in the original stmt (first stmt) and it inserts the overflow check for the arg of the callee or for the return value.
-+ */
-+static interesting_stmts_t search_interesting_stmt(interesting_stmts_t head, next_interesting_function_t next_node, gimple first_stmt, tree orig_node, unsigned int num)
-+{
-+	enum tree_code orig_code;
++	new_rhs1 = expand(expand_from, rhs1);
 +
-+	gcc_assert(orig_node != NULL_TREE);
++	if (new_rhs1 == NULL_TREE)
++		return create_cast_assign(expand_from->visited, stmt);
 +
-+	if (is_gimple_constant(orig_node))
-+		return head;
++	if (pointer_set_contains(expand_from->visited->no_cast_check, stmt))
++		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
 +
-+	orig_code = TREE_CODE(orig_node);
-+	gcc_assert(orig_code != FIELD_DECL && orig_code != FUNCTION_DECL);
++#if BUILDING_GCC_VERSION >= 5000
++	if (short_or_neg_const_ushort(stmt)) {
++		pointer_set_insert(expand_from->visited->no_cast_check, stmt);
++		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
++	}
++#endif
 +
-+	if (skip_types(orig_node))
-+		return head;
++	rhs_code = gimple_assign_rhs_code(stmt);
++	if (rhs_code == BIT_NOT_EXPR || rhs_code == NEGATE_EXPR) {
++		tree size_overflow_type = get_size_overflow_type(expand_from->visited, stmt, rhs1);
 +
-+	// find a defining marked caller argument or struct field for arg
-+	if (check_intentional_size_overflow_asm_and_attribute(orig_node) != MARK_NO)
-+		return head;
++		new_rhs1 = cast_to_new_size_overflow_type(expand_from->visited, stmt, new_rhs1, size_overflow_type, BEFORE_STMT);
++		check_size_overflow(expand_from, stmt, size_overflow_type, new_rhs1, rhs1, BEFORE_STMT);
++		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++	}
 +
-+	if (skip_asm_cast(orig_node))
-+		return head;
++	if (!gimple_assign_cast_p(stmt))
++		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
 +
-+	return create_interesting_stmts(head, next_node, orig_node, first_stmt, num);
++	return create_cast_overflow_check(expand_from, new_rhs1, stmt);
 +}
 +
-+static bool is_signed_error_code_const(const_tree node)
++static tree handle_unary_ops(interesting_stmts_t expand_from, gassign *stmt)
 +{
-+	HOST_WIDE_INT constant = tree_to_shwi(node);
++	tree rhs1, lhs = gimple_assign_lhs(stmt);
++	gimple def_stmt = get_def_stmt(lhs);
 +
-+	return constant >= -4095 && constant <= -1;
++	gcc_assert(gimple_code(def_stmt) != GIMPLE_NOP);
++	rhs1 = gimple_assign_rhs1(def_stmt);
++
++	if (is_gimple_constant(rhs1))
++		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
++
++	switch (TREE_CODE(rhs1)) {
++	case SSA_NAME: {
++		tree ret = handle_unary_rhs(expand_from, as_a_gassign(def_stmt));
++
++		if (gimple_assign_cast_p(stmt))
++			unsigned_signed_cast_intentional_overflow(expand_from->visited, stmt);
++		return ret;
++	}
++	case ARRAY_REF:
++	case BIT_FIELD_REF:
++	case ADDR_EXPR:
++	case COMPONENT_REF:
++	case INDIRECT_REF:
++#if BUILDING_GCC_VERSION >= 4006
++	case MEM_REF:
++#endif
++	case TARGET_MEM_REF:
++	case VIEW_CONVERT_EXPR:
++		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
++	case PARM_DECL:
++	case VAR_DECL:
++		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++
++	default:
++		debug_gimple_stmt(def_stmt);
++		debug_tree(rhs1);
++		gcc_unreachable();
++	}
 +}
 +
-+static bool is_unsigned_error_code_const(const_tree node)
++static void __unused print_the_code_insertions(const_gimple stmt)
 +{
-+	unsigned HOST_WIDE_INT constant = tree_to_uhwi(node);
++	location_t loc = gimple_location(stmt);
 +
-+	// ulong -4095
-+	if (constant >= 0xfffffffffffff001)
-+		return true;
-+	// uint -4095
-+	return constant >= 0xfffff001;
++	inform(loc, "Integer size_overflow check applied here.");
 +}
 +
-+static bool is_error_code_const(const_tree node)
++static bool is_from_cast(const_tree node)
 +{
-+	enum machine_mode mode;
++	gimple def_stmt = get_def_stmt(node);
 +
-+	if (!is_gimple_constant(node))
-+		return false;
-+	mode = TYPE_MODE(TREE_TYPE(node));
-+	if (mode != SImode && mode != DImode)
++	if (!def_stmt)
 +		return false;
 +
-+	if (!TYPE_UNSIGNED(TREE_TYPE(node)) && is_signed_error_code_const(node))
++	if (gimple_assign_cast_p(def_stmt))
 +		return true;
-+	return TYPE_UNSIGNED(TREE_TYPE(node)) && is_unsigned_error_code_const(node);
++
++	return false;
 +}
 +
-+static bool has_error_code(gphi *phi)
++// Skip duplication when there is a minus expr and the type of rhs1 or rhs2 is a pointer_type.
++static bool is_ptr_diff(gassign *stmt)
 +{
-+	unsigned int i, len = gimple_phi_num_args(phi);
-+
-+	for (i = 0; i < len; i++) {
-+		const_tree arg = gimple_phi_arg_def(phi, i);
++	const_tree rhs1, rhs2, ptr1_rhs, ptr2_rhs;
 +
-+		if (is_error_code_const(arg))
-+			return true;
-+	}
++	if (gimple_assign_rhs_code(stmt) != MINUS_EXPR)
++		return false;
 +
-+	return false;
-+}
++	rhs1 = gimple_assign_rhs1(stmt);
++	if (!is_from_cast(rhs1))
++		return false;
 +
-+static interesting_stmts_t search_interesting_rets(interesting_stmts_t head, next_interesting_function_t next_node_ret, greturn *ret)
-+{
-+	tree first_node;
++	rhs2 = gimple_assign_rhs2(stmt);
++	if (!is_from_cast(rhs2))
++		return false;
 +
-+	if (!next_node_ret || next_node_ret->marked == ASM_STMT_SO_MARK)
-+		return head;
++	ptr1_rhs = gimple_assign_rhs1(get_def_stmt(rhs1));
++	ptr2_rhs = gimple_assign_rhs1(get_def_stmt(rhs2));
 +
-+	first_node = gimple_return_retval(ret);
-+	if (first_node == NULL_TREE)
-+		return head;
++	if (TREE_CODE(TREE_TYPE(ptr1_rhs)) != POINTER_TYPE && TREE_CODE(TREE_TYPE(ptr2_rhs)) != POINTER_TYPE)
++		return false;
 +
-+	return search_interesting_stmt(head, next_node_ret, ret, first_node, 0);
++	return true;
 +}
 +
-+static void handle_binary_assign(interesting_stmts_t expand_from, gassign *assign, tree rhs)
++static tree handle_comparison_code_class(interesting_stmts_t expand_from, gassign *stmt, tree new_rhs1, tree new_rhs2)
 +{
-+	tree new_node;
-+	gimple def_orig_node;
++	tree rhs1, rhs2, lhs;
 +
-+	new_node = expand(expand_from, rhs);
-+	if (new_node == NULL_TREE)
-+		return;
++	rhs1 = gimple_assign_rhs1(stmt);
++	if (!is_gimple_constant(rhs1) && new_rhs1 != NULL_TREE)
++		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs1), new_rhs1, rhs1, BEFORE_STMT);
 +
-+	def_orig_node = get_def_stmt(rhs);
-+	if (pointer_set_contains(expand_from->visited->no_cast_check, def_orig_node))
-+		return;
-+	change_orig_node(expand_from->visited, assign, rhs, new_node, 0);
-+	check_size_overflow(expand_from, assign, TREE_TYPE(new_node), new_node, rhs, BEFORE_STMT);
++	lhs = gimple_assign_lhs(stmt);
++	if (new_rhs2 == NULL_TREE)
++		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++
++	rhs2 = gimple_assign_rhs2(stmt);
++	if (!is_gimple_constant(rhs2))
++		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs2), new_rhs2, rhs2, BEFORE_STMT);
++	return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
 +}
 +
-+static bool search_error_codes(gimple_set *visited_error_codes, interesting_stmts_t expand_from, tree lhs, bool error_code)
++static tree handle_binary_ops(interesting_stmts_t expand_from, tree lhs)
 +{
-+	gimple def_stmt;
++	enum intentional_overflow_type res;
++	tree rhs1, rhs2, new_lhs;
++	gassign *def_stmt = as_a_gassign(get_def_stmt(lhs));
++	tree new_rhs1 = NULL_TREE;
++	tree new_rhs2 = NULL_TREE;
 +
-+	def_stmt = get_def_stmt(lhs);
-+	if (!def_stmt || gimple_code(def_stmt) == GIMPLE_NOP)
-+		return error_code;
++	if (is_ptr_diff(def_stmt))
++		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
 +
-+	if (pointer_set_insert(visited_error_codes, def_stmt))
-+		return error_code;
++	rhs1 = gimple_assign_rhs1(def_stmt);
++	rhs2 = gimple_assign_rhs2(def_stmt);
 +
-+	if (is_gimple_constant(lhs))
-+		return error_code;
-+	if (skip_types(lhs))
-+		return is_error_code_const(lhs);
++	/* no DImode/TImode division in the 32/64 bit kernel */
++	switch (gimple_assign_rhs_code(def_stmt)) {
++	case RDIV_EXPR:
++	case TRUNC_DIV_EXPR:
++	case CEIL_DIV_EXPR:
++	case FLOOR_DIV_EXPR:
++	case ROUND_DIV_EXPR:
++	case TRUNC_MOD_EXPR:
++	case CEIL_MOD_EXPR:
++	case FLOOR_MOD_EXPR:
++	case ROUND_MOD_EXPR:
++	case EXACT_DIV_EXPR:
++	case POINTER_PLUS_EXPR:
++	case BIT_AND_EXPR:
++		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
++	default:
++		break;
++	}
 +
-+	switch (gimple_code(def_stmt)) {
-+	case GIMPLE_CALL:
-+	case GIMPLE_ASM:
-+		return error_code;
-+	case GIMPLE_ASSIGN: {
-+		tree rhs1, rhs2;
-+		gassign *assign = as_a_gassign(def_stmt);
++	new_lhs = handle_integer_truncation(expand_from, lhs);
++	if (new_lhs != NULL_TREE)
++		return new_lhs;
 +
-+		switch (gimple_num_ops(assign)) {
-+		case 2:
-+			return search_error_codes(visited_error_codes, expand_from, gimple_assign_rhs1(def_stmt), error_code);
-+		case 3:
-+			if (!error_code)
-+				return error_code;
++	if (TREE_CODE(rhs1) == SSA_NAME)
++		new_rhs1 = expand(expand_from, rhs1);
++	if (TREE_CODE(rhs2) == SSA_NAME)
++		new_rhs2 = expand(expand_from, rhs2);
 +
-+			/* Run stmt duplication from the binary assignment ops (rhs1 and rhs2)
-+			 * so that size_overflow checking skips the lhs of the last binary assignment
-+			 * before the error code PHI.
-+			 */
-+			rhs1 = gimple_assign_rhs1(assign);
-+			handle_binary_assign(expand_from, assign, rhs1);
-+			rhs2 = gimple_assign_rhs2(assign);
-+			handle_binary_assign(expand_from, assign, rhs2);
-+			return error_code;
-+		}
-+		gcc_unreachable();
++	res = add_mul_intentional_overflow(def_stmt);
++	if (res != NO_INTENTIONAL_OVERFLOW) {
++		new_lhs = dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, NULL_TREE);
++		insert_cast_expr(expand_from->visited, as_a_gassign(get_def_stmt(new_lhs)), res);
++		return new_lhs;
 +	}
-+	case GIMPLE_PHI: {
-+		unsigned int i;
 +
-+		error_code = has_error_code(as_a_gphi(def_stmt));
-+		for (i = 0; i < gimple_phi_num_args(def_stmt); i++) {
-+			error_code = search_error_codes(visited_error_codes, expand_from, gimple_phi_arg_def(def_stmt, i), error_code);
-+		}
-+		return error_code;
-+	}
-+	default:
-+		debug_gimple_stmt(def_stmt);
-+		error("%s: unknown gimple code", __func__);
-+		gcc_unreachable();
++	if (skip_expr_on_double_type(def_stmt)) {
++		new_lhs = dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, NULL_TREE);
++		insert_cast_expr(expand_from->visited, as_a_gassign(get_def_stmt(new_lhs)), NO_INTENTIONAL_OVERFLOW);
++		return new_lhs;
 +	}
-+}
 +
-+static bool handle_error_codes(interesting_stmts_t expand_from)
-+{
-+	bool error_code;
-+	gimple_set *visited_error_codes;
++	if (is_a_neg_overflow(def_stmt, rhs2))
++		return handle_intentional_overflow(expand_from, true, def_stmt, new_rhs1, NULL_TREE);
++	if (is_a_neg_overflow(def_stmt, rhs1))
++		return handle_intentional_overflow(expand_from, true, def_stmt, new_rhs2, new_rhs2);
 +
-+	// expand the data flow from a return stmt
-+	if (expand_from->next_node->num != 0 || strcmp(expand_from->next_node->context, "fndecl"))
-+		return false;
 +
-+	visited_error_codes = pointer_set_create();
-+	error_code = search_error_codes(visited_error_codes, expand_from, expand_from->orig_node, false);
-+	pointer_set_destroy(visited_error_codes);
++	if (is_a_constant_overflow(def_stmt, rhs2))
++		return handle_intentional_overflow(expand_from, !is_a_cast_and_const_overflow(rhs1), def_stmt, new_rhs1, NULL_TREE);
++	if (is_a_constant_overflow(def_stmt, rhs1))
++		return handle_intentional_overflow(expand_from, !is_a_cast_and_const_overflow(rhs2), def_stmt, new_rhs2, new_rhs2);
 +
-+	return error_code;
++	// the const is between 0 and (signed) MAX
++	if (is_gimple_constant(rhs1))
++		new_rhs1 = create_assign(expand_from->visited, def_stmt, rhs1, BEFORE_STMT);
++	if (is_gimple_constant(rhs2))
++		new_rhs2 = create_assign(expand_from->visited, def_stmt, rhs2, BEFORE_STMT);
++
++	if (TREE_CODE_CLASS(gimple_assign_rhs_code(def_stmt)) == tcc_comparison)
++		return handle_comparison_code_class(expand_from, def_stmt, new_rhs1, new_rhs2);
++
++	if (uconst_neg_intentional_overflow(def_stmt)) {
++		inform(gimple_location(def_stmt), "%s: gcc intentional overflow", __func__);
++		gcc_unreachable();
++	}
++
++	return dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, NULL_TREE);
 +}
 +
-+static void handle_interesting_stmt(struct visited *visited, interesting_stmts_t head)
++#if BUILDING_GCC_VERSION >= 4006
++static tree get_new_rhs(interesting_stmts_t expand_from, tree size_overflow_type, tree rhs)
 +{
-+	interesting_stmts_t cur;
++	if (is_gimple_constant(rhs))
++		return cast_a_tree(size_overflow_type, rhs);
++	if (TREE_CODE(rhs) != SSA_NAME)
++		return NULL_TREE;
++	return expand(expand_from, rhs);
++}
 +
-+	for (cur = head; cur; cur = cur->next) {
-+		tree new_node;
-+		gimple orig_def_stmt;
++static tree handle_ternary_ops(interesting_stmts_t expand_from, tree lhs)
++{
++	tree rhs1, rhs2, rhs3, new_rhs1, new_rhs2, new_rhs3, size_overflow_type;
++	gassign *def_stmt = as_a_gassign(get_def_stmt(lhs));
 +
-+		cur->visited = visited;
-+		if (handle_error_codes(cur))
-+			continue;
++	size_overflow_type = get_size_overflow_type(expand_from->visited, def_stmt, lhs);
 +
-+		new_node = expand(cur, cur->orig_node);
-+		if (new_node == NULL_TREE)
-+			continue;
++	rhs1 = gimple_assign_rhs1(def_stmt);
++	rhs2 = gimple_assign_rhs2(def_stmt);
++	rhs3 = gimple_assign_rhs3(def_stmt);
++	new_rhs1 = get_new_rhs(expand_from, size_overflow_type, rhs1);
++	new_rhs2 = get_new_rhs(expand_from, size_overflow_type, rhs2);
++	new_rhs3 = get_new_rhs(expand_from, size_overflow_type, rhs3);
 +
-+		orig_def_stmt = get_def_stmt(cur->orig_node);
-+		if (pointer_set_contains(visited->no_cast_check, orig_def_stmt))
-+			continue;
-+		change_orig_node(visited, cur->first_stmt, cur->orig_node, new_node, cur->num);
-+		check_size_overflow(cur, cur->first_stmt, TREE_TYPE(new_node), new_node, cur->orig_node, BEFORE_STMT);
-+	}
++	return dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, new_rhs3);
 +}
++#endif
 +
-+static next_interesting_function_t get_interesting_function_next_node(tree decl, unsigned int num)
++static tree expand_visited(struct visited *visited, gimple def_stmt)
 +{
-+	next_interesting_function_t next_node;
-+	const struct size_overflow_hash *so_hash;
-+	struct fn_raw_data raw_data;
++	gimple_stmt_iterator gsi;
++	enum gimple_code code = gimple_code(def_stmt);
 +
-+	raw_data.decl = decl;
-+	raw_data.decl_str = DECL_NAME_POINTER(decl);
-+	raw_data.num = num;
-+	raw_data.marked = YES_SO_MARK;
++	if (code == GIMPLE_ASM)
++		return NULL_TREE;
 +
-+	next_node = get_global_next_interesting_function_entry_with_hash(&raw_data);
-+	if (next_node && next_node->marked != NO_SO_MARK)
-+		return next_node;
++	gsi = gsi_for_stmt(def_stmt);
++	gsi_next(&gsi);
 +
-+	so_hash = get_size_overflow_hash_entry_tree(raw_data.decl, raw_data.num, SIZE_OVERFLOW);
-+	if (so_hash)
-+		return get_and_create_next_node_from_global_next_nodes(&raw_data, NULL);
-+	return NULL;
++	if (gimple_code(def_stmt) == GIMPLE_PHI && gsi_end_p(gsi))
++		return NULL_TREE;
++	return get_my_stmt_lhs(visited, def_stmt);
 +}
 +
-+tree handle_fnptr_assign(const_gimple stmt)
++tree expand(interesting_stmts_t expand_from, tree lhs)
 +{
-+	tree field, rhs, op0;
-+	const_tree op0_type;
-+	enum tree_code rhs_code;
++	gimple def_stmt;
 +
-+	// TODO skip binary assignments for now (fs/sync.c _591 = __bpf_call_base + _590;)
-+	if (gimple_num_ops(stmt) != 2)
-+		return NULL_TREE;
++	def_stmt = get_def_stmt(lhs);
 +
-+	gcc_assert(gimple_num_ops(stmt) == 2);
-+	// TODO skip asm_stmt for now
-+	if (gimple_code(stmt) == GIMPLE_ASM)
-+		return NULL_TREE;
-+	rhs = gimple_assign_rhs1(stmt);
-+	if (is_gimple_constant(rhs))
++	if (!def_stmt || gimple_code(def_stmt) == GIMPLE_NOP)
 +		return NULL_TREE;
 +
-+	rhs_code = TREE_CODE(rhs);
-+	if (rhs_code == VAR_DECL)
-+		return rhs;
++	if (pointer_set_contains(expand_from->visited->my_stmts, def_stmt))
++		return lhs;
 +
-+	switch (rhs_code) {
-+	case ADDR_EXPR:
-+		op0 = TREE_OPERAND(rhs, 0);
-+		gcc_assert(TREE_CODE(op0) == FUNCTION_DECL);
-+		return op0;
-+	case COMPONENT_REF:
-+		break;
-+	// TODO skip array_ref for now
-+	case ARRAY_REF:
-+		return NULL_TREE;
-+	// TODO skip ssa_name because it can lead to parm_decl
-+	case SSA_NAME:
++	if (pointer_set_contains(expand_from->visited->stmts, def_stmt))
++		return expand_visited(expand_from->visited, def_stmt);
++
++	if (is_gimple_constant(lhs))
 +		return NULL_TREE;
-+	// TODO skip mem_ref and indirect_ref for now
-+#if BUILDING_GCC_VERSION >= 4006
-+	case MEM_REF:
-+#endif
-+	case INDIRECT_REF:
++	if (skip_types(lhs))
 +		return NULL_TREE;
-+	default:
-+		debug_tree(rhs);
-+		debug_gimple_stmt((gimple)stmt);
-+		gcc_unreachable();
-+	}
 +
-+	op0 = TREE_OPERAND(rhs, 0);
-+	switch (TREE_CODE(op0)) {
-+	// TODO skip array_ref and parm_decl for now
-+	case ARRAY_REF:
-+	case PARM_DECL:
-+		return NULL_TREE;
-+	case COMPONENT_REF:
++	switch (gimple_code(def_stmt)) {
++	case GIMPLE_PHI:
++		return handle_phi(expand_from, lhs);
++	case GIMPLE_CALL:
++	case GIMPLE_ASM:
++		if (is_size_overflow_asm(def_stmt))
++			return expand(expand_from, get_size_overflow_asm_input(as_a_gasm(def_stmt)));
++		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
++	case GIMPLE_ASSIGN:
++		switch (gimple_num_ops(def_stmt)) {
++		case 2:
++			return handle_unary_ops(expand_from, as_a_gassign(def_stmt));
++		case 3:
++			return handle_binary_ops(expand_from, lhs);
 +#if BUILDING_GCC_VERSION >= 4006
-+	case MEM_REF:
++		case 4:
++			return handle_ternary_ops(expand_from, lhs);
 +#endif
-+	case INDIRECT_REF:
-+	case VAR_DECL:
-+		break;
++		}
 +	default:
-+		debug_tree(op0);
++		debug_gimple_stmt(def_stmt);
++		error("%s: unknown gimple code", __func__);
 +		gcc_unreachable();
 +	}
-+
-+	op0_type = TREE_TYPE(op0);
-+	// TODO skip unions for now
-+	if (TREE_CODE(op0_type) == UNION_TYPE)
-+		return NULL_TREE;
-+	gcc_assert(TREE_CODE(op0_type) == RECORD_TYPE);
-+
-+	field = TREE_OPERAND(rhs, 1);
-+	gcc_assert(TREE_CODE(field) == FIELD_DECL);
-+	return field;
 +}
+diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
+new file mode 100644
+index 0000000..8b69bd4
+--- /dev/null
++++ b/scripts/gcc-plugins/stackleak_plugin.c
+@@ -0,0 +1,350 @@
++/*
++ * Copyright 2011-2016 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 implement various PaX features
++ *
++ * - track lowest stack pointer
++ *
++ * TODO:
++ * - initialize all local variables
++ *
++ * BUGS:
++ * - none known
++ */
 +
-+static tree get_fn_or_fnptr_decl(const gcall *call_stmt)
-+{
-+	const_tree fnptr;
-+	const_gimple def_stmt;
-+	tree decl = gimple_call_fndecl(call_stmt);
++#include "gcc-common.h"
 +
-+	if (decl != NULL_TREE)
-+		return decl;
++int plugin_is_GPL_compatible;
 +
-+	fnptr = gimple_call_fn(call_stmt);
-+	if (fnptr == NULL_TREE)
-+		return NULL_TREE;
++static int track_frame_size = -1;
++static const char track_function[] = "pax_track_stack";
++static const char check_function[] = "pax_check_alloca";
++static GTY(()) tree track_function_decl;
++static GTY(()) tree check_function_decl;
++static bool init_locals;
 +
-+	// !!! assertot kell irni 0-ra, mert csak az lehet ott
-+	if (is_gimple_constant(fnptr))
-+		return NULL_TREE;
-+	def_stmt = get_fnptr_def_stmt(fnptr);
-+	return handle_fnptr_assign(def_stmt);
-+}
++static struct plugin_info stackleak_plugin_info = {
++	.version	= "201602181345",
++	.help		= "track-lowest-sp=nn\ttrack sp in functions whose frame size is at least nn bytes\n"
++//			  "initialize-locals\t\tforcibly initialize all stack frames\n"
++};
 +
-+// Start stmt duplication on marked function parameters
-+static interesting_stmts_t search_interesting_calls(interesting_stmts_t head, gcall *call_stmt)
++static void stackleak_check_alloca(gimple_stmt_iterator *gsi)
 +{
-+	tree decl;
-+	unsigned int i, len;
-+
-+	len = gimple_call_num_args(call_stmt);
-+	if (len == 0)
-+		return head;
-+
-+	decl = get_fn_or_fnptr_decl(call_stmt);
-+	if (decl == NULL_TREE)
-+		return head;
-+
-+	for (i = 0; i < len; i++) {
-+		tree arg;
-+		next_interesting_function_t next_node;
++	gimple stmt;
++	gcall *check_alloca;
++	tree alloca_size;
++	cgraph_node_ptr node;
++	int frequency;
++	basic_block bb;
 +
-+		arg = gimple_call_arg(call_stmt, i);
-+		if (is_gimple_constant(arg))
-+			continue;
-+		if (skip_types(arg))
-+			continue;
-+		next_node = get_interesting_function_next_node(decl, i + 1);
-+		if (next_node)
-+			head = search_interesting_stmt(head, next_node, call_stmt, arg, i + 1);
-+	}
++	// insert call to void pax_check_alloca(unsigned long size)
++	alloca_size = gimple_call_arg(gsi_stmt(*gsi), 0);
++	stmt = gimple_build_call(check_function_decl, 1, alloca_size);
++	check_alloca = as_a_gcall(stmt);
++	gsi_insert_before(gsi, check_alloca, GSI_SAME_STMT);
 +
-+	return head;
++	// update the cgraph
++	bb = gimple_bb(check_alloca);
++	node = cgraph_get_create_node(check_function_decl);
++	gcc_assert(node);
++	frequency = compute_call_stmt_bb_frequency(current_function_decl, bb);
++	cgraph_create_edge(cgraph_get_node(current_function_decl), node, check_alloca, bb->count, frequency, bb->loop_depth);
 +}
 +
-+// Find assignements to structure fields and vardecls
-+static interesting_stmts_t search_interesting_structs_vardecls(interesting_stmts_t head, gassign *assign)
++static void stackleak_add_instrumentation(gimple_stmt_iterator *gsi, bool after)
 +{
-+	enum intentional_mark mark;
-+	next_interesting_function_t next_node;
-+	tree rhs1, rhs2, lhs, decl;
-+#if BUILDING_GCC_VERSION >= 4006
-+	tree rhs3;
-+#endif
-+
-+	lhs = gimple_assign_lhs(assign);
-+
-+	if (VAR_P(lhs))
-+		decl = lhs;
-+	else
-+		decl = get_ref_field(lhs);
-+	if (decl == NULL_TREE)
-+		return head;
-+	if (DECL_NAME(decl) == NULL_TREE)
-+		return head;
-+
-+	if (is_bitfield_unnamed_cast(decl, assign))
-+		return head;
-+
-+	next_node = get_interesting_function_next_node(decl, 0);
-+	if (!next_node)
-+		return head;
-+
-+	mark = get_intentional_attr_type(decl);
-+	if (mark != MARK_NO)
-+		return head;
-+
-+	rhs1 = gimple_assign_rhs1(assign);
-+	head = search_interesting_stmt(head, next_node, assign, rhs1, 0);
++	gimple stmt;
++	gcall *track_stack;
++	cgraph_node_ptr node;
++	int frequency;
++	basic_block bb;
 +
-+	rhs2 = gimple_assign_rhs2(assign);
-+	if (rhs2)
-+		head = search_interesting_stmt(head, next_node, assign, rhs2, 0);
++	// insert call to void pax_track_stack(void)
++	stmt = gimple_build_call(track_function_decl, 0);
++	track_stack = as_a_gcall(stmt);
++	if (after)
++		gsi_insert_after(gsi, track_stack, GSI_CONTINUE_LINKING);
++	else
++		gsi_insert_before(gsi, track_stack, GSI_SAME_STMT);
 +
-+#if BUILDING_GCC_VERSION >= 4006
-+	rhs3 = gimple_assign_rhs3(assign);
-+	if (rhs3)
-+		head = search_interesting_stmt(head, next_node, assign, rhs3, 0);
-+#endif
-+	return head;
++	// update the cgraph
++	bb = gimple_bb(track_stack);
++	node = cgraph_get_create_node(track_function_decl);
++	gcc_assert(node);
++	frequency = compute_call_stmt_bb_frequency(current_function_decl, bb);
++	cgraph_create_edge(cgraph_get_node(current_function_decl), node, track_stack, bb->count, frequency, bb->loop_depth);
 +}
 +
-+static next_interesting_function_t create_so_asm_next_interesting_function_node(const gasm *stmt)
++static bool is_alloca(gimple stmt)
 +{
-+	next_interesting_function_t next_node;
-+	struct fn_raw_data raw_data;
-+
-+	raw_data.decl = NULL_TREE;
-+	raw_data.decl_str = gimple_asm_string(stmt);
-+	raw_data.context = "attr";
-+	raw_data.hash = 0;
-+	raw_data.num = 0;
-+	raw_data.marked = ASM_STMT_SO_MARK;
++	if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA))
++		return true;
 +
-+	next_node = get_global_next_interesting_function_entry(&raw_data);
-+	if (next_node)
-+		return next_node;
-+	next_node = create_new_next_interesting_entry(&raw_data, NULL);
-+	gcc_assert(next_node);
++#if BUILDING_GCC_VERSION >= 4007
++	if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
++		return true;
++#endif
 +
-+	add_to_global_next_interesting_function(next_node);
-+	return next_node;
++	return false;
 +}
 +
-+// Collect interesting stmts for duplication
-+static void search_interesting_stmts(struct visited *visited)
++static unsigned int stackleak_tree_instrument_execute(void)
 +{
-+	basic_block bb;
-+	next_interesting_function_t next_node_ret;
-+	interesting_stmts_t head = NULL;
++	basic_block bb, entry_bb;
++	bool prologue_instrumented = false, is_leaf = true;
 +
-+	next_node_ret = get_interesting_function_next_node(current_function_decl, 0);
++	entry_bb = ENTRY_BLOCK_PTR_FOR_FN(cfun)->next_bb;
 +
++	// 1. loop through BBs and GIMPLE statements
 +	FOR_EACH_BB_FN(bb, cfun) {
 +		gimple_stmt_iterator gsi;
 +
 +		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
-+			gimple stmt = gsi_stmt(gsi);
++			gimple stmt;
 +
-+			switch (gimple_code(stmt)) {
-+			case GIMPLE_ASM: {
-+				tree first_node;
-+				next_interesting_function_t next_node;
-+				const gasm *asm_stmt = as_a_gasm(stmt);
++			stmt = gsi_stmt(gsi);
 +
-+				if (!is_size_overflow_insert_check_asm(asm_stmt))
-+					continue;
-+				next_node = create_so_asm_next_interesting_function_node(asm_stmt);
-+				first_node = get_size_overflow_asm_input(asm_stmt);
-+				head = search_interesting_stmt(head, next_node, stmt, first_node, 0);
-+				break;
-+			}
-+			case GIMPLE_RETURN:
-+				head = search_interesting_rets(head, next_node_ret, as_a_greturn(stmt));
-+				break;
-+			case GIMPLE_CALL:
-+				head = search_interesting_calls(head, as_a_gcall(stmt));
-+				break;
-+			case GIMPLE_ASSIGN:
-+				/* !!! TODO LTO modeban nincs duplikalas a globalis valtozora, mert a tree mergek
-+				 * utan mar nem lehet megkulonboztetni attol a globalis valtozotol, aminek a scopeja csak a file
-+				 * igy a context nem vardecl lesz, hanem vardecl_filenev. De execute-ban kiirja, ha hianyzik a hash tablabol
-+				 * IPA-ban van duplikalas.
-+				 */
-+				head = search_interesting_structs_vardecls(head, as_a_gassign(stmt));
-+				break;
-+			default:
-+				break;
-+			}
++			if (is_gimple_call(stmt))
++				is_leaf = false;
++
++			// gimple match: align 8 built-in BUILT_IN_NORMAL:BUILT_IN_ALLOCA attributes <tree_list 0xb7576450>
++			if (!is_alloca(stmt))
++				continue;
++
++			// 2. insert stack overflow check before each __builtin_alloca call
++			stackleak_check_alloca(&gsi);
++
++			// 3. insert track call after each __builtin_alloca call
++			stackleak_add_instrumentation(&gsi, true);
++			if (bb == entry_bb)
++				prologue_instrumented = true;
 +		}
 +	}
 +
-+	handle_interesting_stmt(visited, head);
-+	free_interesting_stmts(head);
-+}
++	// special cases for some bad linux code: taking the address of static inline functions will materialize them
++	// but we mustn't instrument some of them as the resulting stack alignment required by the function call ABI
++	// will break other assumptions regarding the expected (but not otherwise enforced) register clobbering  ABI.
++	// case in point: native_save_fl on amd64 when optimized for size clobbers rdx if it were instrumented here.
++	if (is_leaf && !TREE_PUBLIC(current_function_decl) && DECL_DECLARED_INLINE_P(current_function_decl))
++		return 0;
++	if (is_leaf && !strncmp(IDENTIFIER_POINTER(DECL_NAME(current_function_decl)), "_paravirt_", 10))
++		return 0;
 +
-+static struct visited *create_visited(void)
-+{
-+	struct visited *new_node;
++	// 4. insert track call at the beginning
++	if (!prologue_instrumented) {
++		gimple_stmt_iterator gsi;
 +
-+	new_node = (struct visited *)xmalloc(sizeof(*new_node));
-+	new_node->stmts = pointer_set_create();
-+	new_node->my_stmts = pointer_set_create();
-+	new_node->skip_expr_casts = pointer_set_create();
-+	new_node->no_cast_check = pointer_set_create();
-+	return new_node;
++		gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++		bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
++		if (!single_pred_p(bb)) {
++//			gcc_assert(bb_loop_depth(bb) || (bb->flags & BB_IRREDUCIBLE_LOOP));
++			split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++			gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++			bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
++		}
++		gsi = gsi_after_labels(bb);
++		stackleak_add_instrumentation(&gsi, false);
++	}
++
++	return 0;
 +}
 +
-+static void free_visited(struct visited *visited)
++static unsigned int stackleak_final_execute(void)
 +{
-+	pointer_set_destroy(visited->stmts);
-+	pointer_set_destroy(visited->my_stmts);
-+	pointer_set_destroy(visited->skip_expr_casts);
-+	pointer_set_destroy(visited->no_cast_check);
++	rtx_insn *insn, *next;
 +
-+	free(visited);
-+}
++	if (cfun->calls_alloca)
++		return 0;
 +
-+// Remove the size_overflow asm stmt and create an assignment from the input and output of the asm
-+static void replace_size_overflow_asm_with_assign(gasm *asm_stmt, tree lhs, tree rhs)
-+{
-+	gassign *assign;
-+	gimple_stmt_iterator gsi;
++	// keep calls only if function frame is big enough
++	if (get_frame_size() >= track_frame_size)
++		return 0;
 +
-+	// already removed
-+	if (gimple_bb(asm_stmt) == NULL)
-+		return;
-+	gsi = gsi_for_stmt(asm_stmt);
++	// 1. find pax_track_stack calls
++	for (insn = get_insns(); insn; insn = next) {
++		// rtl match: (call_insn 8 7 9 3 (call (mem (symbol_ref ("pax_track_stack") [flags 0x41] <function_decl 0xb7470e80 pax_track_stack>) [0 S1 A8]) (4)) -1 (nil) (nil))
++		rtx body;
 +
-+	assign = gimple_build_assign(lhs, rhs);
-+	gsi_insert_before(&gsi, assign, GSI_SAME_STMT);
-+	SSA_NAME_DEF_STMT(lhs) = assign;
++		next = NEXT_INSN(insn);
++		if (!CALL_P(insn))
++			continue;
++		body = PATTERN(insn);
++		if (GET_CODE(body) != CALL)
++			continue;
++		body = XEXP(body, 0);
++		if (GET_CODE(body) != MEM)
++			continue;
++		body = XEXP(body, 0);
++		if (GET_CODE(body) != SYMBOL_REF)
++			continue;
++//		if (strcmp(XSTR(body, 0), track_function))
++		if (SYMBOL_REF_DECL(body) != track_function_decl)
++			continue;
++//		warning(0, "track_frame_size: %d %ld %d", cfun->calls_alloca, get_frame_size(), track_frame_size);
++		// 2. delete call
++		delete_insn_and_edges(insn);
++#if BUILDING_GCC_VERSION >= 4007
++		if (GET_CODE(next) == NOTE && NOTE_KIND(next) == NOTE_INSN_CALL_ARG_LOCATION) {
++			insn = next;
++			next = NEXT_INSN(insn);
++			delete_insn_and_edges(insn);
++		}
++#endif
++	}
 +
-+	gsi_remove(&gsi, true);
++//	print_simple_rtl(stderr, get_insns());
++//	print_rtl(stderr, get_insns());
++//	warning(0, "track_frame_size: %d %ld %d", cfun->calls_alloca, get_frame_size(), track_frame_size);
++
++	return 0;
 +}
 +
-+// Replace our asm stmts with assignments (they are no longer needed and may interfere with later optimizations)
-+static void remove_size_overflow_asm(gimple stmt)
++static bool stackleak_track_stack_gate(void)
 +{
-+	gimple_stmt_iterator gsi;
-+	tree input, output;
++	tree section;
 +
-+	if (!is_size_overflow_asm(stmt))
-+		return;
++	if (ix86_cmodel != CM_KERNEL)
++		return false;
 +
-+	if (gimple_asm_noutputs(as_a_gasm(stmt)) == 0) {
-+		gsi = gsi_for_stmt(stmt);
++	section = lookup_attribute("section", DECL_ATTRIBUTES(current_function_decl));
++	if (section && TREE_VALUE(section)) {
++		section = TREE_VALUE(TREE_VALUE(section));
 +
-+		ipa_remove_stmt_references(cgraph_get_node(current_function_decl), stmt);
-+		gsi_remove(&gsi, true);
-+		return;
++		if (!strncmp(TREE_STRING_POINTER(section), ".init.text", 10))
++			return false;
++		if (!strncmp(TREE_STRING_POINTER(section), ".devinit.text", 13))
++			return false;
++		if (!strncmp(TREE_STRING_POINTER(section), ".cpuinit.text", 13))
++			return false;
++		if (!strncmp(TREE_STRING_POINTER(section), ".meminit.text", 13))
++			return false;
 +	}
 +
-+	input = gimple_asm_input_op(as_a_gasm(stmt), 0);
-+	output = gimple_asm_output_op(as_a_gasm(stmt), 0);
-+	replace_size_overflow_asm_with_assign(as_a_gasm(stmt), TREE_VALUE(output), TREE_VALUE(input));
++	return track_frame_size >= 0;
 +}
 +
-+static void remove_all_size_overflow_asm(void)
++static void stackleak_start_unit(void *gcc_data, void *user_data)
 +{
-+	basic_block bb;
++	tree fntype;
 +
-+	FOR_EACH_BB_FN(bb, cfun) {
-+		gimple_stmt_iterator si;
++	// void pax_track_stack(void)
++	fntype = build_function_type_list(void_type_node, NULL_TREE);
++	track_function_decl = build_fn_decl(track_function, fntype);
++	DECL_ASSEMBLER_NAME(track_function_decl); // for LTO
++	TREE_PUBLIC(track_function_decl) = 1;
++	TREE_USED(track_function_decl) = 1;
++	DECL_EXTERNAL(track_function_decl) = 1;
++	DECL_ARTIFICIAL(track_function_decl) = 1;
++	DECL_PRESERVE_P(track_function_decl) = 1;
 +
-+		for (si = gsi_start_bb(bb); !gsi_end_p(si); gsi_next(&si))
-+			remove_size_overflow_asm(gsi_stmt(si));
-+	}
++	// void pax_check_alloca(unsigned long)
++	fntype = build_function_type_list(void_type_node, long_unsigned_type_node, NULL_TREE);
++	check_function_decl = build_fn_decl(check_function, fntype);
++	DECL_ASSEMBLER_NAME(check_function_decl); // for LTO
++	TREE_PUBLIC(check_function_decl) = 1;
++	TREE_USED(check_function_decl) = 1;
++	DECL_EXTERNAL(check_function_decl) = 1;
++	DECL_ARTIFICIAL(check_function_decl) = 1;
++	DECL_PRESERVE_P(check_function_decl) = 1;
 +}
 +
-+unsigned int size_overflow_function_transform(struct cgraph_node *node __unused)
++static bool stackleak_tree_instrument_gate(void)
 +{
-+	struct visited *visited;
++	return stackleak_track_stack_gate();
++}
 +
-+#if BUILDING_GCC_VERSION >= 4008
-+	if (dump_file) {
-+		fprintf(dump_file, "BEFORE TRANSFORM -------------------------\n");
-+		size_overflow_dump_function(dump_file, node);
-+	}
-+#endif
-+	visited = create_visited();
-+	set_dominance_info();
++#define PASS_NAME stackleak_tree_instrument
++#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
++#define TODO_FLAGS_START TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts
++#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_update_ssa | TODO_rebuild_cgraph_edges
++#include "gcc-generate-gimple-pass.h"
 +
-+	search_interesting_stmts(visited);
++static bool stackleak_final_gate(void)
++{
++	return stackleak_track_stack_gate();
++}
 +
-+	remove_all_size_overflow_asm();
++#define PASS_NAME stackleak_final
++#define TODO_FLAGS_FINISH TODO_dump_func
++#include "gcc-generate-rtl-pass.h"
 +
-+	unset_dominance_info();
-+	free_visited(visited);
++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
++{
++	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	int i;
++	struct register_pass_info stackleak_tree_instrument_pass_info;
++	struct register_pass_info stackleak_final_pass_info;
++	static const struct ggc_root_tab gt_ggc_r_gt_stackleak[] = {
++		{
++			.base = &track_function_decl,
++			.nelt = 1,
++			.stride = sizeof(track_function_decl),
++			.cb = &gt_ggc_mx_tree_node,
++			.pchw = &gt_pch_nx_tree_node
++		},
++		{
++			.base = &check_function_decl,
++			.nelt = 1,
++			.stride = sizeof(check_function_decl),
++			.cb = &gt_ggc_mx_tree_node,
++			.pchw = &gt_pch_nx_tree_node
++		},
++		LAST_GGC_ROOT_TAB
++	};
 +
-+#if BUILDING_GCC_VERSION >= 4008
-+	if (dump_file) {
-+		fprintf(dump_file, "AFTER TRANSFORM -------------------------\n");
-+		size_overflow_dump_function(dump_file, node);
++	stackleak_tree_instrument_pass_info.pass			= make_stackleak_tree_instrument_pass();
++//	stackleak_tree_instrument_pass_info.reference_pass_name		= "tree_profile";
++	stackleak_tree_instrument_pass_info.reference_pass_name		= "optimized";
++	stackleak_tree_instrument_pass_info.ref_pass_instance_number	= 1;
++	stackleak_tree_instrument_pass_info.pos_op 			= PASS_POS_INSERT_BEFORE;
++
++	stackleak_final_pass_info.pass				= make_stackleak_final_pass();
++	stackleak_final_pass_info.reference_pass_name		= "final";
++	stackleak_final_pass_info.ref_pass_instance_number	= 1;
++	stackleak_final_pass_info.pos_op 			= PASS_POS_INSERT_BEFORE;
++
++	if (!plugin_default_version_check(version, &gcc_version)) {
++		error(G_("incompatible gcc/plugin versions"));
++		return 1;
 +	}
-+#endif
-+	return TODO_dump_func | TODO_verify_stmts | TODO_remove_unused_locals | TODO_update_ssa_no_phi | TODO_ggc_collect | TODO_verify_flow;
++
++	register_callback(plugin_name, PLUGIN_INFO, NULL, &stackleak_plugin_info);
++
++	for (i = 0; i < argc; ++i) {
++		if (!strcmp(argv[i].key, "track-lowest-sp")) {
++			if (!argv[i].value) {
++				error(G_("no value supplied for option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++				continue;
++			}
++			track_frame_size = atoi(argv[i].value);
++			if (argv[i].value[0] < '0' || argv[i].value[0] > '9' || track_frame_size < 0)
++				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"), plugin_name, argv[i].key, argv[i].value);
++			continue;
++		}
++		if (!strcmp(argv[i].key, "initialize-locals")) {
++			if (argv[i].value) {
++				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"), plugin_name, argv[i].key, argv[i].value);
++				continue;
++			}
++			init_locals = true;
++			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
++
++	register_callback(plugin_name, PLUGIN_START_UNIT, &stackleak_start_unit, NULL);
++	register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_stackleak);
++	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &stackleak_tree_instrument_pass_info);
++	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &stackleak_final_pass_info);
++
++	return 0;
 +}
-diff --git a/tools/gcc/size_overflow_plugin/size_overflow_transform_core.c b/tools/gcc/size_overflow_plugin/size_overflow_transform_core.c
+diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c
 new file mode 100644
-index 0000000..062204a
+index 0000000..d7596e6
 --- /dev/null
-+++ b/tools/gcc/size_overflow_plugin/size_overflow_transform_core.c
-@@ -0,0 +1,1025 @@
++++ b/scripts/gcc-plugins/structleak_plugin.c
+@@ -0,0 +1,239 @@
 +/*
-+ * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
-+ * Licensed under the GPL v2, or (at your option) v3
++ * Copyright 2013-2016 by PaX Team <pageexec@freemail.hu>
++ * Licensed under the GPL v2
 + *
-+ * Homepage:
-+ * https://github.com/ephox-gcc-plugins/size_overflow
++ * 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
 + *
-+ * Documentation:
-+ * http://forums.grsecurity.net/viewtopic.php?f=7&t=3043
++ * gcc plugin to forcibly initialize certain local variables that could
++ * otherwise leak kernel stack to userland if they aren't properly initialized
++ * by later code
 + *
-+ * This plugin recomputes expressions of function arguments marked by a size_overflow attribute
-+ * with double integer precision (DImode/TImode for 32/64 bit integer types).
-+ * The recomputed argument is checked against TYPE_MAX and an event is logged on overflow and the triggering process is killed.
++ * Homepage: http://pax.grsecurity.net/
 + *
 + * Usage:
-+ * $ make
-+ * $ make run
++ * $ # for 4.5/4.6/C based 4.7
++ * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c
++ * $ # for C++ based 4.7/4.8+
++ * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c
++ * $ gcc -fplugin=./structleak_plugin.so test.c -O2
++ *
++ * TODO: eliminate redundant initializers
++ *       increase type coverage
 + */
 +
-+#include "size_overflow.h"
++#include "gcc-common.h"
 +
-+#define MIN_CHECK true
-+#define MAX_CHECK false
++// unused C type flag in all versions 4.5-6
++#define TYPE_USERSPACE(TYPE) TYPE_LANG_FLAG_5(TYPE)
 +
-+unsigned int call_count = 0;
++int plugin_is_GPL_compatible;
 +
-+tree get_size_overflow_type(struct visited *visited, const_gimple stmt, const_tree node)
-+{
-+	const_tree type;
-+	tree new_type;
++static struct plugin_info structleak_plugin_info = {
++	.version	= "201602181345",
++	.help		= "disable\tdo not activate plugin\n",
++};
 +
-+	gcc_assert(node != NULL_TREE);
++static tree handle_user_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
++{
++	*no_add_attrs = true;
 +
-+	type = TREE_TYPE(node);
++	// check for types? for now accept everything linux has to offer
++	if (TREE_CODE(*node) != FIELD_DECL)
++		return NULL_TREE;
 +
-+	if (pointer_set_contains(visited->my_stmts, stmt))
-+		return TREE_TYPE(node);
++	*no_add_attrs = false;
++	return NULL_TREE;
++}
 +
-+	switch (TYPE_MODE(type)) {
-+	case QImode:
-+	case HImode:
-+		new_type = size_overflow_type_SI;
-+		break;
-+	case SImode:
-+		new_type = size_overflow_type_DI;
-+		break;
-+	case DImode:
-+		if (LONG_TYPE_SIZE == GET_MODE_BITSIZE(SImode))
-+			new_type = TYPE_UNSIGNED(type) ? unsigned_intDI_type_node : intDI_type_node;
-+		else
-+			new_type = size_overflow_type_TI;
-+		break;
-+	case TImode:
-+		gcc_assert(!TYPE_UNSIGNED(type));
-+		new_type = size_overflow_type_TI;
-+		break;
-+	default:
-+		debug_tree(node);
-+		error("%s: unsupported gcc configuration (%qE).", __func__, current_function_decl);
-+		gcc_unreachable();
-+	}
++static struct attribute_spec user_attr = {
++	.name			= "user",
++	.min_length		= 0,
++	.max_length		= 0,
++	.decl_required		= false,
++	.type_required		= false,
++	.function_type_required	= false,
++	.handler		= handle_user_attribute,
++#if BUILDING_GCC_VERSION >= 4007
++	.affects_type_identity	= true
++#endif
++};
 +
-+	if (TYPE_QUALS(type) != 0)
-+		return build_qualified_type(new_type, TYPE_QUALS(type));
-+	return new_type;
++static void register_attributes(void *event_data, void *data)
++{
++	register_attribute(&user_attr);
++//	register_attribute(&force_attr);
 +}
 +
-+tree cast_to_new_size_overflow_type(struct visited *visited, gimple stmt, tree rhs, tree size_overflow_type, bool before)
++static tree get_field_type(tree field)
 +{
-+	gimple_stmt_iterator gsi;
-+	gimple new_stmt;
-+
-+	if (rhs == NULL_TREE)
-+		return NULL_TREE;
-+
-+	gsi = gsi_for_stmt(stmt);
-+	new_stmt = build_cast_stmt(visited, size_overflow_type, rhs, CREATE_NEW_VAR, &gsi, before, false);
-+	if (gimple_assign_cast_p(new_stmt))
-+		gimple_assign_set_rhs_code(new_stmt, CONVERT_EXPR);
-+	pointer_set_insert(visited->my_stmts, new_stmt);
-+
-+	return get_lhs(new_stmt);
++	return strip_array_types(TREE_TYPE(field));
 +}
 +
-+tree create_assign(struct visited *visited, gimple oldstmt, tree rhs1, bool before)
++static bool is_userspace_type(tree type)
 +{
-+	tree lhs, dst_type;
-+	gimple_stmt_iterator gsi;
-+
-+	if (rhs1 == NULL_TREE) {
-+		debug_gimple_stmt(oldstmt);
-+		error("%s: rhs1 is NULL_TREE", __func__);
-+		gcc_unreachable();
-+	}
-+
-+	switch (gimple_code(oldstmt)) {
-+	case GIMPLE_ASM:
-+		lhs = rhs1;
-+		break;
-+	case GIMPLE_CALL:
-+	case GIMPLE_ASSIGN:
-+		lhs = gimple_get_lhs(oldstmt);
-+		break;
-+	default:
-+		debug_gimple_stmt(oldstmt);
-+		gcc_unreachable();
-+	}
-+
-+	gsi = gsi_for_stmt(oldstmt);
-+	pointer_set_insert(visited->stmts, oldstmt);
-+	if (lookup_stmt_eh_lp(oldstmt) != 0) {
-+		basic_block next_bb, cur_bb;
-+		const_edge e;
-+
-+		gcc_assert(before == false);
-+		gcc_assert(stmt_can_throw_internal(oldstmt));
-+		gcc_assert(gimple_code(oldstmt) == GIMPLE_CALL);
-+		gcc_assert(!gsi_end_p(gsi));
++	tree field;
 +
-+		cur_bb = gimple_bb(oldstmt);
-+		next_bb = cur_bb->next_bb;
-+		e = find_edge(cur_bb, next_bb);
-+		gcc_assert(e != NULL);
-+		gcc_assert(e->flags & EDGE_FALLTHRU);
++	for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) {
++		tree fieldtype = get_field_type(field);
++		enum tree_code code = TREE_CODE(fieldtype);
 +
-+		gsi = gsi_after_labels(next_bb);
-+		gcc_assert(!gsi_end_p(gsi));
++		if (code == RECORD_TYPE || code == UNION_TYPE)
++			if (is_userspace_type(fieldtype))
++				return true;
 +
-+		before = true;
-+		oldstmt = gsi_stmt(gsi);
++		if (lookup_attribute("user", DECL_ATTRIBUTES(field)))
++			return true;
 +	}
-+
-+	if (is_gimple_constant(rhs1) && TREE_CODE_CLASS(gimple_assign_rhs_code(oldstmt)) == tcc_comparison)
-+		dst_type = get_size_overflow_type(visited, oldstmt, rhs1);
-+	else
-+		dst_type = get_size_overflow_type(visited, oldstmt, lhs);
-+
-+	if (is_gimple_constant(rhs1))
-+		return cast_a_tree(dst_type, rhs1);
-+	return cast_to_new_size_overflow_type(visited, oldstmt, rhs1, dst_type, before);
++	return false;
 +}
 +
-+tree dup_assign(struct visited *visited, gassign *oldstmt, const_tree node, tree rhs1, tree rhs2, tree __unused rhs3)
++static void finish_type(void *event_data, void *data)
 +{
-+	gassign *stmt;
-+	gimple_stmt_iterator gsi;
-+	tree size_overflow_type, new_var, lhs = gimple_assign_lhs(oldstmt);
-+
-+	if (pointer_set_contains(visited->my_stmts, oldstmt))
-+		return lhs;
-+
-+	if (gimple_num_ops(oldstmt) != 4 && rhs1 == NULL_TREE) {
-+		rhs1 = gimple_assign_rhs1(oldstmt);
-+		rhs1 = create_assign(visited, oldstmt, rhs1, BEFORE_STMT);
-+	}
-+	if (gimple_num_ops(oldstmt) == 3 && rhs2 == NULL_TREE) {
-+		rhs2 = gimple_assign_rhs2(oldstmt);
-+		rhs2 = create_assign(visited, oldstmt, rhs2, BEFORE_STMT);
-+	}
-+
-+	stmt = as_a_gassign(gimple_copy(oldstmt));
-+	gimple_set_location(stmt, gimple_location(oldstmt));
-+	pointer_set_insert(visited->my_stmts, stmt);
-+
-+	if (gimple_assign_rhs_code(oldstmt) == WIDEN_MULT_EXPR)
-+		gimple_assign_set_rhs_code(stmt, MULT_EXPR);
-+
-+	size_overflow_type = get_size_overflow_type(visited, oldstmt, node);
-+
-+	new_var = create_new_var(size_overflow_type);
-+	new_var = make_ssa_name(new_var, stmt);
-+	gimple_assign_set_lhs(stmt, new_var);
++	tree type = (tree)event_data;
 +
-+	if (rhs1 != NULL_TREE)
-+		gimple_assign_set_rhs1(stmt, rhs1);
++	if (type == NULL_TREE || type == error_mark_node)
++		return;
 +
-+	if (rhs2 != NULL_TREE)
-+		gimple_assign_set_rhs2(stmt, rhs2);
-+#if BUILDING_GCC_VERSION >= 4006
-+	if (rhs3 != NULL_TREE)
-+		gimple_assign_set_rhs3(stmt, rhs3);
++#if BUILDING_GCC_VERSION >= 5000
++	if (TREE_CODE(type) == ENUMERAL_TYPE)
++		return;
 +#endif
-+	gimple_set_vuse(stmt, gimple_vuse(oldstmt));
-+	gimple_set_vdef(stmt, gimple_vdef(oldstmt));
 +
-+	gsi = gsi_for_stmt(oldstmt);
-+	gsi_insert_after(&gsi, stmt, GSI_SAME_STMT);
-+	update_stmt(stmt);
-+	pointer_set_insert(visited->stmts, oldstmt);
-+	return gimple_assign_lhs(stmt);
++	if (TYPE_USERSPACE(type))
++		return;
++
++	if (is_userspace_type(type))
++		TYPE_USERSPACE(type) = 1;
 +}
 +
-+static tree cast_parm_decl(struct visited *visited, tree phi_ssa_name, tree arg, tree size_overflow_type, basic_block bb)
++static void initialize(tree var)
 +{
-+	const_gimple assign;
++	basic_block bb;
 +	gimple_stmt_iterator gsi;
-+	basic_block first_bb;
++	tree initializer;
++	gimple init_stmt;
 +
-+	gcc_assert(SSA_NAME_IS_DEFAULT_DEF(arg));
++	// this is the original entry bb before the forced split
++	bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
 +
-+	if (bb->index == 0) {
-+		first_bb = split_block_after_labels(ENTRY_BLOCK_PTR_FOR_FN(cfun))->dest;
-+		gcc_assert(dom_info_available_p(CDI_DOMINATORS));
-+		set_immediate_dominator(CDI_DOMINATORS, first_bb, ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+		bb = first_bb;
-+	}
++	// first check if the variable is already initialized, warn otherwise
++	for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
++		gimple stmt = gsi_stmt(gsi);
++		tree rhs1;
 +
-+	gsi = gsi_after_labels(bb);
-+	assign = build_cast_stmt(visited, size_overflow_type, arg, phi_ssa_name, &gsi, BEFORE_STMT, false);
-+	pointer_set_insert(visited->my_stmts, assign);
-+	return get_lhs(assign);
-+}
++		// we're looking for an assignment of a single rhs...
++		if (!gimple_assign_single_p(stmt))
++			continue;
++		rhs1 = gimple_assign_rhs1(stmt);
++#if BUILDING_GCC_VERSION >= 4007
++		// ... of a non-clobbering expression...
++		if (TREE_CLOBBER_P(rhs1))
++			continue;
++#endif
++		// ... to our variable...
++		if (gimple_get_lhs(stmt) != var)
++			continue;
++		// if it's an initializer then we're good
++		if (TREE_CODE(rhs1) == CONSTRUCTOR)
++			return;
++	}
 +
-+static tree use_phi_ssa_name(struct visited *visited, tree ssa_name_var, tree new_arg)
-+{
-+	gimple_stmt_iterator gsi;
-+	const_gimple assign;
-+	gimple def_stmt = get_def_stmt(new_arg);
++	// these aren't the 0days you're looking for
++//	inform(DECL_SOURCE_LOCATION(var), "userspace variable will be forcibly initialized");
 +
-+	if (gimple_code(def_stmt) == GIMPLE_PHI) {
-+		gsi = gsi_after_labels(gimple_bb(def_stmt));
-+		assign = build_cast_stmt(visited, TREE_TYPE(new_arg), new_arg, ssa_name_var, &gsi, BEFORE_STMT, true);
-+	} else {
-+		gsi = gsi_for_stmt(def_stmt);
-+		assign = build_cast_stmt(visited, TREE_TYPE(new_arg), new_arg, ssa_name_var, &gsi, AFTER_STMT, true);
-+	}
++	// build the initializer expression
++	initializer = build_constructor(TREE_TYPE(var), NULL);
 +
-+	pointer_set_insert(visited->my_stmts, assign);
-+	return get_lhs(assign);
++	// build the initializer stmt
++	init_stmt = gimple_build_assign(var, initializer);
++	gsi = gsi_after_labels(single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++	gsi_insert_before(&gsi, init_stmt, GSI_NEW_STMT);
++	update_stmt(init_stmt);
 +}
 +
-+static tree cast_visited_phi_arg(struct visited *visited, tree ssa_name_var, tree arg, tree size_overflow_type)
++static unsigned int structleak_execute(void)
 +{
 +	basic_block bb;
-+	gimple_stmt_iterator gsi;
-+	const_gimple def_stmt;
-+	const_gimple assign;
-+
-+	def_stmt = get_def_stmt(arg);
-+	bb = gimple_bb(def_stmt);
-+	gcc_assert(bb->index != 0);
-+	gsi = gsi_after_labels(bb);
-+
-+	assign = build_cast_stmt(visited, size_overflow_type, arg, ssa_name_var, &gsi, BEFORE_STMT, false);
-+	pointer_set_insert(visited->my_stmts, assign);
-+	return get_lhs(assign);
-+}
++	unsigned int ret = 0;
++	tree var;
++	unsigned int i;
 +
-+static tree create_new_phi_arg(struct visited *visited, tree ssa_name_var, tree new_arg, gphi *oldstmt, unsigned int i)
-+{
-+	tree size_overflow_type;
-+	tree arg;
-+	const_gimple def_stmt;
++	// split the first bb where we can put the forced initializers
++	gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++	bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
++	if (!single_pred_p(bb)) {
++//		gcc_assert(bb_loop_depth(bb) || (bb->flags & BB_IRREDUCIBLE_LOOP));
++		split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++		gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
++	}
 +
-+	if (new_arg != NULL_TREE && is_gimple_constant(new_arg))
-+		return new_arg;
++	// enumarate all local variables and forcibly initialize our targets
++	FOR_EACH_LOCAL_DECL(cfun, i, var) {
++		tree type = TREE_TYPE(var);
 +
-+	arg = gimple_phi_arg_def(oldstmt, i);
-+	def_stmt = get_def_stmt(arg);
-+	gcc_assert(def_stmt != NULL);
-+	size_overflow_type = get_size_overflow_type(visited, oldstmt, arg);
++		gcc_assert(DECL_P(var));
++		if (!auto_var_in_fn_p(var, current_function_decl))
++			continue;
 +
-+	switch (gimple_code(def_stmt)) {
-+	case GIMPLE_PHI:
-+		return cast_visited_phi_arg(visited, ssa_name_var, arg, size_overflow_type);
-+	case GIMPLE_NOP: {
-+		basic_block bb;
++		// only care about structure types
++		if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
++			continue;
 +
-+		bb = gimple_phi_arg_edge(oldstmt, i)->src;
-+		return cast_parm_decl(visited, ssa_name_var, arg, size_overflow_type, bb);
++		// if the type is of interest, examine the variable
++		if (TYPE_USERSPACE(type))
++			initialize(var);
 +	}
-+	case GIMPLE_ASM: {
-+		gimple_stmt_iterator gsi;
-+		const_gimple assign;
-+		gimple stmt = get_def_stmt(arg);
 +
-+		gsi = gsi_for_stmt(stmt);
-+		assign = build_cast_stmt(visited, size_overflow_type, arg, ssa_name_var, &gsi, AFTER_STMT, false);
-+		pointer_set_insert(visited->my_stmts, assign);
-+		return get_lhs(assign);
-+	}
-+	default:
-+		gcc_assert(new_arg != NULL_TREE);
-+		gcc_assert(types_compatible_p(TREE_TYPE(new_arg), size_overflow_type));
-+		return use_phi_ssa_name(visited, ssa_name_var, new_arg);
-+	}
++	return ret;
 +}
 +
-+static gphi *overflow_create_phi_node(struct visited *visited, gphi *oldstmt, tree result)
++#define PASS_NAME structleak
++#define NO_GATE
++#define PROPERTIES_REQUIRED PROP_cfg
++#define TODO_FLAGS_FINISH TODO_verify_il | TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_remove_unused_locals | TODO_update_ssa | TODO_ggc_collect | TODO_verify_flow
++#include "gcc-generate-gimple-pass.h"
++
++int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
 +{
-+	basic_block bb;
-+	gphi *phi;
-+	gimple_seq seq;
-+	gimple_stmt_iterator gsi = gsi_for_stmt(oldstmt);
++	int i;
++	const char * const plugin_name = plugin_info->base_name;
++	const int argc = plugin_info->argc;
++	const struct plugin_argument * const argv = plugin_info->argv;
++	bool enable = true;
++	struct register_pass_info structleak_pass_info;
 +
-+	bb = gsi_bb(gsi);
++	structleak_pass_info.pass			= make_structleak_pass();
++	structleak_pass_info.reference_pass_name	= "ssa";
++	structleak_pass_info.ref_pass_instance_number	= 1;
++	structleak_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
 +
-+	if (result == NULL_TREE) {
-+		tree old_result = gimple_phi_result(oldstmt);
-+		tree size_overflow_type = get_size_overflow_type(visited, oldstmt, old_result);
++	if (!plugin_default_version_check(version, &gcc_version)) {
++		error(G_("incompatible gcc/plugin versions"));
++		return 1;
++	}
 +
-+		result = create_new_var(size_overflow_type);
++	if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {
++		inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);
++		enable = false;
 +	}
 +
-+	phi = as_a_gphi(create_phi_node(result, bb));
-+	gimple_phi_set_result(phi, make_ssa_name(result, phi));
-+	seq = phi_nodes(bb);
-+	gsi = gsi_last(seq);
-+	gsi_remove(&gsi, false);
++	for (i = 0; i < argc; ++i) {
++		if (!strcmp(argv[i].key, "disable")) {
++			enable = false;
++			continue;
++		}
++		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	}
 +
-+	gsi = gsi_for_stmt(oldstmt);
-+	gsi_insert_after(&gsi, phi, GSI_NEW_STMT);
-+	gimple_set_bb(phi, bb);
-+	return phi;
++	register_callback(plugin_name, PLUGIN_INFO, NULL, &structleak_plugin_info);
++	if (enable) {
++		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &structleak_pass_info);
++		register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
++	}
++	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
++
++	return 0;
 +}
+diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
+index fdebd66..a349e33 100755
+--- a/scripts/headers_install.sh
++++ b/scripts/headers_install.sh
+@@ -32,6 +32,7 @@ do
+ 	FILE="$(basename "$i")"
+ 	sed -r \
+ 		-e 's/([ \t(])(__user|__force|__iomem)[ \t]/\1/g' \
++		-e 's/__intentional_overflow\([- \t,0-9]*\)//g' \
+ 		-e 's/__attribute_const__([ \t]|$)/\1/g' \
+ 		-e 's@^#include <linux/compiler.h>@@' \
+ 		-e 's/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g' \
+diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
+index 8fa81e8..a9ac144 100644
+--- a/scripts/kallsyms.c
++++ b/scripts/kallsyms.c
+@@ -89,7 +89,7 @@ static inline int is_arm_mapping_symbol(const char *str)
+ }
+ 
+ static int check_symbol_range(const char *sym, unsigned long long addr,
+-			      struct addr_range *ranges, int entries)
++			      struct addr_range *ranges, size_t entries)
+ {
+ 	size_t i;
+ 	struct addr_range *ar;
+@@ -178,7 +178,7 @@ static int read_symbol(FILE *in, struct sym_entry *s)
+ }
+ 
+ static int symbol_in_range(struct sym_entry *s, struct addr_range *ranges,
+-			   int entries)
++			   size_t entries)
+ {
+ 	size_t i;
+ 	struct addr_range *ar;
+diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
+index 91ca126..5f7cad6 100644
+--- a/scripts/kconfig/lkc.h
++++ b/scripts/kconfig/lkc.h
+@@ -108,7 +108,8 @@ void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
+ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+ void menu_add_option(int token, char *arg);
+ void menu_finalize(struct menu *parent);
+-void menu_set_type(int type);
++enum symbol_type;
++void menu_set_type(enum symbol_type type);
+ 
+ /* util.c */
+ struct file *file_lookup(const char *name);
+@@ -123,7 +124,7 @@ struct gstr {
+ 	* when max_width is not zero long lines in string s (if any) get
+ 	* wrapped not to exceed the max_width value
+ 	*/
+-	int max_width;
++	size_t max_width;
+ };
+ struct gstr str_new(void);
+ void str_free(struct gstr *gs);
+diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
+index aed678e..1a703de 100644
+--- a/scripts/kconfig/menu.c
++++ b/scripts/kconfig/menu.c
+@@ -109,7 +109,7 @@ void menu_add_dep(struct expr *dep)
+ 	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
+ }
+ 
+-void menu_set_type(int type)
++void menu_set_type(enum symbol_type type)
+ {
+ 	struct symbol *sym = current_entry->sym;
+ 
+diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
+index 25cf0c2..eb178ce 100644
+--- a/scripts/kconfig/symbol.c
++++ b/scripts/kconfig/symbol.c
+@@ -956,7 +956,7 @@ const char *sym_escape_string_value(const char *in)
+ 
+ struct sym_match {
+ 	struct symbol	*sym;
+-	off_t		so, eo;
++	regoff_t	so, eo;
+ };
+ 
+ /* Compare matched symbols as thus:
+@@ -978,8 +978,8 @@ static int sym_rel_comp(const void *sym1, const void *sym2)
+ 	 * exactly; if this is the case, we can't decide which comes first,
+ 	 * and we fallback to sorting alphabetically.
+ 	 */
+-	exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
+-	exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
++	exact1 = (s1->eo - s1->so) == (long)strlen(s1->sym->name);
++	exact2 = (s2->eo - s2->so) == (long)strlen(s2->sym->name);
+ 	if (exact1 && !exact2)
+ 		return -1;
+ 	if (!exact1 && exact2)
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index ba6c34e..ea10bce 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -179,7 +179,7 @@ else
+ fi;
+ 
+ # final build of init/
+-${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init
++${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="${GCC_PLUGINS_CFLAGS}" GCC_PLUGINS_AFLAGS="${GCC_PLUGINS_AFLAGS}"
+ 
+ kallsymso=""
+ kallsyms_vmlinux=""
+diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
+index a915507..27c1b41 100644
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -156,7 +156,7 @@ static void device_id_check(const char *modname, const char *device_id,
+ 			    unsigned long size, unsigned long id_size,
+ 			    void *symval)
+ {
+-	int i;
++	unsigned int i;
+ 
+ 	if (size % id_size || size < id_size) {
+ 		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
+@@ -185,7 +185,7 @@ static void device_id_check(const char *modname, const char *device_id,
+ /* USB is special because the bcdDevice can be matched against a numeric range */
+ /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
+ static void do_usb_entry(void *symval,
+-			 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
++			 unsigned int bcdDevice_initial, unsigned int bcdDevice_initial_digits,
+ 			 unsigned char range_lo, unsigned char range_hi,
+ 			 unsigned char max, struct module *mod)
+ {
+@@ -295,7 +295,7 @@ static void do_usb_entry_multi(void *symval, struct module *mod)
+ {
+ 	unsigned int devlo, devhi;
+ 	unsigned char chi, clo, max;
+-	int ndigits;
++	unsigned int ndigits;
+ 
+ 	DEF_FIELD(symval, usb_device_id, match_flags);
+ 	DEF_FIELD(symval, usb_device_id, idVendor);
+@@ -619,7 +619,7 @@ static void do_pnp_device_entry(void *symval, unsigned long size,
+ 	for (i = 0; i < count; i++) {
+ 		DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
+ 		char acpi_id[sizeof(*id)];
+-		int j;
++		unsigned int j;
+ 
+ 		buf_printf(&mod->dev_table_buf,
+ 			   "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
+@@ -648,7 +648,7 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
+ 
+ 		for (j = 0; j < PNP_MAX_DEVICES; j++) {
+ 			const char *id = (char *)(*devs)[j].id;
+-			int i2, j2;
++			unsigned int i2, j2;
+ 			int dup = 0;
+ 
+ 			if (!id[0])
+@@ -674,7 +674,7 @@ static void do_pnp_card_entries(void *symval, unsigned long size,
+ 			/* add an individual alias for every device entry */
+ 			if (!dup) {
+ 				char acpi_id[PNP_ID_LEN];
+-				int k;
++				unsigned int k;
+ 
+ 				buf_printf(&mod->dev_table_buf,
+ 					   "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+@@ -999,7 +999,7 @@ static void dmi_ascii_filter(char *d, const char *s)
+ static int do_dmi_entry(const char *filename, void *symval,
+ 			char *alias)
+ {
+-	int i, j;
++	unsigned int i, j;
+ 	DEF_FIELD_ADDR(symval, dmi_system_id, matches);
+ 	sprintf(alias, "dmi*");
+ 
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 48958d3..d5ccb52 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -37,6 +37,7 @@ static int vmlinux_section_warnings = 1;
+ static int warn_unresolved = 0;
+ /* How a symbol is exported */
+ static int sec_mismatch_count = 0;
++static int writable_fptr_count = 0;
+ static int sec_mismatch_verbose = 1;
+ static int sec_mismatch_fatal = 0;
+ /* ignore missing files */
+@@ -947,6 +948,7 @@ enum mismatch {
+ 	ANY_EXIT_TO_ANY_INIT,
+ 	EXPORT_TO_INIT_EXIT,
+ 	EXTABLE_TO_NON_TEXT,
++	DATA_TO_TEXT
+ };
+ 
+ /**
+@@ -1073,6 +1075,12 @@ static const struct sectioncheck sectioncheck[] = {
+ 	.good_tosec = {ALL_TEXT_SECTIONS , NULL},
+ 	.mismatch = EXTABLE_TO_NON_TEXT,
+ 	.handler = extable_mismatch_handler,
++},
++/* Do not reference code from writable data */
++{
++	.fromsec = { DATA_SECTIONS, NULL },
++	.bad_tosec = { ALL_TEXT_SECTIONS, NULL },
++	.mismatch = DATA_TO_TEXT
+ }
+ };
+ 
+@@ -1222,10 +1230,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
+ 			continue;
+ 		if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
+ 			continue;
+-		if (sym->st_value == addr)
+-			return sym;
+ 		/* Find a symbol nearby - addr are maybe negative */
+ 		d = sym->st_value - addr;
++		if (d == 0)
++			return sym;
+ 		if (d < 0)
+ 			d = addr - sym->st_value;
+ 		if (d < distance) {
+@@ -1384,7 +1392,11 @@ static void report_sec_mismatch(const char *modname,
+ 	char *prl_from;
+ 	char *prl_to;
+ 
+-	sec_mismatch_count++;
++	if (mismatch->mismatch == DATA_TO_TEXT)
++		writable_fptr_count++;
++	else
++		sec_mismatch_count++;
 +
-+#if BUILDING_GCC_VERSION <= 4007
-+static tree create_new_phi_node(struct visited *visited, VEC(tree, heap) **args, tree ssa_name_var, gimple oldstmt)
-+#else
-+static tree create_new_phi_node(struct visited *visited, vec<tree, va_heap, vl_embed> *&args, tree ssa_name_var, gphi *oldstmt)
+ 	if (!sec_mismatch_verbose)
+ 		return;
+ 
+@@ -1508,6 +1520,14 @@ static void report_sec_mismatch(const char *modname,
+ 		fatal("There's a special handler for this mismatch type, "
+ 		      "we should never get here.");
+ 		break;
++	case DATA_TO_TEXT:
++#if 0
++		fprintf(stderr,
++		"The %s %s:%s references\n"
++		"the %s %s:%s%s\n",
++		from, fromsec, fromsym, to, tosec, tosym, to_p);
 +#endif
-+{
-+	gphi *new_phi;
++		break;
+ 	}
+ 	fprintf(stderr, "\n");
+ }
+@@ -1897,7 +1917,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
+ static void check_sec_ref(struct module *mod, const char *modname,
+ 			  struct elf_info *elf)
+ {
+-	int i;
 +	unsigned int i;
-+	tree arg, result;
-+	location_t loc = gimple_location(oldstmt);
-+
-+#if BUILDING_GCC_VERSION <= 4007
-+	gcc_assert(!VEC_empty(tree, *args));
-+#else
-+	gcc_assert(!args->is_empty());
-+#endif
-+
-+	new_phi = overflow_create_phi_node(visited, oldstmt, ssa_name_var);
-+	result = gimple_phi_result(new_phi);
-+	ssa_name_var = SSA_NAME_VAR(result);
-+
-+#if BUILDING_GCC_VERSION <= 4007
-+	FOR_EACH_VEC_ELT(tree, *args, i, arg) {
-+#else
-+	FOR_EACH_VEC_SAFE_ELT(args, i, arg) {
-+#endif
-+		arg = create_new_phi_arg(visited, ssa_name_var, arg, oldstmt, i);
-+		add_phi_arg(new_phi, arg, gimple_phi_arg_edge(oldstmt, i), loc);
-+	}
-+
-+#if BUILDING_GCC_VERSION <= 4007
-+	VEC_free(tree, heap, *args);
-+#else
-+	vec_free(args);
-+#endif
-+	update_stmt(new_phi);
-+	pointer_set_insert(visited->my_stmts, new_phi);
-+	return result;
-+}
-+
-+static tree handle_phi(interesting_stmts_t expand_from, tree orig_result)
-+{
-+#if BUILDING_GCC_VERSION <= 4007
-+	VEC(tree, heap) *args = NULL;
-+#else
-+	vec<tree, va_heap, vl_embed> *args = NULL;
-+#endif
-+	unsigned int i, len;
-+	tree ssa_name_var = NULL_TREE;
-+	gphi *oldstmt = as_a_gphi(get_def_stmt(orig_result));
-+
-+	len = gimple_phi_num_args(oldstmt);
-+	pointer_set_insert(expand_from->visited->stmts, oldstmt);
-+	for (i = 0; i < len; i++) {
-+		tree arg, new_arg;
-+
-+		arg = gimple_phi_arg_def(oldstmt, i);
-+		new_arg = expand(expand_from, arg);
-+
-+		if (ssa_name_var == NULL_TREE && new_arg != NULL_TREE)
-+			ssa_name_var = SSA_NAME_VAR(new_arg);
-+
-+		if (is_gimple_constant(arg)) {
-+			tree size_overflow_type = get_size_overflow_type(expand_from->visited, oldstmt, arg);
-+
-+			new_arg = cast_a_tree(size_overflow_type, arg);
+ 	Elf_Shdr *sechdrs = elf->sechdrs;
+ 
+ 	/* Walk through all sections */
+@@ -2028,7 +2048,7 @@ void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
+ 	va_end(ap);
+ }
+ 
+-void buf_write(struct buffer *buf, const char *s, int len)
++void buf_write(struct buffer *buf, const char *s, unsigned int len)
+ {
+ 	if (buf->size - buf->pos < len) {
+ 		buf->size += len + SZ;
+@@ -2258,7 +2278,7 @@ static void write_if_changed(struct buffer *b, const char *fname)
+ 	if (fstat(fileno(file), &st) < 0)
+ 		goto close_write;
+ 
+-	if (st.st_size != b->pos)
++	if (st.st_size != (off_t)b->pos)
+ 		goto close_write;
+ 
+ 	tmp = NOFAIL(malloc(b->pos));
+@@ -2496,6 +2516,14 @@ int main(int argc, char **argv)
+ 			      "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
+ 		}
+ 	}
++	if (writable_fptr_count) {
++		if (!sec_mismatch_verbose) {
++			warn("modpost: Found %d writable function pointer(s).\n"
++			     "To see full details build your kernel with:\n"
++			     "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
++			     writable_fptr_count);
 +		}
-+
-+#if BUILDING_GCC_VERSION <= 4007
-+		VEC_safe_push(tree, heap, args, new_arg);
-+#else
-+		vec_safe_push(args, new_arg);
-+#endif
 +	}
-+
-+#if BUILDING_GCC_VERSION <= 4007
-+	return create_new_phi_node(expand_from->visited, &args, ssa_name_var, oldstmt);
-+#else
-+	return create_new_phi_node(expand_from->visited, args, ssa_name_var, oldstmt);
-+#endif
-+}
-+
-+static tree create_cast_assign(struct visited *visited, gassign *stmt)
-+{
-+	tree rhs1 = gimple_assign_rhs1(stmt);
-+	tree lhs = gimple_assign_lhs(stmt);
-+	const_tree rhs1_type = TREE_TYPE(rhs1);
-+	const_tree lhs_type = TREE_TYPE(lhs);
-+
-+	if (TYPE_UNSIGNED(rhs1_type) == TYPE_UNSIGNED(lhs_type))
-+		return create_assign(visited, stmt, lhs, AFTER_STMT);
-+
-+	return create_assign(visited, stmt, rhs1, AFTER_STMT);
-+}
-+
-+static bool skip_lhs_cast_check(struct visited *visited, const gassign *stmt)
-+{
-+	const_tree rhs = gimple_assign_rhs1(stmt);
-+	const_gimple def_stmt = get_def_stmt(rhs);
-+
-+	// 3.8.2 kernel/futex_compat.c compat_exit_robust_list(): get_user() 64 ulong -> int (compat_long_t), int max
-+	if (gimple_code(def_stmt) == GIMPLE_ASM)
-+		return true;
-+
-+	if (is_const_plus_unsigned_signed_truncation(rhs)) {
-+		pointer_set_insert(visited->no_cast_check, stmt);
-+		return true;
+ 
+ 	return err;
+ }
+diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
+index 6a5e151..f2fbaf5 100644
+--- a/scripts/mod/modpost.h
++++ b/scripts/mod/modpost.h
+@@ -98,15 +98,15 @@ void *do_nofail(void *ptr, const char *expr);
+ 
+ struct buffer {
+ 	char *p;
+-	int pos;
+-	int size;
++	unsigned int pos;
++	unsigned int size;
+ };
+ 
+ void __attribute__((format(printf, 2, 3)))
+ buf_printf(struct buffer *buf, const char *fmt, ...);
+ 
+ void
+-buf_write(struct buffer *buf, const char *s, int len);
++buf_write(struct buffer *buf, const char *s, unsigned int len);
+ 
+ struct module {
+ 	struct module *next;
+diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
+index 944418d..15291e4 100644
+--- a/scripts/mod/sumversion.c
++++ b/scripts/mod/sumversion.c
+@@ -470,7 +470,7 @@ static void write_version(const char *filename, const char *sum,
+ 		goto out;
+ 	}
+ 
+-	if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
++	if (write(fd, sum, strlen(sum)+1) != (ssize_t)strlen(sum)+1) {
+ 		warn("writing sum in %s failed: %s\n",
+ 			filename, strerror(errno));
+ 		goto out;
+diff --git a/scripts/module-common.lds b/scripts/module-common.lds
+index 73a2c7d..df11b31 100644
+--- a/scripts/module-common.lds
++++ b/scripts/module-common.lds
+@@ -6,6 +6,10 @@
+ SECTIONS {
+ 	/DISCARD/ : { *(.discard) }
+ 
++	.rodata			0: {
++		*(.rodata) *(.rodata.*)
++		*(.data..read_only)
 +	}
+ 	__ksymtab		0 : { *(SORT(___ksymtab+*)) }
+ 	__ksymtab_gpl		0 : { *(SORT(___ksymtab_gpl+*)) }
+ 	__ksymtab_unused	0 : { *(SORT(___ksymtab_unused+*)) }
+diff --git a/scripts/package/Makefile b/scripts/package/Makefile
+index c2c7389..81b8117 100644
+--- a/scripts/package/Makefile
++++ b/scripts/package/Makefile
+@@ -40,7 +40,7 @@ if test "$(objtree)" != "$(srctree)"; then \
+ fi ; \
+ $(srctree)/scripts/setlocalversion --save-scmversion; \
+ ln -sf $(srctree) $(2); \
+-tar -cz $(RCS_TAR_IGNORE) -f $(2).tar.gz \
++tar --owner=root --group=root -cz $(RCS_TAR_IGNORE) -f $(2).tar.gz \
+ 	$(addprefix $(2)/,$(TAR_CONTENT) $(3)); \
+ rm -f $(2) $(objtree)/.scmversion
+ 
+diff --git a/scripts/package/builddeb b/scripts/package/builddeb
+index 6c3b038..4bac93f 100755
+--- a/scripts/package/builddeb
++++ b/scripts/package/builddeb
+@@ -326,6 +326,7 @@ fi
+ (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
+ (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
+ (cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
++(cd $objtree; find scripts/gcc-plugins -name \*.so -o -name gcc-common.h) >> "$objtree/debian/hdrobjfiles"
+ destdir=$kernel_headers_dir/usr/src/linux-headers-$version
+ mkdir -p "$destdir"
+ (cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
+diff --git a/scripts/package/mkspec b/scripts/package/mkspec
+index fe44d68..3874acb 100755
+--- a/scripts/package/mkspec
++++ b/scripts/package/mkspec
+@@ -120,29 +120,40 @@ echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/{build,source}"
+ echo "mkdir -p "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE"
+ echo "EXCLUDES=\"$RCS_TAR_IGNORE --exclude .tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude=firmware --exclude .config.old --exclude .missing-syscalls.d\""
+ echo "tar "'$EXCLUDES'" -cf- . | (cd "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE;tar xvf -)"
+-echo 'cd $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE"
+-echo "ln -sf /usr/src/kernels/$KERNELRELEASE build"
+-echo "ln -sf /usr/src/kernels/$KERNELRELEASE source"
+ fi
+ 
+ echo ""
+ echo "%clean"
+ echo 'rm -rf $RPM_BUILD_ROOT'
+ echo ""
++echo "%pre"
++echo 'chmod -f 0500 /boot'
++echo 'if [ -d /lib/modules ]; then'
++echo 'chmod -f 0500 /lib/modules'
++echo 'fi'
++echo 'if [ -d /lib32/modules ]; then'
++echo 'chmod -f 0500 /lib32/modules'
++echo 'fi'
++echo 'if [ -d /lib64/modules ]; then'
++echo 'chmod -f 0500 /lib64/modules'
++echo 'fi'
++echo ""
++echo "%post devel"
++echo "ln -sf /usr/src/kernels/$KERNELRELEASE /lib/modules/$KERNELRELEASE/build"
++echo "ln -sf /usr/src/kernels/$KERNELRELEASE /lib/modules/$KERNELRELEASE/source"
++echo ""
+ echo "%post"
+-echo "if [ -x /sbin/installkernel -a -r /boot/vmlinuz-$KERNELRELEASE -a -r /boot/System.map-$KERNELRELEASE ]; then"
+-echo "cp /boot/vmlinuz-$KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm"
+-echo "cp /boot/System.map-$KERNELRELEASE /boot/.System.map-$KERNELRELEASE-rpm"
+-echo "rm -f /boot/vmlinuz-$KERNELRELEASE /boot/System.map-$KERNELRELEASE"
+-echo "/sbin/installkernel $KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm"
+-echo "rm -f /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm"
++echo "if [ -x /sbin/dracut ]; then"
++echo '/sbin/new-kernel-pkg --dracut --mkinitrd --depmod --install --make-default '"$KERNELRELEASE"' || exit $?'
++echo "else"
++echo '/sbin/new-kernel-pkg --mkinitrd --depmod --install --make-default '"$KERNELRELEASE"' || exit $?'
+ echo "fi"
+ echo ""
+ echo "%files"
+-echo '%defattr (-, root, root)'
+-echo "/lib/modules/$KERNELRELEASE"
++echo '%defattr (400, root, root, 500)'
+ echo "%exclude /lib/modules/$KERNELRELEASE/build"
+ echo "%exclude /lib/modules/$KERNELRELEASE/source"
++echo "/lib/modules/$KERNELRELEASE"
+ echo "/lib/firmware/$KERNELRELEASE"
+ echo "/boot/*"
+ echo ""
+@@ -152,9 +163,11 @@ echo "/usr/include"
+ echo ""
+ if ! $PREBUILT; then
+ echo "%files devel"
+-echo '%defattr (-, root, root)'
++echo '%defattr (400, root, root, 500)'
++echo "%dir /lib/modules/$KERNELRELEASE"
+ echo "/usr/src/kernels/$KERNELRELEASE"
+-echo "/lib/modules/$KERNELRELEASE/build"
+-echo "/lib/modules/$KERNELRELEASE/source"
++echo "%attr (500, root, root) /usr/src/kernels/$KERNELRELEASE/scripts/recordmcount"
++echo "%attr (500, root, root) /usr/src/kernels/$KERNELRELEASE/scripts/basic/fixdep"
++echo "%attr (500, root, root) /usr/src/kernels/$KERNELRELEASE/scripts/mod/modpost"
+ echo ""
+ fi
+diff --git a/scripts/pnmtologo.c b/scripts/pnmtologo.c
+index 4718d78..9220d58 100644
+--- a/scripts/pnmtologo.c
++++ b/scripts/pnmtologo.c
+@@ -244,14 +244,14 @@ static void write_header(void)
+     fprintf(out, " *  Linux logo %s\n", logoname);
+     fputs(" */\n\n", out);
+     fputs("#include <linux/linux_logo.h>\n\n", out);
+-    fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
++    fprintf(out, "static unsigned char %s_data[] = {\n",
+ 	    logoname);
+ }
+ 
+ static void write_footer(void)
+ {
+     fputs("\n};\n\n", out);
+-    fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
++    fprintf(out, "const struct linux_logo %s = {\n", logoname);
+     fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
+     fprintf(out, "\t.width\t\t= %d,\n", logo_width);
+     fprintf(out, "\t.height\t\t= %d,\n", logo_height);
+@@ -381,7 +381,7 @@ static void write_logo_clut224(void)
+     fputs("\n};\n\n", out);
+ 
+     /* write logo clut */
+-    fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
++    fprintf(out, "static unsigned char %s_clut[] = {\n",
+ 	    logoname);
+     write_hex_cnt = 0;
+     for (i = 0; i < logo_clutsize; i++) {
+diff --git a/scripts/sortextable.h b/scripts/sortextable.h
+index ba87004..3f4852c 100644
+--- a/scripts/sortextable.h
++++ b/scripts/sortextable.h
+@@ -108,9 +108,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
+ 	const char *secstrtab;
+ 	const char *strtab;
+ 	char *extab_image;
+-	int extab_index = 0;
+-	int i;
+-	int idx;
++	unsigned int extab_index = 0;
++	unsigned int i;
++	unsigned int idx;
+ 	unsigned int num_sections;
+ 	unsigned int secindex_strings;
+ 
+diff --git a/scripts/tags.sh b/scripts/tags.sh
+index 23ba1c6..cad2484 100755
+--- a/scripts/tags.sh
++++ b/scripts/tags.sh
+@@ -26,7 +26,7 @@ else
+ fi
+ 
+ # ignore userspace tools
+-ignore="$ignore ( -path ${tree}tools ) -prune -o"
++ignore="$ignore ( -path \"${tree}tools/[^g]*\" ) -prune -o"
+ 
+ # Find all available archs
+ find_all_archs()
+diff --git a/security/Kconfig b/security/Kconfig
+index e452378..8059bd2 100644
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -4,6 +4,993 @@
+ 
+ menu "Security options"
+ 
++menu "Grsecurity"
 +
-+	return false;
-+}
-+
-+static tree create_string_param(tree string)
-+{
-+	tree i_type, a_type;
-+	const int length = TREE_STRING_LENGTH(string);
++	config ARCH_TRACK_EXEC_LIMIT
++	bool
 +
-+	gcc_assert(length > 0);
++	config PAX_KERNEXEC_PLUGIN
++	bool
++	depends on GCC_PLUGINS
 +
-+	i_type = build_index_type(build_int_cst(NULL_TREE, length - 1));
-+	a_type = build_array_type(char_type_node, i_type);
++	config PAX_PER_CPU_PGD
++	bool
 +
-+	TREE_TYPE(string) = a_type;
-+	TREE_CONSTANT(string) = 1;
-+	TREE_READONLY(string) = 1;
++	config TASK_SIZE_MAX_SHIFT
++	int
++	depends on X86_64
++	default 47 if !PAX_PER_CPU_PGD
++	default 42 if PAX_PER_CPU_PGD
 +
-+	return build1(ADDR_EXPR, ptr_type_node, string);
-+}
++	config PAX_ENABLE_PAE
++	bool
++	default y if (X86_32 && (MPENTIUM4 || MK8 || MPSC || MCORE2 || MATOM))
++	
++	config PAX_USERCOPY_SLABS
++	bool
 +
-+static void insert_cond(basic_block cond_bb, tree arg, enum tree_code cond_code, tree type_value)
-+{
-+	gcond *cond_stmt;
-+	gimple_stmt_iterator gsi = gsi_last_bb(cond_bb);
++config GRKERNSEC
++	bool "Grsecurity"
++	select CRYPTO
++	select CRYPTO_SHA256
++	select PROC_FS
++	select STOP_MACHINE
++	select TTY
++	select DEBUG_KERNEL
++	select DEBUG_LIST
++	select MULTIUSER
++	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
++	  recommended that you say Y here and read through the help
++	  for each option so that you fully understand the features and
++	  can evaluate their usefulness for your machine.
 +
-+	cond_stmt = gimple_build_cond(cond_code, arg, type_value, NULL_TREE, NULL_TREE);
-+	gsi_insert_after(&gsi, cond_stmt, GSI_CONTINUE_LINKING);
-+	update_stmt(cond_stmt);
-+}
++choice
++	prompt "Configuration Method"
++	depends on GRKERNSEC
++	default GRKERNSEC_CONFIG_CUSTOM
++	help
 +
-+static void insert_cond_result(interesting_stmts_t expand_from, basic_block bb_true, const_gimple stmt, const_tree arg, bool min)
-+{
-+	gcall *func_stmt;
-+	const_gimple def_stmt;
-+	const_tree loc_line;
-+	tree loc_file, ssa_name, current_func;
-+	expanded_location xloc;
-+	char *ssa_name_buf;
-+	int len;
-+	struct cgraph_edge *edge;
-+	struct cgraph_node *report_node;
-+	int frequency;
-+	gimple_stmt_iterator gsi = gsi_start_bb(bb_true);
++config GRKERNSEC_CONFIG_AUTO
++	bool "Automatic"
++	help
++	  If you choose this configuration method, you'll be able to answer a small
++	  number of simple questions about how you plan to use this kernel.
++	  The settings of grsecurity and PaX will be automatically configured for
++	  the highest commonly-used settings within the provided constraints.
 +
-+	def_stmt = get_def_stmt(arg);
-+	if (gimple_has_location(def_stmt))
-+		xloc = expand_location(gimple_location(def_stmt));
-+	else if (gimple_has_location(stmt))
-+		xloc = expand_location(gimple_location(stmt));
-+	else
-+		xloc = expand_location(DECL_SOURCE_LOCATION(current_function_decl));
++	  If you require additional configuration, custom changes can still be made
++	  from the "custom configuration" menu.
 +
-+	loc_line = build_int_cstu(unsigned_type_node, xloc.line);
++config GRKERNSEC_CONFIG_CUSTOM
++	bool "Custom"
++	help
++	  If you choose this configuration method, you'll be able to configure all
++	  grsecurity and PaX settings manually.  Via this method, no options are
++	  automatically enabled.
 +
-+	loc_file = build_string(strlen(xloc.file) + 1, xloc.file);
-+	loc_file = create_string_param(loc_file);
++	  Take note that if menuconfig is exited with this configuration method
++	  chosen, you will not be able to use the automatic configuration methods
++	  without starting again with a kernel configuration with no grsecurity
++	  or PaX options specified inside.
 +
-+	current_func = build_string(DECL_NAME_LENGTH(current_function_decl) + 1, DECL_NAME_POINTER(current_function_decl));
-+	current_func = create_string_param(current_func);
++endchoice
 +
-+	gcc_assert(DECL_NAME(SSA_NAME_VAR(arg)) != NULL);
-+	call_count++;
-+	len = asprintf(&ssa_name_buf, "%s_%u %s, count: %u, decl: %s; num: %u; context: %s;\n", DECL_NAME_POINTER(SSA_NAME_VAR(arg)), SSA_NAME_VERSION(arg), min ? "min" : "max", call_count, expand_from->next_node->decl_name, expand_from->next_node->num, expand_from->next_node->context);
-+	gcc_assert(len > 0);
-+	ssa_name = build_string(len + 1, ssa_name_buf);
-+	free(ssa_name_buf);
-+	ssa_name = create_string_param(ssa_name);
++choice
++	prompt "Usage Type"
++	depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO)
++	default GRKERNSEC_CONFIG_SERVER
++	help
 +
-+	// void report_size_overflow(const char *file, unsigned int line, const char *func, const char *ssa_name)
-+	func_stmt = as_a_gcall(gimple_build_call(report_size_overflow_decl, 4, loc_file, loc_line, current_func, ssa_name));
-+	gsi_insert_after(&gsi, func_stmt, GSI_CONTINUE_LINKING);
++config GRKERNSEC_CONFIG_SERVER
++	bool "Server"
++	help
++	  Choose this option if you plan to use this kernel on a server.
 +
-+	report_node = cgraph_get_create_node(report_size_overflow_decl);
-+	gcc_assert(report_node);
-+	frequency = compute_call_stmt_bb_frequency(current_function_decl, bb_true);
++config GRKERNSEC_CONFIG_DESKTOP
++	bool "Desktop"
++	help
++	  Choose this option if you plan to use this kernel on a desktop.
 +
-+	edge = cgraph_create_edge(get_cnode(current_function_decl), report_node, func_stmt, bb_true->count, frequency, bb_true->loop_depth);
-+	gcc_assert(edge != NULL);
-+}
++endchoice
 +
-+static void insert_check_size_overflow(interesting_stmts_t expand_from, gimple stmt, enum tree_code cond_code, tree arg, tree type_value, bool before, bool min)
-+{
-+	basic_block cond_bb, join_bb, bb_true;
-+	edge e;
-+	gimple_stmt_iterator gsi = gsi_for_stmt(stmt);
++choice
++	prompt "Virtualization Type"
++	depends on (GRKERNSEC && X86 && GRKERNSEC_CONFIG_AUTO)
++	default GRKERNSEC_CONFIG_VIRT_NONE
++	help
 +
-+	cond_bb = gimple_bb(stmt);
-+	if (before)
-+		gsi_prev(&gsi);
-+	if (gsi_end_p(gsi))
-+		e = split_block_after_labels(cond_bb);
-+	else
-+		e = split_block(cond_bb, gsi_stmt(gsi));
-+	cond_bb = e->src;
-+	join_bb = e->dest;
-+	e->flags = EDGE_FALSE_VALUE;
-+	e->probability = REG_BR_PROB_BASE;
++config GRKERNSEC_CONFIG_VIRT_NONE
++	bool "None"
++	help
++	  Choose this option if this kernel will be run on bare metal.
 +
-+	bb_true = create_empty_bb(cond_bb);
-+	make_edge(cond_bb, bb_true, EDGE_TRUE_VALUE);
-+	make_edge(cond_bb, join_bb, EDGE_FALSE_VALUE);
-+	make_edge(bb_true, join_bb, EDGE_FALLTHRU);
++config GRKERNSEC_CONFIG_VIRT_GUEST
++	bool "Guest"
++	help
++	  Choose this option if this kernel will be run as a VM guest.
 +
-+	gcc_assert(dom_info_available_p(CDI_DOMINATORS));
-+	set_immediate_dominator(CDI_DOMINATORS, bb_true, cond_bb);
-+	set_immediate_dominator(CDI_DOMINATORS, join_bb, cond_bb);
++config GRKERNSEC_CONFIG_VIRT_HOST
++	bool "Host"
++	help
++	  Choose this option if this kernel will be run as a VM host.
 +
-+	if (current_loops != NULL) {
-+		gcc_assert(cond_bb->loop_father == join_bb->loop_father);
-+		add_bb_to_loop(bb_true, cond_bb->loop_father);
-+	}
++endchoice
 +
-+	insert_cond(cond_bb, arg, cond_code, type_value);
-+	insert_cond_result(expand_from, bb_true, stmt, arg, min);
++choice
++	prompt "Virtualization Hardware"
++	depends on (GRKERNSEC && X86 && GRKERNSEC_CONFIG_AUTO && (GRKERNSEC_CONFIG_VIRT_GUEST || GRKERNSEC_CONFIG_VIRT_HOST))
++	help
 +
-+//	print_the_code_insertions(stmt);
-+}
++config GRKERNSEC_CONFIG_VIRT_EPT
++	bool "EPT/RVI Processor Support"
++	depends on X86
++	help
++	  Choose this option if your CPU supports the EPT or RVI features of 2nd-gen
++	  hardware virtualization.  This allows for additional kernel hardening protections
++	  to operate without additional performance impact.
 +
-+void check_size_overflow(interesting_stmts_t expand_from, gimple stmt, tree size_overflow_type, tree cast_rhs, tree rhs, bool before)
-+{
-+	const_tree rhs_type = TREE_TYPE(rhs);
-+	tree cast_rhs_type, type_max_type, type_min_type, type_max, type_min;
++	  To see if your Intel processor supports EPT, see:
++	  http://ark.intel.com/Products/VirtualizationTechnology
++	  (Most Core i3/5/7 support EPT)
 +
-+	if (pointer_set_contains(expand_from->visited->no_cast_check, stmt))
-+		return;
++	  To see if your AMD processor supports RVI, see:
++	  http://support.amd.com/us/kbarticles/Pages/GPU120AMDRVICPUsHyperVWin8.aspx
 +
-+	gcc_assert(rhs_type != NULL_TREE);
-+	if (TREE_CODE(rhs_type) == POINTER_TYPE)
-+		return;
++config GRKERNSEC_CONFIG_VIRT_SOFT
++	bool "First-gen/No Hardware Virtualization"
++	help
++	  Choose this option if you use an Atom/Pentium/Core 2 processor that either doesn't
++	  support hardware virtualization or doesn't support the EPT/RVI extensions.
 +
-+	gcc_assert(TREE_CODE(rhs_type) == INTEGER_TYPE || TREE_CODE(rhs_type) == ENUMERAL_TYPE);
++endchoice
 +
-+	if (is_gimple_assign(stmt) && neg_short_add_intentional_overflow(as_a_gassign(stmt)))
-+		return;
++choice
++	prompt "Virtualization Software"
++	depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO && (GRKERNSEC_CONFIG_VIRT_GUEST || GRKERNSEC_CONFIG_VIRT_HOST))
++	help
 +
-+	type_max = cast_a_tree(size_overflow_type, TYPE_MAX_VALUE(rhs_type));
-+	// typemax (-1) < typemin (0)
-+	if (TREE_OVERFLOW(type_max))
-+		return;
++config GRKERNSEC_CONFIG_VIRT_XEN
++	bool "Xen"
++	help
++	  Choose this option if this kernel is running as a Xen guest or host.
 +
-+	type_min = cast_a_tree(size_overflow_type, TYPE_MIN_VALUE(rhs_type));
++config GRKERNSEC_CONFIG_VIRT_VMWARE
++	bool "VMWare"
++	help
++	  Choose this option if this kernel is running as a VMWare guest or host.
 +
-+	cast_rhs_type = TREE_TYPE(cast_rhs);
-+	type_max_type = TREE_TYPE(type_max);
-+	gcc_assert(types_compatible_p(cast_rhs_type, type_max_type));
++config GRKERNSEC_CONFIG_VIRT_KVM
++	bool "KVM"
++	help
++	  Choose this option if this kernel is running as a KVM guest or host.
 +
-+	insert_check_size_overflow(expand_from, stmt, GT_EXPR, cast_rhs, type_max, before, MAX_CHECK);
++config GRKERNSEC_CONFIG_VIRT_VIRTUALBOX
++	bool "VirtualBox"
++	help
++	  Choose this option if this kernel is running as a VirtualBox guest or host.
 +
-+	// special case: get_size_overflow_type(), 32, u64->s
-+	if (LONG_TYPE_SIZE == GET_MODE_BITSIZE(SImode) && TYPE_UNSIGNED(size_overflow_type) && !TYPE_UNSIGNED(rhs_type))
-+		return;
++config GRKERNSEC_CONFIG_VIRT_HYPERV
++	bool "Hyper-V"
++	help
++	  Choose this option if this kernel is running as a Hyper-V guest.
 +
-+	type_min_type = TREE_TYPE(type_min);
-+	gcc_assert(types_compatible_p(type_max_type, type_min_type));
-+	insert_check_size_overflow(expand_from, stmt, LT_EXPR, cast_rhs, type_min, before, MIN_CHECK);
-+}
++endchoice
 +
-+static tree get_my_stmt_lhs(struct visited *visited, gimple stmt)
-+{
-+	gimple_stmt_iterator gsi;
-+	gimple next_stmt = NULL;
++choice
++	prompt "Required Priorities"
++	depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO)
++	default GRKERNSEC_CONFIG_PRIORITY_PERF
++	help
 +
-+	gsi = gsi_for_stmt(stmt);
++config GRKERNSEC_CONFIG_PRIORITY_PERF
++	bool "Performance"
++	help
++	  Choose this option if performance is of highest priority for this deployment
++	  of grsecurity.  Features like UDEREF on a 64bit kernel, kernel stack clearing,
++	  clearing of structures intended for userland, and freed memory sanitizing will
++	  be disabled.
 +
-+	do {
-+		gsi_next(&gsi);
-+		next_stmt = gsi_stmt(gsi);
++config GRKERNSEC_CONFIG_PRIORITY_SECURITY
++	bool "Security"
++	help
++	  Choose this option if security is of highest priority for this deployment of
++	  grsecurity.  UDEREF, kernel stack clearing, clearing of structures intended
++	  for userland, and freed memory sanitizing will be enabled for this kernel.
++	  In a worst-case scenario, these features can introduce a 20% performance hit
++	  (UDEREF on x64 contributing half of this hit).
 +
-+		if (gimple_code(stmt) == GIMPLE_PHI && !pointer_set_contains(visited->my_stmts, next_stmt))
-+			return NULL_TREE;
++endchoice
 +
-+		if (pointer_set_contains(visited->my_stmts, next_stmt) && !pointer_set_contains(visited->skip_expr_casts, next_stmt))
-+			break;
++menu "Default Special Groups"
++depends on (GRKERNSEC && GRKERNSEC_CONFIG_AUTO)
 +
-+		gcc_assert(pointer_set_contains(visited->my_stmts, next_stmt));
-+	} while (!gsi_end_p(gsi));
++config GRKERNSEC_PROC_GID
++	int "GID exempted from /proc restrictions"
++	default 1001
++	help
++	  Setting this GID determines which group will be exempted from
++	  grsecurity's /proc restrictions, allowing users of the specified
++	  group  to view network statistics and the existence of other users'
++	  processes on the system.  This GID may also be chosen at boot time
++	  via "grsec_proc_gid=" on the kernel commandline.
 +
-+	gcc_assert(next_stmt);
-+	return get_lhs(next_stmt);
-+}
++config GRKERNSEC_TPE_UNTRUSTED_GID
++        int "GID for TPE-untrusted users"
++        depends on GRKERNSEC_CONFIG_SERVER && GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
++        default 1005
++        help
++	  Setting this GID determines which group untrusted users should
++	  be added to.  These users will be placed under grsecurity's Trusted Path
++	  Execution mechanism, preventing them from executing their own binaries.
++	  The users will only be able to execute binaries in directories owned and
++	  writable only by the root user.  If the sysctl option is enabled, a sysctl
++	  option with name "tpe_gid" is created.
 +
-+/* When the result of the negation is cast to a signed type then move
-+ * the size_overflow cast check before negation.
-+ * ssa:
-+ * unsigned _588
-+ * _588 = _587 >> 12;
-+ * _589 = -_588;
-+ * _590 = (long int) _589;
-+ */
-+static bool handle_unsigned_neg_or_bit_not(interesting_stmts_t expand_from, const gassign *stmt)
-+{
-+	gimple def_neg_stmt, neg_stmt;
-+	tree lhs, new_neg_rhs;
-+	const_tree rhs, neg_rhs;
-+	enum tree_code rhs_code;
++config GRKERNSEC_TPE_TRUSTED_GID
++        int "GID for TPE-trusted users"
++        depends on GRKERNSEC_CONFIG_SERVER && GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
++        default 1005
++        help
++          Setting this GID determines what group TPE restrictions will be
++          *disabled* for.  If the sysctl option is enabled, a sysctl option
++          with name "tpe_gid" is created.
 +
-+	rhs = gimple_assign_rhs1(stmt);
-+	lhs = gimple_assign_lhs(stmt);
-+	if (TYPE_UNSIGNED(TREE_TYPE(lhs)) || !TYPE_UNSIGNED(TREE_TYPE(rhs)))
-+		return false;
++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.
 +
-+	neg_stmt = get_def_stmt(rhs);
-+	if (!neg_stmt || !is_gimple_assign(neg_stmt))
-+		return false;
 +
-+	rhs_code = gimple_assign_rhs_code(neg_stmt);
-+	if (rhs_code != BIT_NOT_EXPR && rhs_code != NEGATE_EXPR)
-+		return false;
++endmenu
 +
-+	neg_rhs = gimple_assign_rhs1(neg_stmt);
-+	def_neg_stmt = get_def_stmt(neg_rhs);
-+	if (!def_neg_stmt)
-+		return false;
++menu "Customize Configuration"
++depends on GRKERNSEC
 +
-+	new_neg_rhs = get_my_stmt_lhs(expand_from->visited, def_neg_stmt);
-+	check_size_overflow(expand_from, neg_stmt, TREE_TYPE(new_neg_rhs), new_neg_rhs, lhs, BEFORE_STMT);
-+	pointer_set_insert(expand_from->visited->no_cast_check, stmt);
-+	return true;
-+}
++menu "PaX"
 +
-+static tree create_cast_overflow_check(interesting_stmts_t expand_from, tree new_rhs1, gassign *stmt)
-+{
-+	bool cast_lhs, cast_rhs;
-+	tree lhs = gimple_assign_lhs(stmt);
-+	tree rhs = gimple_assign_rhs1(stmt);
-+	const_tree lhs_type = TREE_TYPE(lhs);
-+	const_tree rhs_type = TREE_TYPE(rhs);
-+	enum machine_mode lhs_mode = TYPE_MODE(lhs_type);
-+	enum machine_mode rhs_mode = TYPE_MODE(rhs_type);
-+	unsigned int lhs_size = GET_MODE_BITSIZE(lhs_mode);
-+	unsigned int rhs_size = GET_MODE_BITSIZE(rhs_mode);
++config PAX
++	bool "Enable various PaX features"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on GRKERNSEC && (ALPHA || ARM || AVR32 || IA64 || MIPS || PARISC || PPC || SPARC || X86)
++	help
++	  This allows you to enable various PaX features.  PaX adds
++	  intrusion prevention mechanisms to the kernel that reduce
++	  the risks posed by exploitable memory corruption bugs.
 +
-+	static bool check_lhs[3][4] = {
-+		// ss    su     us     uu
-+		{ false, true,  true,  false }, // lhs > rhs
-+		{ false, false, false, false }, // lhs = rhs
-+		{ true,  true,  true,  true  }, // lhs < rhs
-+	};
++menu "PaX Control"
++	depends on PAX
 +
-+	static bool check_rhs[3][4] = {
-+		// ss    su     us     uu
-+		{ true,  false, true,  true  }, // lhs > rhs
-+		{ true,  false, true,  true  }, // lhs = rhs
-+		{ true,  false, true,  true  }, // lhs < rhs
-+	};
++config PAX_SOFTMODE
++	bool 'Support soft mode'
++	help
++	  Enabling this option will allow you to run PaX in soft mode, that
++	  is, PaX features will not be enforced by default, only on executables
++	  marked explicitly.  You must also enable PT_PAX_FLAGS or XATTR_PAX_FLAGS
++	  support as they are the only way to mark executables for soft mode use.
 +
-+	if (handle_unsigned_neg_or_bit_not(expand_from, stmt))
-+		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
++	  Soft mode can be activated by using the "pax_softmode=1" kernel command
++	  line option on boot.  Furthermore you can control various PaX features
++	  at runtime via the entries in /proc/sys/kernel/pax.
 +
-+	// skip lhs check on HI -> QI cast
-+	if (rhs_mode == HImode && lhs_mode == QImode) {
-+		pointer_set_insert(expand_from->visited->no_cast_check, stmt);
-+		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
-+	}
++config PAX_EI_PAX
++	bool 'Use legacy ELF header marking'
++	default y if GRKERNSEC_CONFIG_AUTO
++	help
++	  Enabling this option will allow you to control PaX features on
++	  a per executable basis via the 'chpax' utility available at
++	  http://pax.grsecurity.net/.  The control flags will be read from
++	  an otherwise reserved part of the ELF header.  This marking has
++	  numerous drawbacks (no support for soft-mode, toolchain does not
++	  know about the non-standard use of the ELF header) therefore it
++	  has been deprecated in favour of PT_PAX_FLAGS and XATTR_PAX_FLAGS
++	  support.
 +
-+	// skip lhs check on signed SI -> HI cast or signed SI -> QI cast
-+	if (rhs_mode == SImode && !TYPE_UNSIGNED(rhs_type) && (lhs_mode == HImode || lhs_mode == QImode))
-+		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++	  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 (lhs_size > rhs_size) {
-+		cast_lhs = check_lhs[0][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
-+		cast_rhs = check_rhs[0][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
-+	} else if (lhs_size == rhs_size) {
-+		cast_lhs = check_lhs[1][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
-+		cast_rhs = check_rhs[1][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
-+	} else {
-+		cast_lhs = check_lhs[2][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
-+		cast_rhs = check_rhs[2][TYPE_UNSIGNED(rhs_type) + 2 * TYPE_UNSIGNED(lhs_type)];
-+	}
++	  If you enable none of the marking options then all applications
++	  will run with PaX enabled on them by default.
 +
-+	if (!cast_lhs && !cast_rhs)
-+		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
++config PAX_PT_PAX_FLAGS
++	bool 'Use ELF program header marking'
++	default y if GRKERNSEC_CONFIG_AUTO
++	help
++	  Enabling this option will allow you to control PaX features on
++	  a per executable basis via the 'paxctl' utility available at
++	  http://pax.grsecurity.net/.  The control flags will be read from
++	  a PaX specific ELF program header (PT_PAX_FLAGS).  This marking
++	  has the benefits of supporting both soft mode and being fully
++	  integrated into the toolchain (the binutils patch is available
++	  from http://pax.grsecurity.net).
 +
-+	if (cast_lhs && !skip_lhs_cast_check(expand_from->visited, stmt))
-+		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs1), new_rhs1, lhs, BEFORE_STMT);
++	  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 (cast_rhs)
-+		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs1), new_rhs1, rhs, BEFORE_STMT);
++	  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.
 +
-+	return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
-+}
++	  If you enable none of the marking options then all applications
++	  will run with PaX enabled on them by default.
 +
-+static tree handle_unary_rhs(interesting_stmts_t expand_from, gassign *stmt)
-+{
-+	enum tree_code rhs_code;
-+	tree rhs1, new_rhs1, lhs = gimple_assign_lhs(stmt);
++config PAX_XATTR_PAX_FLAGS
++	bool 'Use filesystem extended attributes marking'
++	default y if GRKERNSEC_CONFIG_AUTO
++	select CIFS_XATTR if CIFS
++	select EXT2_FS_XATTR if EXT2_FS
++	select EXT3_FS_XATTR if EXT3_FS
++	select F2FS_FS_XATTR if F2FS_FS
++	select JFFS2_FS_XATTR if JFFS2_FS
++	select REISERFS_FS_XATTR if REISERFS_FS
++	select SQUASHFS_XATTR if SQUASHFS
++	select TMPFS_XATTR if TMPFS
++	help
++	  Enabling this option will allow you to control PaX features on
++	  a per executable basis via the 'setfattr' utility.  The control
++	  flags will be read from the user.pax.flags extended attribute of
++	  the file.  This marking has the benefit of supporting binary-only
++	  applications that self-check themselves (e.g., skype) and would
++	  not tolerate chpax/paxctl changes.  The main drawback is that
++	  extended attributes are not supported by some filesystems (e.g.,
++	  isofs, udf, vfat) so copying files through such filesystems will
++	  lose the extended attributes and these PaX markings.
 +
-+	if (pointer_set_contains(expand_from->visited->my_stmts, stmt))
-+		return lhs;
++	  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.
 +
-+	rhs1 = gimple_assign_rhs1(stmt);
-+	if (TREE_CODE(TREE_TYPE(rhs1)) == POINTER_TYPE)
-+		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++	  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.
 +
-+	new_rhs1 = expand(expand_from, rhs1);
++	  If you enable none of the marking options then all applications
++	  will run with PaX enabled on them by default.
 +
-+	if (new_rhs1 == NULL_TREE)
-+		return create_cast_assign(expand_from->visited, stmt);
++choice
++	prompt 'MAC system integration'
++	default PAX_HAVE_ACL_FLAGS
++	help
++	  Mandatory Access Control systems have the option of controlling
++	  PaX flags on a per executable basis, choose the method supported
++	  by your particular system.
 +
-+	if (pointer_set_contains(expand_from->visited->no_cast_check, stmt))
-+		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
++	  - "none": if your MAC system does not interact with PaX,
++	  - "direct": if your MAC system defines pax_set_initial_flags() itself,
++	  - "hook": if your MAC system uses the pax_set_initial_flags_func callback.
 +
-+#if BUILDING_GCC_VERSION >= 5000
-+	if (short_or_neg_const_ushort(stmt)) {
-+		pointer_set_insert(expand_from->visited->no_cast_check, stmt);
-+		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
-+	}
-+#endif
++	  NOTE: this option is for developers/integrators only.
 +
-+	rhs_code = gimple_assign_rhs_code(stmt);
-+	if (rhs_code == BIT_NOT_EXPR || rhs_code == NEGATE_EXPR) {
-+		tree size_overflow_type = get_size_overflow_type(expand_from->visited, stmt, rhs1);
++	config PAX_NO_ACL_FLAGS
++		bool 'none'
 +
-+		new_rhs1 = cast_to_new_size_overflow_type(expand_from->visited, stmt, new_rhs1, size_overflow_type, BEFORE_STMT);
-+		check_size_overflow(expand_from, stmt, size_overflow_type, new_rhs1, rhs1, BEFORE_STMT);
-+		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
-+	}
++	config PAX_HAVE_ACL_FLAGS
++		bool 'direct'
 +
-+	if (!gimple_assign_cast_p(stmt))
-+		return dup_assign(expand_from->visited, stmt, lhs, new_rhs1, NULL_TREE, NULL_TREE);
++	config PAX_HOOK_ACL_FLAGS
++		bool 'hook'
++endchoice
 +
-+	return create_cast_overflow_check(expand_from, new_rhs1, stmt);
-+}
++endmenu
 +
-+static tree handle_unary_ops(interesting_stmts_t expand_from, gassign *stmt)
-+{
-+	tree rhs1, lhs = gimple_assign_lhs(stmt);
-+	gimple def_stmt = get_def_stmt(lhs);
++menu "Non-executable pages"
++	depends on PAX
 +
-+	gcc_assert(gimple_code(def_stmt) != GIMPLE_NOP);
-+	rhs1 = gimple_assign_rhs1(def_stmt);
++config PAX_NOEXEC
++	bool "Enforce non-executable pages"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on ALPHA || (ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || IA64 || MIPS || PARISC || PPC || S390 || SPARC || X86
++	help
++	  By design some architectures do not allow for protecting memory
++	  pages against execution or even if they do, Linux does not make
++	  use of this feature.  In practice this means that if a page is
++	  readable (such as the stack or heap) it is also executable.
 +
-+	if (is_gimple_constant(rhs1))
-+		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
++	  There is a well known exploit technique that makes use of this
++	  fact and a common programming mistake where an attacker can
++	  introduce code of his choice somewhere in the attacked program's
++	  memory (typically the stack or the heap) and then execute it.
 +
-+	switch (TREE_CODE(rhs1)) {
-+	case SSA_NAME: {
-+		tree ret = handle_unary_rhs(expand_from, as_a_gassign(def_stmt));
++	  If the attacked program was running with different (typically
++	  higher) privileges than that of the attacker, then he can elevate
++	  his own privilege level (e.g. get a root shell, write to files for
++	  which he does not have write access to, etc).
 +
-+		if (gimple_assign_cast_p(stmt))
-+			unsigned_signed_cast_intentional_overflow(expand_from->visited, stmt);
-+		return ret;
-+	}
-+	case ARRAY_REF:
-+	case BIT_FIELD_REF:
-+	case ADDR_EXPR:
-+	case COMPONENT_REF:
-+	case INDIRECT_REF:
-+#if BUILDING_GCC_VERSION >= 4006
-+	case MEM_REF:
-+#endif
-+	case TARGET_MEM_REF:
-+	case VIEW_CONVERT_EXPR:
-+		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
-+	case PARM_DECL:
-+	case VAR_DECL:
-+		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++	  Enabling this option will let you choose from various features
++	  that prevent the injection and execution of 'foreign' code in
++	  a program.
 +
-+	default:
-+		debug_gimple_stmt(def_stmt);
-+		debug_tree(rhs1);
-+		gcc_unreachable();
-+	}
-+}
++	  This will also break programs that rely on the old behaviour and
++	  expect that dynamically allocated memory via the malloc() family
++	  of functions is executable (which it is not).  Notable examples
++	  are the XFree86 4.x server, the java runtime and wine.
 +
-+static void __unused print_the_code_insertions(const_gimple stmt)
-+{
-+	location_t loc = gimple_location(stmt);
++config PAX_PAGEEXEC
++	bool "Paging based non-executable pages"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MATOM || MPENTIUM4 || MPSC || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2 || MVIAC7)
++	select ARCH_TRACK_EXEC_LIMIT if X86_32
++	help
++	  This implementation is based on the paging feature of the CPU.
++	  On i386 without hardware non-executable bit support there is a
++	  variable but usually low performance impact, however on Intel's
++	  P4 core based CPUs it is very high so you should not enable this
++	  for kernels meant to be used on such CPUs.
 +
-+	inform(loc, "Integer size_overflow check applied here.");
-+}
++	  On alpha, avr32, ia64, parisc, sparc, sparc64, x86_64 and i386
++	  with hardware non-executable bit support there is no performance
++	  impact, on ppc the impact is negligible.
 +
-+static bool is_from_cast(const_tree node)
-+{
-+	gimple def_stmt = get_def_stmt(node);
++	  Note that several architectures require various emulations due to
++	  badly designed userland ABIs, this will cause a performance impact
++	  but will disappear as soon as userland is fixed. For example, ppc
++	  userland MUST have been built with secure-plt by a recent toolchain.
 +
-+	if (!def_stmt)
-+		return false;
++config PAX_SEGMEXEC
++	bool "Segmentation based non-executable pages"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on PAX_NOEXEC && X86_32
++	help
++	  This implementation is based on the segmentation feature of the
++	  CPU and has a very small performance impact, however applications
++	  will be limited to a 1.5 GB address space instead of the normal
++	  3 GB.
 +
-+	if (gimple_assign_cast_p(def_stmt))
-+		return true;
++config PAX_EMUTRAMP
++	bool "Emulate trampolines"
++	default y if PARISC || GRKERNSEC_CONFIG_AUTO
++	depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || X86)
++	help
++	  There are some programs and libraries that for one reason or
++	  another attempt to execute special small code snippets from
++	  non-executable memory pages.  Most notable examples are the
++	  signal handler return code generated by the kernel itself and
++	  the GCC trampolines.
 +
-+	return false;
-+}
++	  If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
++	  such programs will no longer work under your kernel.
 +
-+// Skip duplication when there is a minus expr and the type of rhs1 or rhs2 is a pointer_type.
-+static bool is_ptr_diff(gassign *stmt)
-+{
-+	const_tree rhs1, rhs2, ptr1_rhs, ptr2_rhs;
++	  As a remedy you can say Y here and use the 'chpax' or 'paxctl'
++	  utilities to enable trampoline emulation for the affected programs
++	  yet still have the protection provided by the non-executable pages.
 +
-+	if (gimple_assign_rhs_code(stmt) != MINUS_EXPR)
-+		return false;
++	  On parisc you MUST enable this option and EMUSIGRT as well, otherwise
++	  your system will not even boot.
 +
-+	rhs1 = gimple_assign_rhs1(stmt);
-+	if (!is_from_cast(rhs1))
-+		return false;
++	  Alternatively you can say N here and use the 'chpax' or 'paxctl'
++	  utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
++	  for the affected files.
 +
-+	rhs2 = gimple_assign_rhs2(stmt);
-+	if (!is_from_cast(rhs2))
-+		return false;
++	  NOTE: enabling this feature *may* open up a loophole in the
++	  protection provided by non-executable pages that an attacker
++	  could abuse.  Therefore the best solution is to not have any
++	  files on your system that would require this option.  This can
++	  be achieved by not using libc5 (which relies on the kernel
++	  signal handler return code) and not using or rewriting programs
++	  that make use of the nested function implementation of GCC.
++	  Skilled users can just fix GCC itself so that it implements
++	  nested function calls in a way that does not interfere with PaX.
 +
-+	ptr1_rhs = gimple_assign_rhs1(get_def_stmt(rhs1));
-+	ptr2_rhs = gimple_assign_rhs1(get_def_stmt(rhs2));
++config PAX_EMUSIGRT
++	bool "Automatically emulate sigreturn trampolines"
++	depends on PAX_EMUTRAMP && PARISC
++	default y
++	help
++	  Enabling this option will have the kernel automatically detect
++	  and emulate signal return trampolines executing on the stack
++	  that would otherwise lead to task termination.
 +
-+	if (TREE_CODE(TREE_TYPE(ptr1_rhs)) != POINTER_TYPE && TREE_CODE(TREE_TYPE(ptr2_rhs)) != POINTER_TYPE)
-+		return false;
++	  This solution is intended as a temporary one for users with
++	  legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
++	  Modula-3 runtime, etc) or executables linked to such, basically
++	  everything that does not specify its own SA_RESTORER function in
++	  normal executable memory like glibc 2.1+ does.
 +
-+	return true;
-+}
++	  On parisc you MUST enable this option, otherwise your system will
++	  not even boot.
 +
-+static tree handle_comparison_code_class(interesting_stmts_t expand_from, gassign *stmt, tree new_rhs1, tree new_rhs2)
-+{
-+	tree rhs1, rhs2, lhs;
++	  NOTE: this feature cannot be disabled on a per executable basis
++	  and since it *does* open up a loophole in the protection provided
++	  by non-executable pages, the best solution is to not have any
++	  files on your system that would require this option.
 +
-+	rhs1 = gimple_assign_rhs1(stmt);
-+	if (!is_gimple_constant(rhs1) && new_rhs1 != NULL_TREE)
-+		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs1), new_rhs1, rhs1, BEFORE_STMT);
++config PAX_MPROTECT
++	bool "Restrict mprotect()"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on (PAX_PAGEEXEC || PAX_SEGMEXEC)
++	help
++	  Enabling this option will prevent programs from
++	   - changing the executable status of memory pages that were
++	     not originally created as executable,
++	   - making read-only executable pages writable again,
++	   - creating executable pages from anonymous memory,
++	   - making read-only-after-relocations (RELRO) data pages writable again.
 +
-+	lhs = gimple_assign_lhs(stmt);
-+	if (new_rhs2 == NULL_TREE)
-+		return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
++	  You should say Y here to complete the protection provided by
++	  the enforcement of non-executable pages.
 +
-+	rhs2 = gimple_assign_rhs2(stmt);
-+	if (!is_gimple_constant(rhs2))
-+		check_size_overflow(expand_from, stmt, TREE_TYPE(new_rhs2), new_rhs2, rhs2, BEFORE_STMT);
-+	return create_assign(expand_from->visited, stmt, lhs, AFTER_STMT);
-+}
++	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control
++	  this feature on a per file basis.
 +
-+static tree handle_binary_ops(interesting_stmts_t expand_from, tree lhs)
-+{
-+	enum intentional_overflow_type res;
-+	tree rhs1, rhs2, new_lhs;
-+	gassign *def_stmt = as_a_gassign(get_def_stmt(lhs));
-+	tree new_rhs1 = NULL_TREE;
-+	tree new_rhs2 = NULL_TREE;
++config PAX_MPROTECT_COMPAT
++	bool "Use legacy/compat protection demoting (read help)"
++	depends on PAX_MPROTECT
++	default n
++	help
++	  The current implementation of PAX_MPROTECT denies RWX allocations/mprotects
++	  by sending the proper error code to the application.  For some older
++	  userland, this can cause problems with applications that assume such
++	  allocations will not be prevented by PaX or SELinux and other access
++	  control systems and have no fallback mechanisms.  For modern distros,
++	  this option should generally be set to 'N'.
++	  
++config PAX_ELFRELOCS
++	bool "Allow ELF text relocations (read help)"
++	depends on PAX_MPROTECT
++	default n
++	help
++	  Non-executable pages and mprotect() restrictions are effective
++	  in preventing the introduction of new executable code into an
++	  attacked task's address space.  There remain only two venues
++	  for this kind of attack: if the attacker can execute already
++	  existing code in the attacked task then he can either have it
++	  create and mmap() a file containing his code or have it mmap()
++	  an already existing ELF library that does not have position
++	  independent code in it and use mprotect() on it to make it
++	  writable and copy his code there.  While protecting against
++	  the former approach is beyond PaX, the latter can be prevented
++	  by having only PIC ELF libraries on one's system (which do not
++	  need to relocate their code).  If you are sure this is your case,
++	  as is the case with all modern Linux distributions, then leave
++	  this option disabled.  You should say 'n' here.
 +
-+	if (is_ptr_diff(def_stmt))
-+		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
++config PAX_ETEXECRELOCS
++	bool "Allow ELF ET_EXEC text relocations"
++	depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
++	select PAX_ELFRELOCS
++	default y
++	help
++	  On some architectures there are incorrectly created applications
++	  that require text relocations and would not work without enabling
++	  this option.  If you are an alpha, ia64 or parisc user, you should
++	  enable this option and disable it once you have made sure that
++	  none of your applications need it.
 +
-+	rhs1 = gimple_assign_rhs1(def_stmt);
-+	rhs2 = gimple_assign_rhs2(def_stmt);
++config PAX_EMUPLT
++	bool "Automatically emulate ELF PLT"
++	depends on PAX_MPROTECT && (ALPHA || PARISC || SPARC)
++	default y
++	help
++	  Enabling this option will have the kernel automatically detect
++	  and emulate the Procedure Linkage Table entries in ELF files.
++	  On some architectures such entries are in writable memory, and
++	  become non-executable leading to task termination.  Therefore
++	  it is mandatory that you enable this option on alpha, parisc,
++	  sparc and sparc64, otherwise your system would not even boot.
 +
-+	/* no DImode/TImode division in the 32/64 bit kernel */
-+	switch (gimple_assign_rhs_code(def_stmt)) {
-+	case RDIV_EXPR:
-+	case TRUNC_DIV_EXPR:
-+	case CEIL_DIV_EXPR:
-+	case FLOOR_DIV_EXPR:
-+	case ROUND_DIV_EXPR:
-+	case TRUNC_MOD_EXPR:
-+	case CEIL_MOD_EXPR:
-+	case FLOOR_MOD_EXPR:
-+	case ROUND_MOD_EXPR:
-+	case EXACT_DIV_EXPR:
-+	case POINTER_PLUS_EXPR:
-+	case BIT_AND_EXPR:
-+		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
-+	default:
-+		break;
-+	}
++	  NOTE: this feature *does* open up a loophole in the protection
++	  provided by the non-executable pages, therefore the proper
++	  solution is to modify the toolchain to produce a PLT that does
++	  not need to be writable.
 +
-+	new_lhs = handle_integer_truncation(expand_from, lhs);
-+	if (new_lhs != NULL_TREE)
-+		return new_lhs;
++config PAX_DLRESOLVE
++	bool 'Emulate old glibc resolver stub'
++	depends on PAX_EMUPLT && SPARC
++	default n
++	help
++	  This option is needed if userland has an old glibc (before 2.4)
++	  that puts a 'save' instruction into the runtime generated resolver
++	  stub that needs special emulation.
 +
-+	if (TREE_CODE(rhs1) == SSA_NAME)
-+		new_rhs1 = expand(expand_from, rhs1);
-+	if (TREE_CODE(rhs2) == SSA_NAME)
-+		new_rhs2 = expand(expand_from, rhs2);
++config PAX_KERNEXEC
++	bool "Enforce non-executable kernel pages"
++	default y if GRKERNSEC_CONFIG_AUTO && (!X86 || GRKERNSEC_CONFIG_VIRT_NONE || (GRKERNSEC_CONFIG_VIRT_EPT && GRKERNSEC_CONFIG_VIRT_GUEST) || (GRKERNSEC_CONFIG_VIRT_EPT && GRKERNSEC_CONFIG_VIRT_KVM))
++	depends on (X86 || (ARM && (CPU_V6 || CPU_V6K || CPU_V7) && !(ARM_LPAE && MODULES))) && !XEN
++	select PAX_PER_CPU_PGD if X86_64 || (X86_32 && X86_PAE)
++	select PAX_KERNEXEC_PLUGIN if X86_64
++	select ARM_KERNMEM_PERMS if ARM
++	help
++	  This is the kernel land equivalent of PAGEEXEC and MPROTECT,
++	  that is, enabling this option will make it harder to inject
++	  and execute 'foreign' code in kernel memory itself.
 +
-+	res = add_mul_intentional_overflow(def_stmt);
-+	if (res != NO_INTENTIONAL_OVERFLOW) {
-+		new_lhs = dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, NULL_TREE);
-+		insert_cast_expr(expand_from->visited, as_a_gassign(get_def_stmt(new_lhs)), res);
-+		return new_lhs;
-+	}
++	  Note that on amd64, CONFIG_EFI enabled with "efi=old_map" on
++	  the kernel command-line will result in an RWX physical map.
 +
-+	if (skip_expr_on_double_type(def_stmt)) {
-+		new_lhs = dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, NULL_TREE);
-+		insert_cast_expr(expand_from->visited, as_a_gassign(get_def_stmt(new_lhs)), NO_INTENTIONAL_OVERFLOW);
-+		return new_lhs;
-+	}
++	  Likewise, the EFI runtime services are necessarily mapped as
++	  RWX.  If CONFIG_EFI is enabled on an EFI-capable system, it
++	  is recommended that you boot with "noefi" on the kernel
++	  command-line if possible to eliminate the mapping.
 +
-+	if (is_a_neg_overflow(def_stmt, rhs2))
-+		return handle_intentional_overflow(expand_from, true, def_stmt, new_rhs1, NULL_TREE);
-+	if (is_a_neg_overflow(def_stmt, rhs1))
-+		return handle_intentional_overflow(expand_from, true, def_stmt, new_rhs2, new_rhs2);
++choice
++	prompt "Return Address Instrumentation Method"
++	default PAX_KERNEXEC_PLUGIN_METHOD_BTS
++	depends on PAX_KERNEXEC_PLUGIN
++	help
++	  Select the method used to instrument function pointer dereferences.
++	  Note that binary modules cannot be instrumented by this approach.
 +
++	  Note that the implementation requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.
 +
-+	if (is_a_constant_overflow(def_stmt, rhs2))
-+		return handle_intentional_overflow(expand_from, !is_a_cast_and_const_overflow(rhs1), def_stmt, new_rhs1, NULL_TREE);
-+	if (is_a_constant_overflow(def_stmt, rhs1))
-+		return handle_intentional_overflow(expand_from, !is_a_cast_and_const_overflow(rhs2), def_stmt, new_rhs2, new_rhs2);
++	config PAX_KERNEXEC_PLUGIN_METHOD_BTS
++		bool "bts"
++		help
++		  This method is compatible with binary only modules but has
++		  a higher runtime overhead.
 +
-+	// the const is between 0 and (signed) MAX
-+	if (is_gimple_constant(rhs1))
-+		new_rhs1 = create_assign(expand_from->visited, def_stmt, rhs1, BEFORE_STMT);
-+	if (is_gimple_constant(rhs2))
-+		new_rhs2 = create_assign(expand_from->visited, def_stmt, rhs2, BEFORE_STMT);
++	config PAX_KERNEXEC_PLUGIN_METHOD_OR
++		bool "or"
++		depends on !PARAVIRT
++		help
++		  This method is incompatible with binary only modules but has
++		  a lower runtime overhead.
++endchoice
 +
-+	if (TREE_CODE_CLASS(gimple_assign_rhs_code(def_stmt)) == tcc_comparison)
-+		return handle_comparison_code_class(expand_from, def_stmt, new_rhs1, new_rhs2);
++config PAX_KERNEXEC_PLUGIN_METHOD
++	string
++	default "bts" if PAX_KERNEXEC_PLUGIN_METHOD_BTS
++	default "or" if PAX_KERNEXEC_PLUGIN_METHOD_OR
++	default ""
 +
-+	if (uconst_neg_intentional_overflow(def_stmt)) {
-+		inform(gimple_location(def_stmt), "%s: gcc intentional overflow", __func__);
-+		gcc_unreachable();
-+	}
++config PAX_KERNEXEC_MODULE_TEXT
++	int "Minimum amount of memory reserved for module code"
++	default "8" if (!GRKERNSEC_CONFIG_AUTO || GRKERNSEC_CONFIG_SERVER)
++	default "12" if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_DESKTOP)
++	depends on PAX_KERNEXEC && X86_32
++	help
++	  Due to implementation details the kernel must reserve a fixed
++	  amount of memory for runtime allocated code (such as modules)
++	  at compile time that cannot be changed at runtime.  Here you
++	  can specify the minimum amount in MB that will be reserved.
++	  Due to the same implementation details this size will always
++	  be rounded up to the next 2/4 MB boundary (depends on PAE) so
++	  the actually available memory for runtime allocated code will
++	  usually be more than this minimum.
 +
-+	return dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, NULL_TREE);
-+}
++	  The default 4 MB should be enough for most users but if you have
++	  an excessive number of modules (e.g., most distribution configs
++	  compile many drivers as modules) or use huge modules such as
++	  nvidia's kernel driver, you will need to adjust this amount.
++	  A good rule of thumb is to look at your currently loaded kernel
++	  modules and add up their sizes.
 +
-+#if BUILDING_GCC_VERSION >= 4006
-+static tree get_new_rhs(interesting_stmts_t expand_from, tree size_overflow_type, tree rhs)
-+{
-+	if (is_gimple_constant(rhs))
-+		return cast_a_tree(size_overflow_type, rhs);
-+	if (TREE_CODE(rhs) != SSA_NAME)
-+		return NULL_TREE;
-+	return expand(expand_from, rhs);
-+}
++endmenu
 +
-+static tree handle_ternary_ops(interesting_stmts_t expand_from, tree lhs)
-+{
-+	tree rhs1, rhs2, rhs3, new_rhs1, new_rhs2, new_rhs3, size_overflow_type;
-+	gassign *def_stmt = as_a_gassign(get_def_stmt(lhs));
++menu "Address Space Layout Randomization"
++	depends on PAX
 +
-+	size_overflow_type = get_size_overflow_type(expand_from->visited, def_stmt, lhs);
++config PAX_ASLR
++	bool "Address Space Layout Randomization"
++	default y if GRKERNSEC_CONFIG_AUTO
++	help
++	  Many if not most exploit techniques rely on the knowledge of
++	  certain addresses in the attacked program.  The following options
++	  will allow the kernel to apply a certain amount of randomization
++	  to specific parts of the program thereby forcing an attacker to
++	  guess them in most cases.  Any failed guess will most likely crash
++	  the attacked program which allows the kernel to detect such attempts
++	  and react on them.  PaX itself provides no reaction mechanisms,
++	  instead it is strongly encouraged that you make use of grsecurity's
++	  (http://www.grsecurity.net/) built-in crash detection features or
++	  develop one yourself.
 +
-+	rhs1 = gimple_assign_rhs1(def_stmt);
-+	rhs2 = gimple_assign_rhs2(def_stmt);
-+	rhs3 = gimple_assign_rhs3(def_stmt);
-+	new_rhs1 = get_new_rhs(expand_from, size_overflow_type, rhs1);
-+	new_rhs2 = get_new_rhs(expand_from, size_overflow_type, rhs2);
-+	new_rhs3 = get_new_rhs(expand_from, size_overflow_type, rhs3);
++	  By saying Y here you can choose to randomize the following areas:
++	   - top of the task's kernel stack
++	   - top of the task's userland stack
++	   - base address for mmap() requests that do not specify one
++	     (this includes all libraries)
++	   - base address of the main executable
 +
-+	return dup_assign(expand_from->visited, def_stmt, lhs, new_rhs1, new_rhs2, new_rhs3);
-+}
-+#endif
++	  It is strongly recommended to say Y here as address space layout
++	  randomization has negligible impact on performance yet it provides
++	  a very effective protection.
 +
-+static tree expand_visited(struct visited *visited, gimple def_stmt)
-+{
-+	gimple_stmt_iterator gsi;
-+	enum gimple_code code = gimple_code(def_stmt);
++	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control
++	  this feature on a per file basis.
 +
-+	if (code == GIMPLE_ASM)
-+		return NULL_TREE;
++config PAX_RANDKSTACK
++	bool "Randomize kernel stack base"
++	default y if GRKERNSEC_CONFIG_AUTO && !(GRKERNSEC_CONFIG_VIRT_HOST && GRKERNSEC_CONFIG_VIRT_VIRTUALBOX)
++	depends on X86_TSC && X86
++	help
++	  By saying Y here the kernel will randomize every task's kernel
++	  stack on every system call.  This will not only force an attacker
++	  to guess it but also prevent him from making use of possible
++	  leaked information about it.
 +
-+	gsi = gsi_for_stmt(def_stmt);
-+	gsi_next(&gsi);
++	  Since the kernel stack is a rather scarce resource, randomization
++	  may cause unexpected stack overflows, therefore you should very
++	  carefully test your system.  Note that once enabled in the kernel
++	  configuration, this feature cannot be disabled on a per file basis.
 +
-+	if (gimple_code(def_stmt) == GIMPLE_PHI && gsi_end_p(gsi))
-+		return NULL_TREE;
-+	return get_my_stmt_lhs(visited, def_stmt);
-+}
++config PAX_RANDUSTACK
++	bool
 +
-+tree expand(interesting_stmts_t expand_from, tree lhs)
-+{
-+	gimple def_stmt;
++config PAX_RANDMMAP
++	bool "Randomize user stack and mmap() bases"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on PAX_ASLR
++	select PAX_RANDUSTACK
++	help
++	  By saying Y here the kernel will randomize every task's userland
++	  stack and use a randomized base address for mmap() requests that
++	  do not specify one themselves.
 +
-+	def_stmt = get_def_stmt(lhs);
++	  The stack randomization is done in two steps where the second
++	  one may apply a big amount of shift to the top of the stack and
++	  cause problems for programs that want to use lots of memory (more
++	  than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
 +
-+	if (!def_stmt || gimple_code(def_stmt) == GIMPLE_NOP)
-+		return NULL_TREE;
++	  As a result of mmap randomization all dynamically loaded libraries
++	  will appear at random addresses and therefore be harder to exploit
++	  by a technique where an attacker attempts to execute library code
++	  for his purposes (e.g. spawn a shell from an exploited program that
++	  is running at an elevated privilege level).
 +
-+	if (pointer_set_contains(expand_from->visited->my_stmts, def_stmt))
-+		return lhs;
++	  Furthermore, if a program is relinked as a dynamic ELF file, its
++	  base address will be randomized as well, completing the full
++	  randomization of the address space layout.  Attacking such programs
++	  becomes a guess game.  You can find an example of doing this at
++	  http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
++	  http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
 +
-+	if (pointer_set_contains(expand_from->visited->stmts, def_stmt))
-+		return expand_visited(expand_from->visited, def_stmt);
++	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
++	  feature on a per file basis.
 +
-+	if (is_gimple_constant(lhs))
-+		return NULL_TREE;
-+	if (skip_types(lhs))
-+		return NULL_TREE;
++endmenu
 +
-+	switch (gimple_code(def_stmt)) {
-+	case GIMPLE_PHI:
-+		return handle_phi(expand_from, lhs);
-+	case GIMPLE_CALL:
-+	case GIMPLE_ASM:
-+		if (is_size_overflow_asm(def_stmt))
-+			return expand(expand_from, get_size_overflow_asm_input(as_a_gasm(def_stmt)));
-+		return create_assign(expand_from->visited, def_stmt, lhs, AFTER_STMT);
-+	case GIMPLE_ASSIGN:
-+		switch (gimple_num_ops(def_stmt)) {
-+		case 2:
-+			return handle_unary_ops(expand_from, as_a_gassign(def_stmt));
-+		case 3:
-+			return handle_binary_ops(expand_from, lhs);
-+#if BUILDING_GCC_VERSION >= 4006
-+		case 4:
-+			return handle_ternary_ops(expand_from, lhs);
-+#endif
-+		}
-+	default:
-+		debug_gimple_stmt(def_stmt);
-+		error("%s: unknown gimple code", __func__);
-+		gcc_unreachable();
-+	}
-+}
-diff --git a/tools/gcc/stackleak_plugin.c b/tools/gcc/stackleak_plugin.c
-new file mode 100644
-index 0000000..8b69bd4
---- /dev/null
-+++ b/tools/gcc/stackleak_plugin.c
-@@ -0,0 +1,350 @@
-+/*
-+ * Copyright 2011-2016 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 implement various PaX features
-+ *
-+ * - track lowest stack pointer
-+ *
-+ * TODO:
-+ * - initialize all local variables
-+ *
-+ * BUGS:
-+ * - none known
-+ */
++menu "Miscellaneous hardening features"
 +
-+#include "gcc-common.h"
++config PAX_MEMORY_SANITIZE
++	bool "Sanitize all freed memory"
++	default y if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_PRIORITY_SECURITY)
++	help
++	  By saying Y here the kernel will erase memory pages and slab objects
++	  as soon as they are freed.  This in turn reduces the lifetime of data
++	  stored in them, making it less likely that sensitive information such
++	  as passwords, cryptographic secrets, etc stay in memory for too long.
 +
-+int plugin_is_GPL_compatible;
++	  This is especially useful for programs whose runtime is short, long
++	  lived processes and the kernel itself benefit from this as long as
++	  they ensure timely freeing of memory that may hold sensitive
++	  information.
 +
-+static int track_frame_size = -1;
-+static const char track_function[] = "pax_track_stack";
-+static const char check_function[] = "pax_check_alloca";
-+static GTY(()) tree track_function_decl;
-+static GTY(()) tree check_function_decl;
-+static bool init_locals;
++	  A nice side effect of the sanitization of slab objects is the
++	  reduction of possible info leaks caused by padding bytes within the
++	  leaky structures.  Use-after-free bugs for structures containing
++	  pointers can also be detected as dereferencing the sanitized pointer
++	  will generate an access violation.
 +
-+static struct plugin_info stackleak_plugin_info = {
-+	.version	= "201602181345",
-+	.help		= "track-lowest-sp=nn\ttrack sp in functions whose frame size is at least nn bytes\n"
-+//			  "initialize-locals\t\tforcibly initialize all stack frames\n"
-+};
++	  The tradeoff is performance impact, on a single CPU system kernel
++	  compilation sees a 3% slowdown, other systems and workloads may vary
++	  and you are advised to test this feature on your expected workload
++	  before deploying it.
 +
-+static void stackleak_check_alloca(gimple_stmt_iterator *gsi)
-+{
-+	gimple stmt;
-+	gcall *check_alloca;
-+	tree alloca_size;
-+	cgraph_node_ptr node;
-+	int frequency;
-+	basic_block bb;
++	  The slab sanitization feature excludes a few slab caches per default
++	  for performance reasons.  To extend the feature to cover those as
++	  well, pass "pax_sanitize_slab=full" as kernel command line parameter.
 +
-+	// insert call to void pax_check_alloca(unsigned long size)
-+	alloca_size = gimple_call_arg(gsi_stmt(*gsi), 0);
-+	stmt = gimple_build_call(check_function_decl, 1, alloca_size);
-+	check_alloca = as_a_gcall(stmt);
-+	gsi_insert_before(gsi, check_alloca, GSI_SAME_STMT);
++	  To reduce the performance penalty by sanitizing pages only, albeit
++	  limiting the effectiveness of this feature at the same time, slab
++	  sanitization can be disabled with the kernel command line parameter
++	  "pax_sanitize_slab=off".
 +
-+	// update the cgraph
-+	bb = gimple_bb(check_alloca);
-+	node = cgraph_get_create_node(check_function_decl);
-+	gcc_assert(node);
-+	frequency = compute_call_stmt_bb_frequency(current_function_decl, bb);
-+	cgraph_create_edge(cgraph_get_node(current_function_decl), node, check_alloca, bb->count, frequency, bb->loop_depth);
-+}
++	  Note that this feature does not protect data stored in live pages,
++	  e.g., process memory swapped to disk may stay there for a long time.
 +
-+static void stackleak_add_instrumentation(gimple_stmt_iterator *gsi, bool after)
-+{
-+	gimple stmt;
-+	gcall *track_stack;
-+	cgraph_node_ptr node;
-+	int frequency;
-+	basic_block bb;
++config PAX_MEMORY_STACKLEAK
++	bool "Sanitize kernel stack"
++	default y if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_PRIORITY_SECURITY)
++	depends on X86 && GCC_PLUGINS
++	help
++	  By saying Y here the kernel will erase the kernel stack before it
++	  returns from a system call.  This in turn reduces the information
++	  that a kernel stack leak bug can reveal.
 +
-+	// insert call to void pax_track_stack(void)
-+	stmt = gimple_build_call(track_function_decl, 0);
-+	track_stack = as_a_gcall(stmt);
-+	if (after)
-+		gsi_insert_after(gsi, track_stack, GSI_CONTINUE_LINKING);
-+	else
-+		gsi_insert_before(gsi, track_stack, GSI_SAME_STMT);
++	  Note that such a bug can still leak information that was put on
++	  the stack by the current system call (the one eventually triggering
++	  the bug) but traces of earlier system calls on the kernel stack
++	  cannot leak anymore.
 +
-+	// update the cgraph
-+	bb = gimple_bb(track_stack);
-+	node = cgraph_get_create_node(track_function_decl);
-+	gcc_assert(node);
-+	frequency = compute_call_stmt_bb_frequency(current_function_decl, bb);
-+	cgraph_create_edge(cgraph_get_node(current_function_decl), node, track_stack, bb->count, frequency, bb->loop_depth);
-+}
++	  The tradeoff is performance impact: on a single CPU system kernel
++	  compilation sees a 1% slowdown, other systems and workloads may vary
++	  and you are advised to test this feature on your expected workload
++	  before deploying it.
 +
-+static bool is_alloca(gimple stmt)
-+{
-+	if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA))
-+		return true;
++	  Note that the full feature requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.  Using
++	  older gcc versions means that functions with large enough stack
++	  frames may leave uninitialized memory behind that may be exposed
++	  to a later syscall leaking the stack.
 +
-+#if BUILDING_GCC_VERSION >= 4007
-+	if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
-+		return true;
-+#endif
++config PAX_MEMORY_STRUCTLEAK
++	bool "Forcibly initialize local variables copied to userland"
++	default y if (GRKERNSEC_CONFIG_AUTO && GRKERNSEC_CONFIG_PRIORITY_SECURITY)
++	depends on GCC_PLUGINS
++	help
++	  By saying Y here the kernel will zero initialize some local
++	  variables that are going to be copied to userland.  This in
++	  turn prevents unintended information leakage from the kernel
++	  stack should later code forget to explicitly set all parts of
++	  the copied variable.
 +
-+	return false;
-+}
++	  The tradeoff is less performance impact than PAX_MEMORY_STACKLEAK
++	  at a much smaller coverage.
 +
-+static unsigned int stackleak_tree_instrument_execute(void)
-+{
-+	basic_block bb, entry_bb;
-+	bool prologue_instrumented = false, is_leaf = true;
++	  Note that the implementation requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.
 +
-+	entry_bb = ENTRY_BLOCK_PTR_FOR_FN(cfun)->next_bb;
++config PAX_MEMORY_UDEREF
++	bool "Prevent invalid userland pointer dereference"
++	default y if GRKERNSEC_CONFIG_AUTO && !(X86_64 && GRKERNSEC_CONFIG_PRIORITY_PERF) && !(X86_64 && GRKERNSEC_CONFIG_VIRT_HOST && GRKERNSEC_CONFIG_VIRT_VIRTUALBOX) && (!X86 || GRKERNSEC_CONFIG_VIRT_NONE || GRKERNSEC_CONFIG_VIRT_EPT)
++	depends on (X86 || (ARM && (CPU_V6 || CPU_V6K || CPU_V7) && !ARM_LPAE)) && !UML_X86 && !XEN
++	select PAX_PER_CPU_PGD if X86_64
++	help
++	  By saying Y here the kernel will be prevented from dereferencing
++	  userland pointers in contexts where the kernel expects only kernel
++	  pointers.  This is both a useful runtime debugging feature and a
++	  security measure that prevents exploiting a class of kernel bugs.
 +
-+	// 1. loop through BBs and GIMPLE statements
-+	FOR_EACH_BB_FN(bb, cfun) {
-+		gimple_stmt_iterator gsi;
++	  The tradeoff is that some virtualization solutions may experience
++	  a huge slowdown and therefore you should not enable this feature
++	  for kernels meant to run in such environments.  Whether a given VM
++	  solution is affected or not is best determined by simply trying it
++	  out, the performance impact will be obvious right on boot as this
++	  mechanism engages from very early on.  A good rule of thumb is that
++	  VMs running on CPUs without hardware virtualization support (i.e.,
++	  the majority of IA-32 CPUs) will likely experience the slowdown.
 +
-+		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
-+			gimple stmt;
++	  On X86_64 the kernel will make use of PCID support when available
++	  (Intel's Westmere, Sandy Bridge, etc) for better security (default)
++	  or performance impact.  Pass pax_weakuderef on the kernel command
++	  line to choose the latter.
 +
-+			stmt = gsi_stmt(gsi);
++config PAX_REFCOUNT
++	bool "Prevent various kernel object reference counter overflows"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on GRKERNSEC && ((ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || MIPS || PPC || SPARC64 || X86)
++	help
++	  By saying Y here the kernel will detect and prevent overflowing
++	  various (but not all) kinds of object reference counters.  Such
++	  overflows can normally occur due to bugs only and are often, if
++	  not always, exploitable.
 +
-+			if (is_gimple_call(stmt))
-+				is_leaf = false;
++	  The tradeoff is that data structures protected by an overflowed
++	  refcount will never be freed and therefore will leak memory.  Note
++	  that this leak also happens even without this protection but in
++	  that case the overflow can eventually trigger the freeing of the
++	  data structure while it is still being used elsewhere, resulting
++	  in the exploitable situation that this feature prevents.
 +
-+			// gimple match: align 8 built-in BUILT_IN_NORMAL:BUILT_IN_ALLOCA attributes <tree_list 0xb7576450>
-+			if (!is_alloca(stmt))
-+				continue;
++	  Since this has a negligible performance impact, you should enable
++	  this feature.
 +
-+			// 2. insert stack overflow check before each __builtin_alloca call
-+			stackleak_check_alloca(&gsi);
++config PAX_CONSTIFY_PLUGIN
++	bool "Automatically constify eligible structures"
++	default y
++	depends on !UML && PAX_KERNEXEC
++	help
++	  By saying Y here the compiler will automatically constify a class
++	  of types that contain only function pointers.  This reduces the
++	  kernel's attack surface and also produces a better memory layout.
 +
-+			// 3. insert track call after each __builtin_alloca call
-+			stackleak_add_instrumentation(&gsi, true);
-+			if (bb == entry_bb)
-+				prologue_instrumented = true;
-+		}
-+	}
++	  Note that the implementation requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.
++ 
++	  Note that if some code really has to modify constified variables
++	  then the source code will have to be patched to allow it.  Examples
++	  can be found in PaX itself (the no_const attribute) and for some
++	  out-of-tree modules at http://www.grsecurity.net/~paxguy1/ .
 +
-+	// special cases for some bad linux code: taking the address of static inline functions will materialize them
-+	// but we mustn't instrument some of them as the resulting stack alignment required by the function call ABI
-+	// will break other assumptions regarding the expected (but not otherwise enforced) register clobbering  ABI.
-+	// case in point: native_save_fl on amd64 when optimized for size clobbers rdx if it were instrumented here.
-+	if (is_leaf && !TREE_PUBLIC(current_function_decl) && DECL_DECLARED_INLINE_P(current_function_decl))
-+		return 0;
-+	if (is_leaf && !strncmp(IDENTIFIER_POINTER(DECL_NAME(current_function_decl)), "_paravirt_", 10))
-+		return 0;
++config PAX_USERCOPY
++	bool "Harden heap object copies between kernel and userland"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on ARM || IA64 || PPC || SPARC || X86
++	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
++	  userland, even if only a part of the heap object is copied.
 +
-+	// 4. insert track call at the beginning
-+	if (!prologue_instrumented) {
-+		gimple_stmt_iterator gsi;
++	  Specifically, this checking prevents information leaking from the
++	  kernel heap during kernel to userland copies (if the kernel heap
++	  object is otherwise fully initialized) and prevents kernel heap
++	  overflows during userland to kernel copies.
 +
-+		gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+		bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+		if (!single_pred_p(bb)) {
-+//			gcc_assert(bb_loop_depth(bb) || (bb->flags & BB_IRREDUCIBLE_LOOP));
-+			split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+			gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+			bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+		}
-+		gsi = gsi_after_labels(bb);
-+		stackleak_add_instrumentation(&gsi, false);
-+	}
++	  Note that the current implementation provides the strictest bounds
++	  checks for the SLUB allocator.
 +
-+	return 0;
-+}
++	  Enabling this option also enables per-slab cache protection against
++	  data in a given cache being copied into/out of via userland
++	  accessors.  Though the whitelist of regions will be reduced over
++	  time, it notably protects important data structures like task structs.
 +
-+static unsigned int stackleak_final_execute(void)
-+{
-+	rtx_insn *insn, *next;
++	  If frame pointers are enabled on x86, this option will also restrict
++	  copies into and out of the kernel stack to local variables within a
++	  single frame.
 +
-+	if (cfun->calls_alloca)
-+		return 0;
++	  Since this has a negligible performance impact, you should enable
++	  this feature.
 +
-+	// keep calls only if function frame is big enough
-+	if (get_frame_size() >= track_frame_size)
-+		return 0;
++config PAX_USERCOPY_DEBUG
++	bool
++	depends on X86 && PAX_USERCOPY
++	default n
 +
-+	// 1. find pax_track_stack calls
-+	for (insn = get_insns(); insn; insn = next) {
-+		// rtl match: (call_insn 8 7 9 3 (call (mem (symbol_ref ("pax_track_stack") [flags 0x41] <function_decl 0xb7470e80 pax_track_stack>) [0 S1 A8]) (4)) -1 (nil) (nil))
-+		rtx body;
++config PAX_SIZE_OVERFLOW
++	bool "Prevent various integer overflows in function size parameters"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on GCC_PLUGINS
++	help
++	  By saying Y here the kernel recomputes expressions of function
++	  arguments marked by a size_overflow attribute with double integer
++	  precision (DImode/TImode for 32/64 bit integer types).
 +
-+		next = NEXT_INSN(insn);
-+		if (!CALL_P(insn))
-+			continue;
-+		body = PATTERN(insn);
-+		if (GET_CODE(body) != CALL)
-+			continue;
-+		body = XEXP(body, 0);
-+		if (GET_CODE(body) != MEM)
-+			continue;
-+		body = XEXP(body, 0);
-+		if (GET_CODE(body) != SYMBOL_REF)
-+			continue;
-+//		if (strcmp(XSTR(body, 0), track_function))
-+		if (SYMBOL_REF_DECL(body) != track_function_decl)
-+			continue;
-+//		warning(0, "track_frame_size: %d %ld %d", cfun->calls_alloca, get_frame_size(), track_frame_size);
-+		// 2. delete call
-+		delete_insn_and_edges(insn);
-+#if BUILDING_GCC_VERSION >= 4007
-+		if (GET_CODE(next) == NOTE && NOTE_KIND(next) == NOTE_INSN_CALL_ARG_LOCATION) {
-+			insn = next;
-+			next = NEXT_INSN(insn);
-+			delete_insn_and_edges(insn);
-+		}
-+#endif
-+	}
++	  The recomputed argument is checked against TYPE_MAX and an event
++	  is logged on overflow and the triggering process is killed.
 +
-+//	print_simple_rtl(stderr, get_insns());
-+//	print_rtl(stderr, get_insns());
-+//	warning(0, "track_frame_size: %d %ld %d", cfun->calls_alloca, get_frame_size(), track_frame_size);
++	  Homepage: https://github.com/ephox-gcc-plugins
 +
-+	return 0;
-+}
++	  Note that the implementation requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.
 +
-+static bool stackleak_track_stack_gate(void)
-+{
-+	tree section;
++config PAX_LATENT_ENTROPY
++	bool "Generate some entropy during boot and runtime"
++	default y if GRKERNSEC_CONFIG_AUTO
++	depends on GCC_PLUGINS
++	help
++	  By saying Y here the kernel will instrument some kernel 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 and fork and irq processing.
 +
-+	if (ix86_cmodel != CM_KERNEL)
-+		return false;
++	  When pax_extra_latent_entropy is passed on the kernel command line,
++	  entropy will be extracted from up to the first 4GB of RAM while the
++	  runtime memory allocator is being initialized.  This costs even more
++	  slowdown of the boot process.
 +
-+	section = lookup_attribute("section", DECL_ATTRIBUTES(current_function_decl));
-+	if (section && TREE_VALUE(section)) {
-+		section = TREE_VALUE(TREE_VALUE(section));
++	  Note that the implementation requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.
 +
-+		if (!strncmp(TREE_STRING_POINTER(section), ".init.text", 10))
-+			return false;
-+		if (!strncmp(TREE_STRING_POINTER(section), ".devinit.text", 13))
-+			return false;
-+		if (!strncmp(TREE_STRING_POINTER(section), ".cpuinit.text", 13))
-+			return false;
-+		if (!strncmp(TREE_STRING_POINTER(section), ".meminit.text", 13))
-+			return false;
-+	}
++	  Note that entropy extracted this way is not cryptographically
++	  secure!
 +
-+	return track_frame_size >= 0;
-+}
++config PAX_RAP
++	bool "Prevent code reuse attacks"
++	depends on X86_64
++	default y if GRKERNSEC_CONFIG_AUTO
++	help
++	  By saying Y here the kernel will check indirect control transfers
++	  in order to detect and prevent attacks that try to hijack control
++	  flow by overwriting code pointers.
 +
-+static void stackleak_start_unit(void *gcc_data, void *user_data)
-+{
-+	tree fntype;
++	  Note that binary modules cannot be instrumented by this approach.
 +
-+	// void pax_track_stack(void)
-+	fntype = build_function_type_list(void_type_node, NULL_TREE);
-+	track_function_decl = build_fn_decl(track_function, fntype);
-+	DECL_ASSEMBLER_NAME(track_function_decl); // for LTO
-+	TREE_PUBLIC(track_function_decl) = 1;
-+	TREE_USED(track_function_decl) = 1;
-+	DECL_EXTERNAL(track_function_decl) = 1;
-+	DECL_ARTIFICIAL(track_function_decl) = 1;
-+	DECL_PRESERVE_P(track_function_decl) = 1;
++	  Note that the implementation requires a gcc with plugin support,
++	  i.e., gcc 4.5 or newer.  You may need to install the supporting
++	  headers explicitly in addition to the normal gcc package.
 +
-+	// void pax_check_alloca(unsigned long)
-+	fntype = build_function_type_list(void_type_node, long_unsigned_type_node, NULL_TREE);
-+	check_function_decl = build_fn_decl(check_function, fntype);
-+	DECL_ASSEMBLER_NAME(check_function_decl); // for LTO
-+	TREE_PUBLIC(check_function_decl) = 1;
-+	TREE_USED(check_function_decl) = 1;
-+	DECL_EXTERNAL(check_function_decl) = 1;
-+	DECL_ARTIFICIAL(check_function_decl) = 1;
-+	DECL_PRESERVE_P(check_function_decl) = 1;
-+}
++endmenu
 +
-+static bool stackleak_tree_instrument_gate(void)
-+{
-+	return stackleak_track_stack_gate();
-+}
++endmenu
 +
-+#define PASS_NAME stackleak_tree_instrument
-+#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
-+#define TODO_FLAGS_START TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts
-+#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_update_ssa | TODO_rebuild_cgraph_edges
-+#include "gcc-generate-gimple-pass.h"
++source grsecurity/Kconfig
 +
-+static bool stackleak_final_gate(void)
-+{
-+	return stackleak_track_stack_gate();
-+}
++endmenu
 +
-+#define PASS_NAME stackleak_final
-+#define TODO_FLAGS_FINISH TODO_dump_func
-+#include "gcc-generate-rtl-pass.h"
++endmenu
 +
-+int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
+ source security/keys/Kconfig
+ 
+ config SECURITY_DMESG_RESTRICT
+@@ -104,7 +1091,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
+-	default 32768 if ARM || (ARM64 && COMPAT)
++	default 32768 if ALPHA || ARM || (ARM64 && COMPAT) || PARISC || SPARC32
+ 	default 65536
+ 	help
+ 	  This is the portion of low virtual memory which should be protected
+diff --git a/security/apparmor/file.c b/security/apparmor/file.c
+index 913f377..6e392d5 100644
+--- a/security/apparmor/file.c
++++ b/security/apparmor/file.c
+@@ -348,8 +348,8 @@ static inline bool xindex_is_subset(u32 link, u32 target)
+ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
+ 		 struct path *new_dir, struct dentry *new_dentry)
+ {
+-	struct path link = { new_dir->mnt, new_dentry };
+-	struct path target = { new_dir->mnt, old_dentry };
++	struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
++	struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry };
+ 	struct path_cond cond = {
+ 		d_backing_inode(old_dentry)->i_uid,
+ 		d_backing_inode(old_dentry)->i_mode
+diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
+index c28b0f2..3b9fee0 100644
+--- a/security/apparmor/include/policy.h
++++ b/security/apparmor/include/policy.h
+@@ -134,7 +134,7 @@ struct aa_namespace {
+ 	struct aa_ns_acct acct;
+ 	struct aa_profile *unconfined;
+ 	struct list_head sub_ns;
+-	atomic_t uniq_null;
++	atomic_unchecked_t uniq_null;
+ 	long uniq_id;
+ 
+ 	struct dentry *dents[AAFS_NS_SIZEOF];
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
+index dec607c..37fe357 100644
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -176,7 +176,7 @@ static int common_perm_dir_dentry(int op, struct path *dir,
+ 				  struct dentry *dentry, u32 mask,
+ 				  struct path_cond *cond)
+ {
+-	struct path path = { dir->mnt, dentry };
++	struct path path = { .mnt = dir->mnt, .dentry = dentry };
+ 
+ 	return common_perm(op, &path, mask, cond);
+ }
+@@ -193,7 +193,7 @@ static int common_perm_dir_dentry(int op, struct path *dir,
+ static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
+ 				  struct dentry *dentry, u32 mask)
+ {
+-	struct path path = { mnt, dentry };
++	struct path path = { .mnt = mnt, .dentry = dentry };
+ 	struct path_cond cond = { d_backing_inode(dentry)->i_uid,
+ 				  d_backing_inode(dentry)->i_mode
+ 	};
+@@ -315,8 +315,8 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ 
+ 	profile = aa_current_profile();
+ 	if (!unconfined(profile)) {
+-		struct path old_path = { old_dir->mnt, old_dentry };
+-		struct path new_path = { new_dir->mnt, new_dentry };
++		struct path old_path = { .mnt = old_dir->mnt, .dentry = old_dentry };
++		struct path new_path = { .mnt = new_dir->mnt, .dentry = new_dentry };
+ 		struct path_cond cond = { d_backing_inode(old_dentry)->i_uid,
+ 					  d_backing_inode(old_dentry)->i_mode
+ 		};
+@@ -677,11 +677,11 @@ static const struct kernel_param_ops param_ops_aalockpolicy = {
+ 	.get = param_get_aalockpolicy
+ };
+ 
+-static int param_set_audit(const char *val, struct kernel_param *kp);
+-static int param_get_audit(char *buffer, struct kernel_param *kp);
++static int param_set_audit(const char *val, const struct kernel_param *kp);
++static int param_get_audit(char *buffer, const struct kernel_param *kp);
+ 
+-static int param_set_mode(const char *val, struct kernel_param *kp);
+-static int param_get_mode(char *buffer, struct kernel_param *kp);
++static int param_set_mode(const char *val, const struct kernel_param *kp);
++static int param_get_mode(char *buffer, const struct kernel_param *kp);
+ 
+ /* Flag values, also controllable via /sys/module/apparmor/parameters
+  * We define special types as we want to do additional mediation.
+@@ -791,7 +791,7 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp)
+ 	return param_get_uint(buffer, kp);
+ }
+ 
+-static int param_get_audit(char *buffer, struct kernel_param *kp)
++static int param_get_audit(char *buffer, const struct kernel_param *kp)
+ {
+ 	if (!capable(CAP_MAC_ADMIN))
+ 		return -EPERM;
+@@ -802,7 +802,7 @@ static int param_get_audit(char *buffer, struct kernel_param *kp)
+ 	return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
+ }
+ 
+-static int param_set_audit(const char *val, struct kernel_param *kp)
++static int param_set_audit(const char *val, const struct kernel_param *kp)
+ {
+ 	int i;
+ 	if (!capable(CAP_MAC_ADMIN))
+@@ -824,7 +824,7 @@ static int param_set_audit(const char *val, struct kernel_param *kp)
+ 	return -EINVAL;
+ }
+ 
+-static int param_get_mode(char *buffer, struct kernel_param *kp)
++static int param_get_mode(char *buffer, const struct kernel_param *kp)
+ {
+ 	if (!capable(CAP_MAC_ADMIN))
+ 		return -EPERM;
+@@ -835,7 +835,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
+ 	return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
+ }
+ 
+-static int param_set_mode(const char *val, struct kernel_param *kp)
++static int param_set_mode(const char *val, const struct kernel_param *kp)
+ {
+ 	int i;
+ 	if (!capable(CAP_MAC_ADMIN))
+diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
+index 705c287..81257f1 100644
+--- a/security/apparmor/policy.c
++++ b/security/apparmor/policy.c
+@@ -298,7 +298,7 @@ static struct aa_namespace *alloc_namespace(const char *prefix,
+ 	/* ns and ns->unconfined share ns->unconfined refcount */
+ 	ns->unconfined->ns = ns;
+ 
+-	atomic_set(&ns->uniq_null, 0);
++	atomic_set_unchecked(&ns->uniq_null, 0);
+ 
+ 	return ns;
+ 
+@@ -689,7 +689,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
+ {
+ 	struct aa_profile *profile = NULL;
+ 	char *name;
+-	int uniq = atomic_inc_return(&parent->ns->uniq_null);
++	int uniq = atomic_inc_return_unchecked(&parent->ns->uniq_null);
+ 
+ 	/* freed below */
+ 	name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 48071ed..b805e0f 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -438,6 +438,32 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
+ 	return 0;
+ }
+ 
++/* returns:
++	1 for suid privilege
++	2 for sgid privilege
++	3 for fscap privilege
++*/
++int is_privileged_binary(const struct dentry *dentry)
 +{
-+	const char * const plugin_name = plugin_info->base_name;
-+	const int argc = plugin_info->argc;
-+	const struct plugin_argument * const argv = plugin_info->argv;
-+	int i;
-+	struct register_pass_info stackleak_tree_instrument_pass_info;
-+	struct register_pass_info stackleak_final_pass_info;
-+	static const struct ggc_root_tab gt_ggc_r_gt_stackleak[] = {
-+		{
-+			.base = &track_function_decl,
-+			.nelt = 1,
-+			.stride = sizeof(track_function_decl),
-+			.cb = &gt_ggc_mx_tree_node,
-+			.pchw = &gt_pch_nx_tree_node
-+		},
-+		{
-+			.base = &check_function_decl,
-+			.nelt = 1,
-+			.stride = sizeof(check_function_decl),
-+			.cb = &gt_ggc_mx_tree_node,
-+			.pchw = &gt_pch_nx_tree_node
-+		},
-+		LAST_GGC_ROOT_TAB
-+	};
-+
-+	stackleak_tree_instrument_pass_info.pass			= make_stackleak_tree_instrument_pass();
-+//	stackleak_tree_instrument_pass_info.reference_pass_name		= "tree_profile";
-+	stackleak_tree_instrument_pass_info.reference_pass_name		= "optimized";
-+	stackleak_tree_instrument_pass_info.ref_pass_instance_number	= 1;
-+	stackleak_tree_instrument_pass_info.pos_op 			= PASS_POS_INSERT_BEFORE;
++	struct cpu_vfs_cap_data capdata;
++	struct inode *inode = dentry->d_inode;
 +
-+	stackleak_final_pass_info.pass				= make_stackleak_final_pass();
-+	stackleak_final_pass_info.reference_pass_name		= "final";
-+	stackleak_final_pass_info.ref_pass_instance_number	= 1;
-+	stackleak_final_pass_info.pos_op 			= PASS_POS_INSERT_BEFORE;
++	if (!inode || S_ISDIR(inode->i_mode))
++		return 0;
 +
-+	if (!plugin_default_version_check(version, &gcc_version)) {
-+		error(G_("incompatible gcc/plugin versions"));
++	if (inode->i_mode & S_ISUID)
 +		return 1;
-+	}
-+
-+	register_callback(plugin_name, PLUGIN_INFO, NULL, &stackleak_plugin_info);
++	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
++		return 2;
 +
-+	for (i = 0; i < argc; ++i) {
-+		if (!strcmp(argv[i].key, "track-lowest-sp")) {
-+			if (!argv[i].value) {
-+				error(G_("no value supplied for option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+				continue;
-+			}
-+			track_frame_size = atoi(argv[i].value);
-+			if (argv[i].value[0] < '0' || argv[i].value[0] > '9' || track_frame_size < 0)
-+				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"), plugin_name, argv[i].key, argv[i].value);
-+			continue;
-+		}
-+		if (!strcmp(argv[i].key, "initialize-locals")) {
-+			if (argv[i].value) {
-+				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"), plugin_name, argv[i].key, argv[i].value);
-+				continue;
-+			}
-+			init_locals = true;
-+			continue;
-+		}
-+		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
++	if (!get_vfs_caps_from_disk(dentry, &capdata)) {
++		if (!cap_isclear(capdata.inheritable) || !cap_isclear(capdata.permitted))
++			return 3;
 +	}
 +
-+	register_callback(plugin_name, PLUGIN_START_UNIT, &stackleak_start_unit, NULL);
-+	register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_stackleak);
-+	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &stackleak_tree_instrument_pass_info);
-+	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &stackleak_final_pass_info);
-+
 +	return 0;
 +}
-diff --git a/tools/gcc/structleak_plugin.c b/tools/gcc/structleak_plugin.c
-new file mode 100644
-index 0000000..d7596e6
---- /dev/null
-+++ b/tools/gcc/structleak_plugin.c
-@@ -0,0 +1,239 @@
-+/*
-+ * Copyright 2013-2016 by 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 forcibly initialize certain local variables that could
-+ * otherwise leak kernel stack to userland if they aren't properly initialized
-+ * by later code
-+ *
-+ * Homepage: http://pax.grsecurity.net/
-+ *
-+ * Usage:
-+ * $ # for 4.5/4.6/C based 4.7
-+ * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c
-+ * $ # for C++ based 4.7/4.8+
-+ * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c
-+ * $ gcc -fplugin=./structleak_plugin.so test.c -O2
-+ *
-+ * TODO: eliminate redundant initializers
-+ *       increase type coverage
-+ */
 +
-+#include "gcc-common.h"
+ /*
+  * Attempt to get the on-exec apply capability sets for an executable file from
+  * its xattrs and, if present, apply them to the proposed credentials being
+@@ -628,6 +654,9 @@ int cap_bprm_secureexec(struct linux_binprm *bprm)
+ 	const struct cred *cred = current_cred();
+ 	kuid_t root_uid = make_kuid(cred->user_ns, 0);
+ 
++	if (gr_acl_enable_at_secure())
++		return 1;
 +
-+// unused C type flag in all versions 4.5-6
-+#define TYPE_USERSPACE(TYPE) TYPE_LANG_FLAG_5(TYPE)
+ 	if (!uid_eq(cred->uid, root_uid)) {
+ 		if (bprm->cap_effective)
+ 			return 1;
+diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
+index 585af61..b7d35ff 100644
+--- a/security/integrity/ima/ima.h
++++ b/security/integrity/ima/ima.h
+@@ -125,8 +125,8 @@ int ima_init_template(void);
+ extern spinlock_t ima_queue_lock;
+ 
+ struct ima_h_table {
+-	atomic_long_t len;	/* number of stored measurements in the list */
+-	atomic_long_t violations;
++	atomic_long_unchecked_t len;	/* number of stored measurements in the list */
++	atomic_long_unchecked_t violations;
+ 	struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
+ };
+ extern struct ima_h_table ima_htable;
+diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
+index 1d950fb..a8f4eab 100644
+--- a/security/integrity/ima/ima_api.c
++++ b/security/integrity/ima/ima_api.c
+@@ -137,7 +137,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
+ 	int result;
+ 
+ 	/* can overflow, only indicator */
+-	atomic_long_inc(&ima_htable.violations);
++	atomic_long_inc_unchecked(&ima_htable.violations);
+ 
+ 	result = ima_alloc_init_template(&event_data, &entry);
+ 	if (result < 0) {
+diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
+index f355231..c71f640 100644
+--- a/security/integrity/ima/ima_fs.c
++++ b/security/integrity/ima/ima_fs.c
+@@ -30,12 +30,12 @@ static DEFINE_MUTEX(ima_write_mutex);
+ static int valid_policy = 1;
+ #define TMPBUFLEN 12
+ static ssize_t ima_show_htable_value(char __user *buf, size_t count,
+-				     loff_t *ppos, atomic_long_t *val)
++				     loff_t *ppos, atomic_long_unchecked_t *val)
+ {
+ 	char tmpbuf[TMPBUFLEN];
+ 	ssize_t len;
+ 
+-	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
++	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read_unchecked(val));
+ 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
+ }
+ 
+diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
+index 552705d..9920f4fb 100644
+--- a/security/integrity/ima/ima_queue.c
++++ b/security/integrity/ima/ima_queue.c
+@@ -83,7 +83,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
+ 	INIT_LIST_HEAD(&qe->later);
+ 	list_add_tail_rcu(&qe->later, &ima_measurements);
+ 
+-	atomic_long_inc(&ima_htable.len);
++	atomic_long_inc_unchecked(&ima_htable.len);
+ 	key = ima_hash_key(entry->digest);
+ 	hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+ 	return 0;
+diff --git a/security/keys/internal.h b/security/keys/internal.h
+index 5105c2c..a5010e6 100644
+--- a/security/keys/internal.h
++++ b/security/keys/internal.h
+@@ -90,12 +90,16 @@ extern void key_type_put(struct key_type *ktype);
+ 
+ extern int __key_link_begin(struct key *keyring,
+ 			    const struct keyring_index_key *index_key,
+-			    struct assoc_array_edit **_edit);
++			    struct assoc_array_edit **_edit)
++			    __acquires(&keyring->sem)
++			    __acquires(&keyring_serialise_link_sem);
+ extern int __key_link_check_live_key(struct key *keyring, struct key *key);
+ extern void __key_link(struct key *key, struct assoc_array_edit **_edit);
+ extern void __key_link_end(struct key *keyring,
+ 			   const struct keyring_index_key *index_key,
+-			   struct assoc_array_edit *edit);
++			   struct assoc_array_edit *edit)
++			   __releases(&keyring->sem)
++			   __releases(&keyring_serialise_link_sem);
+ 
+ extern key_ref_t find_key_to_update(key_ref_t keyring_ref,
+ 				    const struct keyring_index_key *index_key);
+@@ -191,7 +195,7 @@ struct request_key_auth {
+ 	void			*callout_info;
+ 	size_t			callout_len;
+ 	pid_t			pid;
+-};
++} __randomize_layout;
+ 
+ extern struct key_type key_type_request_key_auth;
+ extern struct key *request_key_auth_new(struct key *target,
+diff --git a/security/keys/key.c b/security/keys/key.c
+index 09ef276..ab2894f 100644
+--- a/security/keys/key.c
++++ b/security/keys/key.c
+@@ -283,7 +283,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
+ 
+ 	atomic_set(&key->usage, 1);
+ 	init_rwsem(&key->sem);
+-	lockdep_set_class(&key->sem, &type->lock_class);
++	lockdep_set_class(&key->sem, (struct lock_class_key *)&type->lock_class);
+ 	key->index_key.type = type;
+ 	key->user = user;
+ 	key->quotalen = quotalen;
+@@ -1077,7 +1077,9 @@ int register_key_type(struct key_type *ktype)
+ 	struct key_type *p;
+ 	int ret;
+ 
+-	memset(&ktype->lock_class, 0, sizeof(ktype->lock_class));
++	pax_open_kernel();
++	memset((void *)&ktype->lock_class, 0, sizeof(ktype->lock_class));
++	pax_close_kernel();
+ 
+ 	ret = -EEXIST;
+ 	down_write(&key_types_sem);
+@@ -1089,7 +1091,7 @@ int register_key_type(struct key_type *ktype)
+ 	}
+ 
+ 	/* store the type */
+-	list_add(&ktype->link, &key_types_list);
++	pax_list_add((struct list_head *)&ktype->link, &key_types_list);
+ 
+ 	pr_notice("Key type %s registered\n", ktype->name);
+ 	ret = 0;
+@@ -1111,7 +1113,7 @@ EXPORT_SYMBOL(register_key_type);
+ void unregister_key_type(struct key_type *ktype)
+ {
+ 	down_write(&key_types_sem);
+-	list_del_init(&ktype->link);
++	pax_list_del_init((struct list_head *)&ktype->link);
+ 	downgrade_write(&key_types_sem);
+ 	key_gc_keytype(ktype);
+ 	pr_notice("Key type %s unregistered\n", ktype->name);
+@@ -1129,10 +1131,10 @@ void __init key_init(void)
+ 			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+ 
+ 	/* add the special key types */
+-	list_add_tail(&key_type_keyring.link, &key_types_list);
+-	list_add_tail(&key_type_dead.link, &key_types_list);
+-	list_add_tail(&key_type_user.link, &key_types_list);
+-	list_add_tail(&key_type_logon.link, &key_types_list);
++	pax_list_add_tail((struct list_head *)&key_type_keyring.link, &key_types_list);
++	pax_list_add_tail((struct list_head *)&key_type_dead.link, &key_types_list);
++	pax_list_add_tail((struct list_head *)&key_type_user.link, &key_types_list);
++	pax_list_add_tail((struct list_head *)&key_type_logon.link, &key_types_list);
+ 
+ 	/* record the root user tracking */
+ 	rb_link_node(&root_key_user.node,
+diff --git a/security/keys/keyring.c b/security/keys/keyring.c
+index f931ccf..ed9cd36 100644
+--- a/security/keys/keyring.c
++++ b/security/keys/keyring.c
+@@ -1071,8 +1071,6 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
+ int __key_link_begin(struct key *keyring,
+ 		     const struct keyring_index_key *index_key,
+ 		     struct assoc_array_edit **_edit)
+-	__acquires(&keyring->sem)
+-	__acquires(&keyring_serialise_link_sem)
+ {
+ 	struct assoc_array_edit *edit;
+ 	int ret;
+@@ -1172,8 +1170,6 @@ void __key_link(struct key *key, struct assoc_array_edit **_edit)
+ void __key_link_end(struct key *keyring,
+ 		    const struct keyring_index_key *index_key,
+ 		    struct assoc_array_edit *edit)
+-	__releases(&keyring->sem)
+-	__releases(&keyring_serialise_link_sem)
+ {
+ 	BUG_ON(index_key->type == NULL);
+ 	kenter("%d,%s,", keyring->serial, index_key->type->name);
+diff --git a/security/min_addr.c b/security/min_addr.c
+index f728728..6457a0c 100644
+--- a/security/min_addr.c
++++ b/security/min_addr.c
+@@ -14,6 +14,7 @@ unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
+  */
+ static void update_mmap_min_addr(void)
+ {
++#ifndef SPARC
+ #ifdef CONFIG_LSM_MMAP_MIN_ADDR
+ 	if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
+ 		mmap_min_addr = dac_mmap_min_addr;
+@@ -22,6 +23,7 @@ static void update_mmap_min_addr(void)
+ #else
+ 	mmap_min_addr = dac_mmap_min_addr;
+ #endif
++#endif
+ }
+ 
+ /*
+diff --git a/security/selinux/avc.c b/security/selinux/avc.c
+index e60c79d..41fb721 100644
+--- a/security/selinux/avc.c
++++ b/security/selinux/avc.c
+@@ -71,7 +71,7 @@ struct avc_xperms_node {
+ struct avc_cache {
+ 	struct hlist_head	slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
+ 	spinlock_t		slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
+-	atomic_t		lru_hint;	/* LRU hint for reclaim scan */
++	atomic_unchecked_t	lru_hint;	/* LRU hint for reclaim scan */
+ 	atomic_t		active_nodes;
+ 	u32			latest_notif;	/* latest revocation notification */
+ };
+@@ -183,7 +183,7 @@ void __init avc_init(void)
+ 		spin_lock_init(&avc_cache.slots_lock[i]);
+ 	}
+ 	atomic_set(&avc_cache.active_nodes, 0);
+-	atomic_set(&avc_cache.lru_hint, 0);
++	atomic_set_unchecked(&avc_cache.lru_hint, 0);
+ 
+ 	avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
+ 					0, SLAB_PANIC, NULL);
+@@ -521,7 +521,7 @@ static inline int avc_reclaim_node(void)
+ 	spinlock_t *lock;
+ 
+ 	for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
+-		hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
++		hvalue = atomic_inc_return_unchecked(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
+ 		head = &avc_cache.slots[hvalue];
+ 		lock = &avc_cache.slots_lock[hvalue];
+ 
+diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
+index 1450f85..a91e0bc 100644
+--- a/security/selinux/include/xfrm.h
++++ b/security/selinux/include/xfrm.h
+@@ -48,7 +48,7 @@ static inline void selinux_xfrm_notify_policyload(void)
+ 
+ 	rtnl_lock();
+ 	for_each_net(net) {
+-		atomic_inc(&net->xfrm.flow_cache_genid);
++		atomic_inc_unchecked(&net->xfrm.flow_cache_genid);
+ 		rt_genid_bump_all(net);
+ 	}
+ 	rtnl_unlock();
+diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
+index 2367b10..a0c3c51 100644
+--- a/security/tomoyo/file.c
++++ b/security/tomoyo/file.c
+@@ -692,7 +692,7 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
+ {
+ 	struct tomoyo_request_info r;
+ 	struct tomoyo_obj_info obj = {
+-		.path1 = *path,
++		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
+ 	};
+ 	int error = -ENOMEM;
+ 	struct tomoyo_path_info buf;
+@@ -740,7 +740,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
+ 	struct tomoyo_path_info buf;
+ 	struct tomoyo_request_info r;
+ 	struct tomoyo_obj_info obj = {
+-		.path1 = *path,
++		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
+ 	};
+ 	int idx;
+ 
+@@ -786,7 +786,7 @@ int tomoyo_path_perm(const u8 operation, const struct path *path, const char *ta
+ {
+ 	struct tomoyo_request_info r;
+ 	struct tomoyo_obj_info obj = {
+-		.path1 = *path,
++		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
+ 	};
+ 	int error;
+ 	struct tomoyo_path_info buf;
+@@ -843,7 +843,7 @@ int tomoyo_mkdev_perm(const u8 operation, struct path *path,
+ {
+ 	struct tomoyo_request_info r;
+ 	struct tomoyo_obj_info obj = {
+-		.path1 = *path,
++		.path1 = { .mnt = path->mnt, .dentry = path->dentry },
+ 	};
+ 	int error = -ENOMEM;
+ 	struct tomoyo_path_info buf;
+@@ -890,8 +890,8 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
+ 	struct tomoyo_path_info buf2;
+ 	struct tomoyo_request_info r;
+ 	struct tomoyo_obj_info obj = {
+-		.path1 = *path1,
+-		.path2 = *path2,
++		.path1 = { .mnt = path1->mnt, .dentry = path1->dentry },
++		.path2 = { .mnt = path2->mnt, .dentry = path2->dentry }
+ 	};
+ 	int idx;
+ 
+diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
+index 390c646..f2f8db3 100644
+--- a/security/tomoyo/mount.c
++++ b/security/tomoyo/mount.c
+@@ -118,6 +118,10 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r,
+ 		   type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) {
+ 		need_dev = -1; /* dev_name is a directory */
+ 	} else {
++		if (!capable(CAP_SYS_ADMIN)) {
++			error = -EPERM;
++			goto out;
++		}
+ 		fstype = get_fs_type(type);
+ 		if (!fstype) {
+ 			error = -ENODEV;
+diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
+index cbf3df4..22b11df 100644
+--- a/security/tomoyo/tomoyo.c
++++ b/security/tomoyo/tomoyo.c
+@@ -165,7 +165,7 @@ static int tomoyo_path_truncate(struct path *path)
+  */
+ static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
+ {
+-	struct path path = { parent->mnt, dentry };
++	struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ 	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL);
+ }
+ 
+@@ -181,7 +181,7 @@ static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
+ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
+ 			     umode_t mode)
+ {
+-	struct path path = { parent->mnt, dentry };
++	struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ 	return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,
+ 				       mode & S_IALLUGO);
+ }
+@@ -196,7 +196,7 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
+  */
+ static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
+ {
+-	struct path path = { parent->mnt, dentry };
++	struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ 	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL);
+ }
+ 
+@@ -212,7 +212,7 @@ static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
+ static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
+ 			       const char *old_name)
+ {
+-	struct path path = { parent->mnt, dentry };
++	struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ 	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name);
+ }
+ 
+@@ -229,7 +229,7 @@ static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
+ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
+ 			     umode_t mode, unsigned int dev)
+ {
+-	struct path path = { parent->mnt, dentry };
++	struct path path = { .mnt = parent->mnt, .dentry = dentry };
+ 	int type = TOMOYO_TYPE_CREATE;
+ 	const unsigned int perm = mode & S_IALLUGO;
+ 
+@@ -268,8 +268,8 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
+ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
+ 			    struct dentry *new_dentry)
+ {
+-	struct path path1 = { new_dir->mnt, old_dentry };
+-	struct path path2 = { new_dir->mnt, new_dentry };
++	struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry };
++	struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry };
+ 	return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
+ }
+ 
+@@ -288,8 +288,8 @@ static int tomoyo_path_rename(struct path *old_parent,
+ 			      struct path *new_parent,
+ 			      struct dentry *new_dentry)
+ {
+-	struct path path1 = { old_parent->mnt, old_dentry };
+-	struct path path2 = { new_parent->mnt, new_dentry };
++	struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry };
++	struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry };
+ 	return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2);
+ }
+ 
+@@ -417,7 +417,7 @@ static int tomoyo_sb_mount(const char *dev_name, struct path *path,
+  */
+ static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
+ {
+-	struct path path = { mnt, mnt->mnt_root };
++	struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
+ 	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL);
+ }
+ 
+diff --git a/security/yama/Kconfig b/security/yama/Kconfig
+index 90c605e..bf3a29a 100644
+--- a/security/yama/Kconfig
++++ b/security/yama/Kconfig
+@@ -1,6 +1,6 @@
+ config SECURITY_YAMA
+ 	bool "Yama support"
+-	depends on SECURITY
++	depends on SECURITY && !GRKERNSEC
+ 	default n
+ 	help
+ 	  This selects Yama, which extends DAC support with additional
+diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
+index cb6ed10..fb00554 100644
+--- a/security/yama/yama_lsm.c
++++ b/security/yama/yama_lsm.c
+@@ -357,7 +357,7 @@ static struct security_hook_list yama_hooks[] = {
+ static int yama_dointvec_minmax(struct ctl_table *table, int write,
+ 				void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+-	struct ctl_table table_copy;
++	ctl_table_no_const table_copy;
+ 
+ 	if (write && !capable(CAP_SYS_PTRACE))
+ 		return -EPERM;
+diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
+index a04edff..6811b91 100644
+--- a/sound/aoa/codecs/onyx.c
++++ b/sound/aoa/codecs/onyx.c
+@@ -54,7 +54,7 @@ struct onyx {
+ 				spdif_locked:1,
+ 				analog_locked:1,
+ 				original_mute:2;
+-	int			open_count;
++	local_t			open_count;
+ 	struct codec_info	*codec_info;
+ 
+ 	/* mutex serializes concurrent access to the device
+@@ -747,7 +747,7 @@ static int onyx_open(struct codec_info_item *cii,
+ 	struct onyx *onyx = cii->codec_data;
+ 
+ 	mutex_lock(&onyx->mutex);
+-	onyx->open_count++;
++	local_inc(&onyx->open_count);
+ 	mutex_unlock(&onyx->mutex);
+ 
+ 	return 0;
+@@ -759,8 +759,7 @@ static int onyx_close(struct codec_info_item *cii,
+ 	struct onyx *onyx = cii->codec_data;
+ 
+ 	mutex_lock(&onyx->mutex);
+-	onyx->open_count--;
+-	if (!onyx->open_count)
++	if (local_dec_and_test(&onyx->open_count))
+ 		onyx->spdif_locked = onyx->analog_locked = 0;
+ 	mutex_unlock(&onyx->mutex);
+ 
+diff --git a/sound/aoa/codecs/onyx.h b/sound/aoa/codecs/onyx.h
+index ffd2025..df062c9 100644
+--- a/sound/aoa/codecs/onyx.h
++++ b/sound/aoa/codecs/onyx.h
+@@ -11,6 +11,7 @@
+ #include <linux/i2c.h>
+ #include <asm/pmac_low_i2c.h>
+ #include <asm/prom.h>
++#include <asm/local.h>
+ 
+ /* PCM3052 register definitions */
+ 
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index ebc9fdf..61f491e 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1193,10 +1193,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
+ 		if (in_kernel) {
+ 			mm_segment_t fs;
+ 			fs = snd_enter_user();
+-			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
++			ret = snd_pcm_lib_write(substream, (void __force_user *)ptr, frames);
+ 			snd_leave_user(fs);
+ 		} else {
+-			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
++			ret = snd_pcm_lib_write(substream, (void __force_user *)ptr, frames);
+ 		}
+ 		if (ret != -EPIPE && ret != -ESTRPIPE)
+ 			break;
+@@ -1236,10 +1236,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
+ 		if (in_kernel) {
+ 			mm_segment_t fs;
+ 			fs = snd_enter_user();
+-			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
++			ret = snd_pcm_lib_read(substream, (void __force_user *)ptr, frames);
+ 			snd_leave_user(fs);
+ 		} else {
+-			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
++			ret = snd_pcm_lib_read(substream, (void __force_user *)ptr, frames);
+ 		}
+ 		if (ret == -EPIPE) {
+ 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+@@ -1335,7 +1335,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
+ 		struct snd_pcm_plugin_channel *channels;
+ 		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
+ 		if (!in_kernel) {
+-			if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes))
++			if (copy_from_user(runtime->oss.buffer, (const char __force_user *)buf, bytes))
+ 				return -EFAULT;
+ 			buf = runtime->oss.buffer;
+ 		}
+@@ -1405,7 +1405,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
+ 			}
+ 		} else {
+ 			tmp = snd_pcm_oss_write2(substream,
+-						 (const char __force *)buf,
++						 (const char __force_kernel *)buf,
+ 						 runtime->oss.period_bytes, 0);
+ 			if (tmp <= 0)
+ 				goto err;
+@@ -1431,7 +1431,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
+ 	struct snd_pcm_runtime *runtime = substream->runtime;
+ 	snd_pcm_sframes_t frames, frames1;
+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
+-	char __user *final_dst = (char __force __user *)buf;
++	char __user *final_dst = (char __force_user *)buf;
+ 	if (runtime->oss.plugin_first) {
+ 		struct snd_pcm_plugin_channel *channels;
+ 		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
+@@ -1493,7 +1493,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
+ 			xfer += tmp;
+ 			runtime->oss.buffer_used -= tmp;
+ 		} else {
+-			tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
++			tmp = snd_pcm_oss_read2(substream, (char __force_kernel *)buf,
+ 						runtime->oss.period_bytes, 0);
+ 			if (tmp <= 0)
+ 				goto err;
+@@ -1662,7 +1662,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
+ 								   size1);
+ 					size1 /= runtime->channels; /* frames */
+ 					fs = snd_enter_user();
+-					snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
++					snd_pcm_lib_write(substream, (void __force_user *)runtime->oss.buffer, size1);
+ 					snd_leave_user(fs);
+ 				}
+ 			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index 1f64ab0..26a7233 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -31,7 +31,7 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
+ 	int err;
+ 
+ 	fs = snd_enter_user();
+-	err = snd_pcm_delay(substream, &delay);
++	err = snd_pcm_delay(substream, (snd_pcm_sframes_t __force_user *)&delay);
+ 	snd_leave_user(fs);
+ 	if (err < 0)
+ 		return err;
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 3a9b66c..2b38b21 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1867,8 +1867,9 @@ EXPORT_SYMBOL(snd_pcm_lib_ioctl);
+  * Even if more than one periods have elapsed since the last call, you
+  * have to call this only once.
+  */
+-void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
++void snd_pcm_period_elapsed(void *_substream)
+ {
++	struct snd_pcm_substream *substream = _substream;
+ 	struct snd_pcm_runtime *runtime;
+ 	unsigned long flags;
+ 
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 9106d8e..e7e2e3c 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3014,11 +3014,11 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ 	switch (substream->stream) {
+ 	case SNDRV_PCM_STREAM_PLAYBACK:
+ 		result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
+-						 (void __user *)arg);
++						 (void __force_user *)arg);
+ 		break;
+ 	case SNDRV_PCM_STREAM_CAPTURE:
+ 		result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
+-						(void __user *)arg);
++						(void __force_user *)arg);
+ 		break;
+ 	default:
+ 		result = -EINVAL;
+diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
+index 795437b..3650746 100644
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -871,9 +871,10 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
+  *
+  * Return: The size of read data, or a negative error code on failure.
+  */
+-int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
+-			const unsigned char *buffer, int count)
++int snd_rawmidi_receive(void *_substream, const void *_buffer, int count)
+ {
++	struct snd_rawmidi_substream *substream = _substream;
++	const unsigned char *buffer = _buffer;
+ 	unsigned long flags;
+ 	int result = 0, count1;
+ 	struct snd_rawmidi_runtime *runtime = substream->runtime;
+diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
+index b16dbef04..8eb05a4 100644
+--- a/sound/core/seq/oss/seq_oss_synth.c
++++ b/sound/core/seq/oss/seq_oss_synth.c
+@@ -653,8 +653,8 @@ snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
+ 			    rec->synth_type, rec->synth_subtype,
+ 			    rec->nr_voices);
+ 		snd_iprintf(buf, "  capabilities : ioctl %s / load_patch %s\n",
+-			    enabled_str((long)rec->oper.ioctl),
+-			    enabled_str((long)rec->oper.load_patch));
++			    enabled_str(!!rec->oper.ioctl),
++			    enabled_str(!!rec->oper.load_patch));
+ 		snd_use_lock_free(&rec->use_lock);
+ 	}
+ }
+diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
+index 58e79e0..19751d1 100644
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -416,7 +416,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
+ 	if (!client->accept_input || (fifo = client->data.user.fifo) == NULL)
+ 		return -ENXIO;
+ 
+-	if (atomic_read(&fifo->overflow) > 0) {
++	if (atomic_read_unchecked(&fifo->overflow) > 0) {
+ 		/* buffer overflow is detected */
+ 		snd_seq_fifo_clear(fifo);
+ 		/* return error code */
+@@ -446,7 +446,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
+ 			count -= sizeof(struct snd_seq_event);
+ 			buf += sizeof(struct snd_seq_event);
+ 			err = snd_seq_expand_var_event(&cell->event, count,
+-						       (char __force *)buf, 0,
++						       (char __force_kernel *)buf, 0,
+ 						       sizeof(struct snd_seq_event));
+ 			if (err < 0)
+ 				break;
+@@ -1062,13 +1062,13 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
+ 			}
+ 			/* set user space pointer */
+ 			event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;
+-			event.data.ext.ptr = (char __force *)buf
++			event.data.ext.ptr = (char __force_kernel *)buf
+ 						+ sizeof(struct snd_seq_event);
+ 			len += extlen; /* increment data length */
+ 		} else {
+ #ifdef CONFIG_COMPAT
+ 			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
+-				void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]);
++				void *ptr = (void __force_kernel *)compat_ptr(event.data.raw32.d[1]);
+ 				event.data.ext.ptr = ptr;
+ 			}
+ #endif
+@@ -2423,7 +2423,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
+ 	if (client == NULL)
+ 		return -ENXIO;
+ 	fs = snd_enter_user();
+-	result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg);
++	result = snd_seq_do_ioctl(client, cmd, (void __force_user *)arg);
+ 	snd_leave_user(fs);
+ 	return result;
+ }
+diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
+index 6517590..9905cee 100644
+--- a/sound/core/seq/seq_compat.c
++++ b/sound/core/seq/seq_compat.c
+@@ -60,7 +60,7 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
+ 	data->kernel = NULL;
+ 
+ 	fs = snd_enter_user();
+-	err = snd_seq_do_ioctl(client, cmd, data);
++	err = snd_seq_do_ioctl(client, cmd, (void __force_user *)data);
+ 	snd_leave_user(fs);
+ 	if (err < 0)
+ 		goto error;
+diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
+index 1d5acbe..5f55223 100644
+--- a/sound/core/seq/seq_fifo.c
++++ b/sound/core/seq/seq_fifo.c
+@@ -50,7 +50,7 @@ struct snd_seq_fifo *snd_seq_fifo_new(int poolsize)
+ 	spin_lock_init(&f->lock);
+ 	snd_use_lock_init(&f->use_lock);
+ 	init_waitqueue_head(&f->input_sleep);
+-	atomic_set(&f->overflow, 0);
++	atomic_set_unchecked(&f->overflow, 0);
+ 
+ 	f->head = NULL;
+ 	f->tail = NULL;
+@@ -96,7 +96,7 @@ void snd_seq_fifo_clear(struct snd_seq_fifo *f)
+ 	unsigned long flags;
+ 
+ 	/* clear overflow flag */
+-	atomic_set(&f->overflow, 0);
++	atomic_set_unchecked(&f->overflow, 0);
+ 
+ 	snd_use_lock_sync(&f->use_lock);
+ 	spin_lock_irqsave(&f->lock, flags);
+@@ -123,7 +123,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
+ 	err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */
+ 	if (err < 0) {
+ 		if ((err == -ENOMEM) || (err == -EAGAIN))
+-			atomic_inc(&f->overflow);
++			atomic_inc_unchecked(&f->overflow);
+ 		snd_use_lock_free(&f->use_lock);
+ 		return err;
+ 	}
+diff --git a/sound/core/seq/seq_fifo.h b/sound/core/seq/seq_fifo.h
+index 062c446..a4b6f4c 100644
+--- a/sound/core/seq/seq_fifo.h
++++ b/sound/core/seq/seq_fifo.h
+@@ -35,7 +35,7 @@ struct snd_seq_fifo {
+ 	spinlock_t lock;
+ 	snd_use_lock_t use_lock;
+ 	wait_queue_head_t input_sleep;
+-	atomic_t overflow;
++	atomic_unchecked_t overflow;
+ 
+ };
+ 
+diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
+index c850345..ec0a853 100644
+--- a/sound/core/seq/seq_memory.c
++++ b/sound/core/seq/seq_memory.c
+@@ -87,7 +87,7 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
+ 
+ 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
+ 		char buf[32];
+-		char __user *curptr = (char __force __user *)event->data.ext.ptr;
++		char __user *curptr = (char __force_user *)event->data.ext.ptr;
+ 		while (len > 0) {
+ 			int size = sizeof(buf);
+ 			if (len < size)
+@@ -126,15 +126,19 @@ EXPORT_SYMBOL(snd_seq_dump_var_event);
+  * expand the variable length event to linear buffer space.
+  */
+ 
+-static int seq_copy_in_kernel(char **bufptr, const void *src, int size)
++static int seq_copy_in_kernel(void *_bufptr, const void *src, int size)
+ {
++	char **bufptr = (char **)_bufptr;
++
+ 	memcpy(*bufptr, src, size);
+ 	*bufptr += size;
+ 	return 0;
+ }
+ 
+-static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
++static int seq_copy_in_user(void *_bufptr, const void *src, int size)
+ {
++	char __user **bufptr = (char __user **)_bufptr;
++
+ 	if (copy_to_user(*bufptr, src, size))
+ 		return -EFAULT;
+ 	*bufptr += size;
+@@ -158,13 +162,13 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
+ 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
+ 		if (! in_kernel)
+ 			return -EINVAL;
+-		if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len))
++		if (copy_from_user(buf, (void __force_user *)event->data.ext.ptr, len))
+ 			return -EFAULT;
+ 		return newlen;
+ 	}
+ 	err = snd_seq_dump_var_event(event,
+-				     in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel :
+-				     (snd_seq_dump_func_t)seq_copy_in_user,
++				     in_kernel ? seq_copy_in_kernel :
++				     seq_copy_in_user,
+ 				     &buf);
+ 	return err < 0 ? err : newlen;
+ }
+@@ -344,7 +348,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
+ 				tmp->event = src->event;
+ 				src = src->next;
+ 			} else if (is_usrptr) {
+-				if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) {
++				if (copy_from_user(&tmp->event, (char __force_user *)buf, size)) {
+ 					err = -EFAULT;
+ 					goto __error;
+ 				}
+diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
+index 5dd0ee2..0208e35 100644
+--- a/sound/core/seq/seq_midi.c
++++ b/sound/core/seq/seq_midi.c
+@@ -111,8 +111,9 @@ static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
+ 	}
+ }
+ 
+-static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, int count)
++static int dump_midi(void *_substream, const void *buf, int count)
+ {
++	struct snd_rawmidi_substream *substream = _substream;
+ 	struct snd_rawmidi_runtime *runtime;
+ 	int tmp;
+ 
+@@ -148,7 +149,7 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,
+ 			pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
+ 			return 0;
+ 		}
+-		snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
++		snd_seq_dump_var_event(ev, dump_midi, substream);
+ 		snd_midi_event_reset_decode(msynth->parser);
+ 	} else {
+ 		if (msynth->parser == NULL)
+diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
+index c82ed3e..e11d039 100644
+--- a/sound/core/seq/seq_virmidi.c
++++ b/sound/core/seq/seq_virmidi.c
+@@ -90,7 +90,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
+ 		if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
+ 			if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
+ 				continue;
+-			snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream);
++			snd_seq_dump_var_event(ev, snd_rawmidi_receive, vmidi->substream);
+ 		} else {
+ 			len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev);
+ 			if (len > 0)
+diff --git a/sound/core/sound.c b/sound/core/sound.c
+index 175f9e4..3518d31 100644
+--- a/sound/core/sound.c
++++ b/sound/core/sound.c
+@@ -86,7 +86,7 @@ static void snd_request_other(int minor)
+ 	case SNDRV_MINOR_TIMER:		str = "snd-timer";	break;
+ 	default:			return;
+ 	}
+-	request_module(str);
++	request_module("%s", str);
+ }
+ 
+ #endif	/* modular kernel */
+diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
+index 2a008a9..a1efb3f 100644
+--- a/sound/drivers/mts64.c
++++ b/sound/drivers/mts64.c
+@@ -29,6 +29,7 @@
+ #include <sound/initval.h>
+ #include <sound/rawmidi.h>
+ #include <sound/control.h>
++#include <asm/local.h>
+ 
+ #define CARD_NAME "Miditerminal 4140"
+ #define DRIVER_NAME "MTS64"
+@@ -67,7 +68,7 @@ struct mts64 {
+ 	struct pardevice *pardev;
+ 	int pardev_claimed;
+ 
+-	int open_count;
++	local_t open_count;
+ 	int current_midi_output_port;
+ 	int current_midi_input_port;
+ 	u8 mode[MTS64_NUM_INPUT_PORTS];
+@@ -687,7 +688,7 @@ static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream)
+ {
+ 	struct mts64 *mts = substream->rmidi->private_data;
+ 
+-	if (mts->open_count == 0) {
++	if (local_read(&mts->open_count) == 0) {
+ 		/* We don't need a spinlock here, because this is just called 
+ 		   if the device has not been opened before. 
+ 		   So there aren't any IRQs from the device */
+@@ -695,7 +696,7 @@ static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream)
+ 
+ 		msleep(50);
+ 	}
+-	++(mts->open_count);
++	local_inc(&mts->open_count);
+ 
+ 	return 0;
+ }
+@@ -705,8 +706,7 @@ static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream)
+ 	struct mts64 *mts = substream->rmidi->private_data;
+ 	unsigned long flags;
+ 
+-	--(mts->open_count);
+-	if (mts->open_count == 0) {
++	if (local_dec_return(&mts->open_count) == 0) {
+ 		/* We need the spinlock_irqsave here because we can still
+ 		   have IRQs at this point */
+ 		spin_lock_irqsave(&mts->lock, flags);
+@@ -715,8 +715,8 @@ static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream)
+ 
+ 		msleep(500);
+ 
+-	} else if (mts->open_count < 0)
+-		mts->open_count = 0;
++	} else if (local_read(&mts->open_count) < 0)
++		local_set(&mts->open_count, 0);
+ 
+ 	return 0;
+ }
+diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
+index 89c7aa0..6d75e49 100644
+--- a/sound/drivers/opl4/opl4_lib.c
++++ b/sound/drivers/opl4/opl4_lib.c
+@@ -29,7 +29,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+ MODULE_DESCRIPTION("OPL4 driver");
+ MODULE_LICENSE("GPL");
+ 
+-static void inline snd_opl4_wait(struct snd_opl4 *opl4)
++static inline void snd_opl4_wait(struct snd_opl4 *opl4)
+ {
+ 	int timeout = 10;
+ 	while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
+diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
+index 464385a..46ab3f6 100644
+--- a/sound/drivers/portman2x4.c
++++ b/sound/drivers/portman2x4.c
+@@ -48,6 +48,7 @@
+ #include <sound/initval.h>
+ #include <sound/rawmidi.h>
+ #include <sound/control.h>
++#include <asm/local.h>
+ 
+ #define CARD_NAME "Portman 2x4"
+ #define DRIVER_NAME "portman"
+@@ -85,7 +86,7 @@ struct portman {
+ 	struct pardevice *pardev;
+ 	int pardev_claimed;
+ 
+-	int open_count;
++	local_t open_count;
+ 	int mode[PORTMAN_NUM_INPUT_PORTS];
+ 	struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS];
+ };
+diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c
+index bebddc6..f5976be 100644
+--- a/sound/firewire/amdtp-am824.c
++++ b/sound/firewire/amdtp-am824.c
+@@ -314,7 +314,7 @@ void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port,
+ 	struct amdtp_am824 *p = s->protocol;
+ 
+ 	if (port < p->midi_ports)
+-		ACCESS_ONCE(p->midi[port]) = midi;
++		ACCESS_ONCE_RW(p->midi[port]) = midi;
+ }
+ EXPORT_SYMBOL_GPL(amdtp_am824_midi_trigger);
+ 
+diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
+index ed29026..933d2ae 100644
+--- a/sound/firewire/amdtp-stream.c
++++ b/sound/firewire/amdtp-stream.c
+@@ -344,7 +344,7 @@ static void update_pcm_pointers(struct amdtp_stream *s,
+ 	ptr = s->pcm_buffer_pointer + frames;
+ 	if (ptr >= pcm->runtime->buffer_size)
+ 		ptr -= pcm->runtime->buffer_size;
+-	ACCESS_ONCE(s->pcm_buffer_pointer) = ptr;
++	ACCESS_ONCE_RW(s->pcm_buffer_pointer) = ptr;
+ 
+ 	s->pcm_period_pointer += frames;
+ 	if (s->pcm_period_pointer >= pcm->runtime->period_size) {
+@@ -811,7 +811,7 @@ EXPORT_SYMBOL(amdtp_stream_pcm_pointer);
+ void amdtp_stream_update(struct amdtp_stream *s)
+ {
+ 	/* Precomputing. */
+-	ACCESS_ONCE(s->source_node_id_field) =
++	ACCESS_ONCE_RW(s->source_node_id_field) =
+ 		(fw_parent_device(s->unit)->card->node_id << CIP_SID_SHIFT) &
+ 								CIP_SID_MASK;
+ }
+diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
+index 8775704..8fea566 100644
+--- a/sound/firewire/amdtp-stream.h
++++ b/sound/firewire/amdtp-stream.h
+@@ -215,7 +215,7 @@ static inline bool amdtp_stream_pcm_running(struct amdtp_stream *s)
+ static inline void amdtp_stream_pcm_trigger(struct amdtp_stream *s,
+ 					    struct snd_pcm_substream *pcm)
+ {
+-	ACCESS_ONCE(s->pcm) = pcm;
++	ACCESS_ONCE_RW(s->pcm) = pcm;
+ }
+ 
+ static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
+diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c
+index 0ac92ab..a2081aa 100644
+--- a/sound/firewire/digi00x/amdtp-dot.c
++++ b/sound/firewire/digi00x/amdtp-dot.c
+@@ -365,7 +365,7 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
+ 	struct amdtp_dot *p = s->protocol;
+ 
+ 	if (port < p->midi_ports)
+-		ACCESS_ONCE(p->midi[port]) = midi;
++		ACCESS_ONCE_RW(p->midi[port]) = midi;
+ }
+ 
+ static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
+diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
+index 48d6dca..a0266c23 100644
+--- a/sound/firewire/isight.c
++++ b/sound/firewire/isight.c
+@@ -96,7 +96,7 @@ static void isight_update_pointers(struct isight *isight, unsigned int count)
+ 	ptr += count;
+ 	if (ptr >= runtime->buffer_size)
+ 		ptr -= runtime->buffer_size;
+-	ACCESS_ONCE(isight->buffer_pointer) = ptr;
++	ACCESS_ONCE_RW(isight->buffer_pointer) = ptr;
+ 
+ 	isight->period_counter += count;
+ 	if (isight->period_counter >= runtime->period_size) {
+@@ -293,7 +293,7 @@ static int isight_hw_params(struct snd_pcm_substream *substream,
+ 	if (err < 0)
+ 		return err;
+ 
+-	ACCESS_ONCE(isight->pcm_active) = true;
++	ACCESS_ONCE_RW(isight->pcm_active) = true;
+ 
+ 	return 0;
+ }
+@@ -331,7 +331,7 @@ static int isight_hw_free(struct snd_pcm_substream *substream)
+ {
+ 	struct isight *isight = substream->private_data;
+ 
+-	ACCESS_ONCE(isight->pcm_active) = false;
++	ACCESS_ONCE_RW(isight->pcm_active) = false;
+ 
+ 	mutex_lock(&isight->mutex);
+ 	isight_stop_streaming(isight);
+@@ -424,10 +424,10 @@ static int isight_trigger(struct snd_pcm_substream *substream, int cmd)
+ 
+ 	switch (cmd) {
+ 	case SNDRV_PCM_TRIGGER_START:
+-		ACCESS_ONCE(isight->pcm_running) = true;
++		ACCESS_ONCE_RW(isight->pcm_running) = true;
+ 		break;
+ 	case SNDRV_PCM_TRIGGER_STOP:
+-		ACCESS_ONCE(isight->pcm_running) = false;
++		ACCESS_ONCE_RW(isight->pcm_running) = false;
+ 		break;
+ 	default:
+ 		return -EINVAL;
+diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c
+index bb53eb3..670cd89 100644
+--- a/sound/firewire/oxfw/oxfw-scs1x.c
++++ b/sound/firewire/oxfw/oxfw-scs1x.c
+@@ -278,9 +278,9 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
+ 
+ 	if (up) {
+ 		scs->input_escape_count = 0;
+-		ACCESS_ONCE(scs->input) = stream;
++		ACCESS_ONCE_RW(scs->input) = stream;
+ 	} else {
+-		ACCESS_ONCE(scs->input) = NULL;
++		ACCESS_ONCE_RW(scs->input) = NULL;
+ 	}
+ }
+ 
+@@ -310,10 +310,10 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
+ 		scs->output_escaped = false;
+ 		scs->output_idle = false;
+ 
+-		ACCESS_ONCE(scs->output) = stream;
++		ACCESS_ONCE_RW(scs->output) = stream;
+ 		tasklet_schedule(&scs->tasklet);
+ 	} else {
+-		ACCESS_ONCE(scs->output) = NULL;
++		ACCESS_ONCE_RW(scs->output) = NULL;
+ 	}
+ }
+ static void midi_playback_drain(struct snd_rawmidi_substream *stream)
+diff --git a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c
+index dc91072..d85a10a 100644
+--- a/sound/oss/sb_audio.c
++++ b/sound/oss/sb_audio.c
+@@ -900,7 +900,7 @@ sb16_copy_from_user(int dev,
+ 		buf16 = (signed short *)(localbuf + localoffs);
+ 		while (c)
+ 		{
+-			locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
++			locallen = ((unsigned)c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);
+ 			if (copy_from_user(lbuf8,
+ 					   userbuf+useroffs + p,
+ 					   locallen))
+diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
+index 213a416..aeab5c9 100644
+--- a/sound/oss/swarm_cs4297a.c
++++ b/sound/oss/swarm_cs4297a.c
+@@ -2623,7 +2623,6 @@ static int __init cs4297a_init(void)
+ {
+ 	struct cs4297a_state *s;
+ 	u32 pwr, id;
+-	mm_segment_t fs;
+ 	int rval;
+ 	u64 cfg;
+ 	int mdio_val;
+@@ -2709,22 +2708,23 @@ static int __init cs4297a_init(void)
+         if (!rval) {
+ 		char *sb1250_duart_present;
+ 
++#if 0
++                mm_segment_t fs;
+                 fs = get_fs();
+                 set_fs(KERNEL_DS);
+-#if 0
+                 val = SOUND_MASK_LINE;
+                 mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
+                 for (i = 0; i < ARRAY_SIZE(initvol); i++) {
+                         val = initvol[i].vol;
+                         mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val);
+                 }
++                set_fs(fs);
+ //                cs4297a_write_ac97(s, 0x18, 0x0808);
+ #else
+                 //                cs4297a_write_ac97(s, 0x5e, 0x180);
+                 cs4297a_write_ac97(s, 0x02, 0x0808);
+                 cs4297a_write_ac97(s, 0x18, 0x0808);
+ #endif
+-                set_fs(fs);
+ 
+                 list_add(&s->list, &cs4297a_devs);
+ 
+diff --git a/sound/pci/als300.c b/sound/pci/als300.c
+index add3176..c9394d9 100644
+--- a/sound/pci/als300.c
++++ b/sound/pci/als300.c
+@@ -647,7 +647,7 @@ static int snd_als300_create(struct snd_card *card,
+ 			     struct snd_als300 **rchip)
+ {
+ 	struct snd_als300 *chip;
+-	void *irq_handler;
++	irq_handler_t irq_handler;
+ 	int err;
+ 
+ 	static struct snd_device_ops ops = {
+diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
+index 1677143..85aca1d 100644
+--- a/sound/pci/aw2/aw2-alsa.c
++++ b/sound/pci/aw2/aw2-alsa.c
+@@ -458,7 +458,6 @@ static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
+ 
+ 	/* Define Interrupt callback */
+ 	snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
+-						    (snd_aw2_saa7146_it_cb)
+ 						    snd_pcm_period_elapsed,
+ 						    (void *)substream);
+ 
+@@ -487,7 +486,6 @@ static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
+ 
+ 	/* Define Interrupt callback */
+ 	snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
+-						   (snd_aw2_saa7146_it_cb)
+ 						   snd_pcm_period_elapsed,
+ 						   (void *)substream);
+ 
+diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
+index 1d78904..d9c1056 100644
+--- a/sound/pci/aw2/aw2-saa7146.c
++++ b/sound/pci/aw2/aw2-saa7146.c
+@@ -262,7 +262,7 @@ void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
+ {
+ 	if (stream_number < NB_STREAM_PLAYBACK) {
+ 		arr_substream_it_playback_cb[stream_number].p_it_callback =
+-		    (snd_aw2_saa7146_it_cb) p_it_callback;
++		    p_it_callback;
+ 		arr_substream_it_playback_cb[stream_number].p_callback_param =
+ 		    (void *)p_callback_param;
+ 	}
+@@ -275,7 +275,7 @@ void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
+ {
+ 	if (stream_number < NB_STREAM_CAPTURE) {
+ 		arr_substream_it_capture_cb[stream_number].p_it_callback =
+-		    (snd_aw2_saa7146_it_cb) p_it_callback;
++		    p_it_callback;
+ 		arr_substream_it_capture_cb[stream_number].p_callback_param =
+ 		    (void *)p_callback_param;
+ 	}
+diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c
+index 5fcbb06..f4b85df 100644
+--- a/sound/pci/ctxfi/ctamixer.c
++++ b/sound/pci/ctxfi/ctamixer.c
+@@ -297,8 +297,9 @@ static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer)
+ 	return 0;
+ }
+ 
+-int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr)
++int amixer_mgr_create(struct hw *hw, void **_ramixer_mgr)
+ {
++	struct amixer_mgr **ramixer_mgr = (struct amixer_mgr **)_ramixer_mgr;
+ 	int err;
+ 	struct amixer_mgr *amixer_mgr;
+ 
+@@ -326,8 +327,10 @@ error:
+ 	return err;
+ }
+ 
+-int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr)
++int amixer_mgr_destroy(void *_amixer_mgr)
+ {
++	struct amixer_mgr *amixer_mgr = _amixer_mgr;
 +
-+int plugin_is_GPL_compatible;
+ 	rsc_mgr_uninit(&amixer_mgr->mgr);
+ 	kfree(amixer_mgr);
+ 	return 0;
+@@ -452,8 +455,9 @@ static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum)
+ 	return 0;
+ }
+ 
+-int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr)
++int sum_mgr_create(struct hw *hw, void **_rsum_mgr)
+ {
++	struct sum_mgr **rsum_mgr = (struct sum_mgr **)_rsum_mgr;
+ 	int err;
+ 	struct sum_mgr *sum_mgr;
+ 
+@@ -481,8 +485,10 @@ error:
+ 	return err;
+ }
+ 
+-int sum_mgr_destroy(struct sum_mgr *sum_mgr)
++int sum_mgr_destroy(void *_sum_mgr)
+ {
++	struct sum_mgr *sum_mgr = _sum_mgr;
 +
-+static struct plugin_info structleak_plugin_info = {
-+	.version	= "201602181345",
-+	.help		= "disable\tdo not activate plugin\n",
-+};
+ 	rsc_mgr_uninit(&sum_mgr->mgr);
+ 	kfree(sum_mgr);
+ 	return 0;
+diff --git a/sound/pci/ctxfi/ctamixer.h b/sound/pci/ctxfi/ctamixer.h
+index 2de18aa..2fbd01b 100644
+--- a/sound/pci/ctxfi/ctamixer.h
++++ b/sound/pci/ctxfi/ctamixer.h
+@@ -47,8 +47,8 @@ struct sum_mgr {
+ };
+ 
+ /* Constructor and destructor of daio resource manager */
+-int sum_mgr_create(struct hw *hw, struct sum_mgr **rsum_mgr);
+-int sum_mgr_destroy(struct sum_mgr *sum_mgr);
++int sum_mgr_create(struct hw *hw, void **rsum_mgr);
++int sum_mgr_destroy(void *sum_mgr);
+ 
+ /* Define the descriptor of a amixer resource */
+ struct amixer_rsc_ops;
+@@ -93,7 +93,7 @@ struct amixer_mgr {
+ };
+ 
+ /* Constructor and destructor of amixer resource manager */
+-int amixer_mgr_create(struct hw *hw, struct amixer_mgr **ramixer_mgr);
+-int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr);
++int amixer_mgr_create(struct hw *hw, void **ramixer_mgr);
++int amixer_mgr_destroy(void *amixer_mgr);
+ 
+ #endif /* CTAMIXER_H */
+diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
+index 977a598..a787004 100644
+--- a/sound/pci/ctxfi/ctatc.c
++++ b/sound/pci/ctxfi/ctatc.c
+@@ -113,16 +113,16 @@ static struct {
+ 	int (*create)(struct hw *hw, void **rmgr);
+ 	int (*destroy)(void *mgr);
+ } rsc_mgr_funcs[NUM_RSCTYP] = {
+-	[SRC] 		= { .create 	= (create_t)src_mgr_create,
+-			    .destroy 	= (destroy_t)src_mgr_destroy	},
+-	[SRCIMP] 	= { .create 	= (create_t)srcimp_mgr_create,
+-			    .destroy 	= (destroy_t)srcimp_mgr_destroy	},
+-	[AMIXER]	= { .create	= (create_t)amixer_mgr_create,
+-			    .destroy	= (destroy_t)amixer_mgr_destroy	},
+-	[SUM]		= { .create	= (create_t)sum_mgr_create,
+-			    .destroy	= (destroy_t)sum_mgr_destroy	},
+-	[DAIO]		= { .create	= (create_t)daio_mgr_create,
+-			    .destroy	= (destroy_t)daio_mgr_destroy	}
++	[SRC] 		= { .create 	= src_mgr_create,
++			    .destroy 	= src_mgr_destroy	},
++	[SRCIMP] 	= { .create 	= srcimp_mgr_create,
++			    .destroy 	= srcimp_mgr_destroy	},
++	[AMIXER]	= { .create	= amixer_mgr_create,
++			    .destroy	= amixer_mgr_destroy	},
++	[SUM]		= { .create	= sum_mgr_create,
++			    .destroy	= sum_mgr_destroy	},
++	[DAIO]		= { .create	= daio_mgr_create,
++			    .destroy	= daio_mgr_destroy	}
+ };
+ 
+ static int
+diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
+index 7f089cb..6bea28e 100644
+--- a/sound/pci/ctxfi/ctdaio.c
++++ b/sound/pci/ctxfi/ctdaio.c
+@@ -687,8 +687,9 @@ static int daio_mgr_commit_write(struct daio_mgr *mgr)
+ 	return 0;
+ }
+ 
+-int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr)
++int daio_mgr_create(struct hw *hw, void **_rdaio_mgr)
+ {
++	struct daio_mgr **rdaio_mgr = (struct daio_mgr **)_rdaio_mgr;
+ 	int err, i;
+ 	struct daio_mgr *daio_mgr;
+ 	struct imapper *entry;
+@@ -741,8 +742,9 @@ error1:
+ 	return err;
+ }
+ 
+-int daio_mgr_destroy(struct daio_mgr *daio_mgr)
++int daio_mgr_destroy(void *_daio_mgr)
+ {
++	struct daio_mgr *daio_mgr = _daio_mgr;
+ 	unsigned long flags;
+ 
+ 	/* free daio input mapper list */
+diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h
+index a30be73..91b8dbd 100644
+--- a/sound/pci/ctxfi/ctdaio.h
++++ b/sound/pci/ctxfi/ctdaio.h
+@@ -119,7 +119,7 @@ struct daio_mgr {
+ };
+ 
+ /* Constructor and destructor of daio resource manager */
+-int daio_mgr_create(struct hw *hw, struct daio_mgr **rdaio_mgr);
+-int daio_mgr_destroy(struct daio_mgr *daio_mgr);
++int daio_mgr_create(struct hw *hw, void **rdaio_mgr);
++int daio_mgr_destroy(void *daio_mgr);
+ 
+ #endif /* CTDAIO_H */
+diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
+index a5a72df..f86edb8 100644
+--- a/sound/pci/ctxfi/ctsrc.c
++++ b/sound/pci/ctxfi/ctsrc.c
+@@ -544,8 +544,9 @@ static int src_mgr_commit_write(struct src_mgr *mgr)
+ 	return 0;
+ }
+ 
+-int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr)
++int src_mgr_create(struct hw *hw, void **_rsrc_mgr)
+ {
++	struct src_mgr **rsrc_mgr = (struct src_mgr **)_rsrc_mgr;
+ 	int err, i;
+ 	struct src_mgr *src_mgr;
+ 
+@@ -584,8 +585,10 @@ error1:
+ 	return err;
+ }
+ 
+-int src_mgr_destroy(struct src_mgr *src_mgr)
++int src_mgr_destroy(void *_src_mgr)
+ {
++	struct src_mgr *src_mgr = _src_mgr;
 +
-+static tree handle_user_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
+ 	rsc_mgr_uninit(&src_mgr->mgr);
+ 	kfree(src_mgr);
+ 
+@@ -828,8 +831,9 @@ static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
+ 	return err;
+ }
+ 
+-int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr)
++int srcimp_mgr_create(struct hw *hw, void **_rsrcimp_mgr)
+ {
++	struct srcimp_mgr **rsrcimp_mgr = (struct srcimp_mgr **)_rsrcimp_mgr;
+ 	int err;
+ 	struct srcimp_mgr *srcimp_mgr;
+ 	struct imapper *entry;
+@@ -873,8 +877,9 @@ error1:
+ 	return err;
+ }
+ 
+-int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr)
++int srcimp_mgr_destroy(void *_srcimp_mgr)
+ {
++	struct srcimp_mgr *srcimp_mgr = _srcimp_mgr;
+ 	unsigned long flags;
+ 
+ 	/* free src input mapper list */
+diff --git a/sound/pci/ctxfi/ctsrc.h b/sound/pci/ctxfi/ctsrc.h
+index 92944a0..fc78ed4 100644
+--- a/sound/pci/ctxfi/ctsrc.h
++++ b/sound/pci/ctxfi/ctsrc.h
+@@ -143,10 +143,10 @@ struct srcimp_mgr {
+ };
+ 
+ /* Constructor and destructor of SRC resource manager */
+-int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr);
+-int src_mgr_destroy(struct src_mgr *src_mgr);
++int src_mgr_create(struct hw *hw, void **rsrc_mgr);
++int src_mgr_destroy(void *src_mgr);
+ /* Constructor and destructor of SRCIMP resource manager */
+-int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrc_mgr);
+-int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr);
++int srcimp_mgr_create(struct hw *hw, void **rsrc_mgr);
++int srcimp_mgr_destroy(void *srcimp_mgr);
+ 
+ #endif /* CTSRC_H */
+diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
+index 8374188..f073778 100644
+--- a/sound/pci/hda/hda_codec.c
++++ b/sound/pci/hda/hda_codec.c
+@@ -1743,7 +1743,7 @@ static int get_kctl_0dB_offset(struct hda_codec *codec,
+ 		/* FIXME: set_fs() hack for obtaining user-space TLV data */
+ 		mm_segment_t fs = get_fs();
+ 		set_fs(get_ds());
+-		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
++		if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), (unsigned int __force_user *)_tlv))
+ 			tlv = _tlv;
+ 		set_fs(fs);
+ 	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
+diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h
+index 149d4cb..7784769 100644
+--- a/sound/pci/ymfpci/ymfpci.h
++++ b/sound/pci/ymfpci/ymfpci.h
+@@ -358,7 +358,7 @@ struct snd_ymfpci {
+ 	spinlock_t reg_lock;
+ 	spinlock_t voice_lock;
+ 	wait_queue_head_t interrupt_sleep;
+-	atomic_t interrupt_sleep_count;
++	atomic_unchecked_t interrupt_sleep_count;
+ 	struct snd_info_entry *proc_entry;
+ 	const struct firmware *dsp_microcode;
+ 	const struct firmware *controller_microcode;
+diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
+index 4c26076..a13f370 100644
+--- a/sound/pci/ymfpci/ymfpci_main.c
++++ b/sound/pci/ymfpci/ymfpci_main.c
+@@ -204,8 +204,8 @@ static void snd_ymfpci_hw_stop(struct snd_ymfpci *chip)
+ 		if ((snd_ymfpci_readl(chip, YDSXGR_STATUS) & 2) == 0)
+ 			break;
+ 	}
+-	if (atomic_read(&chip->interrupt_sleep_count)) {
+-		atomic_set(&chip->interrupt_sleep_count, 0);
++	if (atomic_read_unchecked(&chip->interrupt_sleep_count)) {
++		atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
+ 		wake_up(&chip->interrupt_sleep);
+ 	}
+       __end:
+@@ -789,7 +789,7 @@ static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip)
+ 		 	continue;
+ 		init_waitqueue_entry(&wait, current);
+ 		add_wait_queue(&chip->interrupt_sleep, &wait);
+-		atomic_inc(&chip->interrupt_sleep_count);
++		atomic_inc_unchecked(&chip->interrupt_sleep_count);
+ 		schedule_timeout_uninterruptible(msecs_to_jiffies(50));
+ 		remove_wait_queue(&chip->interrupt_sleep, &wait);
+ 	}
+@@ -827,8 +827,8 @@ static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id)
+ 		snd_ymfpci_writel(chip, YDSXGR_MODE, mode);
+ 		spin_unlock(&chip->reg_lock);
+ 
+-		if (atomic_read(&chip->interrupt_sleep_count)) {
+-			atomic_set(&chip->interrupt_sleep_count, 0);
++		if (atomic_read_unchecked(&chip->interrupt_sleep_count)) {
++			atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
+ 			wake_up(&chip->interrupt_sleep);
+ 		}
+ 	}
+@@ -2384,7 +2384,7 @@ int snd_ymfpci_create(struct snd_card *card,
+ 	spin_lock_init(&chip->reg_lock);
+ 	spin_lock_init(&chip->voice_lock);
+ 	init_waitqueue_head(&chip->interrupt_sleep);
+-	atomic_set(&chip->interrupt_sleep_count, 0);
++	atomic_set_unchecked(&chip->interrupt_sleep_count, 0);
+ 	chip->card = card;
+ 	chip->pci = pci;
+ 	chip->irq = -1;
+diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
+index d6f4abb..5d59f0c 100644
+--- a/sound/soc/codecs/cx20442.c
++++ b/sound/soc/codecs/cx20442.c
+@@ -263,6 +263,12 @@ static int v253_hangup(struct tty_struct *tty)
+ 	return 0;
+ }
+ 
++static int v253_hw_write(void *client, const char *buf, int count)
 +{
-+	*no_add_attrs = true;
-+
-+	// check for types? for now accept everything linux has to offer
-+	if (TREE_CODE(*node) != FIELD_DECL)
-+		return NULL_TREE;
-+
-+	*no_add_attrs = false;
-+	return NULL_TREE;
++	struct tty_struct *tty = client;
++	return tty->ops->write(client, buf, count);
 +}
 +
-+static struct attribute_spec user_attr = {
-+	.name			= "user",
-+	.min_length		= 0,
-+	.max_length		= 0,
-+	.decl_required		= false,
-+	.type_required		= false,
-+	.function_type_required	= false,
-+	.handler		= handle_user_attribute,
-+#if BUILDING_GCC_VERSION >= 4007
-+	.affects_type_identity	= true
-+#endif
-+};
-+
-+static void register_attributes(void *event_data, void *data)
+ /* Line discipline .receive_buf() */
+ static void v253_receive(struct tty_struct *tty,
+ 				const unsigned char *cp, char *fp, int count)
+@@ -280,7 +286,7 @@ static void v253_receive(struct tty_struct *tty,
+ 
+ 		/* Set up codec driver access to modem controls */
+ 		cx20442->control_data = tty;
+-		codec->hw_write = (hw_write_t)tty->ops->write;
++		codec->hw_write = v253_hw_write;
+ 		codec->component.card->pop_time = 1;
+ 	}
+ }
+diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c
+index 160d61a..cd7a4ac 100644
+--- a/sound/soc/codecs/sti-sas.c
++++ b/sound/soc/codecs/sti-sas.c
+@@ -591,11 +591,13 @@ static int sti_sas_driver_probe(struct platform_device *pdev)
+ 	sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops;
+ 
+ 	/* Set dapms*/
+-	sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
+-	sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
++	pax_open_kernel();
++	const_cast(sti_sas_driver.dapm_widgets) = drvdata->dev_data->dapm_widgets;
++	const_cast(sti_sas_driver.num_dapm_widgets) = drvdata->dev_data->num_dapm_widgets;
+ 
+-	sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes;
+-	sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
++	const_cast(sti_sas_driver.dapm_routes) = drvdata->dev_data->dapm_routes;
++	const_cast(sti_sas_driver.num_dapm_routes) = drvdata->dev_data->num_dapm_routes;
++	pax_close_kernel();
+ 
+ 	/* Store context */
+ 	dev_set_drvdata(&pdev->dev, drvdata);
+diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
+index f7a6ce7..82310c8 100644
+--- a/sound/soc/codecs/tlv320dac33.c
++++ b/sound/soc/codecs/tlv320dac33.c
+@@ -1375,13 +1375,18 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ 	return 0;
+ }
+ 
++static int dac33_hw_write(void *client, const char *buf, int count)
 +{
-+	register_attribute(&user_attr);
-+//	register_attribute(&force_attr);
++	return i2c_master_send(client, buf, count);
 +}
 +
-+static tree get_field_type(tree field)
+ static int dac33_soc_probe(struct snd_soc_codec *codec)
+ {
+ 	struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
+ 	int ret = 0;
+ 
+ 	codec->control_data = dac33->control_data;
+-	codec->hw_write = (hw_write_t) i2c_master_send;
++	codec->hw_write = dac33_hw_write;
+ 	dac33->codec = codec;
+ 
+ 	/* Read the tlv320dac33 ID registers */
+diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
+index 35f0469..7c25cd5 100644
+--- a/sound/soc/codecs/uda1380.c
++++ b/sound/soc/codecs/uda1380.c
+@@ -687,6 +687,11 @@ static struct snd_soc_dai_driver uda1380_dai[] = {
+ },
+ };
+ 
++static int uda1380_hw_write(void *client, const char *buf, int count)
 +{
-+	return strip_array_types(TREE_TYPE(field));
++	return i2c_master_send(client, buf, count);
 +}
 +
-+static bool is_userspace_type(tree type)
-+{
-+	tree field;
-+
-+	for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) {
-+		tree fieldtype = get_field_type(field);
-+		enum tree_code code = TREE_CODE(fieldtype);
-+
-+		if (code == RECORD_TYPE || code == UNION_TYPE)
-+			if (is_userspace_type(fieldtype))
-+				return true;
-+
-+		if (lookup_attribute("user", DECL_ATTRIBUTES(field)))
-+			return true;
-+	}
-+	return false;
-+}
+ static int uda1380_probe(struct snd_soc_codec *codec)
+ {
+ 	struct uda1380_platform_data *pdata =codec->dev->platform_data;
+@@ -695,7 +700,7 @@ static int uda1380_probe(struct snd_soc_codec *codec)
+ 
+ 	uda1380->codec = codec;
+ 
+-	codec->hw_write = (hw_write_t)i2c_master_send;
++	codec->hw_write = uda1380_hw_write;
+ 	codec->control_data = uda1380->control_data;
+ 
+ 	if (!pdata)
+diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
+index cbb4075..edda3dd 100644
+--- a/sound/soc/intel/skylake/skl-sst-dsp.h
++++ b/sound/soc/intel/skylake/skl-sst-dsp.h
+@@ -117,14 +117,14 @@ struct skl_dsp_fw_ops {
+ 	int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, char *mod_name);
+ 	int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
+ 
+-};
++} __no_const;
+ 
+ struct skl_dsp_loader_ops {
+ 	int (*alloc_dma_buf)(struct device *dev,
+ 		struct snd_dma_buffer *dmab, size_t size);
+ 	int (*free_dma_buf)(struct device *dev,
+ 		struct snd_dma_buffer *dmab);
+-};
++} __no_const;
+ 
+ struct skl_load_module_info {
+ 	u16 mod_id;
+diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c
+index 7e0acd8..b4b2acb 100644
+--- a/sound/soc/soc-ac97.c
++++ b/sound/soc/soc-ac97.c
+@@ -416,8 +416,10 @@ int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
+ 	if (ret)
+ 		return ret;
+ 
+-	ops->warm_reset = snd_soc_ac97_warm_reset;
+-	ops->reset = snd_soc_ac97_reset;
++	pax_open_kernel();
++	const_cast(ops->warm_reset) = snd_soc_ac97_warm_reset;
++	const_cast(ops->reset) = snd_soc_ac97_reset;
++	pax_close_kernel();
+ 
+ 	snd_ac97_rst_cfg = cfg;
+ 	return 0;
+diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c
+index 8382ffa..86af7d0 100644
+--- a/sound/soc/xtensa/xtfpga-i2s.c
++++ b/sound/soc/xtensa/xtfpga-i2s.c
+@@ -437,7 +437,7 @@ static int xtfpga_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ 	case SNDRV_PCM_TRIGGER_START:
+ 	case SNDRV_PCM_TRIGGER_RESUME:
+ 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+-		ACCESS_ONCE(i2s->tx_ptr) = 0;
++		ACCESS_ONCE_RW(i2s->tx_ptr) = 0;
+ 		rcu_assign_pointer(i2s->tx_substream, substream);
+ 		xtfpga_pcm_refill_fifo(i2s);
+ 		break;
+diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
+index a020920..55579f6 100644
+--- a/sound/synth/emux/emux_seq.c
++++ b/sound/synth/emux/emux_seq.c
+@@ -33,13 +33,13 @@ static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *inf
+  * MIDI emulation operators
+  */
+ static struct snd_midi_op emux_ops = {
+-	snd_emux_note_on,
+-	snd_emux_note_off,
+-	snd_emux_key_press,
+-	snd_emux_terminate_note,
+-	snd_emux_control,
+-	snd_emux_nrpn,
+-	snd_emux_sysex,
++	.note_on = snd_emux_note_on,
++	.note_off = snd_emux_note_off,
++	.key_press = snd_emux_key_press,
++	.note_terminate = snd_emux_terminate_note,
++	.control = snd_emux_control,
++	.nrpn = snd_emux_nrpn,
++	.sysex = snd_emux_sysex,
+ };
+ 
+ 
+diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
+index 81b7da8..bb2676f 100644
+--- a/sound/usb/line6/driver.c
++++ b/sound/usb/line6/driver.c
+@@ -307,7 +307,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
+ {
+ 	struct usb_device *usbdev = line6->usbdev;
+ 	int ret;
+-	unsigned char len;
++	unsigned char *plen;
+ 	unsigned count;
+ 
+ 	if (address > 0xffff || datalen > 0xff)
+@@ -324,6 +324,10 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
+ 		return ret;
+ 	}
+ 
++	plen = kmalloc(1, GFP_KERNEL);
++	if (plen == NULL)
++		return -ENOMEM;
 +
-+static void finish_type(void *event_data, void *data)
-+{
-+	tree type = (tree)event_data;
+ 	/* Wait for data length. We'll get 0xff until length arrives. */
+ 	for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
+ 		mdelay(LINE6_READ_WRITE_STATUS_DELAY);
+@@ -331,30 +335,35 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
+ 		ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+ 				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+ 				      USB_DIR_IN,
+-				      0x0012, 0x0000, &len, 1,
++				      0x0012, 0x0000, plen, 1,
+ 				      LINE6_TIMEOUT * HZ);
+ 		if (ret < 0) {
+ 			dev_err(line6->ifcdev,
+ 				"receive length failed (error %d)\n", ret);
++			kfree(plen);
+ 			return ret;
+ 		}
+ 
+-		if (len != 0xff)
++		if (*plen != 0xff)
+ 			break;
+ 	}
+ 
+-	if (len == 0xff) {
++	if (*plen == 0xff) {
+ 		dev_err(line6->ifcdev, "read failed after %d retries\n",
+ 			count);
++		kfree(plen);
+ 		return -EIO;
+-	} else if (len != datalen) {
++	} else if (*plen != datalen) {
+ 		/* should be equal or something went wrong */
+ 		dev_err(line6->ifcdev,
+ 			"length mismatch (expected %d, got %d)\n",
+-			(int)datalen, (int)len);
++			(int)datalen, (int)*plen);
++		kfree(plen);
+ 		return -EIO;
+ 	}
+ 
++	kfree(plen);
 +
-+	if (type == NULL_TREE || type == error_mark_node)
-+		return;
+ 	/* receive the result: */
+ 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+ 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+@@ -378,7 +387,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
+ {
+ 	struct usb_device *usbdev = line6->usbdev;
+ 	int ret;
+-	unsigned char status;
++	unsigned char *status;
+ 	int count;
+ 
+ 	if (address > 0xffff || datalen > 0xffff)
+@@ -395,6 +404,10 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
+ 		return ret;
+ 	}
+ 
++	status = kmalloc(1, GFP_KERNEL);
++	if (status == NULL)
++		return -ENOMEM;
 +
-+#if BUILDING_GCC_VERSION >= 5000
-+	if (TREE_CODE(type) == ENUMERAL_TYPE)
-+		return;
-+#endif
+ 	for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
+ 		mdelay(LINE6_READ_WRITE_STATUS_DELAY);
+ 
+@@ -403,27 +416,32 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
+ 				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+ 				      USB_DIR_IN,
+ 				      0x0012, 0x0000,
+-				      &status, 1, LINE6_TIMEOUT * HZ);
++				      status, 1, LINE6_TIMEOUT * HZ);
+ 
+ 		if (ret < 0) {
+ 			dev_err(line6->ifcdev,
+ 				"receiving status failed (error %d)\n", ret);
++			kfree(status);
+ 			return ret;
+ 		}
+ 
+-		if (status != 0xff)
++		if (*status != 0xff)
+ 			break;
+ 	}
+ 
+-	if (status == 0xff) {
++	if (*status == 0xff) {
+ 		dev_err(line6->ifcdev, "write failed after %d retries\n",
+ 			count);
++		kfree(status);
+ 		return -EIO;
+-	} else if (status != 0) {
++	} else if (*status != 0) {
+ 		dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
++		kfree(status);
+ 		return -EIO;
+ 	}
+ 
++	kfree(status);
 +
-+	if (TYPE_USERSPACE(type))
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(line6_write_data);
+diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
+index 6d4c50c..aa658c8 100644
+--- a/sound/usb/line6/toneport.c
++++ b/sound/usb/line6/toneport.c
+@@ -367,13 +367,19 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
+ */
+ static void toneport_setup(struct usb_line6_toneport *toneport)
+ {
+-	int ticks;
++	int *ticks;
+ 	struct usb_line6 *line6 = &toneport->line6;
+ 	struct usb_device *usbdev = line6->usbdev;
+ 
++	ticks = kmalloc(sizeof(int), GFP_KERNEL);
++	if (ticks == NULL)
 +		return;
 +
-+	if (is_userspace_type(type))
-+		TYPE_USERSPACE(type) = 1;
-+}
-+
-+static void initialize(tree var)
-+{
-+	basic_block bb;
-+	gimple_stmt_iterator gsi;
-+	tree initializer;
-+	gimple init_stmt;
-+
-+	// this is the original entry bb before the forced split
-+	bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+
-+	// first check if the variable is already initialized, warn otherwise
-+	for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
-+		gimple stmt = gsi_stmt(gsi);
-+		tree rhs1;
-+
-+		// we're looking for an assignment of a single rhs...
-+		if (!gimple_assign_single_p(stmt))
-+			continue;
-+		rhs1 = gimple_assign_rhs1(stmt);
-+#if BUILDING_GCC_VERSION >= 4007
-+		// ... of a non-clobbering expression...
-+		if (TREE_CLOBBER_P(rhs1))
-+			continue;
-+#endif
-+		// ... to our variable...
-+		if (gimple_get_lhs(stmt) != var)
-+			continue;
-+		// if it's an initializer then we're good
-+		if (TREE_CODE(rhs1) == CONSTRUCTOR)
-+			return;
-+	}
-+
-+	// these aren't the 0days you're looking for
-+//	inform(DECL_SOURCE_LOCATION(var), "userspace variable will be forcibly initialized");
-+
-+	// build the initializer expression
-+	initializer = build_constructor(TREE_TYPE(var), NULL);
-+
-+	// build the initializer stmt
-+	init_stmt = gimple_build_assign(var, initializer);
-+	gsi = gsi_after_labels(single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+	gsi_insert_before(&gsi, init_stmt, GSI_NEW_STMT);
-+	update_stmt(init_stmt);
-+}
-+
-+static unsigned int structleak_execute(void)
-+{
-+	basic_block bb;
-+	unsigned int ret = 0;
-+	tree var;
-+	unsigned int i;
-+
-+	// split the first bb where we can put the forced initializers
-+	gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+	bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-+	if (!single_pred_p(bb)) {
-+//		gcc_assert(bb_loop_depth(bb) || (bb->flags & BB_IRREDUCIBLE_LOOP));
-+		split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+		gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
-+	}
-+
-+	// enumarate all local variables and forcibly initialize our targets
-+	FOR_EACH_LOCAL_DECL(cfun, i, var) {
-+		tree type = TREE_TYPE(var);
-+
-+		gcc_assert(DECL_P(var));
-+		if (!auto_var_in_fn_p(var, current_function_decl))
-+			continue;
-+
-+		// only care about structure types
-+		if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
-+			continue;
-+
-+		// if the type is of interest, examine the variable
-+		if (TYPE_USERSPACE(type))
-+			initialize(var);
-+	}
-+
-+	return ret;
-+}
-+
-+#define PASS_NAME structleak
-+#define NO_GATE
-+#define PROPERTIES_REQUIRED PROP_cfg
-+#define TODO_FLAGS_FINISH TODO_verify_il | TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_remove_unused_locals | TODO_update_ssa | TODO_ggc_collect | TODO_verify_flow
-+#include "gcc-generate-gimple-pass.h"
-+
-+int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
-+{
-+	int i;
-+	const char * const plugin_name = plugin_info->base_name;
-+	const int argc = plugin_info->argc;
-+	const struct plugin_argument * const argv = plugin_info->argv;
-+	bool enable = true;
-+	struct register_pass_info structleak_pass_info;
-+
-+	structleak_pass_info.pass			= make_structleak_pass();
-+	structleak_pass_info.reference_pass_name	= "ssa";
-+	structleak_pass_info.ref_pass_instance_number	= 1;
-+	structleak_pass_info.pos_op			= PASS_POS_INSERT_AFTER;
-+
-+	if (!plugin_default_version_check(version, &gcc_version)) {
-+		error(G_("incompatible gcc/plugin versions"));
-+		return 1;
-+	}
-+
-+	if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {
-+		inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);
-+		enable = false;
-+	}
-+
-+	for (i = 0; i < argc; ++i) {
-+		if (!strcmp(argv[i].key, "disable")) {
-+			enable = false;
-+			continue;
-+		}
-+		error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
-+	}
-+
-+	register_callback(plugin_name, PLUGIN_INFO, NULL, &structleak_plugin_info);
-+	if (enable) {
-+		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &structleak_pass_info);
-+		register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
-+	}
-+	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
+ 	/* sync time on device with host: */
+-	ticks = (int)get_seconds();
+-	line6_write_data(line6, 0x80c6, &ticks, 4);
++	*ticks = (int)get_seconds();
++	line6_write_data(line6, 0x80c6, ticks, sizeof(int));
 +
-+	return 0;
-+}
++	kfree(ticks);
+ 
+ 	/* enable device: */
+ 	toneport_send_cmd(usbdev, 0x0301, 0x0000);
 diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
 index fa7208a..d568e71 100644
 --- a/tools/include/linux/compiler.h


^ permalink raw reply related	[relevance 99%]

Results 1-1 of 1 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2016-05-30  7:59 99% [gentoo-commits] proj/hardened-patchset:master commit in: 4.5.5/ Anthony G. Basile

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox