ANDROID: 16K: Fix vm_flags conflicts from mseal

With the introduction of the mseal syscall, bit 63 of the 64-bit
vm_flags is now used to indicate that a VMA has been sealed.

Page size migration mitigations for 16kB uses bits 63-60 to
represent VMA ELF padding.

This conflict lead to VMAs with ELF padding being misinterpreted
as "seal" -- meaning that operations; such as unmapping, moving,
modifying via MAP_FIXED or resizing by mremap; all fail on VMAs
containing ELF padding. In effect, causing boot to fail.

This was caught on the x86_64 16kB emulator, but would have failed
on any device (4kB page sized) that has a page agnostic user space
and the mseal syscall available.

Move filemap fixup flag __VM_NO_COMPAT for x86_64 16kB emulation
to bit 58, which allows moving the ELF padding representation to
bits [62-59].

Bug: 383389169
Bug: 356480574
Change-Id: Ice27271290c12656bb12622dd0a9dfa744a4c730
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
This commit is contained in:
Kalesh Singh
2024-07-31 00:45:25 -07:00
committed by Carlos Llamas
parent 2a651ea884
commit 6fd1ed47f5
2 changed files with 7 additions and 5 deletions

View File

@@ -111,8 +111,8 @@ static __always_inline unsigned __page_shift(void)
* NOTE: __MAP_NO_COMPAT is not new UABI it is only ever set by the kernel
* in ___filemap_fixup()
*/
#define __VM_NO_COMPAT (_AC(1,ULL) << 59)
#define __MAP_NO_COMPAT (_AC(1,UL) << 31)
#define __VM_NO_COMPAT _BITULL(58)
#define __MAP_NO_COMPAT _BITUL(31)
/*
* Conditional page-alignment based on mmap flags

View File

@@ -23,22 +23,24 @@
* This allows the kernel to identify the portion of an ELF LOAD segment VMA
* that is padding.
*
* 4 high bits of vm_flags [63,60] are used to represent ELF segment padding
* 4 high bits of vm_flags [62,59] are used to represent ELF segment padding
* up to 60kB, which is sufficient for ELFs of both 16kB and 64kB segment
* alignment (p_align).
*
* The representation is illustrated below.
*
* 63 62 61 60
* 62 61 60 59
* _________ _________ _________ _________
* | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
* | of 4kB | of 4kB | of 4kB | of 4kB |
* | chunks | chunks | chunks | chunks |
* |_________|_________|_________|_________|
*
* NOTE: Bit 63 is already used by mseal()
*/
#define VM_PAD_WIDTH 4
#define VM_PAD_SHIFT (BITS_PER_LONG - VM_PAD_WIDTH)
#define VM_PAD_SHIFT (BITS_PER_LONG - VM_PAD_WIDTH - 1)
#define VM_TOTAL_PAD_PAGES ((1ULL << VM_PAD_WIDTH) - 1)
#define VM_PAD_MASK (VM_TOTAL_PAD_PAGES << VM_PAD_SHIFT)
#define VMA_PAD_START(vma) (vma->vm_end - (vma_pad_pages(vma) << PAGE_SHIFT))