• Rick Edgecombe's avatar
    x86/shstk: Introduce map_shadow_stack syscall · c35559f9
    Rick Edgecombe authored
    When operating with shadow stacks enabled, the kernel will automatically
    allocate shadow stacks for new threads, however in some cases userspace
    will need additional shadow stacks. The main example of this is the
    ucontext family of functions, which require userspace allocating and
    pivoting to userspace managed stacks.
    
    Unlike most other user memory permissions, shadow stacks need to be
    provisioned with special data in order to be useful. They need to be setup
    with a restore token so that userspace can pivot to them via the RSTORSSP
    instruction. But, the security design of shadow stacks is that they
    should not be written to except in limited circumstances. This presents a
    problem for userspace, as to how userspace can provision this special
    data, without allowing for the shadow stack to be generally writable.
    
    Previously, a new PROT_SHADOW_STACK was attempted, which could be
    mprotect()ed from RW permissions after the data was provisioned. This was
    found to not be secure enough, as other threads could write to the
    shadow stack during the writable window.
    
    The kernel can use a special instruction, WRUSS, to write directly to
    userspace shadow stacks. So the solution can be that memory can be mapped
    as shadow stack permissions from the beginning (never generally writable
    in userspace), and the kernel itself can write the restore token.
    
    First, a new madvise() flag was explored, which could operate on the
    PROT_SHADOW_STACK memory. This had a couple of downsides:
    1. Extra checks were needed in mprotect() to prevent writable memory from
       ever becoming PROT_SHADOW_STACK.
    2. Extra checks/vma state were needed in the new madvise() to prevent
       restore tokens being written into the middle of pre-used shadow stacks.
       It is ideal to prevent restore tokens being added at arbitrary
       locations, so the check was to make sure the shadow stack had never been
       written to.
    3. It stood out from the rest of the madvise flags, as more of direct
       action than a hint at future desired behavior.
    
    So rather than repurpose two existing syscalls (mmap, madvise) that don't
    quite fit, just implement a new map_shadow_stack syscall to allow
    userspace to map and setup new shadow stacks in one step. While ucontext
    is the primary motivator, userspace may have other unforeseen reasons to
    setup its own shadow stacks using the WRSS instruction. Towards this
    provide a flag so that stacks can be optionally setup securely for the
    common case of ucontext without enabling WRSS. Or potentially have the
    kernel set up the shadow stack in some new way.
    
    The following example demonstrates how to create a new shadow stack with
    map_shadow_stack:
    void *shstk = map_shadow_stack(addr, stack_size, SHADOW_STACK_SET_TOKEN);
    Signed-off-by: default avatarRick Edgecombe <rick.p.edgecombe@intel.com>
    Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
    Reviewed-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
    Reviewed-by: default avatarKees Cook <keescook@chromium.org>
    Acked-by: default avatarMike Rapoport (IBM) <rppt@kernel.org>
    Tested-by: default avatarPengfei Xu <pengfei.xu@intel.com>
    Tested-by: default avatarJohn Allen <john.allen@amd.com>
    Tested-by: default avatarKees Cook <keescook@chromium.org>
    Link: https://lore.kernel.org/all/20230613001108.3040476-35-rick.p.edgecombe%40intel.com
    c35559f9
sys_ni.c 9.08 KB