Skip to content

Commit 44d0fb3

Browse files
lrh2000gregkh
authored andcommitted
mm: page_table_check: Ensure user pages are not slab pages
The current uses of PageAnon in page table check functions can lead to type confusion bugs between struct page and slab [1], if slab pages are accidentally mapped into the user space. This is because slab reuses the bits in struct page to store its internal states, which renders PageAnon ineffective on slab pages. Since slab pages are not expected to be mapped into the user space, this patch adds BUG_ON(PageSlab(page)) checks to make sure that slab pages are not inadvertently mapped. Otherwise, there must be some bugs in the kernel. Reported-by: syzbot+fcf1a817ceb50935ce99@syzkaller.appspotmail.com Closes: https://lore.kernel.org/lkml/000000000000258e5e05fae79fc1@google.com/ [1] Fixes: df4e817 ("mm: page table check") Cc: <stable@vger.kernel.org> # 5.17 Signed-off-by: Ruihan Li <lrh2000@pku.edu.cn> Acked-by: Pasha Tatashin <pasha.tatashin@soleen.com> Link: https://lore.kernel.org/r/20230515130958.32471-5-lrh2000@pku.edu.cn Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 81a31a8 commit 44d0fb3

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

include/linux/page-flags.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,12 @@ PAGEFLAG_FALSE(VmemmapSelfHosted, vmemmap_self_hosted)
617617
* Please note that, confusingly, "page_mapping" refers to the inode
618618
* address_space which maps the page from disk; whereas "page_mapped"
619619
* refers to user virtual address space into which the page is mapped.
620+
*
621+
* For slab pages, since slab reuses the bits in struct page to store its
622+
* internal states, the page->mapping does not exist as such, nor do these
623+
* flags below. So in order to avoid testing non-existent bits, please
624+
* make sure that PageSlab(page) actually evaluates to false before calling
625+
* the following functions (e.g., PageAnon). See mm/slab.h.
620626
*/
621627
#define PAGE_MAPPING_ANON 0x1
622628
#define PAGE_MAPPING_MOVABLE 0x2

mm/page_table_check.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ static void page_table_check_clear(struct mm_struct *mm, unsigned long addr,
7171

7272
page = pfn_to_page(pfn);
7373
page_ext = page_ext_get(page);
74+
75+
BUG_ON(PageSlab(page));
7476
anon = PageAnon(page);
7577

7678
for (i = 0; i < pgcnt; i++) {
@@ -107,6 +109,8 @@ static void page_table_check_set(struct mm_struct *mm, unsigned long addr,
107109

108110
page = pfn_to_page(pfn);
109111
page_ext = page_ext_get(page);
112+
113+
BUG_ON(PageSlab(page));
110114
anon = PageAnon(page);
111115

112116
for (i = 0; i < pgcnt; i++) {
@@ -133,6 +137,8 @@ void __page_table_check_zero(struct page *page, unsigned int order)
133137
struct page_ext *page_ext;
134138
unsigned long i;
135139

140+
BUG_ON(PageSlab(page));
141+
136142
page_ext = page_ext_get(page);
137143
BUG_ON(!page_ext);
138144
for (i = 0; i < (1ul << order); i++) {

0 commit comments

Comments
 (0)