Re: [PATCH 20/23] gcc-plugins: always build plugins with C++

2018-02-22 Thread Emese Revfy
On Sat, 17 Feb 2018 03:38:48 +0900
Masahiro Yamada  wrote:

> If the target compiler is GCC 4.8 or newer, plugins are compiled with
> HOSTCXX.  Otherwise, gcc-plugin.sh will select HOSTCC or HOSTCXX.
> 
> To simpily things, let's decide GCC 4.8 is the requirement for GCC
> pulgins.  With this, plugins are always built with HOSTCXX.  This is a
> feature of advanced users, so this requirement whould not be not a big
> issue.

I disagree with such a decision. I think the gcc plugins should compile
with older version because the kernel can be compiled with them too.
The distros use these older versions as well and I can very well imagine
that new plugins will extend these with backported features such as
my sancov plugin.

-- 
Emese


Re: [PATCH 20/23] gcc-plugins: always build plugins with C++

2018-02-22 Thread Emese Revfy
On Sat, 17 Feb 2018 03:38:48 +0900
Masahiro Yamada  wrote:

> If the target compiler is GCC 4.8 or newer, plugins are compiled with
> HOSTCXX.  Otherwise, gcc-plugin.sh will select HOSTCC or HOSTCXX.
> 
> To simpily things, let's decide GCC 4.8 is the requirement for GCC
> pulgins.  With this, plugins are always built with HOSTCXX.  This is a
> feature of advanced users, so this requirement whould not be not a big
> issue.

I disagree with such a decision. I think the gcc plugins should compile
with older version because the kernel can be compiled with them too.
The distros use these older versions as well and I can very well imagine
that new plugins will extend these with backported features such as
my sancov plugin.

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-02-20 Thread Emese Revfy
On Wed, 15 Feb 2017 11:27:06 -0800
Kees Cook <keesc...@chromium.org> wrote:

> On Tue, Feb 14, 2017 at 4:23 PM, Emese Revfy <re.em...@gmail.com> wrote:
> > On Thu, 12 Jan 2017 15:40:41 -0800
> > Kees Cook <keesc...@chromium.org> wrote:
> >
> >> WARNING: drivers/clk/bcm/built-in.o(.text+0xec2): Section mismatch in
> >> reference from the function clk_gate() to the variable
> >> .init.rodata.str:__func__.29708
> >> The function clk_gate() references
> >> the variable __initconst __func__.29708.
> >> This is often because clk_gate lacks a __initconst
> >> annotation or the annotation of __func__.29708 is wrong.
> >
> > Thanks for the report, it will be fixed in the next grsec patch.
> 
> Very cool, thanks! What did the problem turn out to be?

You can find it here:
https://github.com/ephox-gcc-plugins/initify/commit/73e857aa47bde7cc78ed865a008d1519893c0f54

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-02-20 Thread Emese Revfy
On Wed, 15 Feb 2017 11:27:06 -0800
Kees Cook  wrote:

> On Tue, Feb 14, 2017 at 4:23 PM, Emese Revfy  wrote:
> > On Thu, 12 Jan 2017 15:40:41 -0800
> > Kees Cook  wrote:
> >
> >> WARNING: drivers/clk/bcm/built-in.o(.text+0xec2): Section mismatch in
> >> reference from the function clk_gate() to the variable
> >> .init.rodata.str:__func__.29708
> >> The function clk_gate() references
> >> the variable __initconst __func__.29708.
> >> This is often because clk_gate lacks a __initconst
> >> annotation or the annotation of __func__.29708 is wrong.
> >
> > Thanks for the report, it will be fixed in the next grsec patch.
> 
> Very cool, thanks! What did the problem turn out to be?

You can find it here:
https://github.com/ephox-gcc-plugins/initify/commit/73e857aa47bde7cc78ed865a008d1519893c0f54

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-02-14 Thread Emese Revfy
On Thu, 12 Jan 2017 15:40:41 -0800
Kees Cook  wrote:

> WARNING: drivers/clk/bcm/built-in.o(.text+0xec2): Section mismatch in
> reference from the function clk_gate() to the variable
> .init.rodata.str:__func__.29708
> The function clk_gate() references
> the variable __initconst __func__.29708.
> This is often because clk_gate lacks a __initconst
> annotation or the annotation of __func__.29708 is wrong.

Thanks for the report, it will be fixed in the next grsec patch.

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-02-14 Thread Emese Revfy
On Thu, 12 Jan 2017 15:40:41 -0800
Kees Cook  wrote:

> WARNING: drivers/clk/bcm/built-in.o(.text+0xec2): Section mismatch in
> reference from the function clk_gate() to the variable
> .init.rodata.str:__func__.29708
> The function clk_gate() references
> the variable __initconst __func__.29708.
> This is often because clk_gate lacks a __initconst
> annotation or the annotation of __func__.29708 is wrong.

Thanks for the report, it will be fixed in the next grsec patch.

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-01-17 Thread Emese Revfy
On Thu, 12 Jan 2017 15:40:41 -0800
Kees Cook  wrote:

> WARNING: drivers/clk/bcm/built-in.o(.text+0xec2): Section mismatch in
> reference from the function clk_gate() to the variable
> .init.rodata.str:__func__.29708
> The function clk_gate() references
> the variable __initconst __func__.29708.
> This is often because clk_gate lacks a __initconst
> annotation or the annotation of __func__.29708 is wrong.
>
> I used my initify v5 development tree, with the following patch, with
> "make allyesconfig":
> 
> http://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/log/?h=for-next/gcc-plugin/initify

Hi,

I can't reproduce this mismatch with allyesconfig. Could you please send me 
your .config?

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-01-17 Thread Emese Revfy
On Thu, 12 Jan 2017 15:40:41 -0800
Kees Cook  wrote:

> WARNING: drivers/clk/bcm/built-in.o(.text+0xec2): Section mismatch in
> reference from the function clk_gate() to the variable
> .init.rodata.str:__func__.29708
> The function clk_gate() references
> the variable __initconst __func__.29708.
> This is often because clk_gate lacks a __initconst
> annotation or the annotation of __func__.29708 is wrong.
>
> I used my initify v5 development tree, with the following patch, with
> "make allyesconfig":
> 
> http://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/log/?h=for-next/gcc-plugin/initify

Hi,

I can't reproduce this mismatch with allyesconfig. Could you please send me 
your .config?

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-01-12 Thread Emese Revfy
On Tue, 10 Jan 2017 17:09:31 -0800
Kees Cook  wrote:

> WARNING: vmlinux.o(.text+0x1087e7): Section mismatch in reference from
> the function rebind_subsystems() to the variable
> .init.rodata.str:__func__.4400
> The function rebind_subsystems() references
> the variable __initconst __func__.4400.
> This is often because rebind_subsystems lacks a __initconst
> annotation or the annotation of __func__.4400 is wrong.

Thanks for the report, you can find the fix here:
https://github.com/ephox-gcc-plugins/initify/commit/25f34834e3373e067133bc5d39d42c50a3592d56
 
-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-01-12 Thread Emese Revfy
On Tue, 10 Jan 2017 17:09:31 -0800
Kees Cook  wrote:

> WARNING: vmlinux.o(.text+0x1087e7): Section mismatch in reference from
> the function rebind_subsystems() to the variable
> .init.rodata.str:__func__.4400
> The function rebind_subsystems() references
> the variable __initconst __func__.4400.
> This is often because rebind_subsystems lacks a __initconst
> annotation or the annotation of __func__.4400 is wrong.

Thanks for the report, you can find the fix here:
https://github.com/ephox-gcc-plugins/initify/commit/25f34834e3373e067133bc5d39d42c50a3592d56
 
-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-01-10 Thread Emese Revfy
On Tue, 3 Jan 2017 16:23:03 -0800
Kees Cook <keesc...@chromium.org> wrote:

> On Mon, Dec 19, 2016 at 3:10 AM, Emese Revfy <re.em...@gmail.com> wrote:
> > On Fri, 16 Dec 2016 14:19:10 -0800
> > Kees Cook <keesc...@chromium.org> wrote:
> >
> >> FWIW, it still seems to me that these aren't false positives:
> >>
> >> WARNING: vmlinux.o(.text.unlikely+0x1b1): Section mismatch in
> >> reference from the function uncore_pci_exit.part.22() to the function
> >> .init.text:uncore_free_pcibus_map()
> >> The function uncore_pci_exit.part.22() references
> >> the function __init uncore_free_pcibus_map().
> >> This is often because uncore_pci_exit.part.22 lacks a __init
> >> annotation or the annotation of uncore_free_pcibus_map is wrong.

Thanks for the report, you can find the fix here:
https://github.com/ephox-gcc-plugins/initify/commit/5d93a54badd9751b79ef67ce8a8b4081fea37547

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2017-01-10 Thread Emese Revfy
On Tue, 3 Jan 2017 16:23:03 -0800
Kees Cook  wrote:

> On Mon, Dec 19, 2016 at 3:10 AM, Emese Revfy  wrote:
> > On Fri, 16 Dec 2016 14:19:10 -0800
> > Kees Cook  wrote:
> >
> >> FWIW, it still seems to me that these aren't false positives:
> >>
> >> WARNING: vmlinux.o(.text.unlikely+0x1b1): Section mismatch in
> >> reference from the function uncore_pci_exit.part.22() to the function
> >> .init.text:uncore_free_pcibus_map()
> >> The function uncore_pci_exit.part.22() references
> >> the function __init uncore_free_pcibus_map().
> >> This is often because uncore_pci_exit.part.22 lacks a __init
> >> annotation or the annotation of uncore_free_pcibus_map is wrong.

Thanks for the report, you can find the fix here:
https://github.com/ephox-gcc-plugins/initify/commit/5d93a54badd9751b79ef67ce8a8b4081fea37547

-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2016-12-19 Thread Emese Revfy
On Fri, 16 Dec 2016 14:19:10 -0800
Kees Cook  wrote:
 
> FWIW, it still seems to me that these aren't false positives:
> 
> WARNING: vmlinux.o(.text.unlikely+0x1b1): Section mismatch in
> reference from the function uncore_pci_exit.part.22() to the function
> .init.text:uncore_free_pcibus_map()
> The function uncore_pci_exit.part.22() references
> the function __init uncore_free_pcibus_map().
> This is often because uncore_pci_exit.part.22 lacks a __init
> annotation or the annotation of uncore_free_pcibus_map is wrong.

Hi,

I can't reproduce this section mismatch. Could you please send me your .config?
Which gcc version did you use?
I used this tree: git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git 
initify-v4

Thanks
-- 
Emese


Re: [PATCH v4 0/4] Introduce the initify gcc plugin

2016-12-19 Thread Emese Revfy
On Fri, 16 Dec 2016 14:19:10 -0800
Kees Cook  wrote:
 
> FWIW, it still seems to me that these aren't false positives:
> 
> WARNING: vmlinux.o(.text.unlikely+0x1b1): Section mismatch in
> reference from the function uncore_pci_exit.part.22() to the function
> .init.text:uncore_free_pcibus_map()
> The function uncore_pci_exit.part.22() references
> the function __init uncore_free_pcibus_map().
> This is often because uncore_pci_exit.part.22 lacks a __init
> annotation or the annotation of uncore_free_pcibus_map is wrong.

Hi,

I can't reproduce this section mismatch. Could you please send me your .config?
Which gcc version did you use?
I used this tree: git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git 
initify-v4

Thanks
-- 
Emese


Re: [PATCH] gcc-plugin: include memmodel.h and tree_vrp.h for gcc-7

2016-12-16 Thread Emese Revfy
On Fri, 16 Dec 2016 10:00:22 +0100
Arnd Bergmann  wrote:

> Cc: sta...@vger.kernel.org
> Suggested-by: Kugan 
> Signed-off-by: Arnd Bergmann 
> ---
>  scripts/gcc-plugins/gcc-common.h | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/scripts/gcc-plugins/gcc-common.h 
> b/scripts/gcc-plugins/gcc-common.h
> index 950fd2e64bb7..cb4a9518b58a 100644
> --- a/scripts/gcc-plugins/gcc-common.h
> +++ b/scripts/gcc-plugins/gcc-common.h
> @@ -18,6 +18,9 @@
>  
>  #include "tree-inline.h"
>  #include "version.h"
> +#if BUILDING_GCC_VERSION >= 7000
> +#include "memmodel.h"
> +#endif
>  #include "rtl.h"
>  #include "tm_p.h"
>  #include "flags.h"
> @@ -66,6 +69,9 @@
>  #include "tree-flow.h"
>  #else
>  #include "tree-cfgcleanup.h"
> +#if BUILDING_GCC_VERSION >= 7000
> +#include "tree-vrp.h"
> +#endif
>  #include "tree-ssa-operands.h"
>  #include "tree-into-ssa.h"
>  #endif
 
Hi,

Could you please use the upstream gcc-common.h? You can find it here:
https://www.grsecurity.net/~paxguy1/gcc-common.h

Thanks
-- 
Emese


Re: [PATCH] gcc-plugin: include memmodel.h and tree_vrp.h for gcc-7

2016-12-16 Thread Emese Revfy
On Fri, 16 Dec 2016 10:00:22 +0100
Arnd Bergmann  wrote:

> Cc: sta...@vger.kernel.org
> Suggested-by: Kugan 
> Signed-off-by: Arnd Bergmann 
> ---
>  scripts/gcc-plugins/gcc-common.h | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/scripts/gcc-plugins/gcc-common.h 
> b/scripts/gcc-plugins/gcc-common.h
> index 950fd2e64bb7..cb4a9518b58a 100644
> --- a/scripts/gcc-plugins/gcc-common.h
> +++ b/scripts/gcc-plugins/gcc-common.h
> @@ -18,6 +18,9 @@
>  
>  #include "tree-inline.h"
>  #include "version.h"
> +#if BUILDING_GCC_VERSION >= 7000
> +#include "memmodel.h"
> +#endif
>  #include "rtl.h"
>  #include "tm_p.h"
>  #include "flags.h"
> @@ -66,6 +69,9 @@
>  #include "tree-flow.h"
>  #else
>  #include "tree-cfgcleanup.h"
> +#if BUILDING_GCC_VERSION >= 7000
> +#include "tree-vrp.h"
> +#endif
>  #include "tree-ssa-operands.h"
>  #include "tree-into-ssa.h"
>  #endif
 
Hi,

Could you please use the upstream gcc-common.h? You can find it here:
https://www.grsecurity.net/~paxguy1/gcc-common.h

Thanks
-- 
Emese


Re: enabling COMPILE_TEST support for GCC plugins in v4.11

2016-12-10 Thread Emese Revfy
On Fri, 9 Dec 2016 11:12:18 -0800
Kees Cook  wrote:

> On Fri, Dec 9, 2016 at 2:40 AM, Arnd Bergmann  wrote:
> > On Thursday, December 8, 2016 11:00:42 AM CET Kees Cook wrote:
> >
> >> If you have a moment, applying 215e2aa6c024[1] and reverting
> >> a519167e753e for an allyesconfig/allmodconfig build should let you
> >> know if things are working correctly with headers installed. If anyone
> >> sees any problems, please let me know and I can queue up fixes.
> >
> > Using gcc-4.9.3 or gcc-5.3.1 for an ARM allmodconfig build, I get tons of
> > errors such as this one:
> >
> > /git/arm-soc/init/initramfs.c: In function 'error':
> > /git/arm-soc/init/initramfs.c:50:1: error: unrecognizable insn:
> >  }
> >  ^
> > (insn 26 25 27 5 (set (reg:SI 111 [ local_entropy.243 ])
> > (rotatert:SI (reg:SI 116 [ local_entropy.243 ])
> > (const_int -30 [0xffe2]))) -1
> >  (nil))
> > *** WARNING *** there are active plugins, do not report this as a bug 
> > unless you can reproduce it without enabling any plugins.
> > Event| Plugins
> > PLUGIN_ATTRIBUTES| latent_entropy_plugin
> > PLUGIN_START_UNIT| latent_entropy_plugin
> > /git/arm-soc/init/initramfs.c:50:1: internal compiler error: in 
> > extract_insn, at recog.c:2202
> > /git/arm-soc/arch/arm/vfp/vfpmodule.c: In function 'vfp_init':
> > /git/arm-soc/arch/arm/vfp/vfpmodule.c:824:1: error: unrecognizable insn:
> >  }
> >  ^
> > (insn 138 137 139 17 (set (reg:SI 165 [ local_entropy.93 ])
> > (rotatert:SI (reg:SI 150 [ local_entropy.93 ])
> > (const_int -9 [0xfff7]))) -1
> >  (nil))
> > *** WARNING *** there are active plugins, do not report this as a bug 
> > unless you can reproduce it without enabling any plugins.
> 
> Well that's exciting! :P

Hi,

You can find the fix here:
https://github.com/ephox-gcc-plugins/latent_entropy/commit/c91275a1bfcebbcfc0ca1af03396e06039f04db8

-- 
Emese


Re: enabling COMPILE_TEST support for GCC plugins in v4.11

2016-12-10 Thread Emese Revfy
On Fri, 9 Dec 2016 11:12:18 -0800
Kees Cook  wrote:

> On Fri, Dec 9, 2016 at 2:40 AM, Arnd Bergmann  wrote:
> > On Thursday, December 8, 2016 11:00:42 AM CET Kees Cook wrote:
> >
> >> If you have a moment, applying 215e2aa6c024[1] and reverting
> >> a519167e753e for an allyesconfig/allmodconfig build should let you
> >> know if things are working correctly with headers installed. If anyone
> >> sees any problems, please let me know and I can queue up fixes.
> >
> > Using gcc-4.9.3 or gcc-5.3.1 for an ARM allmodconfig build, I get tons of
> > errors such as this one:
> >
> > /git/arm-soc/init/initramfs.c: In function 'error':
> > /git/arm-soc/init/initramfs.c:50:1: error: unrecognizable insn:
> >  }
> >  ^
> > (insn 26 25 27 5 (set (reg:SI 111 [ local_entropy.243 ])
> > (rotatert:SI (reg:SI 116 [ local_entropy.243 ])
> > (const_int -30 [0xffe2]))) -1
> >  (nil))
> > *** WARNING *** there are active plugins, do not report this as a bug 
> > unless you can reproduce it without enabling any plugins.
> > Event| Plugins
> > PLUGIN_ATTRIBUTES| latent_entropy_plugin
> > PLUGIN_START_UNIT| latent_entropy_plugin
> > /git/arm-soc/init/initramfs.c:50:1: internal compiler error: in 
> > extract_insn, at recog.c:2202
> > /git/arm-soc/arch/arm/vfp/vfpmodule.c: In function 'vfp_init':
> > /git/arm-soc/arch/arm/vfp/vfpmodule.c:824:1: error: unrecognizable insn:
> >  }
> >  ^
> > (insn 138 137 139 17 (set (reg:SI 165 [ local_entropy.93 ])
> > (rotatert:SI (reg:SI 150 [ local_entropy.93 ])
> > (const_int -9 [0xfff7]))) -1
> >  (nil))
> > *** WARNING *** there are active plugins, do not report this as a bug 
> > unless you can reproduce it without enabling any plugins.
> 
> Well that's exciting! :P

Hi,

You can find the fix here:
https://github.com/ephox-gcc-plugins/latent_entropy/commit/c91275a1bfcebbcfc0ca1af03396e06039f04db8

-- 
Emese


Re: [PATCH 3/3] powerpc: enable support for GCC plugins

2016-12-06 Thread Emese Revfy
On Tue,  6 Dec 2016 17:28:00 +1100
Andrew Donnellan  wrote:

> +  # Various gccs between 4.5 and 5.1 have bugs on powerpc due to missing
> +  # header files. gcc <= 4.6 doesn't work at all, gccs from 4.8 to 5.1 
> have
> +  # issues with 64-bit targets.
> +  ifeq ($(ARCH),powerpc)
> +ifeq ($(call cc-ifversion, -le, 0501, y), y)
> +   @echo "Cannot use CONFIG_GCC_PLUGINS: plugin support on gcc <= 5.1 is 
> buggy on powerpc, please upgrade to gcc 5.2 or newer" >&2 && exit 1
> +endif
> +  endif

Hi,

What are these missing headers? Because if they aren't necessary then they can
be removed from gcc-common.h. There were missing headers on arm/arm64 and these
archs are supported. I think this version check is unnecessary because
gcc-plugin.sh also checks the missing headers.

What is the problem on gcc-4.5/gcc-4.6?

-- 
Emese


Re: [PATCH 3/3] powerpc: enable support for GCC plugins

2016-12-06 Thread Emese Revfy
On Tue,  6 Dec 2016 17:28:00 +1100
Andrew Donnellan  wrote:

> +  # Various gccs between 4.5 and 5.1 have bugs on powerpc due to missing
> +  # header files. gcc <= 4.6 doesn't work at all, gccs from 4.8 to 5.1 
> have
> +  # issues with 64-bit targets.
> +  ifeq ($(ARCH),powerpc)
> +ifeq ($(call cc-ifversion, -le, 0501, y), y)
> +   @echo "Cannot use CONFIG_GCC_PLUGINS: plugin support on gcc <= 5.1 is 
> buggy on powerpc, please upgrade to gcc 5.2 or newer" >&2 && exit 1
> +endif
> +  endif

Hi,

What are these missing headers? Because if they aren't necessary then they can
be removed from gcc-common.h. There were missing headers on arm/arm64 and these
archs are supported. I think this version check is unnecessary because
gcc-plugin.sh also checks the missing headers.

What is the problem on gcc-4.5/gcc-4.6?

-- 
Emese


Re: scripts/gcc-plugins/gcc-common.h:4:22: fatal error: bversion.h: No such file or directory

2016-11-06 Thread Emese Revfy
On Sun, 6 Nov 2016 07:09:57 +0800
kbuild test robot  wrote:

> Hi Emese,
> 
> FYI, the error/warning still remains.
>
>++(scripts/gcc-plugin.sh:12): main(): gcc-4.6 -E -x c++ - -o /dev/null 
> -Iscripts/gcc-plugins -Iplugin/include
>scripts/Makefile.gcc-plugins:30: warning: your gcc installation does not 
> support plugins, perhaps the necessary headers are missing?

Hi,

You should install the gcc-4.6 plugin headers (gcc-4.6-plugin-dev package on 
debian if I remember well) for the plugins.

-- 
Emese


Re: scripts/gcc-plugins/gcc-common.h:4:22: fatal error: bversion.h: No such file or directory

2016-11-06 Thread Emese Revfy
On Sun, 6 Nov 2016 07:09:57 +0800
kbuild test robot  wrote:

> Hi Emese,
> 
> FYI, the error/warning still remains.
>
>++(scripts/gcc-plugin.sh:12): main(): gcc-4.6 -E -x c++ - -o /dev/null 
> -Iscripts/gcc-plugins -Iplugin/include
>scripts/Makefile.gcc-plugins:30: warning: your gcc installation does not 
> support plugins, perhaps the necessary headers are missing?

