mbox series

[v3,00/11] bring back stack frame warning with KASAN

Message ID 20170622171355.267192-1-arnd@arndb.de
Headers show
Series bring back stack frame warning with KASAN | expand

Message

Arnd Bergmann June 22, 2017, 5:13 p.m. UTC
This is a new version of patches I originally submitted back in
March [1], this time reducing the size of the series even further.

This minimal set of patches only makes sure that we do get
frame size warnings in allmodconfig for x86_64 and arm64 again,
even with KASAN enabled.

The changes this time are reduced to:

- I'm introducing "noinline_if_stackbloat" and use it in a number
  of places that suffer from inline functions with local variables
  - netlink, as used in various parts of the kernel
  - a number of drivers/media drivers
  - a handful of wireless network drivers
- a rework for the brcmsmac driver
- -fsanitize-address-use-after-scope is moved to a separate
  CONFIG_KASAN_EXTRA option that increases the warning limit
- CONFIG_KASAN_EXTRA is disabled with CONFIG_COMPILE_TEST,
  improving compile speed and disabling code that leads to
  valid warnings on gcc-7.0.1
- kmemcheck conflicts with CONFIG_KASAN_EXTRA

Compared to the version 1, I no longer have patches
to fix all the CONFIG_KASAN_EXTRA warnings:

- READ_ONCE/WRITE_ONCE cause problems in lots of code
- typecheck() causes huge problems in a few places
- many more uses of noinline_if_stackbloat

And compared to version 2, I have rewritten the vt-keyboard
patch based on feedback, and made KMEMCHECK mutually exclusive
with KASAN (rather than KASAN_EXTRA), everything else remains
unchanged.

This series lets us add back a stack frame warning for the regular
2048 bytes without CONFIG_KASAN_EXTRA. I set the warning limit with
KASAN_EXTRA to 3072, since I have an additional set of patches
to address all files that surpass that limit. We can debate whether
we want to apply those as a follow-up, or instead remove the option
entirely.

Another follow-up series I have reduces the warning limit with
KASAN to 1536, and without KASAN to 1280 for 64-bit architectures.

I hope that Andrew can pick up the entire series for mmotm, and
we can eventually backport most of it to stable kernels and
address the warnings that kernelci still reports for this problem [2].

     Arnd

[1] https://lkml.org/lkml/2017/3/2/508
[2] https://kernelci.org/build/id/593f89a659b51463306b958d/logs/

Arnd Bergmann (11):
  compiler: introduce noinline_if_stackbloat annotation
  netlink: mark nla_put_{u8,u16,u32} noinline_if_stackbloat
  rocker: mark rocker_tlv_put_* functions as noinline_if_stackbloat
  mtd: cfi: reduce stack size with KASAN
  dvb-frontends: reduce stack size in i2c access
  r820t: mark register functions as noinline_if_stackbloat
  tty: improve tty_insert_flip_char() fast path
  brcmsmac: make some local variables 'static const' to reduce stack
    size
  brcmsmac: split up wlc_phy_workarounds_nphy
  brcmsmac: reindent split functions
  kasan: rework Kconfig settings

 drivers/media/dvb-frontends/ascot2e.c              |    3 +-
 drivers/media/dvb-frontends/cxd2841er.c            |    4 +-
 drivers/media/dvb-frontends/drx39xyj/drxj.c        |   14 +-
 drivers/media/dvb-frontends/helene.c               |    4 +-
 drivers/media/dvb-frontends/horus3a.c              |    2 +-
 drivers/media/dvb-frontends/itd1000.c              |    2 +-
 drivers/media/dvb-frontends/mt312.c                |    2 +-
 drivers/media/dvb-frontends/si2165.c               |   14 +-
 drivers/media/dvb-frontends/stb0899_drv.c          |    2 +-
 drivers/media/dvb-frontends/stb6100.c              |    2 +-
 drivers/media/dvb-frontends/stv0367.c              |    2 +-
 drivers/media/dvb-frontends/stv090x.c              |    2 +-
 drivers/media/dvb-frontends/stv6110.c              |    2 +-
 drivers/media/dvb-frontends/stv6110x.c             |    2 +-
 drivers/media/dvb-frontends/tda8083.c              |    2 +-
 drivers/media/dvb-frontends/zl10039.c              |    2 +-
 drivers/media/tuners/r820t.c                       |    4 +-
 drivers/mtd/chips/cfi_cmdset_0020.c                |    8 +-
 drivers/net/ethernet/rocker/rocker_tlv.h           |   24 +-
 .../broadcom/brcm80211/brcmsmac/phy/phy_n.c        | 1856 ++++++++++----------
 drivers/tty/tty_buffer.c                           |   24 +
 include/linux/compiler.h                           |   11 +
 include/linux/mtd/map.h                            |    8 +-
 include/linux/tty_flip.h                           |    3 +-
 include/net/netlink.h                              |   36 +-
 lib/Kconfig.debug                                  |    4 +-
 lib/Kconfig.kasan                                  |   11 +-
 lib/Kconfig.kmemcheck                              |    1 +
 scripts/Makefile.kasan                             |    3 +
 29 files changed, 1009 insertions(+), 1045 deletions(-)

-- 
2.9.0

Comments

Greg Kroah-Hartman June 23, 2017, 4:07 p.m. UTC | #1
On Thu, Jun 22, 2017 at 07:13:51PM +0200, Arnd Bergmann wrote:
> kernelci.org reports a crazy stack usage for the VT code when CONFIG_KASAN

