17 Jan, 2019

1 commit

  • commit 7bff3c06997374fb9b9991536a547b840549a813 upstream.

    It is easy to trigger this with CONFIG_HARDENED_USERCOPY_PAGESPAN=y,

    usercopy: Kernel memory overwrite attempt detected to spans multiple pages (offset 0, size 23)!
    kernel BUG at mm/usercopy.c:102!

    For example,

    print_worker_info
    char name[WQ_NAME_LEN] = { };
    char desc[WORKER_DESC_LEN] = { };
    probe_kernel_read(name, wq->name, sizeof(name) - 1);
    probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
    __copy_from_user_inatomic
    check_object_size
    check_heap_object
    check_page_span

    This is because on-stack variables could cross PAGE_SIZE boundary, and
    failed this check,

    if (likely(((unsigned long)ptr & (unsigned long)PAGE_MASK) ==
    ((unsigned long)end & (unsigned long)PAGE_MASK)))

    ptr = FFFF889007D7EFF8
    end = FFFF889007D7F00E

    Hence, fix it by checking if it is a stack object first.

    [keescook@chromium.org: improve comments after reorder]
    Link: http://lkml.kernel.org/r/20190103165151.GA32845@beast
    Link: http://lkml.kernel.org/r/20181231030254.99441-1-cai@lca.pw
    Signed-off-by: Qian Cai
    Signed-off-by: Kees Cook
    Acked-by: Kees Cook
    Cc:
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds
    Signed-off-by: Greg Kroah-Hartman

    Qian Cai
     

04 Jul, 2018

1 commit

  • Enabling HARDENED_USERCOPY may cause measurable regressions in networking
    performance: up to 8% under UDP flood.

    I ran a small packet UDP flood using pktgen vs. a host b2b connected. On
    the receiver side the UDP packets are processed by a simple user space
    process that just reads and drops them:

    https://github.com/netoptimizer/network-testing/blob/master/src/udp_sink.c

    Not very useful from a functional PoV, but it helps to pin-point
    bottlenecks in the networking stack.

    When running a kernel with CONFIG_HARDENED_USERCOPY=y, I see a 5-8%
    regression in the receive tput, compared to the same kernel without this
    option enabled.

    With CONFIG_HARDENED_USERCOPY=y, perf shows ~6% of CPU time spent
    cumulatively in __check_object_size (~4%) and __virt_addr_valid (~2%).

    The call-chain is:

    __GI___libc_recvfrom
    entry_SYSCALL_64_after_hwframe
    do_syscall_64
    __x64_sys_recvfrom
    __sys_recvfrom
    inet_recvmsg
    udp_recvmsg
    __check_object_size

    udp_recvmsg() actually calls copy_to_iter() (inlined) and the latters
    calls check_copy_size() (again, inlined).

    A generic distro may want to enable HARDENED_USERCOPY in their default
    kernel config, but at the same time, such distro may want to be able to
    avoid the performance penalties in with the default configuration and
    disable the stricter check on a per-boot basis.

    This change adds a boot parameter that conditionally disables
    HARDENED_USERCOPY via "hardened_usercopy=off".

    Signed-off-by: Chris von Recklinghausen
    Signed-off-by: Kees Cook

    Chris von Recklinghausen
     

16 Jan, 2018

4 commits

  • This patch adds checking of usercopy cache whitelisting, and is modified
    from Brad Spengler/PaX Team's PAX_USERCOPY whitelisting code in the
    last public patch of grsecurity/PaX based on my understanding of the
    code. Changes or omissions from the original code are mine and don't
    reflect the original grsecurity/PaX code.

    The SLAB and SLUB allocators are modified to WARN() on all copy operations
    in which the kernel heap memory being modified falls outside of the cache's
    defined usercopy region.

    Based on an earlier patch from David Windsor.

    Cc: Christoph Lameter
    Cc: Pekka Enberg
    Cc: David Rientjes
    Cc: Joonsoo Kim
    Cc: Andrew Morton
    Cc: Laura Abbott
    Cc: Ingo Molnar
    Cc: Mark Rutland
    Cc: linux-mm@kvack.org
    Cc: linux-xfs@vger.kernel.org
    Signed-off-by: Kees Cook

    Kees Cook
     
  • This refactors the hardened usercopy code so that failure reporting can
    happen within the checking functions instead of at the top level. This
    simplifies the return value handling and allows more details and offsets
    to be included in the report. Having the offset can be much more helpful
    in understanding hardened usercopy bugs.

    Signed-off-by: Kees Cook

    Kees Cook
     
  • In preparation for refactoring the usercopy checks to pass offset to
    the hardened usercopy report, this renames report_usercopy() to the
    more accurate usercopy_abort(), marks it as noreturn because it is,
    adds a hopefully helpful comment for anyone investigating such reports,
    makes the function available to the slab allocators, and adds new "detail"
    and "offset" arguments.

    Signed-off-by: Kees Cook

    Kees Cook
     
  • Using %p was already mostly useless in the usercopy overflow reports,
    so this removes it entirely to avoid confusion now that %p-hashing
    is enabled.

    Fixes: ad67b74d2469d9b8 ("printk: hash addresses printed with %p")
    Signed-off-by: Kees Cook

    Kees Cook
     

06 Apr, 2017

1 commit


05 Apr, 2017

1 commit

  • This patch moves the arch_within_stack_frames() return value enum up in
    the header files so that per-architecture implementations can reuse the
    same return values.

    Signed-off-by: Sahara
    Signed-off-by: James Morse
    [kees: adjusted naming and commit log]
    Signed-off-by: Kees Cook

    Sahara
     

02 Mar, 2017

2 commits


11 Jan, 2017

1 commit

  • The usercopy checking code currently calls __va(__pa(...)) to check for
    aliases on symbols. Switch to using lm_alias instead.

    Reviewed-by: Mark Rutland
    Tested-by: Mark Rutland
    Acked-by: Kees Cook
    Signed-off-by: Laura Abbott
    Signed-off-by: Will Deacon

    Laura Abbott
     

21 Sep, 2016

1 commit

  • While running a compile on arm64, I hit a memory exposure

    usercopy: kernel memory exposure attempt detected from fffffc0000f3b1a8 (buffer_head) (1 bytes)
    ------------[ cut here ]------------
    kernel BUG at mm/usercopy.c:75!
    Internal error: Oops - BUG: 0 [#1] SMP
    Modules linked in: ip6t_rpfilter ip6t_REJECT
    nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_broute bridge stp
    llc ebtable_nat ip6table_security ip6table_raw ip6table_nat
    nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle
    iptable_security iptable_raw iptable_nat nf_conntrack_ipv4
    nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle
    ebtable_filter ebtables ip6table_filter ip6_tables vfat fat xgene_edac
    xgene_enet edac_core i2c_xgene_slimpro i2c_core at803x realtek xgene_dma
    mdio_xgene gpio_dwapb gpio_xgene_sb xgene_rng mailbox_xgene_slimpro nfsd
    auth_rpcgss nfs_acl lockd grace sunrpc xfs libcrc32c sdhci_of_arasan
    sdhci_pltfm sdhci mmc_core xhci_plat_hcd gpio_keys
    CPU: 0 PID: 19744 Comm: updatedb Tainted: G W 4.8.0-rc3-threadinfo+ #1
    Hardware name: AppliedMicro X-Gene Mustang Board/X-Gene Mustang Board, BIOS 3.06.12 Aug 12 2016
    task: fffffe03df944c00 task.stack: fffffe00d128c000
    PC is at __check_object_size+0x70/0x3f0
    LR is at __check_object_size+0x70/0x3f0
    ...
    [] __check_object_size+0x70/0x3f0
    [] filldir64+0x158/0x1a0
    [] __fat_readdir+0x4a0/0x558 [fat]
    [] fat_readdir+0x34/0x40 [fat]
    [] iterate_dir+0x190/0x1e0
    [] SyS_getdents64+0x88/0x120
    [] el0_svc_naked+0x24/0x28

    fffffc0000f3b1a8 is a module address. Modules may have compiled in
    strings which could get copied to userspace. In this instance, it
    looks like "." which matches with a size of 1 byte. Extend the
    is_vmalloc_addr check to be is_vmalloc_or_module_addr to cover
    all possible cases.

    Signed-off-by: Laura Abbott
    Signed-off-by: Kees Cook

    Laura Abbott
     

08 Sep, 2016

1 commit

  • A custom allocator without __GFP_COMP that copies to userspace has been
    found in vmw_execbuf_process[1], so this disables the page-span checker
    by placing it behind a CONFIG for future work where such things can be
    tracked down later.

    [1] https://bugzilla.redhat.com/show_bug.cgi?id=1373326

    Reported-by: Vinson Lee
    Fixes: f5509cc18daa ("mm: Hardened usercopy")
    Signed-off-by: Kees Cook

    Kees Cook
     

23 Aug, 2016

2 commits

  • When running with a local patch which moves the '_stext' symbol to the
    very beginning of the kernel text area, I got the following panic with
    CONFIG_HARDENED_USERCOPY:

    usercopy: kernel memory exposure attempt detected from ffff88103dfff000 () (4096 bytes)
    ------------[ cut here ]------------
    kernel BUG at mm/usercopy.c:79!
    invalid opcode: 0000 [#1] SMP
    ...
    CPU: 0 PID: 4800 Comm: cp Not tainted 4.8.0-rc3.after+ #1
    Hardware name: Dell Inc. PowerEdge R720/0X3D66, BIOS 2.5.4 01/22/2016
    task: ffff880817444140 task.stack: ffff880816274000
    RIP: 0010:[] __check_object_size+0x76/0x413
    RSP: 0018:ffff880816277c40 EFLAGS: 00010246
    RAX: 000000000000006b RBX: ffff88103dfff000 RCX: 0000000000000000
    RDX: 0000000000000000 RSI: ffff88081f80dfa8 RDI: ffff88081f80dfa8
    RBP: ffff880816277c90 R08: 000000000000054c R09: 0000000000000000
    R10: 0000000000000005 R11: 0000000000000006 R12: 0000000000001000
    R13: ffff88103e000000 R14: ffff88103dffffff R15: 0000000000000001
    FS: 00007fb9d1750800(0000) GS:ffff88081f800000(0000) knlGS:0000000000000000
    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00000000021d2000 CR3: 000000081a08f000 CR4: 00000000001406f0
    Stack:
    ffff880816277cc8 0000000000010000 000000043de07000 0000000000000000
    0000000000001000 ffff880816277e60 0000000000001000 ffff880816277e28
    000000000000c000 0000000000001000 ffff880816277ce8 ffffffff8136c3a6
    Call Trace:
    [] copy_page_to_iter_iovec+0xa6/0x1c0
    [] copy_page_to_iter+0x16/0x90
    [] generic_file_read_iter+0x3e3/0x7c0
    [] ? xfs_file_buffered_aio_write+0xad/0x260 [xfs]
    [] ? down_read+0x12/0x40
    [] xfs_file_buffered_aio_read+0x51/0xc0 [xfs]
    [] xfs_file_read_iter+0x62/0xb0 [xfs]
    [] __vfs_read+0xdf/0x130
    [] vfs_read+0x8e/0x140
    [] SyS_read+0x55/0xc0
    [] do_syscall_64+0x67/0x160
    [] entry_SYSCALL64_slow_path+0x25/0x25
    RIP: 0033:[] 0x7fb9d0c33c00
    RSP: 002b:00007ffc9c262f28 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
    RAX: ffffffffffffffda RBX: fffffffffff8ffff RCX: 00007fb9d0c33c00
    RDX: 0000000000010000 RSI: 00000000021c3000 RDI: 0000000000000004
    RBP: 00000000021c3000 R08: 0000000000000000 R09: 00007ffc9c264d6c
    R10: 00007ffc9c262c50 R11: 0000000000000246 R12: 0000000000010000
    R13: 00007ffc9c2630b0 R14: 0000000000000004 R15: 0000000000010000
    Code: 81 48 0f 44 d0 48 c7 c6 90 4d a3 81 48 c7 c0 bb b3 a2 81 48 0f 44 f0 4d 89 e1 48 89 d9 48 c7 c7 68 16 a3 81 31 c0 e8 f4 57 f7 ff 0b 48 8d 90 00 40 00 00 48 39 d3 0f 83 22 01 00 00 48 39 c3
    RIP [] __check_object_size+0x76/0x413
    RSP

    The checked object's range [ffff88103dfff000, ffff88103e000000) is
    valid, so there shouldn't have been a BUG. The hardened usercopy code
    got confused because the range's ending address is the same as the
    kernel's text starting address at 0xffff88103e000000. The overlap check
    is slightly off.

    Fixes: f5509cc18daa ("mm: Hardened usercopy")
    Signed-off-by: Josh Poimboeuf
    Signed-off-by: Kees Cook

    Josh Poimboeuf
     
  • check_bogus_address() checked for pointer overflow using this expression,
    where 'ptr' has type 'const void *':

    ptr + n < ptr

    Since pointer wraparound is undefined behavior, gcc at -O2 by default
    treats it like the following, which would not behave as intended:

    (long)n < 0

    Fortunately, this doesn't currently happen for kernel code because kernel
    code is compiled with -fno-strict-overflow. But the expression should be
    fixed anyway to use well-defined integer arithmetic, since it could be
    treated differently by different compilers in the future or could be
    reported by tools checking for undefined behavior.

    Signed-off-by: Eric Biggers
    Signed-off-by: Kees Cook

    Eric Biggers
     

27 Jul, 2016

1 commit

  • This is the start of porting PAX_USERCOPY into the mainline kernel. This
    is the first set of features, controlled by CONFIG_HARDENED_USERCOPY. The
    work is based on code by PaX Team and Brad Spengler, and an earlier port
    from Casey Schaufler. Additional non-slab page tests are from Rik van Riel.

    This patch contains the logic for validating several conditions when
    performing copy_to_user() and copy_from_user() on the kernel object
    being copied to/from:
    - address range doesn't wrap around
    - address range isn't NULL or zero-allocated (with a non-zero copy size)
    - if on the slab allocator:
    - object size must be less than or equal to copy size (when check is
    implemented in the allocator, which appear in subsequent patches)
    - otherwise, object must not span page allocations (excepting Reserved
    and CMA ranges)
    - if on the stack
    - object must not extend before/after the current process stack
    - object must be contained by a valid stack frame (when there is
    arch/build support for identifying stack frames)
    - object must not overlap with kernel text

    Signed-off-by: Kees Cook
    Tested-by: Valdis Kletnieks
    Tested-by: Michael Ellerman

    Kees Cook