Commit 2ed2db6a authored by Jan Stancek's avatar Jan Stancek Committed by Greg Kroah-Hartman
Browse files

mm: page_mapped: don't assume compound page is huge or THP

commit 8ab88c71 upstream.

LTP proc01 testcase has been observed to rarely trigger crashes
on arm64:

The issue is that page_mapped() assumes that if compound page is not
huge, then it must be THP.  But if this is 'normal' compound page
(COMPOUND_PAGE_DTOR), then following loop can keep running (for
HPAGE_PMD_NR iterations) until it tries to read from memory that isn't
mapped and triggers a panic:

        for (i = 0; i < hpage_nr_pages(page); i++) {
                if (atomic_read(&page[i]._mapcount) >= 0)
                        return true;

I could replicate this on x86 (v4.20-rc4-98-g60b54823) only
with a custom kernel module [1] which:
 - allocates compound page (PAGEC) of order 1
 - allocates 2 normal pages (COPY), which are initialized to 0xff (to
   satisfy _mapcount >= 0)
 - 2 PAGEC page structs are copied to address of first COPY page
 - second page of COPY is marked as not present
 - call to page_mapped(COPY) now triggers fault on access to 2nd COPY
   page at offset 0x30 (_mapcount)


Fix the loop to iterate for "1 << compound_order" pages.

Kirrill said "IIRC, sound subsystem can producuce custom mapped compound

Fixes: e1534ae9

 ("mm: differentiate page_mapped() from page_mapcount() for compound pages")
Signed-off-by: default avatarJan Stancek <>
Debugged-by: default avatarLaszlo Ersek <>
Suggested-by: default avatar"Kirill A. Shutemov" <>
Acked-by: default avatarMichal Hocko <>
Acked-by: default avatarKirill A. Shutemov <>
Reviewed-by: default avatarDavid Hildenbrand <>
Reviewed-by: default avatarAndrea Arcangeli <>
Cc: <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent 096909af
......@@ -478,7 +478,7 @@ bool page_mapped(struct page *page)
return true;
if (PageHuge(page))
return false;
for (i = 0; i < hpage_nr_pages(page); i++) {
for (i = 0; i < (1 << compound_order(page)); i++) {
if (atomic_read(&page[i]._mapcount) >= 0)
return true;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment