| From: Mike Kravetz <mike.kravetz@oracle.com> |
| Subject: hugetlb: fix uninitialized subpool pointer |
| |
| Gerald Schaefer reported a panic on s390 in hugepage_subpool_put_pages() |
| with linux-next 5.12.0-20210222. |
| Call trace: |
| hugepage_subpool_put_pages.part.0+0x2c/0x138 |
| __free_huge_page+0xce/0x310 |
| alloc_pool_huge_page+0x102/0x120 |
| set_max_huge_pages+0x13e/0x350 |
| hugetlb_sysctl_handler_common+0xd8/0x110 |
| hugetlb_sysctl_handler+0x48/0x58 |
| proc_sys_call_handler+0x138/0x238 |
| new_sync_write+0x10e/0x198 |
| vfs_write.part.0+0x12c/0x238 |
| ksys_write+0x68/0xf8 |
| do_syscall+0x82/0xd0 |
| __do_syscall+0xb4/0xc8 |
| system_call+0x72/0x98 |
| |
| This is a result of the change which moved the hugetlb page subpool |
| pointer from page->private to page[1]->private. When new pages are |
| allocated from the buddy allocator, the private field of the head |
| page will be cleared, but the private field of subpages is not modified. |
| Therefore, old values may remain. |
| |
| Fix by initializing hugetlb page subpool pointer in prep_new_huge_page(). |
| |
| Link: https://lkml.kernel.org/r/20210223215544.313871-1-mike.kravetz@oracle.com |
| Fixes: f1280272ae4d ("hugetlb: use page.private for hugetlb specific page flags") |
| Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> |
| Reported-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com> |
| Reviewed-by: Oscar Salvador <osalvador@suse.de> |
| Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com> |
| Cc: Michal Hocko <mhocko@suse.com> |
| Cc: Muchun Song <songmuchun@bytedance.com> |
| Cc: Heiko Carstens <hca@linux.ibm.com> |
| Cc: Sven Schnelle <svens@linux.ibm.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/hugetlb.c | 1 + |
| 1 file changed, 1 insertion(+) |
| |
| --- a/mm/hugetlb.c~hugetlb-use-pageprivate-for-hugetlb-specific-page-flags-fix |
| +++ a/mm/hugetlb.c |
| @@ -1526,6 +1526,7 @@ static void prep_new_huge_page(struct hs |
| { |
| INIT_LIST_HEAD(&page->lru); |
| set_compound_page_dtor(page, HUGETLB_PAGE_DTOR); |
| + hugetlb_set_page_subpool(page, NULL); |
| set_hugetlb_cgroup(page, NULL); |
| set_hugetlb_cgroup_rsvd(page, NULL); |
| spin_lock(&hugetlb_lock); |
| _ |