• Kirill A. Shutemov's avatar
    x86/mm: Rework address range check in get_user() and put_user() · b19b74bc
    Kirill A. Shutemov authored
    The functions get_user() and put_user() check that the target address
    range resides in the user space portion of the virtual address space.
    In order to perform this check, the functions compare the end of the
    range against TASK_SIZE_MAX.
    
    For kernels compiled with CONFIG_X86_5LEVEL, this process requires some
    additional trickery using ALTERNATIVE, as TASK_SIZE_MAX depends on the
    paging mode in use.
    
    Linus suggested that this check could be simplified for 64-bit kernels.
    It is sufficient to check bit 63 of the address to ensure that the range
    belongs to user space. Additionally, the use of branches can be avoided
    by setting the target address to all ones if bit 63 is set.
    
    There's no need to check the end of the access range as there's huge
    gap between end of userspace range and start of the kernel range. The
    gap consists of canonical hole and unused ranges on both kernel and
    userspace sides.
    
    If an address with bit 63 set is passed down, it will trigger a #GP
    exception. _ASM_EXTABLE_UA() complains about this. Replace it with
    plain _ASM_EXTABLE() as it is expected behaviour now.
    
    The updated get_user() and put_user() checks are also compatible with
    Linear Address Masking, which allows user space to encode metadata in
    the upper bits of pointers and eliminates the need to untag the address
    before handling it.
    Suggested-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
    Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
    Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Link: https://lore.kernel.org/all/20230312112612.31869-2-kirill.shutemov%40linux.intel.com
    b19b74bc
putuser.S 2.97 KB