> is enabled:

> 

> drivers/tty/vt/keyboard.c: In function 'kbd_keycode':

> drivers/tty/vt/keyboard.c:1452:1: error: the frame size of 2240 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]

> 

> The problem is that tty_insert_flip_char() gets inlined many times into

> kbd_keycode(), and also into other functions, and each copy requires 128

> bytes for stack redzone to check for a possible out-of-bounds access on

> the 'ch' and 'flags' arguments that are passed into

> tty_insert_flip_string_flags as a variable-length string.

> 

> This introduces a new __tty_insert_flip_char() function for the slow

> path, which receives the two arguments by value. This completely avoids

> the problem and the stack usage goes back down to around 100 bytes.

> 

> Without KASAN, this is also slightly better, as we don't have to

> spill the arguments to the stack but can simply pass 'ch' and 'flag'

> in registers, saving a few bytes in .text for each call site.

> 

> This should be backported to linux-4.0 or later, which first introduced

> the stack sanitizer in the kernel.

> 

> Cc: stable@vger.kernel.org

> Fixes: c420f167db8c ("kasan: enable stack instrumentation")

> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

> ---

> I already submitted this separately to Greg, but he hasn't replied

> yet. I assume that it's fine if Andrew picks it up along with the

> other patches and drops it again in case Greg applies it to linux-next.


I've been traveling in China this week, give me a chance to catch up
please.

And no, I don't like this patch either, I think kasan needs to be fixed
here, not work around it in odd ways in code that is completly
acceptable to "sane" compilers.  But give me a week to catch up on my
pending stuff first...

thanks,

greg k-h
Arnd Bergmann June 26, 2017, 1:58 p.m. UTC | #2
On Fri, Jun 23, 2017 at 6:07 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Thu, Jun 22, 2017 at 07:13:51PM +0200, Arnd Bergmann wrote:

>> kernelci.org reports a crazy stack usage for the VT code when CONFIG_KASAN

>> is enabled:

>>

>> drivers/tty/vt/keyboard.c: In function 'kbd_keycode':

>> drivers/tty/vt/keyboard.c:1452:1: error: the frame size of 2240 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]

>>

>> The problem is that tty_insert_flip_char() gets inlined many times into

>> kbd_keycode(), and also into other functions, and each copy requires 128

>> bytes for stack redzone to check for a possible out-of-bounds access on

>> the 'ch' and 'flags' arguments that are passed into

>> tty_insert_flip_string_flags as a variable-length string.

>>

>> This introduces a new __tty_insert_flip_char() function for the slow

>> path, which receives the two arguments by value. This completely avoids

>> the problem and the stack usage goes back down to around 100 bytes.

>>

>> Without KASAN, this is also slightly better, as we don't have to

>> spill the arguments to the stack but can simply pass 'ch' and 'flag'

>> in registers, saving a few bytes in .text for each call site.

>>

>> This should be backported to linux-4.0 or later, which first introduced

>> the stack sanitizer in the kernel.

>>

>> Cc: stable@vger.kernel.org

>> Fixes: c420f167db8c ("kasan: enable stack instrumentation")

>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

>> ---

>> I already submitted this separately to Greg, but he hasn't replied

>> yet. I assume that it's fine if Andrew picks it up along with the

>> other patches and drops it again in case Greg applies it to linux-next.

>

> I've been traveling in China this week, give me a chance to catch up

> please.


Sorry about the rush, I thought the new version was going to be
uncontroversial.

Having sent a broken patch (unused variable unless tty patch 2/2 is
applied, but that wasn't part of this series) certainly didn't make me
look any better :(

> And no, I don't like this patch either, I think kasan needs to be fixed

> here, not work around it in odd ways in code that is completly

> acceptable to "sane" compilers.  But give me a week to catch up on my

> pending stuff first...


I have done some more research, and in particular found out more about
what the compiler does, and why it shows up with some compilers
but not others for this particular file:

* when CONFIG_OPTIMIZE_INLINING is set, gcc-5 and higher decide
  to inline put_queue() in keyboard.c, regardless of architecture. gcc-4.9
  does not do this, and without CONFIG_OPTIMIZE_INLINING,
  put_queue() remains out of line for all versions of gcc. clang-3.9 always
  inlines put_queue(), regardless of CONFIG_OPTIMIZE_INLINING.

* with -fsanitize=kernel-address enabled (regardless of asan-stack), both
  clang and gcc give each local variable in an inline function a separate
  stack address when it gets passed by reference. Clang normally tries
  to overlap the addresses (without kasan), gcc apparently does not.

* With asan-stack=1, gcc uses at least 64 bytes per such variable
  (two times ASAN_RED_ZONE_SIZE), while clang only uses 16 bytes
  (2 * (1<<kDefaultShadowScale)). With asan-stack=0, they do not
  use any more space than with kasan completely disabled
  (no -fsanitize=kernel-address).

Can you say which behavior you find 'sane' or 'not sane' here,
specifically? Maybe we can make future gcc releases use a
smaller redzone like clang does.

If we find a way to improve gcc so it uses less stack here, we still
have a problem with existing compilers still producing dangerously
high stack usage, as well as annoying warnings for an allmodconfig
build as soon as we start warning about this again.

       Arnd