| From: Miaohe Lin <linmiaohe@huawei.com> |
| Subject: mm: memory-failure: fix race window when trying to get hugetlb folio |
| Date: Tue, 11 Jul 2023 13:50:16 +0800 |
| |
| page_folio() is fetched before calling get_hwpoison_hugetlb_folio() |
| without hugetlb_lock being held. So hugetlb page could be demoted before |
| get_hwpoison_hugetlb_folio() holding hugetlb_lock but after page_folio() |
| is fetched. So get_hwpoison_hugetlb_folio() will hold unexpected extra |
| refcnt of hugetlb folio while leaving demoted page un-refcnted. |
| |
| Link: https://lkml.kernel.org/r/20230711055016.2286677-9-linmiaohe@huawei.com |
| Fixes: 25182f05ffed ("mm,hwpoison: fix race with hugetlb page allocation") |
| Signed-off-by: Miaohe Lin <linmiaohe@huawei.com> |
| Acked-by: Naoya Horiguchi <naoya.horiguchi@nec.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/memory-failure.c | 20 ++++++++++++++++---- |
| 1 file changed, 16 insertions(+), 4 deletions(-) |
| |
| --- a/mm/memory-failure.c~mm-memory-failure-fix-race-window-when-trying-to-get-hugetlb-folio |
| +++ a/mm/memory-failure.c |
| @@ -1383,8 +1383,15 @@ static int __get_hwpoison_page(struct pa |
| bool hugetlb = false; |
| |
| ret = get_hwpoison_hugetlb_folio(folio, &hugetlb, false); |
| - if (hugetlb) |
| - return ret; |
| + if (hugetlb) { |
| + /* Make sure hugetlb demotion did not happen from under us. */ |
| + if (folio == page_folio(page)) |
| + return ret; |
| + if (ret > 0) { |
| + folio_put(folio); |
| + folio = page_folio(page); |
| + } |
| + } |
| |
| /* |
| * This check prevents from calling folio_try_get() for any |
| @@ -1473,8 +1480,13 @@ static int __get_unpoison_page(struct pa |
| bool hugetlb = false; |
| |
| ret = get_hwpoison_hugetlb_folio(folio, &hugetlb, true); |
| - if (hugetlb) |
| - return ret; |
| + if (hugetlb) { |
| + /* Make sure hugetlb demotion did not happen from under us. */ |
| + if (folio == page_folio(page)) |
| + return ret; |
| + if (ret > 0) |
| + folio_put(folio); |
| + } |
| |
| /* |
| * PageHWPoisonTakenOff pages are not only marked as PG_hwpoison, |
| _ |