All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xianting Tian <xianting.tian@linux.alibaba.com>
To: akpm@linux-foundation.org, ziy@nvidia.com,
	gregkh@linuxfoundation.org, stable@vger.kernel.org,
	guoren@kernel.org
Cc: huanyi.xj@alibaba-inc.com, guohanjun@huawei.com,
	zjb194813@alibaba-inc.com, tianhu.hh@alibaba-inc.com,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	Xianting Tian <xianting.tian@linux.alibaba.com>
Subject: [PATCH 5.17] mm: validate buddy page before using
Date: Fri, 17 Jun 2022 00:17:46 +0800	[thread overview]
Message-ID: <20220616161746.3565225-7-xianting.tian@linux.alibaba.com> (raw)
In-Reply-To: <20220616161746.3565225-1-xianting.tian@linux.alibaba.com>

Commit 787af64d05cd ("mm: page_alloc: validate buddy before check its migratetype.")
fixes a bug in 1dd214b8f21c and there is a similar bug in d9dddbf55667 that
can be fixed in a similar way too.

In unset_migratetype_isolate(), we also need the fix, so move page_is_buddy()
from mm/page_alloc.c to mm/internal.h

In addition, for RISC-V arch the first 2MB RAM could be reserved for opensbi,
so it would have pfn_base=512 and mem_map began with 512th PFN when
CONFIG_FLATMEM=y.
But __find_buddy_pfn algorithm thinks the start pfn 0, it could get 0 pfn or
less than the pfn_base value. We need page_is_buddy() to verify the buddy to
prevent accessing an invalid buddy.

Fixes: d9dddbf55667 ("mm/page_alloc: prevent merging between isolated and other pageblocks")
Cc: stable@vger.kernel.org
Reported-by: zjb194813@alibaba-inc.com
Reported-by: tianhu.hh@alibaba-inc.com
Signed-off-by: Xianting Tian <xianting.tian@linux.alibaba.com>
---
 mm/internal.h       | 34 ++++++++++++++++++++++++++++++++++
 mm/page_alloc.c     | 37 +++----------------------------------
 mm/page_isolation.c |  3 ++-
 3 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index d80300392a19..dfa80bdfe5c6 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -386,6 +386,40 @@ static inline bool is_data_mapping(vm_flags_t flags)
 	return (flags & (VM_WRITE | VM_SHARED | VM_STACK)) == VM_WRITE;
 }
 
+/*
+ * This function checks whether a page is free && is the buddy
+ * we can coalesce a page and its buddy if
+ * (a) the buddy is not in a hole (check before calling!) &&
+ * (b) the buddy is in the buddy system &&
+ * (c) a page and its buddy have the same order &&
+ * (d) a page and its buddy are in the same zone.
+ *
+ * For recording whether a page is in the buddy system, we set PageBuddy.
+ * Setting, clearing, and testing PageBuddy is serialized by zone->lock.
+ *
+ * For recording page's order, we use page_private(page).
+ */
+static inline bool page_is_buddy(struct page *page, struct page *buddy,
+							unsigned int order)
+{
+	if (!page_is_guard(buddy) && !PageBuddy(buddy))
+		return false;
+
+	if (buddy_order(buddy) != order)
+		return false;
+
+	/*
+	 * zone check is done late to avoid uselessly calculating
+	 * zone/node ids for pages that could never merge.
+	 */
+	if (page_zone_id(page) != page_zone_id(buddy))
+		return false;
+
+	VM_BUG_ON_PAGE(page_count(buddy) != 0, buddy);
+
+	return true;
+}
+
 /* mm/util.c */
 void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
 		struct vm_area_struct *prev);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b1caa1c6c887..78ada8dedefb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -886,40 +886,6 @@ static inline void set_buddy_order(struct page *page, unsigned int order)
 	__SetPageBuddy(page);
 }
 