Hi,

You should install the gcc-4.6 plugin headers (gcc-4.6-plugin-dev package on 
debian if I remember well) for the plugins.

-- 
Emese


Re: drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 bytes is larger than 1024 bytes

2016-10-18 Thread Emese Revfy
On Tue, 18 Oct 2016 15:05:39 -0700
Kees Cook <keesc...@chromium.org> wrote:

> On Tue, Oct 18, 2016 at 2:36 PM, Emese Revfy <re.em...@gmail.com> wrote:
> > On Tue, 18 Oct 2016 13:57:35 -0700
> > Kees Cook <keesc...@chromium.org> wrote:
> >
> >> This is controlled by CONFIG_FRAME_WARN. I don't think this is a
> >> particular problem or should be avoided, but perhaps we can set the
> >> default to 2048 (as done on 64BIT) if we're building with the entropy
> >> plugin.
> >
> > This is probably a gcc code generation bug on i386 when a plugin uses too 
> > many 64 bit variables
> > so I think PaX Team's patch will be the best solution.
> 
> Okay, cool. If you're able, please CC me with the fix when it happens. :)

This is the plugin side fix:
https://github.com/ephox-gcc-plugins/latent_entropy/commit/12776eab89861239d5194a9241a98e48e3b3e8ae

The kernel side fix will be released in PaX for linux 4.8.

-- 
Emese


Re: drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 bytes is larger than 1024 bytes

2016-10-18 Thread Emese Revfy
On Tue, 18 Oct 2016 15:05:39 -0700
Kees Cook  wrote:

> On Tue, Oct 18, 2016 at 2:36 PM, Emese Revfy  wrote:
> > On Tue, 18 Oct 2016 13:57:35 -0700
> > Kees Cook  wrote:
> >
> >> This is controlled by CONFIG_FRAME_WARN. I don't think this is a
> >> particular problem or should be avoided, but perhaps we can set the
> >> default to 2048 (as done on 64BIT) if we're building with the entropy
> >> plugin.
> >
> > This is probably a gcc code generation bug on i386 when a plugin uses too 
> > many 64 bit variables
> > so I think PaX Team's patch will be the best solution.
> 
> Okay, cool. If you're able, please CC me with the fix when it happens. :)

This is the plugin side fix:
https://github.com/ephox-gcc-plugins/latent_entropy/commit/12776eab89861239d5194a9241a98e48e3b3e8ae

The kernel side fix will be released in PaX for linux 4.8.

-- 
Emese


Re: drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 bytes is larger than 1024 bytes

2016-10-18 Thread Emese Revfy
On Tue, 18 Oct 2016 13:57:35 -0700
Kees Cook  wrote:

> This is controlled by CONFIG_FRAME_WARN. I don't think this is a
> particular problem or should be avoided, but perhaps we can set the
> default to 2048 (as done on 64BIT) if we're building with the entropy
> plugin.

This is probably a gcc code generation bug on i386 when a plugin uses too many 
64 bit variables
so I think PaX Team's patch will be the best solution.

-- 
Emese


Re: drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 bytes is larger than 1024 bytes

2016-10-18 Thread Emese Revfy
On Tue, 18 Oct 2016 13:57:35 -0700
Kees Cook  wrote:

> This is controlled by CONFIG_FRAME_WARN. I don't think this is a
> particular problem or should be avoided, but perhaps we can set the
> default to 2048 (as done on 64BIT) if we're building with the entropy
> plugin.

This is probably a gcc code generation bug on i386 when a plugin uses too many 
64 bit variables
so I think PaX Team's patch will be the best solution.

-- 
Emese


Re: drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 bytes is larger than 1024 bytes

2016-10-17 Thread Emese Revfy
On Sun, 16 Oct 2016 06:52:16 +0800
kbuild test robot  wrote:

>drivers/pci/hotplug/ibmphp_ebda.c: In function 'ibmphp_access_ebda':
> >> drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 
> >> bytes is larger than 1024 bytes [-Wframe-larger-than=]

Hi,

Thanks for the report. The problem is that these are large functions
(there are a lot of basic blocks) and the entropy plugin instruments all basic 
blocks.
I think the solution is to skip these functions which contain more than n basic 
blocks.
Sorry, I haven't time to fix this bug. PaX Team will fix it in PaX.

-- 
Emese


Re: drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 bytes is larger than 1024 bytes

2016-10-17 Thread Emese Revfy
On Sun, 16 Oct 2016 06:52:16 +0800
kbuild test robot  wrote:

>drivers/pci/hotplug/ibmphp_ebda.c: In function 'ibmphp_access_ebda':
> >> drivers/pci/hotplug/ibmphp_ebda.c:409:1: warning: the frame size of 1108 
> >> bytes is larger than 1024 bytes [-Wframe-larger-than=]

Hi,

Thanks for the report. The problem is that these are large functions
(there are a lot of basic blocks) and the entropy plugin instruments all basic 
blocks.
I think the solution is to skip these functions which contain more than n basic 
blocks.
Sorry, I haven't time to fix this bug. PaX Team will fix it in PaX.

-- 
Emese


[PATCH v3 6/7] Mark a few functions with the printf attribute

2016-07-27 Thread Emese Revfy
Fixed format strings warnings exposed by the printf attribute.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 drivers/acpi/acpica/dbhistry.c |  2 +-
 drivers/acpi/acpica/dbinput.c  | 10 ++---
 drivers/acpi/acpica/dbstats.c  | 88 +++---
 drivers/acpi/acpica/utdebug.c  |  2 +-
 drivers/scsi/esas2r/esas2r_init.c  |  2 +-
 drivers/scsi/esas2r/esas2r_ioctl.c |  2 +-
 drivers/scsi/esas2r/esas2r_main.c  |  4 +-
 7 files changed, 55 insertions(+), 55 deletions(-)

diff --git a/drivers/acpi/acpica/dbhistry.c b/drivers/acpi/acpica/dbhistry.c
index 46bd65d..ec9da48 100644
--- a/drivers/acpi/acpica/dbhistry.c
+++ b/drivers/acpi/acpica/dbhistry.c
@@ -155,7 +155,7 @@ void acpi_db_display_history(void)
 
