[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220126183429.1840447-3-pasha.tatashin@soleen.com>
Date: Wed, 26 Jan 2022 18:34:22 +0000
From: Pasha Tatashin <pasha.tatashin@...een.com>
To: pasha.tatashin@...een.com, linux-kernel@...r.kernel.org,
linux-mm@...ck.org, linux-m68k@...ts.linux-m68k.org,
anshuman.khandual@....com, willy@...radead.org,
akpm@...ux-foundation.org, william.kucharski@...cle.com,
mike.kravetz@...cle.com, vbabka@...e.cz, geert@...ux-m68k.org,
schmitzmic@...il.com, rostedt@...dmis.org, mingo@...hat.com,
hannes@...xchg.org, guro@...com, songmuchun@...edance.com,
weixugc@...gle.com, gthelen@...gle.com, rientjes@...gle.com,
pjt@...gle.com, hughd@...gle.com
Subject: [PATCH v3 2/9] mm: Avoid using set_page_count() in set_page_recounted()
set_page_refcounted() converts a non-refcounted page that has
(page->_refcount == 0) into a refcounted page by setting _refcount to
1.
The current apporach uses the following logic:
VM_BUG_ON_PAGE(page_ref_count(page), page);
set_page_count(page, 1);
However, if _refcount changes from 0 to 1 between the VM_BUG_ON_PAGE()
and set_page_count() we can break _refcount, which can cause other
problems such as memory corruptions.
Instead, use a safer method: increment _refcount first and verify
that at increment time it was indeed 1.
refcnt = page_ref_inc_return(page);
VM_BUG_ON_PAGE(refcnt != 1, page);
Use page_ref_inc_return() to avoid unconditionally overwriting
the _refcount value with set_page_count(), and check the return value.
Signed-off-by: Pasha Tatashin <pasha.tatashin@...een.com>
---
mm/internal.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index 4c2d06a2f50b..6b74f7f32613 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -141,9 +141,11 @@ static inline bool page_evictable(struct page *page)
*/
static inline void set_page_refcounted(struct page *page)
{
+ int refcnt;
+
VM_BUG_ON_PAGE(PageTail(page), page);
- VM_BUG_ON_PAGE(page_ref_count(page), page);
- set_page_count(page, 1);
+ refcnt = page_ref_inc_return(page);
+ VM_BUG_ON_PAGE(refcnt != 1, page);
}
extern unsigned long highest_memmap_pfn;
--
2.35.0.rc0.227.g00780c9af4-goog
Powered by blists - more mailing lists