• Mark Rutland's avatar
    arm64: implement syscall wrappers · 4378a7d4
    Mark Rutland authored
    To minimize the risk of userspace-controlled values being used under
    speculation, this patch adds pt_regs based syscall wrappers for arm64,
    which pass the minimum set of required userspace values to syscall
    implementations. For each syscall, a wrapper which takes a pt_regs
    argument is automatically generated, and this extracts the arguments
    before calling the "real" syscall implementation.
    
    Each syscall has three functions generated:
    
    * __do_<compat_>sys_<name> is the "real" syscall implementation, with
      the expected prototype.
    
    * __se_<compat_>sys_<name> is the sign-extension/narrowing wrapper,
      inherited from common code. This takes a series of long parameters,
      casting each to the requisite types required by the "real" syscall
      implementation in __do_<compat_>sys_<name>.
    
      This wrapper *may* not be necessary on arm64 given the AAPCS rules on
      unused register bits, but it seemed safer to keep the wrapper for now.
    
    * __arm64_<compat_>_sys_<name> takes a struct pt_regs pointer, and
      extracts *only* the relevant register values, passing these on to the
      __se_<compat_>sys_<name> wrapper.
    
    The syscall invocation code is updated to handle the calling convention
    required by __arm64_<compat_>_sys_<name>, and passes a single struct
    pt_regs pointer.
    
    The compiler can fold the syscall implementation and its wrappers, such
    that the overhead of this approach is minimized.
    
    Note that we play games with sys_ni_syscall(). It can't be defined with
    SYSCALL_DEFINE0() because we must avoid the possibility of error
    injection. Additionally, there are a couple of locations where we need
    to call it from C code, and we don't (currently) have a
    ksys_ni_syscall().  While it has no wrapper, passing in a redundant
    pt_regs pointer is benign per the AAPCS.
    
    When ARCH_HAS_SYSCALL_WRAPPER is selected, no prototype is defines for
    sys_ni_syscall(). Since we need to treat it differently for in-kernel
    calls and the syscall tables, the prototype is defined as-required.
    
    The wrappers are largely the same as their x86 counterparts, but
    simplified as we don't have a variety of compat calling conventions that
    require separate stubs. Unlike x86, we have some zero-argument compat
    syscalls, and must define COMPAT_SYSCALL_DEFINE0() to ensure that these
    are also given an __arm64_compat_sys_ prefix.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Reviewed-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
    Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: Will Deacon <will.deacon@arm.com>
    Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
    4378a7d4
syscall.c 3.05 KB