for (i = 0; i < acpi_gbl_num_history; i++) {
if (acpi_gbl_history_buffer[history_index].command) {
-   acpi_os_printf("%3ld %s\n",
+   acpi_os_printf("%3u %s\n",
   acpi_gbl_history_buffer[history_index].
   cmd_num,
   acpi_gbl_history_buffer[history_index].
diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c
index 7cd5d2e..a837ce6 100644
--- a/drivers/acpi/acpica/dbinput.c
+++ b/drivers/acpi/acpica/dbinput.c
@@ -606,7 +606,7 @@ static u32 acpi_db_get_line(char *input_buffer)
(acpi_gbl_db_parsed_buf, sizeof(acpi_gbl_db_parsed_buf),
 input_buffer)) {
acpi_os_printf
-   ("Buffer overflow while parsing input line (max %u 
characters)\n",
+   ("Buffer overflow while parsing input line (max %lu 
characters)\n",
 sizeof(acpi_gbl_db_parsed_buf));
return (0);
}
@@ -862,24 +862,24 @@ acpi_db_command_dispatch(char *input_buffer,
 
if (param_count == 0) {
acpi_os_printf
-   ("Current debug level for file output is:
%8.8lX\n",
+   ("Current debug level for file output is:
%8.8X\n",
 acpi_gbl_db_debug_level);
acpi_os_printf
-   ("Current debug level for console output is: 
%8.8lX\n",
+   ("Current debug level for console output is: 
%8.8X\n",
 acpi_gbl_db_console_debug_level);
} else if (param_count == 2) {
temp = acpi_gbl_db_console_debug_level;
acpi_gbl_db_console_debug_level =
strtoul(acpi_gbl_db_args[1], NULL, 16);
acpi_os_printf
-   ("Debug Level for console output was %8.8lX, now 
%8.8lX\n",
+   ("Debug Level for console output was %8.8X, now 
%8.8X\n",
 temp, acpi_gbl_db_console_debug_level);
} else {
temp = acpi_gbl_db_debug_level;
acpi_gbl_db_debug_level =
strtoul(acpi_gbl_db_args[1], NULL, 16);
acpi_os_printf
-   ("Debug Level for file output was %8.8lX, now 
%8.8lX\n",
+   ("Debug Level for file output was %8.8X, now 
%8.8X\n",
 temp, acpi_gbl_db_debug_level);
}
break;
diff --git a/drivers/acpi/acpica/dbstats.c b/drivers/acpi/acpica/dbstats.c
index a414e1f..de70230 100644
--- a/drivers/acpi/acpica/dbstats.c
+++ b/drivers/acpi/acpica/dbstats.c
@@ -377,17 +377,17 @@ acpi_status acpi_db_display_statistics(char *type_arg)
   "ACPI_TYPE", "NODES", "OBJECTS");
 
for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
-   acpi_os_printf("%16.16s % 10ld% 10ld\n",
+   acpi_os_printf("%16.16s % 10d% 10d\n",
   acpi_ut_get_type_name(i),
   acpi_gbl_node_type_count[i],
   acpi_gbl_obj_type_count[i]);
}
 
-   acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
+   acpi_os_printf("%16.16s % 10d% 10d\n", "Misc/Unknown",
   acpi_gbl_node_type_count_misc,
   acpi_gbl_obj_type_count_misc);
 
-   acpi_os_printf("%16.16s % 10ld% 10ld\n", "TOTALS:",
+   acpi_os_printf("%16.16s % 10d% 10d\n", "TOTALS:",
   acpi_gbl_num_nodes, acpi_gbl_num_objects);
   

[PATCH v3 6/7] Mark a few functions with the printf attribute

2016-07-27 Thread Emese Revfy
Fixed format strings warnings exposed by the printf attribute.

Signed-off-by: Emese Revfy 
---
 drivers/acpi/acpica/dbhistry.c |  2 +-
 drivers/acpi/acpica/dbinput.c  | 10 ++---
 drivers/acpi/acpica/dbstats.c  | 88 +++---
 drivers/acpi/acpica/utdebug.c  |  2 +-
 drivers/scsi/esas2r/esas2r_init.c  |  2 +-
 drivers/scsi/esas2r/esas2r_ioctl.c |  2 +-
 drivers/scsi/esas2r/esas2r_main.c  |  4 +-
 7 files changed, 55 insertions(+), 55 deletions(-)

diff --git a/drivers/acpi/acpica/dbhistry.c b/drivers/acpi/acpica/dbhistry.c
index 46bd65d..ec9da48 100644
--- a/drivers/acpi/acpica/dbhistry.c
+++ b/drivers/acpi/acpica/dbhistry.c
@@ -155,7 +155,7 @@ void acpi_db_display_history(void)
 
for (i = 0; i < acpi_gbl_num_history; i++) {
if (acpi_gbl_history_buffer[history_index].command) {
-   acpi_os_printf("%3ld %s\n",
+   acpi_os_printf("%3u %s\n",
   acpi_gbl_history_buffer[history_index].
   cmd_num,
   acpi_gbl_history_buffer[history_index].
diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c
index 7cd5d2e..a837ce6 100644
--- a/drivers/acpi/acpica/dbinput.c
+++ b/drivers/acpi/acpica/dbinput.c
@@ -606,7 +606,7 @@ static u32 acpi_db_get_line(char *input_buffer)
(acpi_gbl_db_parsed_buf, sizeof(acpi_gbl_db_parsed_buf),
 input_buffer)) {
acpi_os_printf
-   ("Buffer overflow while parsing input line (max %u 
characters)\n",
+   ("Buffer overflow while parsing input line (max %lu 
characters)\n",
 sizeof(acpi_gbl_db_parsed_buf));
return (0);
}
@@ -862,24 +862,24 @@ acpi_db_command_dispatch(char *input_buffer,
 
if (param_count == 0) {
acpi_os_printf
-   ("Current debug level for file output is:
%8.8lX\n",
+   ("Current debug level for file output is:
%8.8X\n",
 acpi_gbl_db_debug_level);
acpi_os_printf
-   ("Current debug level for console output is: 
%8.8lX\n",
+   ("Current debug level for console output is: 
%8.8X\n",
 acpi_gbl_db_console_debug_level);
} else if (param_count == 2) {
temp = acpi_gbl_db_console_debug_level;
acpi_gbl_db_console_debug_level =
strtoul(acpi_gbl_db_args[1], NULL, 16);
acpi_os_printf
-   ("Debug Level for console output was %8.8lX, now 
%8.8lX\n",
+   ("Debug Level for console output was %8.8X, now 
%8.8X\n",
 temp, acpi_gbl_db_console_debug_level);
} else {
temp = acpi_gbl_db_debug_level;
acpi_gbl_db_debug_level =
strtoul(acpi_gbl_db_args[1], NULL, 16);
acpi_os_printf
-   ("Debug Level for file output was %8.8lX, now 
%8.8lX\n",
+   ("Debug Level for file output was %8.8X, now 
%8.8X\n",
 temp, acpi_gbl_db_debug_level);
}
break;
diff --git a/drivers/acpi/acpica/dbstats.c b/drivers/acpi/acpica/dbstats.c
index a414e1f..de70230 100644
--- a/drivers/acpi/acpica/dbstats.c
+++ b/drivers/acpi/acpica/dbstats.c
@@ -377,17 +377,17 @@ acpi_status acpi_db_display_statistics(char *type_arg)
   "ACPI_TYPE", "NODES", "OBJECTS");
 
for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) {
-   acpi_os_printf("%16.16s % 10ld% 10ld\n",
+   acpi_os_printf("%16.16s % 10d% 10d\n",
   acpi_ut_get_type_name(i),
   acpi_gbl_node_type_count[i],
   acpi_gbl_obj_type_count[i]);
}
 
-   acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
+   acpi_os_printf("%16.16s % 10d% 10d\n", "Misc/Unknown",
   acpi_gbl_node_type_count_misc,
   acpi_gbl_obj_type_count_misc);
 
-   acpi_os_printf("%16.16s % 10ld% 10ld\n", "TOTALS:",
+   acpi_os_printf("%16.16s % 10d% 10d\n", "TOTALS:",
   acpi_gbl_num_nodes, acpi_gbl_num_objects);
break;
 
@@ -415,16 +415,16 @@

[PATCH v3 2/7] Split up struct warn_args

2016-07-27 Thread Emese Revfy
Disable the initify plugin on the 6th parameter
of __warn() because the va_list type can't be NULL
on the tile arch.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 include/asm-generic/bug.h |  7 +--
 kernel/panic.c| 32 
 lib/bug.c |  2 +-
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 13a9241..f6ae0d7 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -81,9 +81,12 @@ extern __nocapture(1) void warn_slowpath_null(const char 
*file, const int line);
do { printk(arg); __WARN_TAINT(taint); } while (0)
 #endif
 
-__nocapture(1, 6)
+/* used internally by panic.c */
+struct warn_args;
+
+__nocapture(1, 0)
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, const char *fmt, va_list args);
+   struct pt_regs *regs, struct warn_args *args);
 
 #ifndef WARN_ON
 #define WARN_ON(condition) ({  \
diff --git a/kernel/panic.c b/kernel/panic.c
index 993ad20..ca8cea1 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -475,8 +475,13 @@ void oops_exit(void)
kmsg_dump(KMSG_DUMP_OOPS);
 }
 
+struct warn_args {
+   const char *fmt;
+   va_list args;
+};
+
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, const char *fmt, va_list args)
+   struct pt_regs *regs, struct warn_args *args)
 {
disable_trace_on_warning();
 
@@ -490,8 +495,8 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
pr_warn("WARNING: CPU: %d PID: %d at %pS\n",
raw_smp_processor_id(), current->pid, caller);
 
-   if (fmt)
-   vprintk(fmt, args);
+   if (args)
+   vprintk(args->fmt, args->args);
 
if (panic_on_warn) {
/*
@@ -520,28 +525,31 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
 #ifdef WANT_WARN_ON_SLOWPATH
 void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
 {
-   va_list args;
+   struct warn_args args;
 
-   va_start(args, fmt);
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, fmt, 
args);
-   va_end(args);
+   args.fmt = fmt;
+   va_start(args.args, fmt);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL,
+  );
+   va_end(args.args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt);
 
 void warn_slowpath_fmt_taint(const char *file, int line,
 unsigned taint, const char *fmt, ...)
 {
-   va_list args;
+   struct warn_args args;
 
-   va_start(args, fmt);
-   __warn(file, line, __builtin_return_address(0), taint, NULL, fmt, args);
-   va_end(args);
+   args.fmt = fmt;
+   va_start(args.args, fmt);
+   __warn(file, line, __builtin_return_address(0), taint, NULL, );
+   va_end(args.args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt_taint);
 
 void warn_slowpath_null(const char *file, int line)
 {
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL, 
NULL);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL);
 }
 EXPORT_SYMBOL(warn_slowpath_null);
 #endif
diff --git a/lib/bug.c b/lib/bug.c
index c8bdebb..bc3656e 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -168,7 +168,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct 
pt_regs *regs)
if (warning) {
/* this is a WARN_ON rather than BUG/BUG_ON */
__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
-  NULL, NULL);
+  NULL);
return BUG_TRAP_TYPE_WARN;
}
 
-- 
2.8.1



[PATCH v3 2/7] Split up struct warn_args

2016-07-27 Thread Emese Revfy
Disable the initify plugin on the 6th parameter
of __warn() because the va_list type can't be NULL
on the tile arch.

Signed-off-by: Emese Revfy 
---
 include/asm-generic/bug.h |  7 +--
 kernel/panic.c| 32 
 lib/bug.c |  2 +-
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 13a9241..f6ae0d7 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -81,9 +81,12 @@ extern __nocapture(1) void warn_slowpath_null(const char 
*file, const int line);
do { printk(arg); __WARN_TAINT(taint); } while (0)
 #endif
 
-__nocapture(1, 6)
+/* used internally by panic.c */
+struct warn_args;
+
+__nocapture(1, 0)
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, const char *fmt, va_list args);
+   struct pt_regs *regs, struct warn_args *args);
 
 #ifndef WARN_ON
 #define WARN_ON(condition) ({  \
diff --git a/kernel/panic.c b/kernel/panic.c
index 993ad20..ca8cea1 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -475,8 +475,13 @@ void oops_exit(void)
kmsg_dump(KMSG_DUMP_OOPS);
 }
 
+struct warn_args {
+   const char *fmt;
+   va_list args;
+};
+
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, const char *fmt, va_list args)
+   struct pt_regs *regs, struct warn_args *args)
 {
disable_trace_on_warning();
 
@@ -490,8 +495,8 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
pr_warn("WARNING: CPU: %d PID: %d at %pS\n",
raw_smp_processor_id(), current->pid, caller);
 
-   if (fmt)
-   vprintk(fmt, args);
+   if (args)
+   vprintk(args->fmt, args->args);
 
if (panic_on_warn) {
/*
@@ -520,28 +525,31 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
 #ifdef WANT_WARN_ON_SLOWPATH
 void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
 {
-   va_list args;
+   struct warn_args args;
 
-   va_start(args, fmt);
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, fmt, 
args);
-   va_end(args);
+   args.fmt = fmt;
+   va_start(args.args, fmt);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL,
+  );
+   va_end(args.args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt);
 
 void warn_slowpath_fmt_taint(const char *file, int line,
 unsigned taint, const char *fmt, ...)
 {
-   va_list args;
+   struct warn_args args;
 
-   va_start(args, fmt);
-   __warn(file, line, __builtin_return_address(0), taint, NULL, fmt, args);
-   va_end(args);
+   args.fmt = fmt;
+   va_start(args.args, fmt);
+   __warn(file, line, __builtin_return_address(0), taint, NULL, );
+   va_end(args.args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt_taint);
 
 void warn_slowpath_null(const char *file, int line)
 {
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL, 
NULL);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL);
 }
 EXPORT_SYMBOL(warn_slowpath_null);
 #endif
diff --git a/lib/bug.c b/lib/bug.c
index c8bdebb..bc3656e 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -168,7 +168,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct 
pt_regs *regs)
if (warning) {
/* this is a WARN_ON rather than BUG/BUG_ON */
__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
-  NULL, NULL);
+  NULL);
return BUG_TRAP_TYPE_WARN;
}
 
-- 
2.8.1



[PATCH v3 7/7] Mark functions with the __unverified_nocapture attribute

2016-07-26 Thread Emese Revfy
This attribute disables the compile data flow verification of the
designated nocapture parameters of the function. Use it only on function
parameters that are difficult for the plugin to analyze.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 include/linux/compiler-gcc.h | 1 +
 include/linux/compiler.h | 4 
 lib/vsprintf.c   | 4 ++--
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 6697ea3..76797b9 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -207,6 +207,7 @@
  */
 #ifdef INITIFY_PLUGIN
 #define __nocapture(...) __attribute__((nocapture(__VA_ARGS__)))
+#define __unverified_nocapture(...) 
__attribute__((unverified_nocapture(__VA_ARGS__)))
 #endif
 
 /*
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 391b48b..f0b4156 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -416,6 +416,10 @@ static __always_inline void __write_once_size(volatile 
void *p, void *res, int s
 # define __nocapture(...)
 #endif
 
+#ifndef __unverified_nocapture
+# define __unverified_nocapture(...)
+#endif
+
 /*
  * Tell gcc if a function is cold. The compiler will assume any path
  * directly leading to the call is unlikely.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a192761..cb964b5 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -118,7 +118,7 @@ long long simple_strtoll(const char *cp, char **endp, 
unsigned int base)
 }
 EXPORT_SYMBOL(simple_strtoll);
 
-static noinline_for_stack __nocapture(1)
+static noinline_for_stack __nocapture(1) __unverified_nocapture(1)
 int skip_atoi(const char **s)
 {
int i = 0;
@@ -1570,7 +1570,7 @@ int kptr_restrict __read_mostly;
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
  */
-static noinline_for_stack __nocapture(1)
+static noinline_for_stack __nocapture(1) __unverified_nocapture(1)
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
  struct printf_spec spec)
 {
-- 
2.8.1



[PATCH v3 7/7] Mark functions with the __unverified_nocapture attribute

2016-07-26 Thread Emese Revfy
This attribute disables the compile data flow verification of the
designated nocapture parameters of the function. Use it only on function
parameters that are difficult for the plugin to analyze.

Signed-off-by: Emese Revfy 
---
 include/linux/compiler-gcc.h | 1 +
 include/linux/compiler.h | 4 
 lib/vsprintf.c   | 4 ++--
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 6697ea3..76797b9 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -207,6 +207,7 @@
  */
 #ifdef INITIFY_PLUGIN
 #define __nocapture(...) __attribute__((nocapture(__VA_ARGS__)))
+#define __unverified_nocapture(...) 
__attribute__((unverified_nocapture(__VA_ARGS__)))
 #endif
 
 /*
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 391b48b..f0b4156 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -416,6 +416,10 @@ static __always_inline void __write_once_size(volatile 
void *p, void *res, int s
 # define __nocapture(...)
 #endif
 
+#ifndef __unverified_nocapture
+# define __unverified_nocapture(...)
+#endif
+
 /*
  * Tell gcc if a function is cold. The compiler will assume any path
  * directly leading to the call is unlikely.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a192761..cb964b5 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -118,7 +118,7 @@ long long simple_strtoll(const char *cp, char **endp, 
unsigned int base)
 }
 EXPORT_SYMBOL(simple_strtoll);
 
-static noinline_for_stack __nocapture(1)
+static noinline_for_stack __nocapture(1) __unverified_nocapture(1)
 int skip_atoi(const char **s)
 {
int i = 0;
@@ -1570,7 +1570,7 @@ int kptr_restrict __read_mostly;
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
  */
-static noinline_for_stack __nocapture(1)
+static noinline_for_stack __nocapture(1) __unverified_nocapture(1)
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
  struct printf_spec spec)
 {
-- 
2.8.1



[PATCH v3 6/7] Mark a few functions with the printf attribute

2016-07-26 Thread Emese Revfy
This allows not only compile time format string checking but can also
increase the coverage of the initify plugin.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 drivers/scsi/esas2r/esas2r_log.h | 4 ++--
 include/acpi/acpiosxf.h  | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/esas2r/esas2r_log.h b/drivers/scsi/esas2r/esas2r_log.h
index 7b6397b..75b9d23 100644
--- a/drivers/scsi/esas2r/esas2r_log.h
+++ b/drivers/scsi/esas2r/esas2r_log.h
@@ -61,8 +61,8 @@ enum {
 #endif
 };
 
-int esas2r_log(const long level, const char *format, ...);
-int esas2r_log_dev(const long level,
+__printf(2, 3) int esas2r_log(const long level, const char *format, ...);
+__printf(3, 4) int esas2r_log_dev(const long level,
   const struct device *dev,
   const char *format,
   ...);
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 562603d..7ee4475 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -337,11 +337,12 @@ acpi_status acpi_os_signal(u32 function, void *info);
  * Debug print routines
  */
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_printf
+__printf(1, 2)
 void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *format, ...);
 #endif
 
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_vprintf
-void acpi_os_vprintf(const char *format, va_list args);
+__printf(1, 0) void acpi_os_vprintf(const char *format, va_list args);
 #endif
 
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_redirect_output
-- 
2.8.1



[PATCH v3 6/7] Mark a few functions with the printf attribute

2016-07-26 Thread Emese Revfy
This allows not only compile time format string checking but can also
increase the coverage of the initify plugin.

Signed-off-by: Emese Revfy 
---
 drivers/scsi/esas2r/esas2r_log.h | 4 ++--
 include/acpi/acpiosxf.h  | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/esas2r/esas2r_log.h b/drivers/scsi/esas2r/esas2r_log.h
index 7b6397b..75b9d23 100644
--- a/drivers/scsi/esas2r/esas2r_log.h
+++ b/drivers/scsi/esas2r/esas2r_log.h
@@ -61,8 +61,8 @@ enum {
 #endif
 };
 
-int esas2r_log(const long level, const char *format, ...);
-int esas2r_log_dev(const long level,
+__printf(2, 3) int esas2r_log(const long level, const char *format, ...);
+__printf(3, 4) int esas2r_log_dev(const long level,
   const struct device *dev,
   const char *format,
   ...);
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 562603d..7ee4475 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -337,11 +337,12 @@ acpi_status acpi_os_signal(u32 function, void *info);
  * Debug print routines
  */
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_printf
+__printf(1, 2)
 void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *format, ...);
 #endif
 
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_vprintf
-void acpi_os_vprintf(const char *format, va_list args);
+__printf(1, 0) void acpi_os_vprintf(const char *format, va_list args);
 #endif
 
 #ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_redirect_output
-- 
2.8.1



[PATCH v3 5/7] Mark functions with the __nocapture attribute

2016-07-26 Thread Emese Revfy
The nocapture gcc attribute can be on functions only.
The attribute takes zero or more signed integer constants as parameters
that specify the function parameters to initify when the passed arguments
are of const char* type.

A negative attribute parameter value means that the corresponding function
parameter is returned by the function and the passed argument will only be
initified if the data flow of the returned value is not captured in the caller.

If no values are passed to the attribute then all function parameters are
treated as nocapture.

If the marked parameter is a vararg then the plugin initifies all vararg
arguments.

I couldn't test the arm, arm64 and powerpc architectures.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/arm/include/asm/string.h | 10 +++---
 arch/arm64/include/asm/string.h   | 25 ++---
 arch/powerpc/include/asm/string.h | 19 +-
 arch/x86/include/asm/string_32.h  | 25 ++---
 arch/x86/include/asm/string_64.h  | 20 +--
 arch/x86/kernel/hpet.c|  2 +-
 drivers/acpi/acpica/acutils.h |  2 +-
 fs/char_dev.c |  2 +-
 fs/ntfs/debug.h   |  6 ++--
 fs/ocfs2/cluster/masklog.h|  2 +-
 include/acpi/acpixf.h |  2 +-
 include/asm-generic/bug.h |  7 ++--
 include/drm/drmP.h|  2 +-
 include/linux/audit.h |  5 +--
 include/linux/fs.h|  8 +++--
 include/linux/printk.h|  2 +-
 include/linux/ratelimit.h |  3 +-
 include/linux/string.h| 75 ---
 lib/vsprintf.c|  6 ++--
 mm/util.c |  2 +-
 security/integrity/integrity.h|  2 +-
 21 files changed, 119 insertions(+), 108 deletions(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aa..8f2f2d9 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -7,19 +7,19 @@
  */
 
 #define __HAVE_ARCH_STRRCHR
-extern char * strrchr(const char * s, int c);
+extern char * strrchr(const char * s, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_STRCHR
-extern char * strchr(const char * s, int c);
+extern char * strchr(const char * s, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, __kernel_size_t);
+extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void * memmove(void *, const void *, __kernel_size_t);
+extern void * memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void * memchr(const void *, int, __kernel_size_t);
+extern void * memchr(const void *, int, __kernel_size_t) __nocapture(-1);
 
 #define __HAVE_ARCH_MEMSET
 extern void * memset(void *, int, __kernel_size_t);
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..188a102 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -17,40 +17,41 @@
 #define __ASM_STRING_H
 
 #define __HAVE_ARCH_STRRCHR
-extern char *strrchr(const char *, int c);
+extern char *strrchr(const char *, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_STRCHR
-extern char *strchr(const char *, int c);
+extern char *strchr(const char *, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_STRCMP
-extern int strcmp(const char *, const char *);
+extern int strcmp(const char *, const char *) __nocapture();
 
 #define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRLEN
-extern __kernel_size_t strlen(const char *);
+extern __kernel_size_t strlen(const char *) __nocapture(1);
 
 #define __HAVE_ARCH_STRNLEN
-extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-extern void *__memmove(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void *memchr(const void *, int, __kernel_size_t);
+extern void *memchr(const void *, int, __kernel_size_t) __nocapture(-1);
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, __kernel_size_t);
 extern void *__memset(void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, 

[PATCH v3 5/7] Mark functions with the __nocapture attribute

2016-07-26 Thread Emese Revfy
The nocapture gcc attribute can be on functions only.
The attribute takes zero or more signed integer constants as parameters
that specify the function parameters to initify when the passed arguments
are of const char* type.

A negative attribute parameter value means that the corresponding function
parameter is returned by the function and the passed argument will only be
initified if the data flow of the returned value is not captured in the caller.

If no values are passed to the attribute then all function parameters are
treated as nocapture.

If the marked parameter is a vararg then the plugin initifies all vararg
arguments.

I couldn't test the arm, arm64 and powerpc architectures.

Signed-off-by: Emese Revfy 
---
 arch/arm/include/asm/string.h | 10 +++---
 arch/arm64/include/asm/string.h   | 25 ++---
 arch/powerpc/include/asm/string.h | 19 +-
 arch/x86/include/asm/string_32.h  | 25 ++---
 arch/x86/include/asm/string_64.h  | 20 +--
 arch/x86/kernel/hpet.c|  2 +-
 drivers/acpi/acpica/acutils.h |  2 +-
 fs/char_dev.c |  2 +-
 fs/ntfs/debug.h   |  6 ++--
 fs/ocfs2/cluster/masklog.h|  2 +-
 include/acpi/acpixf.h |  2 +-
 include/asm-generic/bug.h |  7 ++--
 include/drm/drmP.h|  2 +-
 include/linux/audit.h |  5 +--
 include/linux/fs.h|  8 +++--
 include/linux/printk.h|  2 +-
 include/linux/ratelimit.h |  3 +-
 include/linux/string.h| 75 ---
 lib/vsprintf.c|  6 ++--
 mm/util.c |  2 +-
 security/integrity/integrity.h|  2 +-
 21 files changed, 119 insertions(+), 108 deletions(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aa..8f2f2d9 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -7,19 +7,19 @@
  */
 
 #define __HAVE_ARCH_STRRCHR
-extern char * strrchr(const char * s, int c);
+extern char * strrchr(const char * s, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_STRCHR
-extern char * strchr(const char * s, int c);
+extern char * strchr(const char * s, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, __kernel_size_t);
+extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void * memmove(void *, const void *, __kernel_size_t);
+extern void * memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void * memchr(const void *, int, __kernel_size_t);
+extern void * memchr(const void *, int, __kernel_size_t) __nocapture(-1);
 
 #define __HAVE_ARCH_MEMSET
 extern void * memset(void *, int, __kernel_size_t);
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..188a102 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -17,40 +17,41 @@
 #define __ASM_STRING_H
 
 #define __HAVE_ARCH_STRRCHR
-extern char *strrchr(const char *, int c);
+extern char *strrchr(const char *, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_STRCHR
-extern char *strchr(const char *, int c);
+extern char *strchr(const char *, int c) __nocapture(-1);
 
 #define __HAVE_ARCH_STRCMP
-extern int strcmp(const char *, const char *);
+extern int strcmp(const char *, const char *) __nocapture();
 
 #define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRLEN
-extern __kernel_size_t strlen(const char *);
+extern __kernel_size_t strlen(const char *) __nocapture(1);
 
 #define __HAVE_ARCH_STRNLEN
-extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-extern void *__memmove(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void *memchr(const void *, int, __kernel_size_t);
+extern void *memchr(const void *, int, __kernel_size_t) __nocapture(-1);
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, __kernel_size_t);
 extern void *__memset(void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, size_t);
+extern int memcmp

[PATCH v3 4/7] Add the initify gcc plugin

2016-07-26 Thread Emese Revfy
The kernel already has a mechanism to free up code and data memory that
is only used during kernel or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization.
It has two passes. The first one tries to find all functions that
can be become __init/__exit. The second one moves string constants
(local variables and function string arguments marked by
the nocapture attribute) only referenced in __init/__exit functions
to the __initconst/__exitconst sections.
It reduces memory usage. This plugin can be useful for embedded systems.

If a function is called by __init and __exit functions as well then
the plugin moves it to the __exit section. This causes false positive
section mismatch errors/warnings that I don't know how to handle yet.

The instrumentation pass of the latent_entropy plugin must run after
the initify plugin to increase coverage.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/Kconfig |   35 +
 arch/x86/Kconfig |1 +
 arch/x86/lib/Makefile|4 +
 include/asm-generic/vmlinux.lds.h|2 +
 include/linux/compiler-gcc.h |   14 +
 include/linux/compiler.h |4 +
 scripts/Makefile.gcc-plugins |9 +
 scripts/gcc-plugins/gcc-common.h |   41 +
 scripts/gcc-plugins/initify_plugin.c | 1883 ++
 9 files changed, 1993 insertions(+)
 create mode 100644 scripts/gcc-plugins/initify_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 88673c2..41eb562 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -417,6 +417,41 @@ config GCC_PLUGIN_LATENT_ENTROPY
   * https://grsecurity.net/
   * https://pax.grsecurity.net/
 
+config GCC_PLUGIN_INITIFY
+   bool "Free more kernel memory after init"
+   depends on GCC_PLUGINS
+   help
+ The kernel has a mechanism to free up code and data memory that is
+ only used during kernel or module initialization.  Enabling this
+ feature will teach the compiler to find more such code and data
+ that can be freed after initialization.
+
+ This plugin is the part of grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
+config HAVE_GCC_PLUGIN_INITIFY_INIT_EXIT
+   bool
+   depends on GCC_PLUGINS
+   help
+ Move functions to the exit section if they are called by __init and
+ __exit functions too.
+
+config GCC_PLUGIN_INITIFY_INIT_EXIT
+   bool
+   depends on GCC_PLUGIN_INITIFY && HAVE_GCC_PLUGIN_INITIFY_INIT_EXIT
+
+config GCC_PLUGIN_INITIFY_VERBOSE
+   bool "Verbose"
+   depends on GCC_PLUGINS
+   depends on GCC_PLUGIN_INITIFY
+   help
+ Print all initified strings and all functions which should be
+ __init/__exit.
+ Note that the candidates identified for __init/__exit markings
+ depend on the current kernel configuration and thus should be verified
+ manually before the source code is patched.
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c580d8c..921a13c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -114,6 +114,7 @@ config X86
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
select HAVE_GCC_PLUGINS
+   select HAVE_GCC_PLUGIN_INITIFY_INIT_EXIT if GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENTif X86_32
select HAVE_HW_BREAKPOINT
select HAVE_IDE
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 34a7413..b98b8fd 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -29,6 +29,10 @@ lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
 obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
 
 ifeq ($(CONFIG_X86_32),y)
+CFLAGS_strstr_32.o += $(INITIFY_DISABLE_VERIFIY_NOCAPTURE_FUNCTIONS)
+CFLAGS_string_32.o += $(INITIFY_DISABLE_VERIFIY_NOCAPTURE_FUNCTIONS)
+CFLAGS_memcpy_32.o += $(INITIFY_DISABLE_VERIFIY_NOCAPTURE_FUNCTIONS)
+
 obj-y += atomic64_32.o
 lib-y += atomic64_cx8_32.o
 lib-y += checksum_32.o
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 2456397..6e292f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -531,6 +531,7 @@
MEM_DISCARD(init.data)  \
KERNEL_CTORS()  \
MCOUNT_REC()\
+   *(.init.rodata.str) \
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS()

[PATCH v3 4/7] Add the initify gcc plugin

2016-07-26 Thread Emese Revfy
The kernel already has a mechanism to free up code and data memory that
is only used during kernel or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization.
It has two passes. The first one tries to find all functions that
can be become __init/__exit. The second one moves string constants
(local variables and function string arguments marked by
the nocapture attribute) only referenced in __init/__exit functions
to the __initconst/__exitconst sections.
It reduces memory usage. This plugin can be useful for embedded systems.

If a function is called by __init and __exit functions as well then
the plugin moves it to the __exit section. This causes false positive
section mismatch errors/warnings that I don't know how to handle yet.

The instrumentation pass of the latent_entropy plugin must run after
the initify plugin to increase coverage.

Signed-off-by: Emese Revfy 
---
 arch/Kconfig |   35 +
 arch/x86/Kconfig |1 +
 arch/x86/lib/Makefile|4 +
 include/asm-generic/vmlinux.lds.h|2 +
 include/linux/compiler-gcc.h |   14 +
 include/linux/compiler.h |4 +
 scripts/Makefile.gcc-plugins |9 +
 scripts/gcc-plugins/gcc-common.h |   41 +
 scripts/gcc-plugins/initify_plugin.c | 1883 ++
 9 files changed, 1993 insertions(+)
 create mode 100644 scripts/gcc-plugins/initify_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 88673c2..41eb562 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -417,6 +417,41 @@ config GCC_PLUGIN_LATENT_ENTROPY
   * https://grsecurity.net/
   * https://pax.grsecurity.net/
 
+config GCC_PLUGIN_INITIFY
+   bool "Free more kernel memory after init"
+   depends on GCC_PLUGINS
+   help
+ The kernel has a mechanism to free up code and data memory that is
+ only used during kernel or module initialization.  Enabling this
+ feature will teach the compiler to find more such code and data
+ that can be freed after initialization.
+
+ This plugin is the part of grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
+config HAVE_GCC_PLUGIN_INITIFY_INIT_EXIT
+   bool
+   depends on GCC_PLUGINS
+   help
+ Move functions to the exit section if they are called by __init and
+ __exit functions too.
+
+config GCC_PLUGIN_INITIFY_INIT_EXIT
+   bool
+   depends on GCC_PLUGIN_INITIFY && HAVE_GCC_PLUGIN_INITIFY_INIT_EXIT
+
+config GCC_PLUGIN_INITIFY_VERBOSE
+   bool "Verbose"
+   depends on GCC_PLUGINS
+   depends on GCC_PLUGIN_INITIFY
+   help
+ Print all initified strings and all functions which should be
+ __init/__exit.
+ Note that the candidates identified for __init/__exit markings
+ depend on the current kernel configuration and thus should be verified
+ manually before the source code is patched.
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c580d8c..921a13c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -114,6 +114,7 @@ config X86
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
select HAVE_GCC_PLUGINS
+   select HAVE_GCC_PLUGIN_INITIFY_INIT_EXIT if GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENTif X86_32
select HAVE_HW_BREAKPOINT
select HAVE_IDE
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 34a7413..b98b8fd 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -29,6 +29,10 @@ lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
 obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
 
 ifeq ($(CONFIG_X86_32),y)
+CFLAGS_strstr_32.o += $(INITIFY_DISABLE_VERIFIY_NOCAPTURE_FUNCTIONS)
+CFLAGS_string_32.o += $(INITIFY_DISABLE_VERIFIY_NOCAPTURE_FUNCTIONS)
+CFLAGS_memcpy_32.o += $(INITIFY_DISABLE_VERIFIY_NOCAPTURE_FUNCTIONS)
+
 obj-y += atomic64_32.o
 lib-y += atomic64_cx8_32.o
 lib-y += checksum_32.o
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 2456397..6e292f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -531,6 +531,7 @@
MEM_DISCARD(init.data)  \
KERNEL_CTORS()  \
MCOUNT_REC()\
+   *(.init.rodata.str) \
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS()\
@@ -558,6 +55

[PATCH v3 3/7] Constify some function parameters

2016-07-26 Thread Emese Revfy
Initify needs const pointer types, the initify plugin caught some __printf
arguments that weren't const yet.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 drivers/isdn/hisax/config.c | 16 
 drivers/isdn/hisax/hisax.h  |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..2d12c6c 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
  va_list args)
 {
/* if head == NULL the fmt contains the full info */
@@ -669,23 +669,24 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
u_char  *p;
isdn_ctrl   ic;
int len;
+   const u_char*data;
 
if (!cs) {
printk(KERN_WARNING "HiSax: No CardStatus for message");
return;
}
spin_lock_irqsave(>statlock, flags);
-   p = tmpbuf;
if (head) {
+   p = tmpbuf;
p += jiftime(p, jiffies);
p += sprintf(p, " %s", head);
p += vsprintf(p, fmt, args);
*p++ = '\n';
*p = 0;
len = p - tmpbuf;
-   p = tmpbuf;
+   data = tmpbuf;
} else {
-   p = fmt;
+   data = fmt;
len = strlen(fmt);
}
if (len > HISAX_STATUS_BUFSIZE) {
@@ -699,13 +700,12 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
if (i >= len)
i = len;
len -= i;
-   memcpy(cs->status_write, p, i);
+   memcpy(cs->status_write, data, i);
cs->status_write += i;
if (cs->status_write > cs->status_end)
cs->status_write = cs->status_buf;
-   p += i;
if (len) {
-   memcpy(cs->status_write, p, len);
+   memcpy(cs->status_write, data + i, len);
cs->status_write += len;
}
 #ifdef KERNELSTACK_DEBUG
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, 
char *fmt,
}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...)
 {
va_list args;
 
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 6ead6314..338d040 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list 
args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
-- 
2.8.1



[PATCH v3 3/7] Constify some function parameters

2016-07-26 Thread Emese Revfy
Initify needs const pointer types, the initify plugin caught some __printf
arguments that weren't const yet.

Signed-off-by: Emese Revfy 
---
 drivers/isdn/hisax/config.c | 16 
 drivers/isdn/hisax/hisax.h  |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..2d12c6c 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
  va_list args)
 {
/* if head == NULL the fmt contains the full info */
@@ -669,23 +669,24 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
u_char  *p;
isdn_ctrl   ic;
int len;
+   const u_char*data;
 
if (!cs) {
printk(KERN_WARNING "HiSax: No CardStatus for message");
return;
}
spin_lock_irqsave(>statlock, flags);
-   p = tmpbuf;
if (head) {
+   p = tmpbuf;
p += jiftime(p, jiffies);
p += sprintf(p, " %s", head);
p += vsprintf(p, fmt, args);
*p++ = '\n';
*p = 0;
len = p - tmpbuf;
-   p = tmpbuf;
+   data = tmpbuf;
} else {
-   p = fmt;
+   data = fmt;
len = strlen(fmt);
}
if (len > HISAX_STATUS_BUFSIZE) {
@@ -699,13 +700,12 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
if (i >= len)
i = len;
len -= i;
-   memcpy(cs->status_write, p, i);
+   memcpy(cs->status_write, data, i);
cs->status_write += i;
if (cs->status_write > cs->status_end)
cs->status_write = cs->status_buf;
-   p += i;
if (len) {
-   memcpy(cs->status_write, p, len);
+   memcpy(cs->status_write, data + i, len);
cs->status_write += len;
}
 #ifdef KERNELSTACK_DEBUG
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, 
char *fmt,
}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...)
 {
va_list args;
 
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 6ead6314..338d040 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list 
args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
-- 
2.8.1



[PATCH v3 2/7] Split up struct warn_args

2016-07-26 Thread Emese Revfy
to enable dataflow verification by the initify plugin. This allows marking
warn_slowpath* parameters as nocapture and compile time verification of
the related dataflows.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 include/asm-generic/bug.h |  5 +
 kernel/panic.c| 32 
 lib/bug.c |  2 +-
 3 files changed, 14 insertions(+), 25 deletions(-)

diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 6f96247..3048d10 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -81,11 +81,8 @@ extern void warn_slowpath_null(const char *file, const int 
line);
do { printk(arg); __WARN_TAINT(taint); } while (0)
 #endif
 
-/* used internally by panic.c */
-struct warn_args;
-
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, struct warn_args *args);
+   struct pt_regs *regs, const char *fmt, va_list args);
 
 #ifndef WARN_ON
 #define WARN_ON(condition) ({  \
diff --git a/kernel/panic.c b/kernel/panic.c
index ca8cea1..993ad20 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -475,13 +475,8 @@ void oops_exit(void)
kmsg_dump(KMSG_DUMP_OOPS);
 }
 
-struct warn_args {
-   const char *fmt;
-   va_list args;
-};
-
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, struct warn_args *args)
+   struct pt_regs *regs, const char *fmt, va_list args)
 {
disable_trace_on_warning();
 
@@ -495,8 +490,8 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
pr_warn("WARNING: CPU: %d PID: %d at %pS\n",
raw_smp_processor_id(), current->pid, caller);
 
-   if (args)
-   vprintk(args->fmt, args->args);
+   if (fmt)
+   vprintk(fmt, args);
 
if (panic_on_warn) {
/*
@@ -525,31 +520,28 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
 #ifdef WANT_WARN_ON_SLOWPATH
 void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
 {
-   struct warn_args args;
+   va_list args;
 
-   args.fmt = fmt;
-   va_start(args.args, fmt);
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL,
-  );
-   va_end(args.args);
+   va_start(args, fmt);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, fmt, 
args);
+   va_end(args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt);
 
 void warn_slowpath_fmt_taint(const char *file, int line,
 unsigned taint, const char *fmt, ...)
 {
-   struct warn_args args;
+   va_list args;
 
-   args.fmt = fmt;
-   va_start(args.args, fmt);
-   __warn(file, line, __builtin_return_address(0), taint, NULL, );
-   va_end(args.args);
+   va_start(args, fmt);
+   __warn(file, line, __builtin_return_address(0), taint, NULL, fmt, args);
+   va_end(args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt_taint);
 
 void warn_slowpath_null(const char *file, int line)
 {
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL, 
NULL);
 }
 EXPORT_SYMBOL(warn_slowpath_null);
 #endif
diff --git a/lib/bug.c b/lib/bug.c
index bc3656e..c8bdebb 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -168,7 +168,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct 
pt_regs *regs)
if (warning) {
/* this is a WARN_ON rather than BUG/BUG_ON */
__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
-  NULL);
+  NULL, NULL);
return BUG_TRAP_TYPE_WARN;
}
 
-- 
2.8.1



[PATCH v3 2/7] Split up struct warn_args

2016-07-26 Thread Emese Revfy
to enable dataflow verification by the initify plugin. This allows marking
warn_slowpath* parameters as nocapture and compile time verification of
the related dataflows.

Signed-off-by: Emese Revfy 
---
 include/asm-generic/bug.h |  5 +
 kernel/panic.c| 32 
 lib/bug.c |  2 +-
 3 files changed, 14 insertions(+), 25 deletions(-)

diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 6f96247..3048d10 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -81,11 +81,8 @@ extern void warn_slowpath_null(const char *file, const int 
line);
do { printk(arg); __WARN_TAINT(taint); } while (0)
 #endif
 
-/* used internally by panic.c */
-struct warn_args;
-
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, struct warn_args *args);
+   struct pt_regs *regs, const char *fmt, va_list args);
 
 #ifndef WARN_ON
 #define WARN_ON(condition) ({  \
diff --git a/kernel/panic.c b/kernel/panic.c
index ca8cea1..993ad20 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -475,13 +475,8 @@ void oops_exit(void)
kmsg_dump(KMSG_DUMP_OOPS);
 }
 
-struct warn_args {
-   const char *fmt;
-   va_list args;
-};
-
 void __warn(const char *file, int line, void *caller, unsigned taint,
-   struct pt_regs *regs, struct warn_args *args)
+   struct pt_regs *regs, const char *fmt, va_list args)
 {
disable_trace_on_warning();
 
@@ -495,8 +490,8 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
pr_warn("WARNING: CPU: %d PID: %d at %pS\n",
raw_smp_processor_id(), current->pid, caller);
 
-   if (args)
-   vprintk(args->fmt, args->args);
+   if (fmt)
+   vprintk(fmt, args);
 
if (panic_on_warn) {
/*
@@ -525,31 +520,28 @@ void __warn(const char *file, int line, void *caller, 
unsigned taint,
 #ifdef WANT_WARN_ON_SLOWPATH
 void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
 {
-   struct warn_args args;
+   va_list args;
 
-   args.fmt = fmt;
-   va_start(args.args, fmt);
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL,
-  );
-   va_end(args.args);
+   va_start(args, fmt);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, fmt, 
args);
+   va_end(args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt);
 
 void warn_slowpath_fmt_taint(const char *file, int line,
 unsigned taint, const char *fmt, ...)
 {
-   struct warn_args args;
+   va_list args;
 
-   args.fmt = fmt;
-   va_start(args.args, fmt);
-   __warn(file, line, __builtin_return_address(0), taint, NULL, );
-   va_end(args.args);
+   va_start(args, fmt);
+   __warn(file, line, __builtin_return_address(0), taint, NULL, fmt, args);
+   va_end(args);
 }
 EXPORT_SYMBOL(warn_slowpath_fmt_taint);
 
 void warn_slowpath_null(const char *file, int line)
 {
-   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL);
+   __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL, 
NULL);
 }
 EXPORT_SYMBOL(warn_slowpath_null);
 #endif
diff --git a/lib/bug.c b/lib/bug.c
index bc3656e..c8bdebb 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -168,7 +168,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct 
pt_regs *regs)
if (warning) {
/* this is a WARN_ON rather than BUG/BUG_ON */
__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
-  NULL);
+  NULL, NULL);
return BUG_TRAP_TYPE_WARN;
}
 