-/*
- * This function checks whether a page is free && is the buddy
- * we can coalesce a page and its buddy if
- * (a) the buddy is not in a hole (check before calling!) &&
- * (b) the buddy is in the buddy system &&
- * (c) a page and its buddy have the same order &&
- * (d) a page and its buddy are in the same zone.
- *
- * For recording whether a page is in the buddy system, we set PageBuddy.
- * Setting, clearing, and testing PageBuddy is serialized by zone->lock.
- *
- * For recording page's order, we use page_private(page).
- */
-static inline bool page_is_buddy(struct page *page, struct page *buddy,
-							unsigned int order)
-{
-	if (!page_is_guard(buddy) && !PageBuddy(buddy))
-		return false;
-
-	if (buddy_order(buddy) != order)
-		return false;
-
-	/*
-	 * zone check is done late to avoid uselessly calculating
-	 * zone/node ids for pages that could never merge.
-	 */
-	if (page_zone_id(page) != page_zone_id(buddy))
-		return false;
-
-	VM_BUG_ON_PAGE(page_count(buddy) != 0, buddy);
-
-	return true;
-}
-
 #ifdef CONFIG_COMPACTION
 static inline struct capture_control *task_capc(struct zone *zone)
 {
@@ -1129,6 +1095,9 @@ static inline void __free_one_page(struct page *page,
 
 			buddy_pfn = __find_buddy_pfn(pfn, order);
 			buddy = page + (buddy_pfn - pfn);
+
+			if (!page_is_buddy(page, buddy, order))
+				goto done_merging;
 			buddy_mt = get_pageblock_migratetype(buddy);
 
 			if (migratetype != buddy_mt
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index f67c4c70f17f..5d14cef812ee 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -93,7 +93,8 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
 			buddy_pfn = __find_buddy_pfn(pfn, order);
 			buddy = page + (buddy_pfn - pfn);
 
-			if (!is_migrate_isolate_page(buddy)) {
+			if (page_is_buddy(page, buddy, order) &&
+			    !is_migrate_isolate_page(buddy)) {
 				isolated_page = !!__isolate_free_page(page, order);
 				/*
 				 * Isolating a free page in an isolated pageblock
-- 
2.17.1


  parent reply	other threads:[~2022-06-16 16:18 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-16 16:17 [PATCH] mm: page_alloc: validate buddy page before using Xianting Tian
2022-06-16 16:17 ` [PATCH 4.14] " Xianting Tian
2022-06-16 16:17 ` [PATCH 4.19] " Xianting Tian
2022-06-16 16:17 ` [PATCH 5.4] " Xianting Tian
2022-06-16 16:17 ` [PATCH 5.10] " Xianting Tian
2022-06-16 16:17 ` [PATCH 5.15] mm: " Xianting Tian
2022-06-20 10:17   ` Greg KH
2022-06-20 10:54     ` Xianting Tian
2022-06-20 11:42       ` Greg KH
2022-06-20 11:57         ` Xianting Tian
2022-06-20 12:06           ` Greg KH
2022-06-20 12:18             ` Xianting Tian
2022-06-20 12:24               ` Greg KH
2022-06-20 12:41                 ` Xianting Tian
2022-06-20 12:45                 ` Zi Yan
2022-06-20 12:54                   ` Greg KH
2022-06-20 14:13                     ` Zi Yan
2022-06-20 20:31                       ` Greg KH
2022-06-22  1:37                         ` Xianting Tian
2022-06-22  1:52                           ` Zi Yan
2022-07-06  2:51                         ` Xianting Tian
2022-06-20 12:25               ` Zi Yan
2022-06-16 16:17 ` Xianting Tian [this message]
2022-06-16 16:20 ` [PATCH] mm: page_alloc: " Xianting Tian
2022-06-16 16:50   ` Greg KH
2022-06-17  1:24     ` Xianting Tian

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220616161746.3565225-7-xianting.tian@linux.alibaba.com \
    --to=xianting.tian@linux.alibaba.com \
    --cc=akpm@linux-foundation.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=guohanjun@huawei.com \
    --cc=guoren@kernel.org \
    --cc=huanyi.xj@alibaba-inc.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=stable@vger.kernel.org \
    --cc=tianhu.hh@alibaba-inc.com \
    --cc=ziy@nvidia.com \
    --cc=zjb194813@alibaba-inc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.