ANDROID: 16K: [s]maps: Fold fixup entries into the parent entry

In x86_64 16kb emulation mode the kernel will insert anonymous VMAs
at the end of filebacked of shmem mappings that are larger than the
backing file. This is done inorder to avoid invalid file faults.

The smaps/maps entries for fixup VMAs are currently hidden from
userspace to prevent processes performing syscalls on non-page
aligned addresses by scanning /proc/<pid>/[s]maps. However the end
of the original VMA is left as a non-16kB aligned address.

Fold the extend of the fixup VMA into the parent (preceding VMA).
This hides fixup VMA completely from userspace and any operations
performed with addresses from maps or smaps will be done on the
orignal range.

Before:

74b028b48000-74b028b49000 r--p 00000000 00:12 1441    /dev/test.so
74b028b4c000-74b028b50000 rw-p 00000000 00:00 0       [anon:Test mapping]

The unaligned gap [74b028b49000-74b028b4c000] between the 2 test
mappings is where the anon fixup was inserted.

After:

74b028b48000-74b028b4c000 r--p 00000000 00:12 1441    /dev/test.so
74b028b4c000-74b028b50000 rw-p 00000000 00:00 0       [anon:Test mapping]

There is no visible gap and the fixup mapping is now transparent to
userpsace.

Bug: 383389337
Bug: 328777915
Bug: 331683943
Change-Id: Ibe2fe630695d875a8d7798f235adcf277b16bd9c
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
This commit is contained in:
Kalesh Singh
2024-07-30 00:26:29 -07:00
committed by Carlos Llamas
parent 57bbcef534
commit 50a96587af
3 changed files with 28 additions and 3 deletions

View File

@@ -345,9 +345,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
start = vma->vm_start;
end = vma->vm_end;
/* Skip page size fixup VMAs */
if (flags & __VM_NO_COMPAT)
return;
__fold_filemap_fixup_entry(&((struct proc_maps_private *)m->private)->iter, &end);
show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino);

View File

@@ -161,6 +161,7 @@ static __always_inline void __filemap_fixup(unsigned long addr, unsigned long pr
___filemap_fixup(addr, prot, old_len, new_len);
}
extern void __fold_filemap_fixup_entry(struct vma_iterator *iter, unsigned long *end);
#endif /* !__ASSEMBLY__ */
#endif /* __LINUX_PAGE_SIZE_COMPAT_H */

View File

@@ -176,3 +176,29 @@ void ___filemap_fixup(unsigned long addr, unsigned long prot, unsigned long old_
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|__MAP_NO_COMPAT,
0, 0, &populate, NULL);
}
/*
* Folds any anon fixup entries created by ___filemap_fixup()
* into the previous mapping so that /proc/<pid>/[s]maps don't
* show unaliged entries.
*/
void __fold_filemap_fixup_entry(struct vma_iterator *iter, unsigned long *end)
{
struct vm_area_struct *next_vma;
/* Not emulating page size? */
if (!static_branch_unlikely(&page_shift_compat_enabled))
return;
/* Advance iterator */
next_vma = vma_next(iter);
/* If fixup VMA, adjust the end to cover its extent */
if (next_vma && (next_vma->vm_flags & __VM_NO_COMPAT)) {
*end = next_vma->vm_end;
return;
}
/* Rewind iterator */
vma_prev(iter);
}