• Thomas Gleixner's avatar
    x86/kaslr: Expose and use the end of the physical memory address space · ea72ce5d
    Thomas Gleixner authored
    iounmap() on x86 occasionally fails to unmap because the provided valid
    ioremap address is not below high_memory. It turned out that this
    happens due to KASLR.
    
    KASLR uses the full address space between PAGE_OFFSET and vaddr_end to
    randomize the starting points of the direct map, vmalloc and vmemmap
    regions.  It thereby limits the size of the direct map by using the
    installed memory size plus an extra configurable margin for hot-plug
    memory.  This limitation is done to gain more randomization space
    because otherwise only the holes between the direct map, vmalloc,
    vmemmap and vaddr_end would be usable for randomizing.
    
    The limited direct map size is not exposed to the rest of the kernel, so
    the memory hot-plug and resource management related code paths still
    operate under the assumption that the available address space can be
    determined with MAX_PHYSMEM_BITS.
    
    request_free_mem_region() allocates from (1 << MAX_PHYSMEM_BITS) - 1
    downwards.  That means the first allocation happens past the end of the
    direct map and if unlucky this address is in the vmalloc space, which
    causes high_memory to become greater than VMALLOC_START and consequently
    causes iounmap() to fail for valid ioremap addresses.
    
    MAX_PHYSMEM_BITS cannot be changed for that because the randomization
    does not align with address bit boundaries and there are other places
    which actually require to know the maximum number of address bits.  All
    remaining usage sites of MAX_PHYSMEM_BITS have been analyzed and found
    to be correct.
    
    Cure this by exposing the end of the direct map via PHYSMEM_END and use
    that for the memory hot-plug and resource management related places
    instead of relying on MAX_PHYSMEM_BITS. In the KASLR case PHYSMEM_END
    maps to a variable which is initialized by the KASLR initialization and
    otherwise it is based on MAX_PHYSMEM_BITS as before.
    
    To prevent future hickups add a check into add_pages() to catch callers
    trying to add memory above PHYSMEM_END.
    
    Fixes: 0483e1fa ("x86/mm: Implement ASLR for kernel memory regions")
    Reported-by: default avatarMax Ramanouski <max8rr8@gmail.com>
    Reported-by: default avatarAlistair Popple <apopple@nvidia.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Tested-By: default avatarMax Ramanouski <max8rr8@gmail.com>
    Tested-by: default avatarAlistair Popple <apopple@nvidia.com>
    Reviewed-by: default avatarDan Williams <dan.j.williams@intel.com>
    Reviewed-by: default avatarAlistair Popple <apopple@nvidia.com>
    Reviewed-by: default avatarKees Cook <kees@kernel.org>
    Cc: stable@vger.kernel.org
    Link: https://lore.kernel.org/all/87ed6soy3z.ffs@tglx
    ea72ce5d
page_64.h 2.87 KB