16 Jun, 2020

1 commit

  • In addition to -ftrivial-auto-var-init=pattern (used by
    CONFIG_INIT_STACK_ALL now) Clang also supports zero initialization for
    locals enabled by -ftrivial-auto-var-init=zero. The future of this flag
    is still being debated (see https://bugs.llvm.org/show_bug.cgi?id=45497).
    Right now it is guarded by another flag,
    -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang,
    which means it may not be supported by future Clang releases. Another
    possible resolution is that -ftrivial-auto-var-init=zero will persist
    (as certain users have already started depending on it), but the name
    of the guard flag will change.

    In the meantime, zero initialization has proven itself as a good
    production mitigation measure against uninitialized locals. Unlike pattern
    initialization, which has a higher chance of triggering existing bugs,
    zero initialization provides safe defaults for strings, pointers, indexes,
    and sizes. On the other hand, pattern initialization remains safer for
    return values. Chrome OS and Android are moving to using zero
    initialization for production builds.

    Performance-wise, the difference between pattern and zero initialization
    is usually negligible, although the generated code for zero
    initialization is more compact.

    This patch renames CONFIG_INIT_STACK_ALL to CONFIG_INIT_STACK_ALL_PATTERN
    and introduces another config option, CONFIG_INIT_STACK_ALL_ZERO, that
    enables zero initialization for locals if the corresponding flags are
    supported by Clang.

    Cc: Kees Cook
    Cc: Nick Desaulniers
    Cc: Greg Kroah-Hartman
    Signed-off-by: Alexander Potapenko
    Link: https://lore.kernel.org/r/20200616083435.223038-1-glider@google.com
    Reviewed-by: Maciej Żenczykowski
    Signed-off-by: Kees Cook

    glider@google.com
     

29 Jul, 2019

1 commit


26 Jul, 2019

1 commit

  • The combination of KASAN_STACK and GCC_PLUGIN_STRUCTLEAK_BYREF
    leads to much larger kernel stack usage, as seen from the warnings
    about functions that now exceed the 2048 byte limit:

    drivers/media/i2c/tvp5150.c:253:1: error: the frame size of 3936 bytes is larger than 2048 bytes
    drivers/media/tuners/r820t.c:1327:1: error: the frame size of 2816 bytes is larger than 2048 bytes
    drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c:16552:1: error: the frame size of 3144 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
    fs/ocfs2/aops.c:1892:1: error: the frame size of 2088 bytes is larger than 2048 bytes
    fs/ocfs2/dlm/dlmrecovery.c:737:1: error: the frame size of 2088 bytes is larger than 2048 bytes
    fs/ocfs2/namei.c:1677:1: error: the frame size of 2584 bytes is larger than 2048 bytes
    fs/ocfs2/super.c:1186:1: error: the frame size of 2640 bytes is larger than 2048 bytes
    fs/ocfs2/xattr.c:3678:1: error: the frame size of 2176 bytes is larger than 2048 bytes
    net/bluetooth/l2cap_core.c:7056:1: error: the frame size of 2144 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
    net/bluetooth/l2cap_core.c: In function 'l2cap_recv_frame':
    net/bridge/br_netlink.c:1505:1: error: the frame size of 2448 bytes is larger than 2048 bytes
    net/ieee802154/nl802154.c:548:1: error: the frame size of 2232 bytes is larger than 2048 bytes
    net/wireless/nl80211.c:1726:1: error: the frame size of 2224 bytes is larger than 2048 bytes
    net/wireless/nl80211.c:2357:1: error: the frame size of 4584 bytes is larger than 2048 bytes
    net/wireless/nl80211.c:5108:1: error: the frame size of 2760 bytes is larger than 2048 bytes
    net/wireless/nl80211.c:6472:1: error: the frame size of 2112 bytes is larger than 2048 bytes

    The structleak plugin was previously disabled for CONFIG_COMPILE_TEST,
    but meant we missed some bugs, so this time we should address them.

    The frame size warnings are distracting, and risking a kernel stack
    overflow is generally not beneficial to performance, so it may be best
    to disallow that particular combination. This can be done by turning
    off either one. I picked the dependency in GCC_PLUGIN_STRUCTLEAK_BYREF
    and GCC_PLUGIN_STRUCTLEAK_BYREF_ALL, as this option is designed to
    make uninitialized stack usage less harmful when enabled on its own,
    but it also prevents KASAN from detecting those cases in which it was
    in fact needed.

    KASAN_STACK is currently implied by KASAN on gcc, but could be made a
    user selectable option if we want to allow combining (non-stack) KASAN
    with GCC_PLUGIN_STRUCTLEAK_BYREF.

    Note that it would be possible to specifically address the files that
    print the warning, but presumably the overall stack usage is still
    significantly higher than in other configurations, so this would not
    address the full problem.

    I could not test this with CONFIG_INIT_STACK_ALL, which may or may not
    suffer from a similar problem.

    Fixes: 81a56f6dcd20 ("gcc-plugins: structleak: Generalize to all variable types")
    Signed-off-by: Arnd Bergmann
    Link: https://lore.kernel.org/r/20190722114134.3123901-1-arnd@arndb.de
    Signed-off-by: Kees Cook

    Arnd Bergmann
     

13 Jul, 2019

1 commit

  • Patch series "add init_on_alloc/init_on_free boot options", v10.

    Provide init_on_alloc and init_on_free boot options.

    These are aimed at preventing possible information leaks and making the
    control-flow bugs that depend on uninitialized values more deterministic.

    Enabling either of the options guarantees that the memory returned by the
    page allocator and SL[AU]B is initialized with zeroes. SLOB allocator
    isn't supported at the moment, as its emulation of kmem caches complicates
    handling of SLAB_TYPESAFE_BY_RCU caches correctly.

    Enabling init_on_free also guarantees that pages and heap objects are
    initialized right after they're freed, so it won't be possible to access
    stale data by using a dangling pointer.

    As suggested by Michal Hocko, right now we don't let the heap users to
    disable initialization for certain allocations. There's not enough
    evidence that doing so can speed up real-life cases, and introducing ways
    to opt-out may result in things going out of control.

    This patch (of 2):

    The new options are needed to prevent possible information leaks and make
    control-flow bugs that depend on uninitialized values more deterministic.

    This is expected to be on-by-default on Android and Chrome OS. And it
    gives the opportunity for anyone else to use it under distros too via the
    boot args. (The init_on_free feature is regularly requested by folks
    where memory forensics is included in their threat models.)

    init_on_alloc=1 makes the kernel initialize newly allocated pages and heap
    objects with zeroes. Initialization is done at allocation time at the
    places where checks for __GFP_ZERO are performed.

    init_on_free=1 makes the kernel initialize freed pages and heap objects
    with zeroes upon their deletion. This helps to ensure sensitive data
    doesn't leak via use-after-free accesses.

    Both init_on_alloc=1 and init_on_free=1 guarantee that the allocator
    returns zeroed memory. The two exceptions are slab caches with
    constructors and SLAB_TYPESAFE_BY_RCU flag. Those are never
    zero-initialized to preserve their semantics.

    Both init_on_alloc and init_on_free default to zero, but those defaults
    can be overridden with CONFIG_INIT_ON_ALLOC_DEFAULT_ON and
    CONFIG_INIT_ON_FREE_DEFAULT_ON.

    If either SLUB poisoning or page poisoning is enabled, those options take
    precedence over init_on_alloc and init_on_free: initialization is only
    applied to unpoisoned allocations.

    Slowdown for the new features compared to init_on_free=0, init_on_alloc=0:

    hackbench, init_on_free=1: +7.62% sys time (st.err 0.74%)
    hackbench, init_on_alloc=1: +7.75% sys time (st.err 2.14%)

    Linux build with -j12, init_on_free=1: +8.38% wall time (st.err 0.39%)
    Linux build with -j12, init_on_free=1: +24.42% sys time (st.err 0.52%)
    Linux build with -j12, init_on_alloc=1: -0.13% wall time (st.err 0.42%)
    Linux build with -j12, init_on_alloc=1: +0.57% sys time (st.err 0.40%)

    The slowdown for init_on_free=0, init_on_alloc=0 compared to the baseline
    is within the standard error.

    The new features are also going to pave the way for hardware memory
    tagging (e.g. arm64's MTE), which will require both on_alloc and on_free
    hooks to set the tags for heap objects. With MTE, tagging will have the
    same cost as memory initialization.

    Although init_on_free is rather costly, there are paranoid use-cases where
    in-memory data lifetime is desired to be minimized. There are various
    arguments for/against the realism of the associated threat models, but
    given that we'll need the infrastructure for MTE anyway, and there are
    people who want wipe-on-free behavior no matter what the performance cost,
    it seems reasonable to include it in this series.

    [glider@google.com: v8]
    Link: http://lkml.kernel.org/r/20190626121943.131390-2-glider@google.com
    [glider@google.com: v9]
    Link: http://lkml.kernel.org/r/20190627130316.254309-2-glider@google.com
    [glider@google.com: v10]
    Link: http://lkml.kernel.org/r/20190628093131.199499-2-glider@google.com
    Link: http://lkml.kernel.org/r/20190617151050.92663-2-glider@google.com
    Signed-off-by: Alexander Potapenko
    Acked-by: Kees Cook
    Acked-by: Michal Hocko [page and dmapool parts
    Acked-by: James Morris ]
    Cc: Christoph Lameter
    Cc: Masahiro Yamada
    Cc: "Serge E. Hallyn"
    Cc: Nick Desaulniers
    Cc: Kostya Serebryany
    Cc: Dmitry Vyukov
    Cc: Sandeep Patil
    Cc: Laura Abbott
    Cc: Randy Dunlap
    Cc: Jann Horn
    Cc: Mark Rutland
    Cc: Marco Elver
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Alexander Potapenko
     

21 May, 2019

1 commit


25 Apr, 2019

3 commits

  • CONFIG_INIT_STACK_ALL turns on stack initialization based on
    -ftrivial-auto-var-init in Clang builds, which has greater coverage
    than CONFIG_GCC_PLUGINS_STRUCTLEAK_BYREF_ALL.

    -ftrivial-auto-var-init Clang option provides trivial initializers for
    uninitialized local variables, variable fields and padding.

    It has three possible values:
    pattern - uninitialized locals are filled with a fixed pattern
    (mostly 0xAA on 64-bit platforms, see https://reviews.llvm.org/D54604
    for more details, but 0x000000AA for 32-bit pointers) likely to cause
    crashes when uninitialized value is used;
    zero (it's still debated whether this flag makes it to the official
    Clang release) - uninitialized locals are filled with zeroes;
    uninitialized (default) - uninitialized locals are left intact.

    This patch uses only the "pattern" mode when CONFIG_INIT_STACK_ALL is
    enabled.

    Developers have the possibility to opt-out of this feature on a
    per-variable basis by using __attribute__((uninitialized)), but such
    use should be well justified in comments.

    Co-developed-by: Alexander Potapenko
    Signed-off-by: Alexander Potapenko
    Signed-off-by: Kees Cook
    Tested-by: Alexander Potapenko
    Acked-by: Masahiro Yamada

    Kees Cook
     
  • This moves the stackleak plugin options to Kconfig.hardening's memory
    initialization menu.

    Signed-off-by: Kees Cook
    Reviewed-by: Alexander Popov
    Acked-by: Masahiro Yamada

    Kees Cook
     
  • Right now kernel hardening options are scattered around various Kconfig
    files. This can be a central place to collect these kinds of options
    going forward. This is initially populated with the memory initialization
    options from the gcc-plugins.

    Signed-off-by: Kees Cook
    Acked-by: Masahiro Yamada

    Kees Cook