-- 
2.8.1



[PATCH v3 1/7] Move type casts into is_kernel_rodata

2016-07-26 Thread Emese Revfy
so that its parameter can be marked as nocapture.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 mm/util.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/mm/util.c b/mm/util.c
index 662cddf..d95f10b 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -17,10 +17,10 @@
 
 #include "internal.h"
 
-static inline int is_kernel_rodata(unsigned long addr)
+static inline int is_kernel_rodata(const void *addr)
 {
-   return addr >= (unsigned long)__start_rodata &&
-   addr < (unsigned long)__end_rodata;
+   return (unsigned long)addr >= (unsigned long)__start_rodata &&
+   (unsigned long)addr < (unsigned long)__end_rodata;
 }
 
 /**
@@ -31,7 +31,7 @@ static inline int is_kernel_rodata(unsigned long addr)
  */
 void kfree_const(const void *x)
 {
-   if (!is_kernel_rodata((unsigned long)x))
+   if (!is_kernel_rodata(x))
kfree(x);
 }
 EXPORT_SYMBOL(kfree_const);
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(kstrdup);
  */
 const char *kstrdup_const(const char *s, gfp_t gfp)
 {
-   if (is_kernel_rodata((unsigned long)s))
+   if (is_kernel_rodata(s))
return s;
 
return kstrdup(s, gfp);
-- 
2.8.1



[PATCH v3 1/7] Move type casts into is_kernel_rodata

2016-07-26 Thread Emese Revfy
so that its parameter can be marked as nocapture.

Signed-off-by: Emese Revfy 
---
 mm/util.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/mm/util.c b/mm/util.c
index 662cddf..d95f10b 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -17,10 +17,10 @@
 
 #include "internal.h"
 
-static inline int is_kernel_rodata(unsigned long addr)
+static inline int is_kernel_rodata(const void *addr)
 {
-   return addr >= (unsigned long)__start_rodata &&
-   addr < (unsigned long)__end_rodata;
+   return (unsigned long)addr >= (unsigned long)__start_rodata &&
+   (unsigned long)addr < (unsigned long)__end_rodata;
 }
 
 /**
@@ -31,7 +31,7 @@ static inline int is_kernel_rodata(unsigned long addr)
  */
 void kfree_const(const void *x)
 {
-   if (!is_kernel_rodata((unsigned long)x))
+   if (!is_kernel_rodata(x))
kfree(x);
 }
 EXPORT_SYMBOL(kfree_const);
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(kstrdup);
  */
 const char *kstrdup_const(const char *s, gfp_t gfp)
 {
-   if (is_kernel_rodata((unsigned long)s))
+   if (is_kernel_rodata(s))
return s;
 
return kstrdup(s, gfp);
-- 
2.8.1



[PATCH v3 0/7] Introduce the initify gcc plugin

2016-07-26 Thread Emese Revfy
I would like to introduce the initify gcc plugin. The kernel already has
a mechanism to free up code and data memory that is only used during kernel
or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization. It reduces memory usage.
The initify gcc plugin can be useful for embedded systems.

Originally it was a CII project supported by the Linux Foundation.

This plugin is the part of grsecurity/PaX.

The plugin supports all gcc versions from 4.5 to 6.0.

I made some changes on top of the PaX version (since March 6.). These are
the important ones:
 * move all local strings to init.rodata.str and exit.rodata.str
   (not just __func__)
 * report all initified strings and functions
   (GCC_PLUGIN_INITIFY_VERBOSE config option)
 * automatically discover init/exit functions and apply the __init or
   __exit attributes on them

You can find more about the changes here:
https://github.com/ephox-gcc-plugins/initify

This patch set is based on next-20160721.

Some statistics about the plugin:

On allyes config (amd64, gcc-6):
* 8412 initified strings
*  167 initified functions

On allmod config (i386, gcc-6):
* 8597 initified strings
*  159 initified functions

On allyes config (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 21746728 (0x14bd428)21488680 (0x147e428)-258048
.init.data   1338376  (0x146c08) 1683016  (0x19ae48)+344640
.text   78270904 (0x4aa51b8)78228280 (0x4a9ab38) -42624
.init.text   1184725  (0x1213d5) 1223257  (0x12aa59) +38532
.exit.data   104  (0x68)   17760  (0x004560) +17656
.exit.text174473  (0x02a989)  175763  (0x02ae93)  +1290

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  102936576 (0x622b000)   102678528 (0x61ec000)   -258048
03   28680192 (0x1b5a000)29081600 (0x1bbc000)   +401408

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


On defconfig (amd64, gcc-6):
* 1957 initified strings
*   29 initified functions

On defconfig (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 2524240 (0x268450)  2462800 (0x259450)  -61440
.init.data   560256 (0x088c80)   644000 (0x09d3a0)  +83744
.text   9377367 (0x8f1657)  9373079 (0x8f0597)   -4288
.init.text   438586 (0x06b13a)   441828 (0x06bde4)   +3242
.exit.data0 832 (0x000340)+832
.exit.text 8857 (0x002299)  8857 (0x002299)  0

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  13398016 (0xcc7000) 13336576 (0xcb8000) -61440
03   2203648 (0x21a000)  2293760 (0x23) +90112

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


Emese Revfy (7):
 Move type casts into is_kernel_rodata
 Split up struct warn_args to enable dataflow verification by the initify plugin
 Constify some function parameters
 Add the initify gcc plugin
 Mark functions with the __nocapture attribute
 Mark a few functions with the printf attribute
 Mark functions with the __unverified_nocapture attribute


Changed from v2:
 * Check all uses when walking a use-def chain.
 * Check all uses of initialized local variables and initify them if they
   have only nocapture uses. Previously only uses in call arguments
   determined whether the initializer value could be initified.
 * Handle the format gcc attribute from the plugin too.
 * Verify nocapture parameters of calls. Track uses of these parameters
   and verify that all uses are not captured. Verify only the nocapture
   attribute (The format attribute should be verified too.).
 * Fixed wrong indexing of function arguments.
 * Fixed decl comparison. When comparing two decls the tree codes must be
   the same.
 * Search capture uses of the return value. Use negative nocapture
   attribute parameter on a function

[PATCH v3 0/7] Introduce the initify gcc plugin

2016-07-26 Thread Emese Revfy
I would like to introduce the initify gcc plugin. The kernel already has
a mechanism to free up code and data memory that is only used during kernel
or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization. It reduces memory usage.
The initify gcc plugin can be useful for embedded systems.

Originally it was a CII project supported by the Linux Foundation.

This plugin is the part of grsecurity/PaX.

The plugin supports all gcc versions from 4.5 to 6.0.

I made some changes on top of the PaX version (since March 6.). These are
the important ones:
 * move all local strings to init.rodata.str and exit.rodata.str
   (not just __func__)
 * report all initified strings and functions
   (GCC_PLUGIN_INITIFY_VERBOSE config option)
 * automatically discover init/exit functions and apply the __init or
   __exit attributes on them

You can find more about the changes here:
https://github.com/ephox-gcc-plugins/initify

This patch set is based on next-20160721.

Some statistics about the plugin:

On allyes config (amd64, gcc-6):
* 8412 initified strings
*  167 initified functions

On allmod config (i386, gcc-6):
* 8597 initified strings
*  159 initified functions

On allyes config (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 21746728 (0x14bd428)21488680 (0x147e428)-258048
.init.data   1338376  (0x146c08) 1683016  (0x19ae48)+344640
.text   78270904 (0x4aa51b8)78228280 (0x4a9ab38) -42624
.init.text   1184725  (0x1213d5) 1223257  (0x12aa59) +38532
.exit.data   104  (0x68)   17760  (0x004560) +17656
.exit.text174473  (0x02a989)  175763  (0x02ae93)  +1290

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  102936576 (0x622b000)   102678528 (0x61ec000)   -258048
03   28680192 (0x1b5a000)29081600 (0x1bbc000)   +401408

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


On defconfig (amd64, gcc-6):
* 1957 initified strings
*   29 initified functions

On defconfig (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 2524240 (0x268450)  2462800 (0x259450)  -61440
.init.data   560256 (0x088c80)   644000 (0x09d3a0)  +83744
.text   9377367 (0x8f1657)  9373079 (0x8f0597)   -4288
.init.text   438586 (0x06b13a)   441828 (0x06bde4)   +3242
.exit.data0 832 (0x000340)+832
.exit.text 8857 (0x002299)  8857 (0x002299)  0

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  13398016 (0xcc7000) 13336576 (0xcb8000) -61440
03   2203648 (0x21a000)  2293760 (0x23) +90112

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


Emese Revfy (7):
 Move type casts into is_kernel_rodata
 Split up struct warn_args to enable dataflow verification by the initify plugin
 Constify some function parameters
 Add the initify gcc plugin
 Mark functions with the __nocapture attribute
 Mark a few functions with the printf attribute
 Mark functions with the __unverified_nocapture attribute


Changed from v2:
 * Check all uses when walking a use-def chain.
 * Check all uses of initialized local variables and initify them if they
   have only nocapture uses. Previously only uses in call arguments
   determined whether the initializer value could be initified.
 * Handle the format gcc attribute from the plugin too.
 * Verify nocapture parameters of calls. Track uses of these parameters
   and verify that all uses are not captured. Verify only the nocapture
   attribute (The format attribute should be verified too.).
 * Fixed wrong indexing of function arguments.
 * Fixed decl comparison. When comparing two decls the tree codes must be
   the same.
 * Search capture uses of the return value. Use negative nocapture
   attribute parameter on a function

Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-13 Thread Emese Revfy
On Tue, 12 Jul 2016 18:38:47 -0400
Kees Cook <keesc...@chromium.org> wrote:

> On Tue, Jul 12, 2016 at 6:08 PM, Russell King - ARM Linux
> <li...@armlinux.org.uk> wrote:
> > On Tue, Jul 12, 2016 at 03:45:56PM -0400, Kees Cook wrote:
> >> On Mon, Jul 4, 2016 at 7:40 PM, Emese Revfy <re.em...@gmail.com> wrote:
> > That sounds like a problem for architectures that still discard the
> > __exit section at link time to reduce the size of the linked kernel
> > image - though, obviously, if using the plugin results in a smaller
> > kernel image _with_ the exit sections, then there's a net benefit
> > size-wise.
> 
> Ah right, __exit is dropped for non-modular builds. So, for "both
> __init and __exit" it sounds like the behavior depends on the build:
> 
> - if modular: remove __init marking (since we need it after init)
> - if non-modular: remove __exit marking (since we'll never call exit)

When gcc compiles vmlinux these functions should be in __init and when
it compiles *.ko then they can be in __exit. I have no time to do this
now but I added it to my todo list.

The temporary fix can be that I enable this section move only on x86
(on other archs it will decrase the coverage).

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-13 Thread Emese Revfy
On Tue, 12 Jul 2016 18:38:47 -0400
Kees Cook  wrote:

> On Tue, Jul 12, 2016 at 6:08 PM, Russell King - ARM Linux
>  wrote:
> > On Tue, Jul 12, 2016 at 03:45:56PM -0400, Kees Cook wrote:
> >> On Mon, Jul 4, 2016 at 7:40 PM, Emese Revfy  wrote:
> > That sounds like a problem for architectures that still discard the
> > __exit section at link time to reduce the size of the linked kernel
> > image - though, obviously, if using the plugin results in a smaller
> > kernel image _with_ the exit sections, then there's a net benefit
> > size-wise.
> 
> Ah right, __exit is dropped for non-modular builds. So, for "both
> __init and __exit" it sounds like the behavior depends on the build:
> 
> - if modular: remove __init marking (since we need it after init)
> - if non-modular: remove __exit marking (since we'll never call exit)

When gcc compiles vmlinux these functions should be in __init and when
it compiles *.ko then they can be in __exit. I have no time to do this
now but I added it to my todo list.

The temporary fix can be that I enable this section move only on x86
(on other archs it will decrase the coverage).

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-13 Thread Emese Revfy
On Tue, 12 Jul 2016 15:45:56 -0400
Kees Cook <keesc...@chromium.org> wrote:

> On Mon, Jul 4, 2016 at 7:40 PM, Emese Revfy <re.em...@gmail.com> wrote:
> > If a function is called by __init and __exit functions as well then
> > the plugin moves it to the __exit section. This causes false positive
> > section mismatch errors/warnings that I don't know how to handle yet.
> 
> Should the mismatch checker be updated to recognize this case? Without
> the plugin, I assume these kinds of functions would only ever be
> marked for __exit? If so, should the plugin strip the __init marking
> and only add __exit?

I don't modify the existing attributes. I just add a new __init/__exit when
a function hasn't a section attribute yet.
There are three cases:
 * when the function is called only by __init functions then the plugin adds
   the __init attribute
 * when the function is called only by __exit functions then the plugin adds
   the __exit attribute
 * when the function is called by __init and __exit functions too then the
   plugin adds the __exit attribute.
The last case causes the false positive(?) message of the section mismatch.

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-13 Thread Emese Revfy
On Tue, 12 Jul 2016 15:45:56 -0400
Kees Cook  wrote:

> On Mon, Jul 4, 2016 at 7:40 PM, Emese Revfy  wrote:
> > If a function is called by __init and __exit functions as well then
> > the plugin moves it to the __exit section. This causes false positive
> > section mismatch errors/warnings that I don't know how to handle yet.
> 
> Should the mismatch checker be updated to recognize this case? Without
> the plugin, I assume these kinds of functions would only ever be
> marked for __exit? If so, should the plugin strip the __init marking
> and only add __exit?

I don't modify the existing attributes. I just add a new __init/__exit when
a function hasn't a section attribute yet.
There are three cases:
 * when the function is called only by __init functions then the plugin adds
   the __init attribute
 * when the function is called only by __exit functions then the plugin adds
   the __exit attribute
 * when the function is called by __init and __exit functions too then the
   plugin adds the __exit attribute.
The last case causes the false positive(?) message of the section mismatch.

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-13 Thread Emese Revfy
On Tue, 12 Jul 2016 16:05:45 -0400
Kees Cook  wrote:

> /*
>  * The initify gcc-plugin attempts to identify const arguments that are only
>  * used during init (see __init), so they can be moved to the .init.rodata
>  * section. If an argument is passed to a non-init function, it must
>  * normally be assumed that such an argument has been captured by that
>  * function and may be used in the future when .init has been unmapped from
>  * memory. In order to identify functions that are confirmed to not capture
>  * their arguments, the __nocapture() attribute is used so that initify can
>  * better identify candidate variables.
>  */
> #ifdef INITIFY_PLUGIN
> # define __nocapture(...) __attribute__((nocapture(__VA_ARGS__)))
> #endif

Thanks, I'll take it in the next patch set with some additions (the attribute
also handles __exit functions and the plugin does other things e.g., it can
identify candidate init/exit functions and move them automatically to 
init.text/exit.text).

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-13 Thread Emese Revfy
On Tue, 12 Jul 2016 16:05:45 -0400
Kees Cook  wrote:

> /*
>  * The initify gcc-plugin attempts to identify const arguments that are only
>  * used during init (see __init), so they can be moved to the .init.rodata
>  * section. If an argument is passed to a non-init function, it must
>  * normally be assumed that such an argument has been captured by that
>  * function and may be used in the future when .init has been unmapped from
>  * memory. In order to identify functions that are confirmed to not capture
>  * their arguments, the __nocapture() attribute is used so that initify can
>  * better identify candidate variables.
>  */
> #ifdef INITIFY_PLUGIN
> # define __nocapture(...) __attribute__((nocapture(__VA_ARGS__)))
> #endif

Thanks, I'll take it in the next patch set with some additions (the attribute
also handles __exit functions and the plugin does other things e.g., it can
identify candidate init/exit functions and move them automatically to 
init.text/exit.text).

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-12 Thread Emese Revfy
On Tue, 12 Jul 2016 15:45:56 -0400
Kees Cook <keesc...@chromium.org> wrote:

> On Mon, Jul 4, 2016 at 7:40 PM, Emese Revfy <re.em...@gmail.com> wrote:
> Thanks for sending this! I'll get it added to my tree for some 0day
> build testing, and then get it into my -next tree.

I'll send a new patch set soon. I'm working on some fixes and
I would like to implement the handling of return uses to increase the coverage
(which decreases because of the bug fixes :) ).
So please hold off with testing until the next patch.

-- 
Emese


Re: [PATCH v2 1/3] Add the initify gcc plugin

2016-07-12 Thread Emese Revfy
On Tue, 12 Jul 2016 15:45:56 -0400
Kees Cook  wrote:

> On Mon, Jul 4, 2016 at 7:40 PM, Emese Revfy  wrote:
> Thanks for sending this! I'll get it added to my tree for some 0day
> build testing, and then get it into my -next tree.

I'll send a new patch set soon. I'm working on some fixes and
I would like to implement the handling of return uses to increase the coverage
(which decreases because of the bug fixes :) ).
So please hold off with testing until the next patch.

-- 
Emese


Re: [PATCH v2 3/3] Constify some function parameters

2016-07-06 Thread Emese Revfy
On Tue, 5 Jul 2016 07:58:04 +0800
kbuild test robot  wrote:

> All warnings (new ones prefixed by >>):
> 
>drivers/isdn/hisax/config.c: In function 'VHiSax_putstatus':
> >> drivers/isdn/hisax/config.c:688:5: warning: assignment discards 'const' 
> >> qualifier from pointer target type [-Wdiscarded-qualifiers]
>   p = fmt;

Hi,

Thanks for the report, I resent "[PATCH v2 3/3] Constify some function 
parameters" with the fix.

-- 
Emese


Re: [PATCH v2 3/3] Constify some function parameters

2016-07-06 Thread Emese Revfy
On Tue, 5 Jul 2016 07:58:04 +0800
kbuild test robot  wrote:

> All warnings (new ones prefixed by >>):
> 
>drivers/isdn/hisax/config.c: In function 'VHiSax_putstatus':
> >> drivers/isdn/hisax/config.c:688:5: warning: assignment discards 'const' 
> >> qualifier from pointer target type [-Wdiscarded-qualifiers]
>   p = fmt;

Hi,

Thanks for the report, I resent "[PATCH v2 3/3] Constify some function 
parameters" with the fix.

-- 
Emese


[PATCH v2 3/3] Constify some function parameters

2016-07-06 Thread Emese Revfy
Initify needs const pointer types, the initify plugin caught some __printf
arguments that weren't const yet.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 drivers/isdn/hisax/config.c | 16 
 drivers/isdn/hisax/hisax.h  |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..2d12c6c 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
  va_list args)
 {
/* if head == NULL the fmt contains the full info */
@@ -669,23 +669,24 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
u_char  *p;
isdn_ctrl   ic;
int len;
+   const u_char*data;
 
if (!cs) {
printk(KERN_WARNING "HiSax: No CardStatus for message");
return;
}
spin_lock_irqsave(>statlock, flags);
-   p = tmpbuf;
if (head) {
+   p = tmpbuf;
p += jiftime(p, jiffies);
p += sprintf(p, " %s", head);
p += vsprintf(p, fmt, args);
*p++ = '\n';
*p = 0;
len = p - tmpbuf;
-   p = tmpbuf;
+   data = tmpbuf;
} else {
-   p = fmt;
+   data = fmt;
len = strlen(fmt);
}
if (len > HISAX_STATUS_BUFSIZE) {
@@ -699,13 +700,12 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
if (i >= len)
i = len;
len -= i;
-   memcpy(cs->status_write, p, i);
+   memcpy(cs->status_write, data, i);
cs->status_write += i;
if (cs->status_write > cs->status_end)
cs->status_write = cs->status_buf;
-   p += i;
if (len) {
-   memcpy(cs->status_write, p, len);
+   memcpy(cs->status_write, data + i, len);
cs->status_write += len;
}
 #ifdef KERNELSTACK_DEBUG
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, 
char *fmt,
}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...)
 {
va_list args;
 
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 6ead6314..338d040 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list 
args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
-- 
2.8.1



[PATCH v2 3/3] Constify some function parameters

2016-07-06 Thread Emese Revfy
Initify needs const pointer types, the initify plugin caught some __printf
arguments that weren't const yet.

Signed-off-by: Emese Revfy 
---
 drivers/isdn/hisax/config.c | 16 
 drivers/isdn/hisax/hisax.h  |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..2d12c6c 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
  va_list args)
 {
/* if head == NULL the fmt contains the full info */
@@ -669,23 +669,24 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
u_char  *p;
isdn_ctrl   ic;
int len;
+   const u_char*data;
 
if (!cs) {
printk(KERN_WARNING "HiSax: No CardStatus for message");
return;
}
spin_lock_irqsave(>statlock, flags);
-   p = tmpbuf;
if (head) {
+   p = tmpbuf;
p += jiftime(p, jiffies);
p += sprintf(p, " %s", head);
p += vsprintf(p, fmt, args);
*p++ = '\n';
*p = 0;
len = p - tmpbuf;
-   p = tmpbuf;
+   data = tmpbuf;
} else {
-   p = fmt;
+   data = fmt;
len = strlen(fmt);
}
if (len > HISAX_STATUS_BUFSIZE) {
@@ -699,13 +700,12 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char 
*head, char *fmt,
if (i >= len)
i = len;
len -= i;
-   memcpy(cs->status_write, p, i);
+   memcpy(cs->status_write, data, i);
cs->status_write += i;
if (cs->status_write > cs->status_end)
cs->status_write = cs->status_buf;
-   p += i;
if (len) {
-   memcpy(cs->status_write, p, len);
+   memcpy(cs->status_write, data + i, len);
cs->status_write += len;
}
 #ifdef KERNELSTACK_DEBUG
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, 
char *fmt,
}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...)
 {
va_list args;
 
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 6ead6314..338d040 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list 
args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
-- 
2.8.1



[PATCH v2 3/3] Constify some function parameters

2016-07-04 Thread Emese Revfy
Initify needs const pointer types, the initify plugin caught some __printf
arguments that weren't const yet.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 drivers/isdn/hisax/config.c | 4 ++--
 drivers/isdn/hisax/hisax.h  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..a7d53c9 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
  va_list args)
 {
/* if head == NULL the fmt contains the full info */
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, 
char *fmt,
}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...)
 {
va_list args;
 
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 6ead6314..338d040 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list 
args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
-- 
2.8.1



[PATCH v2 3/3] Constify some function parameters

2016-07-04 Thread Emese Revfy
Initify needs const pointer types, the initify plugin caught some __printf
arguments that weren't const yet.

Signed-off-by: Emese Revfy 
---
 drivers/isdn/hisax/config.c | 4 ++--
 drivers/isdn/hisax/hisax.h  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index bf04d2a..a7d53c9 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
  va_list args)
 {
/* if head == NULL the fmt contains the full info */
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, 
char *fmt,
}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...)
 {
va_list args;
 
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 6ead6314..338d040 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list 
args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, 
va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
-- 
2.8.1



[PATCH v2 2/3] Mark functions with the __nocapture attribute

2016-07-04 Thread Emese Revfy
The nocapture gcc attribute can be on functions only.
The attribute takes one or more unsigned integer constants as parameters
that specify the function argument(s) of const char* type to initify.
If the marked argument is a vararg then the plugin initifies
all vararg arguments.

I couldn't test the arm, arm64 and powerpc architectures.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/arm/include/asm/string.h |  4 +--
 arch/arm64/include/asm/string.h   | 19 ++--
 arch/powerpc/include/asm/string.h | 19 ++--
 arch/x86/include/asm/string_32.h  | 21 ++---
 arch/x86/include/asm/string_64.h  | 20 ++---
 arch/x86/kernel/hpet.c|  2 +-
 include/asm-generic/bug.h |  6 ++--
 include/linux/compiler-gcc.h  | 10 +--
 include/linux/compiler.h  |  4 +++
 include/linux/fs.h|  5 ++--
 include/linux/printk.h|  2 +-
 include/linux/string.h| 63 ---
 12 files changed, 96 insertions(+), 79 deletions(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aa..ddb9d58 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -13,10 +13,10 @@ extern char * strrchr(const char * s, int c);
 extern char * strchr(const char * s, int c);
 
 #define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, __kernel_size_t);
+extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void * memmove(void *, const void *, __kernel_size_t);
+extern void * memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
 extern void * memchr(const void *, int, __kernel_size_t);
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..4263a27 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -23,24 +23,25 @@ extern char *strrchr(const char *, int c);
 extern char *strchr(const char *, int c);
 
 #define __HAVE_ARCH_STRCMP
-extern int strcmp(const char *, const char *);
+extern int strcmp(const char *, const char *) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRLEN
-extern __kernel_size_t strlen(const char *);
+extern __kernel_size_t strlen(const char *) __nocapture(1);
 
 #define __HAVE_ARCH_STRNLEN
-extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-extern void *__memmove(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
 extern void *memchr(const void *, int, __kernel_size_t);
@@ -50,7 +51,7 @@ extern void *memset(void *, int, __kernel_size_t);
 extern void *__memset(void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, size_t);
+extern int memcmp(const void *, const void *, size_t) __nocapture(1, 2);
 
 
 #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
diff --git a/arch/powerpc/include/asm/string.h 
b/arch/powerpc/include/asm/string.h
index da3cdff..e67f1eb 100644
--- a/arch/powerpc/include/asm/string.h
+++ b/arch/powerpc/include/asm/string.h
@@ -11,16 +11,17 @@
 #define __HAVE_ARCH_MEMCMP
 #define __HAVE_ARCH_MEMCHR
 
-extern char * strcpy(char *,const char *);
-extern char * strncpy(char *,const char *, __kernel_size_t);
-extern __kernel_size_t strlen(const char *);
-extern int strcmp(const char *,const char *);
-extern int strncmp(const char *, const char *, __kernel_size_t);
-extern char * strcat(char *, const char *);
+extern char * strcpy(char *,const char *) __nocapture(2);
+extern char * strncpy(char *,const char *, __kernel_size_t) __nocapture(2);
+extern __kernel_size_t strlen(const char *) __nocapture(1);
+extern int strcmp(const char *,const char *) __nocapture(1, 2);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
+extern char * strcat(char *, const char *) __nocapture(2);
 extern void * memset(void *,int,__kernel_size_t);
-extern void * memcpy(void *,const void *,__kernel_size_t);
-extern void * memmove(void *,const void *,__kernel_size_t);
-extern int memcmp(const void *,const void *,__kernel_size_t)

[PATCH v2 2/3] Mark functions with the __nocapture attribute

2016-07-04 Thread Emese Revfy
The nocapture gcc attribute can be on functions only.
The attribute takes one or more unsigned integer constants as parameters
that specify the function argument(s) of const char* type to initify.
If the marked argument is a vararg then the plugin initifies
all vararg arguments.

I couldn't test the arm, arm64 and powerpc architectures.

Signed-off-by: Emese Revfy 
---
 arch/arm/include/asm/string.h |  4 +--
 arch/arm64/include/asm/string.h   | 19 ++--
 arch/powerpc/include/asm/string.h | 19 ++--
 arch/x86/include/asm/string_32.h  | 21 ++---
 arch/x86/include/asm/string_64.h  | 20 ++---
 arch/x86/kernel/hpet.c|  2 +-
 include/asm-generic/bug.h |  6 ++--
 include/linux/compiler-gcc.h  | 10 +--
 include/linux/compiler.h  |  4 +++
 include/linux/fs.h|  5 ++--
 include/linux/printk.h|  2 +-
 include/linux/string.h| 63 ---
 12 files changed, 96 insertions(+), 79 deletions(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aa..ddb9d58 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -13,10 +13,10 @@ extern char * strrchr(const char * s, int c);
 extern char * strchr(const char * s, int c);
 
 #define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, __kernel_size_t);
+extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void * memmove(void *, const void *, __kernel_size_t);
+extern void * memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
 extern void * memchr(const void *, int, __kernel_size_t);
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..4263a27 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -23,24 +23,25 @@ extern char *strrchr(const char *, int c);
 extern char *strchr(const char *, int c);
 
 #define __HAVE_ARCH_STRCMP
-extern int strcmp(const char *, const char *);
+extern int strcmp(const char *, const char *) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRLEN
-extern __kernel_size_t strlen(const char *);
+extern __kernel_size_t strlen(const char *) __nocapture(1);
 
 #define __HAVE_ARCH_STRNLEN
-extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-extern void *__memmove(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
 extern void *memchr(const void *, int, __kernel_size_t);
@@ -50,7 +51,7 @@ extern void *memset(void *, int, __kernel_size_t);
 extern void *__memset(void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, size_t);
+extern int memcmp(const void *, const void *, size_t) __nocapture(1, 2);
 
 
 #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
diff --git a/arch/powerpc/include/asm/string.h 
b/arch/powerpc/include/asm/string.h
index da3cdff..e67f1eb 100644
--- a/arch/powerpc/include/asm/string.h
+++ b/arch/powerpc/include/asm/string.h
@@ -11,16 +11,17 @@
 #define __HAVE_ARCH_MEMCMP
 #define __HAVE_ARCH_MEMCHR
 
-extern char * strcpy(char *,const char *);
-extern char * strncpy(char *,const char *, __kernel_size_t);
-extern __kernel_size_t strlen(const char *);
-extern int strcmp(const char *,const char *);
-extern int strncmp(const char *, const char *, __kernel_size_t);
-extern char * strcat(char *, const char *);
+extern char * strcpy(char *,const char *) __nocapture(2);
+extern char * strncpy(char *,const char *, __kernel_size_t) __nocapture(2);
+extern __kernel_size_t strlen(const char *) __nocapture(1);
+extern int strcmp(const char *,const char *) __nocapture(1, 2);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
+extern char * strcat(char *, const char *) __nocapture(2);
 extern void * memset(void *,int,__kernel_size_t);
-extern void * memcpy(void *,const void *,__kernel_size_t);
-extern void * memmove(void *,const void *,__kernel_size_t);
-extern int memcmp(const void *,const void *,__kernel_size_t);
+extern void * memcpy(void

[PATCH v2 1/3] Add the initify gcc plugin

2016-07-04 Thread Emese Revfy
The kernel already has a mechanism to free up code and data memory that
is only used during kernel or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization.
It has two passes. The first one tries to find all functions that
can be become __init/__exit. The second one moves string constants
(local variables and function string arguments marked by
the nocapture attribute) only referenced in __init/__exit functions
to the __initconst/__exitconst sections.
It reduces memory usage. This plugin can be useful for embedded systems.

If a function is called by __init and __exit functions as well then
the plugin moves it to the __exit section. This causes false positive
section mismatch errors/warnings that I don't know how to handle yet.

The instrumentation pass of the latent_entropy plugin must run after
the initify plugin to increase coverage.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/Kconfig |   23 +
 include/asm-generic/vmlinux.lds.h|2 +
 scripts/Makefile.gcc-plugins |4 +
 scripts/gcc-plugins/gcc-common.h |   41 ++
 scripts/gcc-plugins/initify_plugin.c | 1183 ++
 5 files changed, 1253 insertions(+)
 create mode 100644 scripts/gcc-plugins/initify_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 1c91f52..0c877f6 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -417,6 +417,29 @@ config GCC_PLUGIN_LATENT_ENTROPY
   * https://grsecurity.net/
   * https://pax.grsecurity.net/
 
+config GCC_PLUGIN_INITIFY
+   bool "Free more kernel memory after init"
+   depends on GCC_PLUGINS
+   help
+ The kernel has a mechanism to free up code and data memory that is
+ only used during kernel or module initialization.  Enabling this
+ feature will teach the compiler to find more such code and data
+ that can be freed after initialization.
+
+ This plugin is the part of grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
+config GCC_PLUGIN_INITIFY_VERBOSE
+   bool "Verbose"
+   depends on GCC_PLUGIN_INITIFY
+   help
+ Print all initified strings and all functions which should be
+ __init/__exit.
+ Note that the candidates identified for __init/__exit markings
+ depend on the current kernel configuration and thus should be verified
+ manually before the source code is patched.
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index ec3b78d..c73537a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -531,6 +531,7 @@
MEM_DISCARD(init.data)  \
KERNEL_CTORS()  \
MCOUNT_REC()\
+   *(.init.rodata.str) \
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS()\
@@ -555,6 +556,7 @@
 #define EXIT_DATA  \
*(.exit.data)   \
MEM_DISCARD(exit.data)  \
+   *(.exit.rodata.str) \
MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT  \
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 1f922df..0ce8392 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -12,6 +12,10 @@ ifdef CONFIG_GCC_PLUGINS
 DISABLE_LATENT_ENTROPY_PLUGIN  += 
-fplugin-arg-latent_entropy_plugin-disable
   endif
 
+  gcc-plugin-$(CONFIG_GCC_PLUGIN_INITIFY)  += initify_plugin.so
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY)   += -DINITIFY_PLUGIN 
-fplugin-arg-initify_plugin-search_init_exit_functions
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY_VERBOSE)+= 
-fplugin-arg-initify_plugin-verbose
+
   ifdef CONFIG_GCC_PLUGIN_SANCOV
 ifeq ($(CFLAGS_KCOV),)
   # It is needed because of the gcc-plugin.sh and gcc version checks.
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 172850b..7f2eb16 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -286,6 +286,26 @@ static inline struct cgraph_node 
*cgraph_next_function_with_gimple_body(struct c
return NULL;
 }
 
+static inline bool cgraph_for_node_and_aliases(cgraph_node_ptr node,
+   bool (

[PATCH v2 1/3] Add the initify gcc plugin

2016-07-04 Thread Emese Revfy
The kernel already has a mechanism to free up code and data memory that
is only used during kernel or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization.
It has two passes. The first one tries to find all functions that
can be become __init/__exit. The second one moves string constants
(local variables and function string arguments marked by
the nocapture attribute) only referenced in __init/__exit functions
to the __initconst/__exitconst sections.
It reduces memory usage. This plugin can be useful for embedded systems.

If a function is called by __init and __exit functions as well then
the plugin moves it to the __exit section. This causes false positive
section mismatch errors/warnings that I don't know how to handle yet.

The instrumentation pass of the latent_entropy plugin must run after
the initify plugin to increase coverage.

Signed-off-by: Emese Revfy 
---
 arch/Kconfig |   23 +
 include/asm-generic/vmlinux.lds.h|2 +
 scripts/Makefile.gcc-plugins |4 +
 scripts/gcc-plugins/gcc-common.h |   41 ++
 scripts/gcc-plugins/initify_plugin.c | 1183 ++
 5 files changed, 1253 insertions(+)
 create mode 100644 scripts/gcc-plugins/initify_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 1c91f52..0c877f6 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -417,6 +417,29 @@ config GCC_PLUGIN_LATENT_ENTROPY
   * https://grsecurity.net/
   * https://pax.grsecurity.net/
 
+config GCC_PLUGIN_INITIFY
+   bool "Free more kernel memory after init"
+   depends on GCC_PLUGINS
+   help
+ The kernel has a mechanism to free up code and data memory that is
+ only used during kernel or module initialization.  Enabling this
+ feature will teach the compiler to find more such code and data
+ that can be freed after initialization.
+
+ This plugin is the part of grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
+config GCC_PLUGIN_INITIFY_VERBOSE
+   bool "Verbose"
+   depends on GCC_PLUGIN_INITIFY
+   help
+ Print all initified strings and all functions which should be
+ __init/__exit.
+ Note that the candidates identified for __init/__exit markings
+ depend on the current kernel configuration and thus should be verified
+ manually before the source code is patched.
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index ec3b78d..c73537a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -531,6 +531,7 @@
MEM_DISCARD(init.data)  \
KERNEL_CTORS()  \
MCOUNT_REC()\
+   *(.init.rodata.str) \
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS()\
@@ -555,6 +556,7 @@
 #define EXIT_DATA  \
*(.exit.data)   \
MEM_DISCARD(exit.data)  \
+   *(.exit.rodata.str) \
MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT  \
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 1f922df..0ce8392 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -12,6 +12,10 @@ ifdef CONFIG_GCC_PLUGINS
 DISABLE_LATENT_ENTROPY_PLUGIN  += 
-fplugin-arg-latent_entropy_plugin-disable
   endif
 
+  gcc-plugin-$(CONFIG_GCC_PLUGIN_INITIFY)  += initify_plugin.so
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY)   += -DINITIFY_PLUGIN 
-fplugin-arg-initify_plugin-search_init_exit_functions
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY_VERBOSE)+= 
-fplugin-arg-initify_plugin-verbose
+
   ifdef CONFIG_GCC_PLUGIN_SANCOV
 ifeq ($(CFLAGS_KCOV),)
   # It is needed because of the gcc-plugin.sh and gcc version checks.
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 172850b..7f2eb16 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -286,6 +286,26 @@ static inline struct cgraph_node 
*cgraph_next_function_with_gimple_body(struct c
return NULL;
 }
 
+static inline bool cgraph_for_node_and_aliases(cgraph_node_ptr node,
+   bool (*callback)(c

[PATCH v2 0/3] Introduce the initify gcc plugin

2016-07-04 Thread Emese Revfy
I would like to introduce the initify gcc plugin. The kernel already has
a mechanism to free up code and data memory that is only used during kernel
or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization. It reduces memory usage.
The initify gcc plugin can be useful for embedded systems.

It is a CII project supported by the Linux Foundation.

This plugin is the part of grsecurity/PaX.

The plugin supports all gcc versions from 4.5 to 6.0.

I made some changes on top of the PaX version (since March 6.). These are
the important ones:
 * move all local strings to init.rodata.str and exit.rodata.str
   (not just __func__)
 * report all initified strings and functions
   (GCC_PLUGIN_INITIFY_VERBOSE config option)
 * automatically discover init/exit functions and apply the __init or
   __exit attributes on them

You can find more about the changes here:
https://github.com/ephox-gcc-plugins/initify

This patch set is based on the "Add support for complex gcc plugins that
don't fit in a single file" patch set
(https://github.com/ephox-gcc-plugins/gcc-plugins_linux-next.git#initify
HEAD: e08eda5d85f7f52641640).

Some statistics about the plugin:

On allyes config (amd64, gcc-6):
* 7765 initified strings
*  231 initified functions

On allmod config (i386, gcc-6):
* 9177 initified strings
*  288 initified functions

On allyes config (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 19054824 (0x122c0e8)18841832 (0x11f80e8)-212992
.init.data   1273768  (0x136fa8) 1583496  (0x182988)+309728
.text   46126301 (0x2bfd4dd)46099805 (0x2bf6d5d) -26496
.init.text836339  (0x0cc2f3)  855952  (0x0d0f90) +19613
.exit.data   104  (0x68)   16736  (0x004160) +16632
.exit.text125511  (0x01ea47)  133267  (0x020893)  +7756

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  67727360 (0x4097000)65417216 (0x3e63000)-2310144
03   2453504  (0x257000) 2809856  (0x2ae000) +356352

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


On defconfig (amd64, gcc-6):
* 2044 initified strings
*   43 initified functions

On defconfig (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 2466736 (0x25a3b0)  2405296 (0x24b3b0)  -61440
.init.data   564656 (0x089db0)   645616 (0x09d9f0)  +80960
.text   9364727 (0x8ee4f7)  9360823 (0x8ed5b7)   -3904
.init.text   436097 (0x06a781)   439161 (0x06b379)   +3064
.exit.data0 864 (0x000360)+864
.exit.text 8806 (0x002266) 9824 (0x002660)   +1018

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  13340672 (0xcb9000) 13279232 (0xcaa000) -61440
03   1097728 (0x10c000)  1183744 (0x121000) +86016

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


Emese Revfy (3):
 Add the initify gcc plugin
 Mark functions with the __nocapture attribute
 Constify some function parameters


Changes from v1:
 * Removed unnecessary nocapture attributes from boot code
   (Reported-by: PaX Team <pagee...@freemail.hu>)
 * Removed nocapture attributes from functions that return
   the marked parameter
   (Reported-by: Rasmus Villemoes <li...@rasmusvillemoes.dk>)
 * Added nocapture attribute to strlen()
 * Updated gcc-common.h from PaX
 * Don't forcibly constify initified string types
   this caused the size reduction of the .data section
   (initify_plugin.c)
 * Added the section mismatch problem in the commit message

---
 arch/Kconfig |   23 +
 arch/arm/include/asm/string.h|4 +-
 arch/arm64/include/asm/string.h  |   19 +-
 arch/powerpc/include/asm/string.h|   19 +-
 arch/x86/include/asm/string_32.h |   21 +-
 arch/x86/include/asm/string_64.h  

[PATCH v2 0/3] Introduce the initify gcc plugin

2016-07-04 Thread Emese Revfy
I would like to introduce the initify gcc plugin. The kernel already has
a mechanism to free up code and data memory that is only used during kernel
or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization. It reduces memory usage.
The initify gcc plugin can be useful for embedded systems.

It is a CII project supported by the Linux Foundation.

This plugin is the part of grsecurity/PaX.

The plugin supports all gcc versions from 4.5 to 6.0.

I made some changes on top of the PaX version (since March 6.). These are
the important ones:
 * move all local strings to init.rodata.str and exit.rodata.str
   (not just __func__)
 * report all initified strings and functions
   (GCC_PLUGIN_INITIFY_VERBOSE config option)
 * automatically discover init/exit functions and apply the __init or
   __exit attributes on them

You can find more about the changes here:
https://github.com/ephox-gcc-plugins/initify

This patch set is based on the "Add support for complex gcc plugins that
don't fit in a single file" patch set
(https://github.com/ephox-gcc-plugins/gcc-plugins_linux-next.git#initify
HEAD: e08eda5d85f7f52641640).

Some statistics about the plugin:

On allyes config (amd64, gcc-6):
* 7765 initified strings
*  231 initified functions

On allmod config (i386, gcc-6):
* 9177 initified strings
*  288 initified functions

On allyes config (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 19054824 (0x122c0e8)18841832 (0x11f80e8)-212992
.init.data   1273768  (0x136fa8) 1583496  (0x182988)+309728
.text   46126301 (0x2bfd4dd)46099805 (0x2bf6d5d) -26496
.init.text836339  (0x0cc2f3)  855952  (0x0d0f90) +19613
.exit.data   104  (0x68)   16736  (0x004160) +16632
.exit.text125511  (0x01ea47)  133267  (0x020893)  +7756

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  67727360 (0x4097000)65417216 (0x3e63000)-2310144
03   2453504  (0x257000) 2809856  (0x2ae000) +356352

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


On defconfig (amd64, gcc-6):
* 2044 initified strings
*   43 initified functions

On defconfig (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 2466736 (0x25a3b0)  2405296 (0x24b3b0)  -61440
.init.data   564656 (0x089db0)   645616 (0x09d9f0)  +80960
.text   9364727 (0x8ee4f7)  9360823 (0x8ed5b7)   -3904
.init.text   436097 (0x06a781)   439161 (0x06b379)   +3064
.exit.data0 864 (0x000360)+864
.exit.text 8806 (0x002266) 9824 (0x002660)   +1018

FileSiz (vanilla)   FileSiz (vanilla + initify)  change

00  13340672 (0xcb9000) 13279232 (0xcaa000) -61440
03   1097728 (0x10c000)  1183744 (0x121000) +86016

00 .text .notes __ex_table .rodata __bug_table .pci_fixup .builtin_fw
   .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings __init_rodata
   __param __modver
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init
   .parainstructions .altinstructions .altinstr_replacement
   .iommu_table .apicdrivers .exit.text .exit.data .smp_locks .bss .brk


Emese Revfy (3):
 Add the initify gcc plugin
 Mark functions with the __nocapture attribute
 Constify some function parameters


Changes from v1:
 * Removed unnecessary nocapture attributes from boot code
   (Reported-by: PaX Team )
 * Removed nocapture attributes from functions that return
   the marked parameter
   (Reported-by: Rasmus Villemoes )
 * Added nocapture attribute to strlen()
 * Updated gcc-common.h from PaX
 * Don't forcibly constify initified string types
   this caused the size reduction of the .data section
   (initify_plugin.c)
 * Added the section mismatch problem in the commit message

---
 arch/Kconfig |   23 +
 arch/arm/include/asm/string.h|4 +-
 arch/arm64/include/asm/string.h  |   19 +-
 arch/powerpc/include/asm/string.h|   19 +-
 arch/x86/include/asm/string_32.h |   21 +-
 arch/x86/include/asm/string_64.h |   20 +-
 arch/x86/kernel/hpet.c   |2 +-
 dr

Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-07-01 Thread Emese Revfy
On Wed, 29 Jun 2016 17:12:45 -0700
Joe Perches <j...@perches.com> wrote:

> On Wed, 2016-06-29 at 20:42 +0200, Emese Revfy wrote:
> > On Tue, 28 Jun 2016 14:00:57 -0700 Joe Perches <j...@perches.com> wrote:
> > > On Tue, 2016-06-28 at 22:40 +0200, Emese Revfy wrote:
> > > > On Tue, 28 Jun 2016 09:43:31 -0700 Joe Perches <j...@perches.com> wrote:
> > > > > On Tue, 2016-06-28 at 13:36 +0200, Emese Revfy wrote:
> > > > > > The nocapture gcc attribute can be on functions only.
> > > > > > The attribute takes one or more unsigned integer constants as 
> > > > > > parameters
> > > > > > that specify the function argument(s) of const char* type to 
> > > > > > initify.
> > > > > Perhaps this should be const *
> > > > For me function arguments are the values passed to a function call so
> > > > the const char* type is good because this is the only one that the 
> > > > plugin handles
> > > > (for now at least).
> > > OK, but this function prototype specified takes a const void *
> > > 
> > > +extern void * memcpy(void *, const void *, __kernel_size_t) 
> > > __nocapture(2);
> > What matters for the plugin is the type of the passed arguments (which can 
> > be const char*
> > in the current implementation), not that of the parameters.
> 
> And how does this work when the prototype requires the compiler to
> implicit cast to const void * before calling the function?


The plugin searches for the nocapture attribute that does not depend on the 
type.
If the function argument is not a string constant just a pointer then
the plugin walks the data flow (use-def chain) and tries to find a string 
constant.
If there is a cast to void * then the use-def chain will walk across it.

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-07-01 Thread Emese Revfy
On Wed, 29 Jun 2016 17:12:45 -0700
Joe Perches  wrote:

> On Wed, 2016-06-29 at 20:42 +0200, Emese Revfy wrote:
> > On Tue, 28 Jun 2016 14:00:57 -0700 Joe Perches  wrote:
> > > On Tue, 2016-06-28 at 22:40 +0200, Emese Revfy wrote:
> > > > On Tue, 28 Jun 2016 09:43:31 -0700 Joe Perches  wrote:
> > > > > On Tue, 2016-06-28 at 13:36 +0200, Emese Revfy wrote:
> > > > > > The nocapture gcc attribute can be on functions only.
> > > > > > The attribute takes one or more unsigned integer constants as 
> > > > > > parameters
> > > > > > that specify the function argument(s) of const char* type to 
> > > > > > initify.
> > > > > Perhaps this should be const *
> > > > For me function arguments are the values passed to a function call so
> > > > the const char* type is good because this is the only one that the 
> > > > plugin handles
> > > > (for now at least).
> > > OK, but this function prototype specified takes a const void *
> > > 
> > > +extern void * memcpy(void *, const void *, __kernel_size_t) 
> > > __nocapture(2);
> > What matters for the plugin is the type of the passed arguments (which can 
> > be const char*
> > in the current implementation), not that of the parameters.
> 
> And how does this work when the prototype requires the compiler to
> implicit cast to const void * before calling the function?


The plugin searches for the nocapture attribute that does not depend on the 
type.
If the function argument is not a string constant just a pointer then
the plugin walks the data flow (use-def chain) and tries to find a string 
constant.
If there is a cast to void * then the use-def chain will walk across it.

-- 
Emese


Re: [PATCH v1 1/2] Add the initify gcc plugin

2016-06-29 Thread Emese Revfy
On Tue, 28 Jun 2016 23:05:56 +0200
Rasmus Villemoes <li...@rasmusvillemoes.dk> wrote:

> On Tue, Jun 28 2016, Emese Revfy <re.em...@gmail.com> wrote:
> 
> > The kernel already has a mechanism to free up code and data memory that
> > is only used during kernel or module initialization.
> > This plugin will teach the compiler to find more such code and data that
> > can be freed after initialization.
> > It has two passes. The first one tries to find all functions that
> > can be become __init/__exit. The second one moves string constants
> > (local variables and function string arguments marked by
> > the nocapture attribute) only referenced in __init/__exit functions
> > to the __initconst/__exitconst sections.
> > It reduces memory usage. This plugin can be useful for embedded systems.
> 
> May I suggest, as a followup patch, a debug option/plugin parameter to
> put the strings in a section which will not be reaped after init, but
> just marked inaccessible, with graceful handling of bad accesses (print
> a big fat warning, make the page(s) readable, continue)?

I think even better would be to verify the whole init section.
Unfortunately, I won't implement it anytime soon because my project ends this 
week.

-- 
Emese


Re: [PATCH v1 1/2] Add the initify gcc plugin

2016-06-29 Thread Emese Revfy
On Tue, 28 Jun 2016 23:05:56 +0200
Rasmus Villemoes  wrote:

> On Tue, Jun 28 2016, Emese Revfy  wrote:
> 
> > The kernel already has a mechanism to free up code and data memory that
> > is only used during kernel or module initialization.
> > This plugin will teach the compiler to find more such code and data that
> > can be freed after initialization.
> > It has two passes. The first one tries to find all functions that
> > can be become __init/__exit. The second one moves string constants
> > (local variables and function string arguments marked by
> > the nocapture attribute) only referenced in __init/__exit functions
> > to the __initconst/__exitconst sections.
> > It reduces memory usage. This plugin can be useful for embedded systems.
> 
> May I suggest, as a followup patch, a debug option/plugin parameter to
> put the strings in a section which will not be reaped after init, but
> just marked inaccessible, with graceful handling of bad accesses (print
> a big fat warning, make the page(s) readable, continue)?

I think even better would be to verify the whole init section.
Unfortunately, I won't implement it anytime soon because my project ends this 
week.

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-29 Thread Emese Revfy
On Tue, 28 Jun 2016 14:00:57 -0700
Joe Perches <j...@perches.com> wrote:

> On Tue, 2016-06-28 at 22:40 +0200, Emese Revfy wrote:
> > On Tue, 28 Jun 2016 09:43:31 -0700 Joe Perches <j...@perches.com> wrote:
> > > On Tue, 2016-06-28 at 13:36 +0200, Emese Revfy wrote:
> > > > The nocapture gcc attribute can be on functions only.
> > > > The attribute takes one or more unsigned integer constants as parameters
> > > > that specify the function argument(s) of const char* type to initify.
> > > Perhaps this should be const *
> > For me function arguments are the values passed to a function call so
> > the const char* type is good because this is the only one that the plugin 
> > handles
> > (for now at least).
> 
> OK, but this function prototype specified takes a const void *
> 
> +extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);

What matters for the plugin is the type of the passed arguments (which can be 
const char*
in the current implementation), not that of the parameters.

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-29 Thread Emese Revfy
On Tue, 28 Jun 2016 14:00:57 -0700
Joe Perches  wrote:

> On Tue, 2016-06-28 at 22:40 +0200, Emese Revfy wrote:
> > On Tue, 28 Jun 2016 09:43:31 -0700 Joe Perches  wrote:
> > > On Tue, 2016-06-28 at 13:36 +0200, Emese Revfy wrote:
> > > > The nocapture gcc attribute can be on functions only.
> > > > The attribute takes one or more unsigned integer constants as parameters
> > > > that specify the function argument(s) of const char* type to initify.
> > > Perhaps this should be const *
> > For me function arguments are the values passed to a function call so
> > the const char* type is good because this is the only one that the plugin 
> > handles
> > (for now at least).
> 
> OK, but this function prototype specified takes a const void *
> 
> +extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);

What matters for the plugin is the type of the passed arguments (which can be 
const char*
in the current implementation), not that of the parameters.

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-29 Thread Emese Revfy
On Tue, 28 Jun 2016 22:50:55 +0200
Rasmus Villemoes <li...@rasmusvillemoes.dk> wrote:

> On Tue, Jun 28 2016, Emese Revfy <re.em...@gmail.com> wrote: 
> > diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
> > index 6f96247..4cdf266 100644
> > --- a/include/asm-generic/bug.h
> > +++ b/include/asm-generic/bug.h
> > @@ -62,13 +62,13 @@ struct bug_entry {
> >   * to provide better diagnostics.
> >   */
> >  #ifndef __WARN_TAINT
> > -extern __printf(3, 4)
> > +extern __printf(3, 4) __nocapture(1, 3, 4)
> >  void warn_slowpath_fmt(const char *file, const int line,
> >const char *fmt, ...);
> > -extern __printf(4, 5)
> > +extern __printf(4, 5) __nocapture(1, 4, 5)
> >  void warn_slowpath_fmt_taint(const char *file, const int line, unsigned 
> > taint,
> >  const char *fmt, ...);
> 
> The 3,4 and 4,5 parts seem redundant when __printf automatically supplies 
> those.

Thanks, I'll fix them in the next patch set.

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-29 Thread Emese Revfy
On Tue, 28 Jun 2016 22:50:55 +0200
Rasmus Villemoes  wrote:

> On Tue, Jun 28 2016, Emese Revfy  wrote: 
> > diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
> > index 6f96247..4cdf266 100644
> > --- a/include/asm-generic/bug.h
> > +++ b/include/asm-generic/bug.h
> > @@ -62,13 +62,13 @@ struct bug_entry {
> >   * to provide better diagnostics.
> >   */
> >  #ifndef __WARN_TAINT
> > -extern __printf(3, 4)
> > +extern __printf(3, 4) __nocapture(1, 3, 4)
> >  void warn_slowpath_fmt(const char *file, const int line,
> >const char *fmt, ...);
> > -extern __printf(4, 5)
> > +extern __printf(4, 5) __nocapture(1, 4, 5)
> >  void warn_slowpath_fmt_taint(const char *file, const int line, unsigned 
> > taint,
> >  const char *fmt, ...);
> 
> The 3,4 and 4,5 parts seem redundant when __printf automatically supplies 
> those.

Thanks, I'll fix them in the next patch set.

-- 
Emese


Re: [kernel-hardening] [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-29 Thread Emese Revfy
On Wed, 29 Jun 2016 18:52:27 +0100
Mark Rutland <mark.rutl...@arm.com> wrote:

> On Wed, Jun 29, 2016 at 09:21:37AM +0100, Mark Rutland wrote:
> > On Tue, Jun 28, 2016 at 01:46:04PM -0700, Kees Cook wrote:
> > > On Tue, Jun 28, 2016 at 9:14 AM, Emese Revfy <re.em...@gmail.com> wrote:
> > > > On Tue, 28 Jun 2016 13:57:49 +0100
> > > > Mark Rutland <mark.rutl...@arm.com> wrote:
> > > >
> > > >> On Tue, Jun 28, 2016 at 01:34:07PM +0200, Emese Revfy wrote:
> > > >> > This patch set is based on the "Add support for complex gcc plugins 
> > > >> > that
> > > >> > don't fit in a single file" patch set (git/kees/linux.git#kspp HEAD:
> > > >> > e5d4798b284cd192c8b).
> > > >>
> > > >> I was hoping to give this a spin on arm/arm64, but I couldn't find the
> > > >> prerequisite branch/tag/commit in that tree:
> > > >>
> > > >> https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?id=e5d4798b284cd192c8b
> > > >>
> > > >> Where should I be looking?
> > > >
> > > > Sorry, this commit was disappear. You can apply these patches to this 
> > > > tree:
> > > > https://github.com/ephox-gcc-plugins/gcc-plugins_linux-next.git 
> > > > (initify branch)
>
> g++: fatal error: no input files
> compilation terminated.
> make[1]: *** [scripts/gcc-plugins/initify_plugin.so] Error 4
> make: *** [gcc-plugins] Error 2

Hi,

There are some missing patches from Kees tree that's why I suggested my tree 
above.

-- 
Emese


Re: [kernel-hardening] [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-29 Thread Emese Revfy
On Wed, 29 Jun 2016 18:52:27 +0100
Mark Rutland  wrote:

> On Wed, Jun 29, 2016 at 09:21:37AM +0100, Mark Rutland wrote:
> > On Tue, Jun 28, 2016 at 01:46:04PM -0700, Kees Cook wrote:
> > > On Tue, Jun 28, 2016 at 9:14 AM, Emese Revfy  wrote:
> > > > On Tue, 28 Jun 2016 13:57:49 +0100
> > > > Mark Rutland  wrote:
> > > >
> > > >> On Tue, Jun 28, 2016 at 01:34:07PM +0200, Emese Revfy wrote:
> > > >> > This patch set is based on the "Add support for complex gcc plugins 
> > > >> > that
> > > >> > don't fit in a single file" patch set (git/kees/linux.git#kspp HEAD:
> > > >> > e5d4798b284cd192c8b).
> > > >>
> > > >> I was hoping to give this a spin on arm/arm64, but I couldn't find the
> > > >> prerequisite branch/tag/commit in that tree:
> > > >>
> > > >> https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?id=e5d4798b284cd192c8b
> > > >>
> > > >> Where should I be looking?
> > > >
> > > > Sorry, this commit was disappear. You can apply these patches to this 
> > > > tree:
> > > > https://github.com/ephox-gcc-plugins/gcc-plugins_linux-next.git 
> > > > (initify branch)
>
> g++: fatal error: no input files
> compilation terminated.
> make[1]: *** [scripts/gcc-plugins/initify_plugin.so] Error 4
> make: *** [gcc-plugins] Error 2

Hi,

There are some missing patches from Kees tree that's why I suggested my tree 
above.

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 09:43:31 -0700
Joe Perches <j...@perches.com> wrote:

> On Tue, 2016-06-28 at 13:36 +0200, Emese Revfy wrote:
> > The nocapture gcc attribute can be on functions only.
> > The attribute takes one or more unsigned integer constants as parameters
> > that specify the function argument(s) of const char* type to initify.
> 
> Perhaps this should be const *

For me function arguments are the values passed to a function call so
the const char* type is good because this is the only one that the plugin 
handles
(for now at least).

-- 
Emese


Re: [PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 09:43:31 -0700
Joe Perches  wrote:

> On Tue, 2016-06-28 at 13:36 +0200, Emese Revfy wrote:
> > The nocapture gcc attribute can be on functions only.
> > The attribute takes one or more unsigned integer constants as parameters
> > that specify the function argument(s) of const char* type to initify.
> 
> Perhaps this should be const *

For me function arguments are the values passed to a function call so
the const char* type is good because this is the only one that the plugin 
handles
(for now at least).

-- 
Emese


Re: [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 21:02:54 +0200
Rasmus Villemoes  wrote:

> It'll get placed in multiple sections by the compiler, and nothing bad
> happens. String deduplication is something the linker does to sections
> equipped with appropriate flags. So in this case that of course means

Note that I didn't add such flags to my sections yet, but I have it on my todo 
list.

> that the kernel image itself would be slightly bigger, while the used
> data after init would be the same. But I don't think there's a lot of
> these cases. (Also, "initfunc" would at least vanish).

-- 
Emese


Re: [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 21:02:54 +0200
Rasmus Villemoes  wrote:

> It'll get placed in multiple sections by the compiler, and nothing bad
> happens. String deduplication is something the linker does to sections
> equipped with appropriate flags. So in this case that of course means

Note that I didn't add such flags to my sections yet, but I have it on my todo 
list.

> that the kernel image itself would be slightly bigger, while the used
> data after init would be the same. But I don't think there's a lot of
> these cases. (Also, "initfunc" would at least vanish).

-- 
Emese


Re: [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 19:00:22 +0200
Mathias Krause  wrote:

> > section vanilla vanilla + initifychange
> > ---
> > .rodata 39059688 (0x25400e8)38527210 (0x24be0ea)-532478
> > .data   45744128 (0x2ba)45404160 (0x2b4d000)-339968
> > .init.data   1361144  (0x14c4f8) 1674200  (0x198bd8)+313056
> > .text   77615128 (0x4a05018)77576664 (0x49fb9d8) -38464
> > .init.text   1108455  (0x10e9e7) 1137618  (0x115bd2) +29163
> 
> You should probably provide numbers for .init.rodata.str, .exit.rodata.str
> and .exit.text as well. Otherwise this delta calculation suggests a rather
> gigantic image size reduction which is probably not the case ;)

init.rodata.str is an input section that merges into the INIT_DATA output 
section.
I didn't make statistics for exit* yet because I have a problem with that (I 
asked
for help in a previous e-mail).
 
> Also a comparison of the final kernel image size would be nice to see if

I no longer have the vmlinux images but I saved away the readelf outputs,
here's the PT_LOAD size data:

FileSiz (vanilla)   FileSiz (vanilla+initify)   change
---
00  119189504 (0x71ab000)   118657024 (0x7129000)   -532480
01   45838336 (0x2bb7000)45498368 (0x2b64000)   -339968
032830336  (0x2b3000) 3198976  (0x30d000)   +368640


00 .text .text.exit .text.startup .notes __ex_table .rodata __bug_table 
.pci_fixup
   .builtin_fw .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings 
__init_rodata __param __modver
01 .data .fini_array .vvar
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init .parainstructions 
.altinstructions
   .altinstr_replacement .iommu_table .apicdrivers .exit.text .exit.data 
.smp_locks .bss .brk

I think the smaller .data section is wrong, so I'll look into it.

-- 
Emese


Re: [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 19:00:22 +0200
Mathias Krause  wrote:

> > section vanilla vanilla + initifychange
> > ---
> > .rodata 39059688 (0x25400e8)38527210 (0x24be0ea)-532478
> > .data   45744128 (0x2ba)45404160 (0x2b4d000)-339968
> > .init.data   1361144  (0x14c4f8) 1674200  (0x198bd8)+313056
> > .text   77615128 (0x4a05018)77576664 (0x49fb9d8) -38464
> > .init.text   1108455  (0x10e9e7) 1137618  (0x115bd2) +29163
> 
> You should probably provide numbers for .init.rodata.str, .exit.rodata.str
> and .exit.text as well. Otherwise this delta calculation suggests a rather
> gigantic image size reduction which is probably not the case ;)

init.rodata.str is an input section that merges into the INIT_DATA output 
section.
I didn't make statistics for exit* yet because I have a problem with that (I 
asked
for help in a previous e-mail).
 
> Also a comparison of the final kernel image size would be nice to see if

I no longer have the vmlinux images but I saved away the readelf outputs,
here's the PT_LOAD size data:

FileSiz (vanilla)   FileSiz (vanilla+initify)   change
---
00  119189504 (0x71ab000)   118657024 (0x7129000)   -532480
01   45838336 (0x2bb7000)45498368 (0x2b64000)   -339968
032830336  (0x2b3000) 3198976  (0x30d000)   +368640


00 .text .text.exit .text.startup .notes __ex_table .rodata __bug_table 
.pci_fixup
   .builtin_fw .tracedata __ksymtab __ksymtab_gpl __ksymtab_strings 
__init_rodata __param __modver
01 .data .fini_array .vvar
03 .init.text .altinstr_aux .init.data .x86_cpu_dev.init .parainstructions 
.altinstructions
   .altinstr_replacement .iommu_table .apicdrivers .exit.text .exit.data 
.smp_locks .bss .brk

I think the smaller .data section is wrong, so I'll look into it.

-- 
Emese


Re: [kernel-hardening] [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 13:57:49 +0100
Mark Rutland <mark.rutl...@arm.com> wrote:

> On Tue, Jun 28, 2016 at 01:34:07PM +0200, Emese Revfy wrote:
> > This patch set is based on the "Add support for complex gcc plugins that
> > don't fit in a single file" patch set (git/kees/linux.git#kspp HEAD:
> > e5d4798b284cd192c8b).
> 
> I was hoping to give this a spin on arm/arm64, but I couldn't find the
> prerequisite branch/tag/commit in that tree:
> 
> https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?id=e5d4798b284cd192c8b
> 
> Where should I be looking?

Sorry, this commit was disappear. You can apply these patches to this tree:
https://github.com/ephox-gcc-plugins/gcc-plugins_linux-next.git (initify branch)

-- 
Emese


Re: [kernel-hardening] [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 13:57:49 +0100
Mark Rutland  wrote:

> On Tue, Jun 28, 2016 at 01:34:07PM +0200, Emese Revfy wrote:
> > This patch set is based on the "Add support for complex gcc plugins that
> > don't fit in a single file" patch set (git/kees/linux.git#kspp HEAD:
> > e5d4798b284cd192c8b).
> 
> I was hoping to give this a spin on arm/arm64, but I couldn't find the
> prerequisite branch/tag/commit in that tree:
> 
> https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?id=e5d4798b284cd192c8b
> 
> Where should I be looking?

Sorry, this commit was disappear. You can apply these patches to this tree:
https://github.com/ephox-gcc-plugins/gcc-plugins_linux-next.git (initify branch)

-- 
Emese


Re: [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 13:34:07 +0200
Emese Revfy <re.em...@gmail.com> wrote:

>  * automatically discover init/exit functions and apply the __init or
>__exit attributes on them

Hi,

I have a question about this. If a function is called by __init and __exit 
functions as well then
I move it to the __exit section. I think this is correct because such a 
function is available to
both __init and __exit functions as well at runtime.
However this generates a section mismatch (from scripts/mod/modpost.c) e.g.,

   WARNING: vmlinux.o(.init.text+0x196849): Section mismatch in reference from 
the function sctp_init() to the function .exit.text:sctp_v4_del_protocol()
   The function __init sctp_init() references
   a function __exit sctp_v4_del_protocol().
   This is often seen when error handling in the init function
   uses functionality in the exit path.
   The fix is often to remove the __exit annotation of
   sctp_v4_del_protocol() so it may be used outside an exit section.

This check was introduced by this commit (588ccd732ba2d):
kbuild: add verbose option to Section mismatch reporting in modpost

If this move doesn't cause a problem then I would like to keep it because there 
are a lot of functions that can become __exit and I would like to remove this 
warning.

Thanks
-- 
Emese


Re: [PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
On Tue, 28 Jun 2016 13:34:07 +0200
Emese Revfy  wrote:

>  * automatically discover init/exit functions and apply the __init or
>__exit attributes on them

Hi,

I have a question about this. If a function is called by __init and __exit 
functions as well then
I move it to the __exit section. I think this is correct because such a 
function is available to
both __init and __exit functions as well at runtime.
However this generates a section mismatch (from scripts/mod/modpost.c) e.g.,

   WARNING: vmlinux.o(.init.text+0x196849): Section mismatch in reference from 
the function sctp_init() to the function .exit.text:sctp_v4_del_protocol()
   The function __init sctp_init() references
   a function __exit sctp_v4_del_protocol().
   This is often seen when error handling in the init function
   uses functionality in the exit path.
   The fix is often to remove the __exit annotation of
   sctp_v4_del_protocol() so it may be used outside an exit section.

This check was introduced by this commit (588ccd732ba2d):
kbuild: add verbose option to Section mismatch reporting in modpost

If this move doesn't cause a problem then I would like to keep it because there 
are a lot of functions that can become __exit and I would like to remove this 
warning.

Thanks
-- 
Emese


[PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-28 Thread Emese Revfy
The nocapture gcc attribute can be on functions only.
The attribute takes one or more unsigned integer constants as parameters
that specify the function argument(s) of const char* type to initify.
If the marked argument is a vararg then the plugin initifies
all vararg arguments.

I couldn't test the arm, arm64 and powerpc architectures.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/arm/include/asm/string.h | 10 +++---
 arch/arm64/include/asm/string.h   | 23 ++--
 arch/powerpc/include/asm/string.h | 19 +-
 arch/x86/boot/string.h|  4 +--
 arch/x86/include/asm/string_32.h  | 21 +--
 arch/x86/include/asm/string_64.h  | 18 +-
 arch/x86/kernel/hpet.c|  2 +-
 include/asm-generic/bug.h |  6 ++--
 include/linux/compiler-gcc.h  | 10 --
 include/linux/compiler.h  |  4 +++
 include/linux/fs.h|  5 +--
 include/linux/printk.h|  2 +-
 include/linux/string.h| 73 ---
 13 files changed, 107 insertions(+), 90 deletions(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aa..3f68273 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -7,19 +7,19 @@
  */
 
 #define __HAVE_ARCH_STRRCHR
-extern char * strrchr(const char * s, int c);
+extern char * strrchr(const char * s, int c) __nocapture(1);
 
 #define __HAVE_ARCH_STRCHR
-extern char * strchr(const char * s, int c);
+extern char * strchr(const char * s, int c) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, __kernel_size_t);
+extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void * memmove(void *, const void *, __kernel_size_t);
+extern void * memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void * memchr(const void *, int, __kernel_size_t);
+extern void * memchr(const void *, int, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMSET
 extern void * memset(void *, int, __kernel_size_t);
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..0b3662b 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -17,40 +17,41 @@
 #define __ASM_STRING_H
 
 #define __HAVE_ARCH_STRRCHR
-extern char *strrchr(const char *, int c);
+extern char *strrchr(const char *, int c) __nocapture(1);
 
 #define __HAVE_ARCH_STRCHR
-extern char *strchr(const char *, int c);
+extern char *strchr(const char *, int c) __nocapture(1);
 
 #define __HAVE_ARCH_STRCMP
-extern int strcmp(const char *, const char *);
+extern int strcmp(const char *, const char *) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRLEN
 extern __kernel_size_t strlen(const char *);
 
 #define __HAVE_ARCH_STRNLEN
-extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-extern void *__memmove(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void *memchr(const void *, int, __kernel_size_t);
+extern void *memchr(const void *, int, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, __kernel_size_t);
 extern void *__memset(void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, size_t);
+extern int memcmp(const void *, const void *, size_t) __nocapture(1, 2);
 
 
 #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
diff --git a/arch/powerpc/include/asm/string.h 
b/arch/powerpc/include/asm/string.h
index e40010a..b29fc74 100644
--- a/arch/powerpc/include/asm/string.h
+++ b/arch/powerpc/include/asm/string.h
@@ -15,17 +15,18 @@
 #define __HAVE_ARCH_MEMCMP
 #define __HAVE_ARCH_MEMCHR
 
-extern char * strcpy(char *,const char *);
-extern char * strncpy(char *,const char *, __kernel_size_t);
+extern char * strcpy(char *,const char *) __nocapture(2);
+extern char * strncpy(char *,const char *, __kernel_size_t) __nocapture(2);
 extern __kernel_size_t strlen(const char *);
-extern int strcmp(const char *,const char *);
-exte

[PATCH v1 1/2] Add the initify gcc plugin

2016-06-28 Thread Emese Revfy
The kernel already has a mechanism to free up code and data memory that
is only used during kernel or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization.
It has two passes. The first one tries to find all functions that
can be become __init/__exit. The second one moves string constants
(local variables and function string arguments marked by
the nocapture attribute) only referenced in __init/__exit functions
to the __initconst/__exitconst sections.
It reduces memory usage. This plugin can be useful for embedded systems.

The instrumentation pass of the latent_entropy plugin must run after
the initify plugin to increase coverage.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/Kconfig |   23 +
 include/asm-generic/vmlinux.lds.h|2 +
 scripts/Makefile.gcc-plugins |4 +
 scripts/gcc-plugins/initify_plugin.c | 1147 ++
 4 files changed, 1176 insertions(+)
 create mode 100644 scripts/gcc-plugins/initify_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 9f8c6ee..35b01a4 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -417,6 +417,29 @@ config GCC_PLUGIN_LATENT_ENTROPY
   * https://grsecurity.net/
   * https://pax.grsecurity.net/
 
+config GCC_PLUGIN_INITIFY
+   bool "Free more kernel memory after init"
+   depends on GCC_PLUGINS
+   help
+ The kernel has a mechanism to free up code and data memory that is
+ only used during kernel or module initialization.  Enabling this
+ feature will teach the compiler to find more such code and data
+ that can be freed after initialization.
+
+ This plugin is the part of grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
+config GCC_PLUGIN_INITIFY_VERBOSE
+   bool "Verbose"
+   depends on GCC_PLUGIN_INITIFY
+   help
+ Print all initified strings and all functions which should be
+ __init/__exit.
+ Note that the candidates identified for __init/__exit markings
+ depend on the current kernel configuration and thus should be verified
+ manually before the source code is patched.
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 6a67ab9..651980b 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -523,6 +523,7 @@
MEM_DISCARD(init.data)  \
KERNEL_CTORS()  \
MCOUNT_REC()\
+   *(.init.rodata.str) \
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS()\
@@ -547,6 +548,7 @@
 #define EXIT_DATA  \
*(.exit.data)   \
MEM_DISCARD(exit.data)  \
+   *(.exit.rodata.str) \
MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT  \
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 1f922df..0ce8392 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -12,6 +12,10 @@ ifdef CONFIG_GCC_PLUGINS
 DISABLE_LATENT_ENTROPY_PLUGIN  += 
-fplugin-arg-latent_entropy_plugin-disable
   endif
 
+  gcc-plugin-$(CONFIG_GCC_PLUGIN_INITIFY)  += initify_plugin.so
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY)   += -DINITIFY_PLUGIN 
-fplugin-arg-initify_plugin-search_init_exit_functions
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY_VERBOSE)+= 
-fplugin-arg-initify_plugin-verbose
+
   ifdef CONFIG_GCC_PLUGIN_SANCOV
 ifeq ($(CFLAGS_KCOV),)
   # It is needed because of the gcc-plugin.sh and gcc version checks.
diff --git a/scripts/gcc-plugins/initify_plugin.c 
b/scripts/gcc-plugins/initify_plugin.c
new file mode 100644
index 000..d5dfce5
--- /dev/null
+++ b/scripts/gcc-plugins/initify_plugin.c
@@ -0,0 +1,1147 @@
+/*
+ * Copyright 2015-2016 by Emese Revfy <re.em...@gmail.com>
+ * Licensed under the GPL v2
+ *
+ * Homepage:
+ * https://github.com/ephox-gcc-plugins/initify
+ *
+ * This plugin has two passes. The first one tries to find all functions that
+ * can be become __init/__exit. The second one moves string constants
+ * (local variables and function string arguments marked by
+ * the nocapture attribute) only referenced in __init/__exit functions
+ * to __initconst

[PATCH v1 2/2] Mark functions with the __nocapture attribute

2016-06-28 Thread Emese Revfy
The nocapture gcc attribute can be on functions only.
The attribute takes one or more unsigned integer constants as parameters
that specify the function argument(s) of const char* type to initify.
If the marked argument is a vararg then the plugin initifies
all vararg arguments.

I couldn't test the arm, arm64 and powerpc architectures.

Signed-off-by: Emese Revfy 
---
 arch/arm/include/asm/string.h | 10 +++---
 arch/arm64/include/asm/string.h   | 23 ++--
 arch/powerpc/include/asm/string.h | 19 +-
 arch/x86/boot/string.h|  4 +--
 arch/x86/include/asm/string_32.h  | 21 +--
 arch/x86/include/asm/string_64.h  | 18 +-
 arch/x86/kernel/hpet.c|  2 +-
 include/asm-generic/bug.h |  6 ++--
 include/linux/compiler-gcc.h  | 10 --
 include/linux/compiler.h  |  4 +++
 include/linux/fs.h|  5 +--
 include/linux/printk.h|  2 +-
 include/linux/string.h| 73 ---
 13 files changed, 107 insertions(+), 90 deletions(-)

diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aa..3f68273 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -7,19 +7,19 @@
  */
 
 #define __HAVE_ARCH_STRRCHR
-extern char * strrchr(const char * s, int c);
+extern char * strrchr(const char * s, int c) __nocapture(1);
 
 #define __HAVE_ARCH_STRCHR
-extern char * strchr(const char * s, int c);
+extern char * strchr(const char * s, int c) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *, const void *, __kernel_size_t);
+extern void * memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void * memmove(void *, const void *, __kernel_size_t);
+extern void * memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void * memchr(const void *, int, __kernel_size_t);
+extern void * memchr(const void *, int, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMSET
 extern void * memset(void *, int, __kernel_size_t);
diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h
index 2eb714c..0b3662b 100644
--- a/arch/arm64/include/asm/string.h
+++ b/arch/arm64/include/asm/string.h
@@ -17,40 +17,41 @@
 #define __ASM_STRING_H
 
 #define __HAVE_ARCH_STRRCHR
-extern char *strrchr(const char *, int c);
+extern char *strrchr(const char *, int c) __nocapture(1);
 
 #define __HAVE_ARCH_STRCHR
-extern char *strchr(const char *, int c);
+extern char *strchr(const char *, int c) __nocapture(1);
 
 #define __HAVE_ARCH_STRCMP
-extern int strcmp(const char *, const char *);
+extern int strcmp(const char *, const char *) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
+extern int
+strncmp(const char *, const char *, __kernel_size_t) __nocapture(1, 2);
 
 #define __HAVE_ARCH_STRLEN
 extern __kernel_size_t strlen(const char *);
 
 #define __HAVE_ARCH_STRNLEN
-extern __kernel_size_t strnlen(const char *, __kernel_size_t);
+extern __kernel_size_t strnlen(const char *, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memcpy(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-extern void *__memmove(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t) __nocapture(2);
+extern void *__memmove(void *, const void *, __kernel_size_t) __nocapture(2);
 
 #define __HAVE_ARCH_MEMCHR
-extern void *memchr(const void *, int, __kernel_size_t);
+extern void *memchr(const void *, int, __kernel_size_t) __nocapture(1);
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, __kernel_size_t);
 extern void *__memset(void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, size_t);
+extern int memcmp(const void *, const void *, size_t) __nocapture(1, 2);
 
 
 #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
diff --git a/arch/powerpc/include/asm/string.h 
b/arch/powerpc/include/asm/string.h
index e40010a..b29fc74 100644
--- a/arch/powerpc/include/asm/string.h
+++ b/arch/powerpc/include/asm/string.h
@@ -15,17 +15,18 @@
 #define __HAVE_ARCH_MEMCMP
 #define __HAVE_ARCH_MEMCHR
 
-extern char * strcpy(char *,const char *);
-extern char * strncpy(char *,const char *, __kernel_size_t);
+extern char * strcpy(char *,const char *) __nocapture(2);
+extern char * strncpy(char *,const char *, __kernel_size_t) __nocapture(2);
 extern __kernel_size_t strlen(const char *);
-extern int strcmp(const char *,const char *);
-extern int strncmp(const char 

[PATCH v1 1/2] Add the initify gcc plugin

2016-06-28 Thread Emese Revfy
The kernel already has a mechanism to free up code and data memory that
is only used during kernel or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization.
It has two passes. The first one tries to find all functions that
can be become __init/__exit. The second one moves string constants
(local variables and function string arguments marked by
the nocapture attribute) only referenced in __init/__exit functions
to the __initconst/__exitconst sections.
It reduces memory usage. This plugin can be useful for embedded systems.

The instrumentation pass of the latent_entropy plugin must run after
the initify plugin to increase coverage.

Signed-off-by: Emese Revfy 
---
 arch/Kconfig |   23 +
 include/asm-generic/vmlinux.lds.h|2 +
 scripts/Makefile.gcc-plugins |4 +
 scripts/gcc-plugins/initify_plugin.c | 1147 ++
 4 files changed, 1176 insertions(+)
 create mode 100644 scripts/gcc-plugins/initify_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 9f8c6ee..35b01a4 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -417,6 +417,29 @@ config GCC_PLUGIN_LATENT_ENTROPY
   * https://grsecurity.net/
   * https://pax.grsecurity.net/
 
+config GCC_PLUGIN_INITIFY
+   bool "Free more kernel memory after init"
+   depends on GCC_PLUGINS
+   help
+ The kernel has a mechanism to free up code and data memory that is
+ only used during kernel or module initialization.  Enabling this
+ feature will teach the compiler to find more such code and data
+ that can be freed after initialization.
+
+ This plugin is the part of grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
+config GCC_PLUGIN_INITIFY_VERBOSE
+   bool "Verbose"
+   depends on GCC_PLUGIN_INITIFY
+   help
+ Print all initified strings and all functions which should be
+ __init/__exit.
+ Note that the candidates identified for __init/__exit markings
+ depend on the current kernel configuration and thus should be verified
+ manually before the source code is patched.
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 6a67ab9..651980b 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -523,6 +523,7 @@
MEM_DISCARD(init.data)  \
KERNEL_CTORS()  \
MCOUNT_REC()\
+   *(.init.rodata.str) \
*(.init.rodata) \
FTRACE_EVENTS() \
TRACE_SYSCALLS()\
@@ -547,6 +548,7 @@
 #define EXIT_DATA  \
*(.exit.data)   \
MEM_DISCARD(exit.data)  \
+   *(.exit.rodata.str) \
MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT  \
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 1f922df..0ce8392 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -12,6 +12,10 @@ ifdef CONFIG_GCC_PLUGINS
 DISABLE_LATENT_ENTROPY_PLUGIN  += 
-fplugin-arg-latent_entropy_plugin-disable
   endif
 
+  gcc-plugin-$(CONFIG_GCC_PLUGIN_INITIFY)  += initify_plugin.so
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY)   += -DINITIFY_PLUGIN 
-fplugin-arg-initify_plugin-search_init_exit_functions
+  gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_INITIFY_VERBOSE)+= 
-fplugin-arg-initify_plugin-verbose
+
   ifdef CONFIG_GCC_PLUGIN_SANCOV
 ifeq ($(CFLAGS_KCOV),)
   # It is needed because of the gcc-plugin.sh and gcc version checks.
diff --git a/scripts/gcc-plugins/initify_plugin.c 
b/scripts/gcc-plugins/initify_plugin.c
new file mode 100644
index 000..d5dfce5
--- /dev/null
+++ b/scripts/gcc-plugins/initify_plugin.c
@@ -0,0 +1,1147 @@
+/*
+ * Copyright 2015-2016 by Emese Revfy 
+ * Licensed under the GPL v2
+ *
+ * Homepage:
+ * https://github.com/ephox-gcc-plugins/initify
+ *
+ * This plugin has two passes. The first one tries to find all functions that
+ * can be become __init/__exit. The second one moves string constants
+ * (local variables and function string arguments marked by
+ * the nocapture attribute) only referenced in __init/__exit functions
+ * to __initconst/__exitconst sections.
+ * Based on an idea

[PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
I would like to introduce the initify gcc plugin. The kernel already has
a mechanism to free up code and data memory that is only used during kernel
or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization. It reduces memory usage.
The initify gcc plugin can be useful for embedded systems.

It is a CII project supported by the Linux Foundation.

This plugin is the part of grsecurity/PaX.

The plugin supports all gcc versions from 4.5 to 6.0.

I made some changes on top of the PaX version (since March 6.). These are
the important ones:
 * move all local strings to init.rodata.str and exit.rodata.str
   (not just __func__)
 * report all initified strings and functions
   (GCC_PLUGIN_INITIFY_VERBOSE config option)
 * automatically discover init/exit functions and apply the __init or
   __exit attributes on them

You can find more about the changes here:
https://github.com/ephox-gcc-plugins/initify

This patch set is based on the "Add support for complex gcc plugins that
don't fit in a single file" patch set (git/kees/linux.git#kspp HEAD:
e5d4798b284cd192c8b).

Some statistics about the plugin:

On allyes config (amd64, gcc-6):
* 7731 initified strings
*  231 initified functions

On allmod config (i386, gcc-6):
* 8846 initified strings
*  252 initified functions

On allyes config (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 39059688 (0x25400e8)38527210 (0x24be0ea)-532478
.data   45744128 (0x2ba)45404160 (0x2b4d000)-339968
.init.data   1361144  (0x14c4f8) 1674200  (0x198bd8)+313056
.text   77615128 (0x4a05018)77576664 (0x49fb9d8) -38464
.init.text   1108455  (0x10e9e7) 1137618  (0x115bd2) +29163


Emese Revfy (2):
 Add the initify gcc plugin
 Mark functions with the __nocapture attribute

---
 arch/Kconfig |   23 +
 arch/arm/include/asm/string.h|   10 +-
 arch/arm64/include/asm/string.h  |   23 +-
 arch/powerpc/include/asm/string.h|   19 +-
 arch/x86/boot/string.h   |4 +-
 arch/x86/include/asm/string_32.h |   21 +-
 arch/x86/include/asm/string_64.h |   18 +-
 arch/x86/kernel/hpet.c   |2 +-
 include/asm-generic/bug.h|6 +-
 include/asm-generic/vmlinux.lds.h|2 +
 include/linux/compiler-gcc.h |   10 +-
 include/linux/compiler.h |4 +
 include/linux/fs.h   |5 +-
 include/linux/printk.h   |2 +-
 include/linux/string.h   |   73 +--
 scripts/Makefile.gcc-plugins |4 +
 scripts/gcc-plugins/initify_plugin.c | 1147 ++
 17 files changed, 1283 insertions(+), 90 deletions(-)


[PATCH v1 0/2] Introduce the initify gcc plugin

2016-06-28 Thread Emese Revfy
I would like to introduce the initify gcc plugin. The kernel already has
a mechanism to free up code and data memory that is only used during kernel
or module initialization.
This plugin will teach the compiler to find more such code and data that
can be freed after initialization. It reduces memory usage.
The initify gcc plugin can be useful for embedded systems.

It is a CII project supported by the Linux Foundation.

This plugin is the part of grsecurity/PaX.

The plugin supports all gcc versions from 4.5 to 6.0.

I made some changes on top of the PaX version (since March 6.). These are
the important ones:
 * move all local strings to init.rodata.str and exit.rodata.str
   (not just __func__)
 * report all initified strings and functions
   (GCC_PLUGIN_INITIFY_VERBOSE config option)
 * automatically discover init/exit functions and apply the __init or
   __exit attributes on them

You can find more about the changes here:
https://github.com/ephox-gcc-plugins/initify

This patch set is based on the "Add support for complex gcc plugins that
don't fit in a single file" patch set (git/kees/linux.git#kspp HEAD:
e5d4798b284cd192c8b).

Some statistics about the plugin:

On allyes config (amd64, gcc-6):
* 7731 initified strings
*  231 initified functions

On allmod config (i386, gcc-6):
* 8846 initified strings
*  252 initified functions

On allyes config (amd64, gcc-6):

section vanilla vanilla + initifychange
---
.rodata 39059688 (0x25400e8)38527210 (0x24be0ea)-532478
.data   45744128 (0x2ba)45404160 (0x2b4d000)-339968
.init.data   1361144  (0x14c4f8) 1674200  (0x198bd8)+313056
.text   77615128 (0x4a05018)77576664 (0x49fb9d8) -38464
.init.text   1108455  (0x10e9e7) 1137618  (0x115bd2) +29163


Emese Revfy (2):
 Add the initify gcc plugin
 Mark functions with the __nocapture attribute

---
 arch/Kconfig |   23 +
 arch/arm/include/asm/string.h|   10 +-
 arch/arm64/include/asm/string.h  |   23 +-
 arch/powerpc/include/asm/string.h|   19 +-
 arch/x86/boot/string.h   |4 +-
 arch/x86/include/asm/string_32.h |   21 +-
 arch/x86/include/asm/string_64.h |   18 +-
 arch/x86/kernel/hpet.c   |2 +-
 include/asm-generic/bug.h|6 +-
 include/asm-generic/vmlinux.lds.h|2 +
 include/linux/compiler-gcc.h |   10 +-
 include/linux/compiler.h |4 +
 include/linux/fs.h   |5 +-
 include/linux/printk.h   |2 +-
 include/linux/string.h   |   73 +--
 scripts/Makefile.gcc-plugins |4 +
 scripts/gcc-plugins/initify_plugin.c | 1147 ++
 17 files changed, 1283 insertions(+), 90 deletions(-)


[PATCH v4 4/4] Add the extra_latent_entropy kernel parameter

2016-06-20 Thread Emese Revfy
When 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.

Based on work created by the PaX Team.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 Documentation/kernel-parameters.txt |  5 +
 arch/Kconfig|  5 +
 mm/page_alloc.c | 26 ++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 82b42c9..d870702 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2862,6 +2862,11 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
the specified number of seconds.  This is to be used if
your oopses keep scrolling off the screen.
 
+   extra_latent_entropy
+   Enable a very simple form of latent entropy extraction
+   from the first 4GB of memory as the bootmem allocator
+   passes the memory pages to the buddy allocator.
+
pcbit=  [HW,ISDN]
 
pcd.[PARIDE]
diff --git a/arch/Kconfig b/arch/Kconfig
index 4b7cc2f..3374d50 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -404,6 +404,11 @@ config GCC_PLUGIN_LATENT_ENTROPY
  is some slowdown of the boot process (about 0.5%) and fork and
  irq processing.
 
+ When 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.
+
  Note that entropy extracted this way is not cryptographically
  secure!
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ffc4f4a..0a40c12 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -63,6 +63,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -1234,6 +1235,15 @@ static void __free_pages_ok(struct page *page, unsigned 
int order)
local_irq_restore(flags);
 }
 
+bool __meminitdata extra_latent_entropy;
+
+static int __init setup_extra_latent_entropy(char *str)
+{
+   extra_latent_entropy = true;
+   return 0;
+}
+early_param("extra_latent_entropy", setup_extra_latent_entropy);
+
 #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
 volatile u64 latent_entropy __latent_entropy;
 EXPORT_SYMBOL(latent_entropy);
@@ -1254,6 +1264,22 @@ static void __init __free_pages_boot_core(struct page 
*page, unsigned int order)
__ClearPageReserved(p);
set_page_count(p, 0);
 
+   if (extra_latent_entropy && !PageHighMem(page) &&
+   page_to_pfn(page) < 0x10) {
+   u64 hash = 0;
+   size_t index, end = PAGE_SIZE * nr_pages / sizeof(hash);
+   const u64 *data = lowmem_page_address(page);
+
+   for (index = 0; index < end; index++)
+   hash ^= hash + data[index];
+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+   latent_entropy ^= hash;
+   add_device_randomness((const void *)_entropy, 
sizeof(latent_entropy));
+#else
+   add_device_randomness((const void *), sizeof(hash));
+#endif
+   }
+
page_zone(page)->managed_pages += nr_pages;
set_page_refcounted(page);
__free_pages(page, order);
-- 
2.8.1



[PATCH v4 4/4] Add the extra_latent_entropy kernel parameter

2016-06-20 Thread Emese Revfy
When 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.

Based on work created by the PaX Team.

Signed-off-by: Emese Revfy 
---
 Documentation/kernel-parameters.txt |  5 +
 arch/Kconfig|  5 +
 mm/page_alloc.c | 26 ++
 3 files changed, 36 insertions(+)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 82b42c9..d870702 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2862,6 +2862,11 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
the specified number of seconds.  This is to be used if
your oopses keep scrolling off the screen.
 
+   extra_latent_entropy
+   Enable a very simple form of latent entropy extraction
+   from the first 4GB of memory as the bootmem allocator
+   passes the memory pages to the buddy allocator.
+
pcbit=  [HW,ISDN]
 
pcd.[PARIDE]
diff --git a/arch/Kconfig b/arch/Kconfig
index 4b7cc2f..3374d50 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -404,6 +404,11 @@ config GCC_PLUGIN_LATENT_ENTROPY
  is some slowdown of the boot process (about 0.5%) and fork and
  irq processing.
 
+ When 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.
+
  Note that entropy extracted this way is not cryptographically
  secure!
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ffc4f4a..0a40c12 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -63,6 +63,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -1234,6 +1235,15 @@ static void __free_pages_ok(struct page *page, unsigned 
int order)
local_irq_restore(flags);
 }
 
+bool __meminitdata extra_latent_entropy;
+
+static int __init setup_extra_latent_entropy(char *str)
+{
+   extra_latent_entropy = true;
+   return 0;
+}
+early_param("extra_latent_entropy", setup_extra_latent_entropy);
+
 #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
 volatile u64 latent_entropy __latent_entropy;
 EXPORT_SYMBOL(latent_entropy);
@@ -1254,6 +1264,22 @@ static void __init __free_pages_boot_core(struct page 
*page, unsigned int order)
__ClearPageReserved(p);
set_page_count(p, 0);
 
+   if (extra_latent_entropy && !PageHighMem(page) &&
+   page_to_pfn(page) < 0x10) {
+   u64 hash = 0;
+   size_t index, end = PAGE_SIZE * nr_pages / sizeof(hash);
+   const u64 *data = lowmem_page_address(page);
+
+   for (index = 0; index < end; index++)
+   hash ^= hash + data[index];
+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+   latent_entropy ^= hash;
+   add_device_randomness((const void *)_entropy, 
sizeof(latent_entropy));
+#else
+   add_device_randomness((const void *), sizeof(hash));
+#endif
+   }
+
page_zone(page)->managed_pages += nr_pages;
set_page_refcounted(page);
__free_pages(page, order);
-- 
2.8.1



[PATCH v4 3/4] Mark functions with the latent_entropy attribute

2016-06-20 Thread Emese Revfy
The latent_entropy gcc attribute can be only on functions and variables.
If it is on a function then the plugin will instrument it. If the attribute
is on a variable then the plugin will initialize it with a random value.
The variable must be an integer, an integer array type or a structure
with integer fields.

These functions have been selected because they are init functions or
are called at random times or they have variable loops.

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 block/blk-softirq.c  | 2 +-
 drivers/char/random.c| 6 +++---
 fs/namespace.c   | 1 +
 include/linux/compiler-gcc.h | 7 +++
 include/linux/compiler.h | 4 
 include/linux/fdtable.h  | 2 +-
 include/linux/genhd.h| 2 +-
 include/linux/init.h | 5 +++--
 include/linux/random.h   | 4 ++--
 kernel/fork.c| 6 --
 kernel/rcu/tiny.c| 2 +-
 kernel/rcu/tree.c| 2 +-
 kernel/sched/fair.c  | 2 +-
 kernel/softirq.c | 4 ++--
 kernel/time/timer.c  | 2 +-
 lib/irq_poll.c   | 2 +-
 lib/random32.c   | 2 +-
 mm/page_alloc.c  | 2 +-
 net/core/dev.c   | 4 ++--
 19 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index 53b1737..489eab8 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -18,7 +18,7 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done);
  * Softirq action handler - move entries to local list and loop over them
  * while passing them to the queue registered handler.
  */
-static void blk_done_softirq(struct softirq_action *h)
+static __latent_entropy void blk_done_softirq(struct softirq_action *h)
 {
struct list_head *cpu_list, local_list;
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0158d3b..6cca3ed 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -443,9 +443,9 @@ struct entropy_store {
 };
 
 static void push_to_pool(struct work_struct *work);
-static __u32 input_pool_data[INPUT_POOL_WORDS];
-static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
-static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy;
+static __u32 blocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy;
+static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy;
 
 static struct entropy_store input_pool = {
.poolinfo = _table[0],
diff --git a/fs/namespace.c b/fs/namespace.c
index 4fb1691..0951eca 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2778,6 +2778,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct 
user_namespace *user_ns)
return new_ns;
 }
 
+__latent_entropy
 struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace 
*ns,
struct user_namespace *user_ns, struct fs_struct *new_fs)
 {
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index e294939..0ef8329 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -188,6 +188,13 @@
 #endif /* GCC_VERSION >= 40300 */
 
 #if GCC_VERSION >= 40500
+
+#ifndef __CHECKER__
+#ifdef LATENT_ENTROPY_PLUGIN
+#define __latent_entropy __attribute__((latent_entropy))
+#endif
+#endif
+
 /*
  * 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 793c082..c65327b 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -425,6 +425,10 @@ static __always_inline void __write_once_size(volatile 
void *p, void *res, int s
 # define __attribute_const__   /* unimplemented */
 #endif
 
+#ifndef __latent_entropy
+# define __latent_entropy
+#endif
+
 /*
  * Tell gcc if a function is cold. The compiler will assume any path
  * directly leading to the call is unlikely.
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 5295535..9852c7e 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -105,7 +105,7 @@ struct files_struct *get_files_struct(struct task_struct *);
 void put_files_struct(struct files_struct *fs);
 void reset_files_struct(struct files_struct *);
 int unshare_files(struct files_struct **);
-struct files_struct *dup_fd(struct files_struct *, int *);
+struct files_struct *dup_fd(struct files_struct *, int *) __latent_entropy;
 void do_close_on_exec(struct files_struct *);
 int iterate_fd(struct files_struct *, unsigned,
int (*)(const void *, struct file *, unsigned),
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 359a8e4..8736c1f 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -433,7 +433,7 @@ extern void disk_flush_events(struct gendisk *disk, 
unsigned int mask);
 extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask);
 
 /* drivers/char/random.c */
-extern void add_dis

[PATCH v4 3/4] Mark functions with the latent_entropy attribute

2016-06-20 Thread Emese Revfy
The latent_entropy gcc attribute can be only on functions and variables.
If it is on a function then the plugin will instrument it. If the attribute
is on a variable then the plugin will initialize it with a random value.
The variable must be an integer, an integer array type or a structure
with integer fields.

These functions have been selected because they are init functions or
are called at random times or they have variable loops.

Signed-off-by: Emese Revfy 
---
 block/blk-softirq.c  | 2 +-
 drivers/char/random.c| 6 +++---
 fs/namespace.c   | 1 +
 include/linux/compiler-gcc.h | 7 +++
 include/linux/compiler.h | 4 
 include/linux/fdtable.h  | 2 +-
 include/linux/genhd.h| 2 +-
 include/linux/init.h | 5 +++--
 include/linux/random.h   | 4 ++--
 kernel/fork.c| 6 --
 kernel/rcu/tiny.c| 2 +-
 kernel/rcu/tree.c| 2 +-
 kernel/sched/fair.c  | 2 +-
 kernel/softirq.c | 4 ++--
 kernel/time/timer.c  | 2 +-
 lib/irq_poll.c   | 2 +-
 lib/random32.c   | 2 +-
 mm/page_alloc.c  | 2 +-
 net/core/dev.c   | 4 ++--
 19 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index 53b1737..489eab8 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -18,7 +18,7 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done);
  * Softirq action handler - move entries to local list and loop over them
  * while passing them to the queue registered handler.
  */
-static void blk_done_softirq(struct softirq_action *h)
+static __latent_entropy void blk_done_softirq(struct softirq_action *h)
 {
struct list_head *cpu_list, local_list;
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0158d3b..6cca3ed 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -443,9 +443,9 @@ struct entropy_store {
 };
 
 static void push_to_pool(struct work_struct *work);
-static __u32 input_pool_data[INPUT_POOL_WORDS];
-static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
-static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy;
+static __u32 blocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy;
+static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy;
 
 static struct entropy_store input_pool = {
.poolinfo = _table[0],
diff --git a/fs/namespace.c b/fs/namespace.c
index 4fb1691..0951eca 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2778,6 +2778,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct 
user_namespace *user_ns)
return new_ns;
 }
 
+__latent_entropy
 struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace 
*ns,
struct user_namespace *user_ns, struct fs_struct *new_fs)
 {
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index e294939..0ef8329 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -188,6 +188,13 @@
 #endif /* GCC_VERSION >= 40300 */
 
 #if GCC_VERSION >= 40500
+
+#ifndef __CHECKER__
+#ifdef LATENT_ENTROPY_PLUGIN
+#define __latent_entropy __attribute__((latent_entropy))
+#endif
+#endif
+
 /*
  * 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 793c082..c65327b 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -425,6 +425,10 @@ static __always_inline void __write_once_size(volatile 
void *p, void *res, int s
 # define __attribute_const__   /* unimplemented */
 #endif
 
+#ifndef __latent_entropy
+# define __latent_entropy
+#endif
+
 /*
  * Tell gcc if a function is cold. The compiler will assume any path
  * directly leading to the call is unlikely.
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 5295535..9852c7e 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -105,7 +105,7 @@ struct files_struct *get_files_struct(struct task_struct *);
 void put_files_struct(struct files_struct *fs);
 void reset_files_struct(struct files_struct *);
 int unshare_files(struct files_struct **);
-struct files_struct *dup_fd(struct files_struct *, int *);
+struct files_struct *dup_fd(struct files_struct *, int *) __latent_entropy;
 void do_close_on_exec(struct files_struct *);
 int iterate_fd(struct files_struct *, unsigned,
int (*)(const void *, struct file *, unsigned),
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 359a8e4..8736c1f 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -433,7 +433,7 @@ extern void disk_flush_events(struct gendisk *disk, 
unsigned int mask);
 extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask);
 
 /* drivers/char/random.c */
-extern void add_disk_randomness(struct gendisk

[PATCH v4 2/4] Add the latent_entropy gcc plugin

2016-06-20 Thread Emese Revfy
This plugin mitigates the problem of the kernel having too little entropy
during and after boot for generating crypto keys.

It creates a local variable in every marked function. The value of
this variable is modified by randomly chosen operations (add, xor and rol)
and random values (gcc generates them at compile time and the stack pointer
at runtime).
It depends on the control flow (e.g., loops, conditions).

Before the function returns the plugin writes this local variable
into the latent_entropy global variable. The value of this global variable
is added to the kernel entropy pool in do_one_initcall() and _do_fork().

Signed-off-by: Emese Revfy <re.em...@gmail.com>
---
 arch/Kconfig|  18 +
 arch/powerpc/kernel/Makefile|   4 +
 include/linux/random.h  |  10 +
 init/main.c |   1 +
 kernel/fork.c   |   1 +
 mm/page_alloc.c |   5 +
 scripts/Makefile.gcc-plugins|   8 +-
 scripts/gcc-plugins/Makefile|   1 +
 scripts/gcc-plugins/latent_entropy_plugin.c | 639 
 9 files changed, 686 insertions(+), 1 deletion(-)
 create mode 100644 scripts/gcc-plugins/latent_entropy_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 05f1e95..4b7cc2f 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -393,6 +393,24 @@ config GCC_PLUGIN_SANCOV
  gcc-4.5 on). It is based on the commit "Add fuzzing coverage support"
  by Dmitry Vyukov <dvyu...@google.com>.
 
+config GCC_PLUGIN_LATENT_ENTROPY
+   bool "Generate some entropy during boot and runtime"
+   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 (about 0.5%) and fork and
+ irq processing.
+
+ Note that entropy extracted this way is not cryptographically
+ secure!
+
+ This plugin was ported from grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 2da380f..01935b8 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -15,6 +15,10 @@ CFLAGS_btext.o   += -fPIC
 endif
 
 ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 # Do not trace early boot code
 CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
diff --git a/include/linux/random.h b/include/linux/random.h
index e47e533..752e7df 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -18,6 +18,16 @@ struct random_ready_callback {
 };
 
 extern void add_device_randomness(const void *, unsigned int);
+
+#if defined(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) && !defined(__CHECKER__)
+static inline void add_latent_entropy(void)
+{
+   add_device_randomness((const void *)_entropy, 
sizeof(latent_entropy));
+}
+#else
+static inline void add_latent_entropy(void) {}
+#endif
+
 extern void add_input_randomness(unsigned int type, unsigned int code,
 unsigned int value);
 extern void add_interrupt_randomness(int irq, int irq_flags);
diff --git a/init/main.c b/init/main.c
index 4c17fda..07e4174 100644
--- a/init/main.c
+++ b/init/main.c
@@ -781,6 +781,7 @@ int __init_or_module do_one_initcall(initcall_t fn)
}
WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf);
 
+   add_latent_entropy();
return ret;
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 5c2c355..fd1b3c2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1761,6 +1761,7 @@ long _do_fork(unsigned long clone_flags,
 
p = copy_process(clone_flags, stack_start, stack_size,
 child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
+   add_latent_entropy();
/*
 * Do this prior waking up the new thread - the thread pointer
 * might get invalid after that point, if the thread exits quickly.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f8f3bfc..d10324e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1234,6 +1234,11 @@ static void __free_pages_ok(struct page *page, unsigned 
int order)
local_irq_restore(flags);
 }
 
+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+volatile u64 latent_entropy;
+EXP

[PATCH v4 2/4] Add the latent_entropy gcc plugin

2016-06-20 Thread Emese Revfy
This plugin mitigates the problem of the kernel having too little entropy
during and after boot for generating crypto keys.

It creates a local variable in every marked function. The value of
this variable is modified by randomly chosen operations (add, xor and rol)
and random values (gcc generates them at compile time and the stack pointer
at runtime).
It depends on the control flow (e.g., loops, conditions).

Before the function returns the plugin writes this local variable
into the latent_entropy global variable. The value of this global variable
is added to the kernel entropy pool in do_one_initcall() and _do_fork().

Signed-off-by: Emese Revfy 
---
 arch/Kconfig|  18 +
 arch/powerpc/kernel/Makefile|   4 +
 include/linux/random.h  |  10 +
 init/main.c |   1 +
 kernel/fork.c   |   1 +
 mm/page_alloc.c |   5 +
 scripts/Makefile.gcc-plugins|   8 +-
 scripts/gcc-plugins/Makefile|   1 +
 scripts/gcc-plugins/latent_entropy_plugin.c | 639 
 9 files changed, 686 insertions(+), 1 deletion(-)
 create mode 100644 scripts/gcc-plugins/latent_entropy_plugin.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 05f1e95..4b7cc2f 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -393,6 +393,24 @@ config GCC_PLUGIN_SANCOV
  gcc-4.5 on). It is based on the commit "Add fuzzing coverage support"
  by Dmitry Vyukov .
 
+config GCC_PLUGIN_LATENT_ENTROPY
+   bool "Generate some entropy during boot and runtime"
+   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 (about 0.5%) and fork and
+ irq processing.
+
+ Note that entropy extracted this way is not cryptographically
+ secure!
+
+ This plugin was ported from grsecurity/PaX. More information at:
+  * https://grsecurity.net/
+  * https://pax.grsecurity.net/
+
 config HAVE_CC_STACKPROTECTOR
bool
help
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 2da380f..01935b8 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -15,6 +15,10 @@ CFLAGS_btext.o   += -fPIC
 endif
 
 ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 # Do not trace early boot code
 CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
diff --git a/include/linux/random.h b/include/linux/random.h
index e47e533..752e7df 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -18,6 +18,16 @@ struct random_ready_callback {
 };
 
 extern void add_device_randomness(const void *, unsigned int);
+
+#if defined(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) && !defined(__CHECKER__)
+static inline void add_latent_entropy(void)
+{
+   add_device_randomness((const void *)_entropy, 
sizeof(latent_entropy));
+}
+#else
+static inline void add_latent_entropy(void) {}
+#endif
+
 extern void add_input_randomness(unsigned int type, unsigned int code,
 unsigned int value);
 extern void add_interrupt_randomness(int irq, int irq_flags);
diff --git a/init/main.c b/init/main.c
index 4c17fda..07e4174 100644
--- a/init/main.c
+++ b/init/main.c
@@ -781,6 +781,7 @@ int __init_or_module do_one_initcall(initcall_t fn)
}
WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf);
 
+   add_latent_entropy();
return ret;
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 5c2c355..fd1b3c2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1761,6 +1761,7 @@ long _do_fork(unsigned long clone_flags,
 
p = copy_process(clone_flags, stack_start, stack_size,
 child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
+   add_latent_entropy();
/*
 * Do this prior waking up the new thread - the thread pointer
 * might get invalid after that point, if the thread exits quickly.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f8f3bfc..d10324e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1234,6 +1234,11 @@ static void __free_pages_ok(struct page *page, unsigned 
int order)
local_irq_restore(flags);
 }
 
+#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+volatile u64 latent_entropy;
+EXPORT_SYMBOL(latent_entropy);
+#endif
+
 static void __i

  1   2   3   >