ANDROID: 16K: Don't set padding vm_flags on 32-bit archs
vma_pad_fixup_flags() and is_mergable_pad_vma() were inadvertently affecting the vm_flags on 32-bit arch, making some VMAs not mergable. This causes zygote to crash as the Art GC's heap compaction fails. The compaction depends on mremap() which will fail when operating on a range that spans multiple VMAs [1]. This can happen now due to the incorrect is_mergable_pad_vma() check. Make all the pgsize_migration APIs no-ops in 32-bit architectures, since Android only performs ELF segment extension in 64-bit archs. [1] https://github.com/torvalds/linux/blob/v6.9/mm/mremap.c#L841-L843 Bug: 353667356 Change-Id: Id9b0076ef173d75a4afc85577355d340fce03e65 Signed-off-by: Kalesh Singh <kaleshsingh@google.com> (cherry picked from commit f3437db87063f624f189e1cd38347a971fdd3fa0)
This commit is contained in:
parent
dc1385281a
commit
adc9210e7e
2 changed files with 48 additions and 22 deletions
|
|
@ -62,6 +62,14 @@ extern void show_map_pad_vma(struct vm_area_struct *vma,
|
||||||
|
|
||||||
extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
||||||
unsigned long addr, int new_below);
|
unsigned long addr, int new_below);
|
||||||
|
|
||||||
|
extern unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
||||||
|
unsigned long newflags);
|
||||||
|
|
||||||
|
extern bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
||||||
|
unsigned long vm_flags);
|
||||||
|
|
||||||
|
extern unsigned long vma_data_pages(struct vm_area_struct *vma);
|
||||||
#else /* PAGE_SIZE != SZ_4K || !defined(CONFIG_64BIT) */
|
#else /* PAGE_SIZE != SZ_4K || !defined(CONFIG_64BIT) */
|
||||||
static inline void vma_set_pad_pages(struct vm_area_struct *vma,
|
static inline void vma_set_pad_pages(struct vm_area_struct *vma,
|
||||||
unsigned long nr_pages)
|
unsigned long nr_pages)
|
||||||
|
|
@ -98,36 +106,22 @@ static inline void split_pad_vma(struct vm_area_struct *vma, struct vm_area_stru
|
||||||
unsigned long addr, int new_below)
|
unsigned long addr, int new_below)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
|
|
||||||
|
|
||||||
static inline unsigned long vma_data_pages(struct vm_area_struct *vma)
|
|
||||||
{
|
|
||||||
return vma_pages(vma) - vma_pad_pages(vma);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the correct padding bits / flags for a VMA split.
|
|
||||||
*/
|
|
||||||
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
||||||
unsigned long newflags)
|
unsigned long newflags)
|
||||||
{
|
{
|
||||||
if (newflags & VM_PAD_MASK)
|
return newflags;
|
||||||
return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
|
|
||||||
else
|
|
||||||
return newflags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Merging of padding VMAs is uncommon, as padding is only allowed
|
|
||||||
* from the linker context.
|
|
||||||
*
|
|
||||||
* To simplify the semantics, adjacent VMAs with padding are not
|
|
||||||
* allowed to merge.
|
|
||||||
*/
|
|
||||||
static inline bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
static inline bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
||||||
unsigned long vm_flags)
|
unsigned long vm_flags)
|
||||||
{
|
{
|
||||||
/* Padding VMAs cannot be merged with other padding or real VMAs */
|
return true;
|
||||||
return !((vma->vm_flags | vm_flags) & VM_PAD_MASK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned long vma_data_pages(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
return vma_pages(vma);
|
||||||
|
}
|
||||||
|
#endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
|
||||||
#endif /* _LINUX_PAGE_SIZE_MIGRATION_H */
|
#endif /* _LINUX_PAGE_SIZE_MIGRATION_H */
|
||||||
|
|
|
||||||
|
|
@ -405,5 +405,37 @@ void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
|
||||||
vma_set_pad_pages(second, nr_vma2_pages);
|
vma_set_pad_pages(second, nr_vma2_pages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the correct padding bits / flags for a VMA split.
|
||||||
|
*/
|
||||||
|
unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
|
||||||
|
unsigned long newflags)
|
||||||
|
{
|
||||||
|
if (newflags & VM_PAD_MASK)
|
||||||
|
return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
|
||||||
|
else
|
||||||
|
return newflags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merging of padding VMAs is uncommon, as padding is only allowed
|
||||||
|
* from the linker context.
|
||||||
|
*
|
||||||
|
* To simplify the semantics, adjacent VMAs with padding are not
|
||||||
|
* allowed to merge.
|
||||||
|
*/
|
||||||
|
bool is_mergable_pad_vma(struct vm_area_struct *vma,
|
||||||
|
unsigned long vm_flags)
|
||||||
|
{
|
||||||
|
/* Padding VMAs cannot be merged with other padding or real VMAs */
|
||||||
|
return !((vma->vm_flags | vm_flags) & VM_PAD_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long vma_data_pages(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
return vma_pages(vma) - vma_pad_pages(vma);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* PAGE_SIZE == SZ_4K */
|
#endif /* PAGE_SIZE == SZ_4K */
|
||||||
#endif /* CONFIG_64BIT */
|
#endif /* CONFIG_64BIT */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue