Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] mm/page_table_check: widen map counters
       [not found] <cover.1784337674.git.roxy520tt@gmail.com>
@ 2026-07-18  4:27 ` Ren Wei
  2026-07-18  5:11   ` Andrew Morton
                     ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Ren Wei @ 2026-07-18  4:27 UTC (permalink / raw)
  To: linux-mm; +Cc: pasha.tatashin, akpm, vega, roxy520tt, enjou1224z

From: Zhiling Zou <roxy520tt@gmail.com>

page_table_check_set() and page_table_check_clear() store per-page
anonymous and file map counts in signed atomic_t counters. A page can
have more than INT_MAX read-only mappings while still being mapped
legally.

The global zero page is one example: repeated read faults on private
anonymous mappings install read-only PTEs that are accounted as file
mappings. Once file_map_count wraps, the next set or clear observes a
negative count and trips BUG_ON(), allowing an unprivileged user to panic
a kernel with CONFIG_PAGE_TABLE_CHECK enabled.

Use atomic64_t for both counters so page_table_check can keep the same
type-conflict checks without overflowing at INT_MAX mappings.

Fixes: df4e817b7108 ("mm: page table check")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
Reviewed-by: Ren Wei <enjou1224z@gmail.com>
---
 mm/page_table_check.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/mm/page_table_check.c b/mm/page_table_check.c
index 53a8997ec043..edd9d9edf6fc 100644
--- a/mm/page_table_check.c
+++ b/mm/page_table_check.c
@@ -14,8 +14,8 @@
 #define pr_fmt(fmt)	"page_table_check: " fmt
 
 struct page_table_check {
-	atomic_t anon_map_count;
-	atomic_t file_map_count;
+	atomic64_t anon_map_count;
+	atomic64_t file_map_count;
 };
 
 static bool __page_table_check_enabled __initdata =
@@ -79,11 +79,11 @@ static void page_table_check_clear(unsigned long pfn, unsigned long pgcnt)
 		struct page_table_check *ptc = get_page_table_check(page_ext);
 
 		if (anon) {
-			BUG_ON(atomic_read(&ptc->file_map_count));
-			BUG_ON(atomic_dec_return(&ptc->anon_map_count) < 0);
+			BUG_ON(atomic64_read(&ptc->file_map_count));
+			BUG_ON(atomic64_dec_return(&ptc->anon_map_count) < 0);
 		} else {
-			BUG_ON(atomic_read(&ptc->anon_map_count));
-			BUG_ON(atomic_dec_return(&ptc->file_map_count) < 0);
+			BUG_ON(atomic64_read(&ptc->anon_map_count));
+			BUG_ON(atomic64_dec_return(&ptc->file_map_count) < 0);
 		}
 	}
 	rcu_read_unlock();
@@ -114,11 +114,11 @@ static void page_table_check_set(unsigned long pfn, unsigned long pgcnt,
 		struct page_table_check *ptc = get_page_table_check(page_ext);
 
 		if (anon) {
-			BUG_ON(atomic_read(&ptc->file_map_count));
-			BUG_ON(atomic_inc_return(&ptc->anon_map_count) > 1 && rw);
+			BUG_ON(atomic64_read(&ptc->file_map_count));
+			BUG_ON(atomic64_inc_return(&ptc->anon_map_count) > 1 && rw);
 		} else {
-			BUG_ON(atomic_read(&ptc->anon_map_count));
-			BUG_ON(atomic_inc_return(&ptc->file_map_count) < 0);
+			BUG_ON(atomic64_read(&ptc->anon_map_count));
+			BUG_ON(atomic64_inc_return(&ptc->file_map_count) < 0);
 		}
 	}
 	rcu_read_unlock();
@@ -139,8 +139,8 @@ void __page_table_check_zero(struct page *page, unsigned int order)
 	for_each_page_ext(page, 1 << order, page_ext, iter) {
 		struct page_table_check *ptc = get_page_table_check(page_ext);
 
-		BUG_ON(atomic_read(&ptc->anon_map_count));
-		BUG_ON(atomic_read(&ptc->file_map_count));
+		BUG_ON(atomic64_read(&ptc->anon_map_count));
+		BUG_ON(atomic64_read(&ptc->file_map_count));
 	}
 	rcu_read_unlock();
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] mm/page_table_check: widen map counters
  2026-07-18  4:27 ` [PATCH 1/1] mm/page_table_check: widen map counters Ren Wei
@ 2026-07-18  5:11   ` Andrew Morton
  2026-07-18  5:31     ` Andrew Morton
  2026-07-18  5:17   ` Matthew Wilcox
  2026-09-01 23:50   ` Andrew Morton
  2 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2026-07-18  5:11 UTC (permalink / raw)
  To: Ren Wei
  Cc: linux-mm, pasha.tatashin, vega, roxy520tt, Vlastimil Babka,
	Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner

On Sat, 18 Jul 2026 12:27:20 +0800 Ren Wei <enjou1224z@gmail.com> wrote:

> From: Zhiling Zou <roxy520tt@gmail.com>
> 
> page_table_check_set() and page_table_check_clear() store per-page
> anonymous and file map counts in signed atomic_t counters. A page can
> have more than INT_MAX read-only mappings while still being mapped
> legally.
> 
> The global zero page is one example: repeated read faults on private
> anonymous mappings install read-only PTEs that are accounted as file
> mappings. Once file_map_count wraps, the next set or clear observes a
> negative count and trips BUG_ON(), allowing an unprivileged user to panic
> a kernel with CONFIG_PAGE_TABLE_CHECK enabled.
> 
> Use atomic64_t for both counters so page_table_check can keep the same
> type-conflict checks without overflowing at INT_MAX mappings.

Thanks.

> Fixes: df4e817b7108 ("mm: page table check")
> Cc: stable@vger.kernel.org
>
> ...
>
> index 53a8997ec043..edd9d9edf6fc 100644
> --- a/mm/page_table_check.c
> +++ b/mm/page_table_check.c
> @@ -14,8 +14,8 @@
>  #define pr_fmt(fmt)	"page_table_check: " fmt
>  
>  struct page_table_check {
> -	atomic_t anon_map_count;
> -	atomic_t file_map_count;
> +	atomic64_t anon_map_count;
> +	atomic64_t file_map_count;
>  };

AI review suggest this might cause problems in, of all places, page_ext.c:

	https://sashiko.dev/#/patchset/b4414b588418c52a99d959d35a40e064ae8b6e72.1784337674.git.roxy520tt@gmail.com

My googling indicates that a 64-bit atomic op on a 32-bit-aligned
address is probably usually OK, but it doesn't sound smart.

Probably adding __aligned(sizeof(atomic64_t)) will address?


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] mm/page_table_check: widen map counters
  2026-07-18  4:27 ` [PATCH 1/1] mm/page_table_check: widen map counters Ren Wei
  2026-07-18  5:11   ` Andrew Morton
@ 2026-07-18  5:17   ` Matthew Wilcox
  2026-09-01 23:50   ` Andrew Morton
  2 siblings, 0 replies; 7+ messages in thread
From: Matthew Wilcox @ 2026-07-18  5:17 UTC (permalink / raw)
  To: Ren Wei; +Cc: linux-mm, pasha.tatashin, akpm, vega, roxy520tt

On Sat, Jul 18, 2026 at 12:27:20PM +0800, Ren Wei wrote:
> page_table_check_set() and page_table_check_clear() store per-page
> anonymous and file map counts in signed atomic_t counters. A page can
> have more than INT_MAX read-only mappings while still being mapped
> legally.

No it can't.  mapcount is 32-bit.

> The global zero page is one example: repeated read faults on private

You mean "is a special case".  page_table_check should handle this
case specially.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] mm/page_table_check: widen map counters
  2026-07-18  5:11   ` Andrew Morton
@ 2026-07-18  5:31     ` Andrew Morton
  2026-07-18 10:21       ` tt roxy
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2026-07-18  5:31 UTC (permalink / raw)
  To: Ren Wei, linux-mm, pasha.tatashin, vega, roxy520tt,
	Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
	Brendan Jackman, Johannes Weiner

On Fri, 17 Jul 2026 22:11:08 -0700 Andrew Morton <akpm@linux-foundation.org> wrote:

> Probably adding __aligned(sizeof(atomic64_t)) will address?

err, no.  I think page_ext code will need alteration for this.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] mm/page_table_check: widen map counters
  2026-07-18  5:31     ` Andrew Morton
@ 2026-07-18 10:21       ` tt roxy
  2026-07-19 15:20         ` Pasha Tatashin
  0 siblings, 1 reply; 7+ messages in thread
From: tt roxy @ 2026-07-18 10:21 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Ren Wei, linux-mm, pasha.tatashin, vega, Vlastimil Babka,
	Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner

On Sat, Jul 18, 2026 at 1:31 PM Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Fri, 17 Jul 2026 22:11:08 -0700 Andrew Morton <akpm@linux-foundation.org> wrote:
>
> > Probably adding __aligned(sizeof(atomic64_t)) will address?
>
> err, no.  I think page_ext code will need alteration for this.

Thanks Andrew and Matthew.

Agreed. Widening the counters is not the right direction: it changes the
page_ext storage/alignment requirements, and normal page mapcount is still
32-bit as Matthew pointed out.

I'll rework this around a zero-page-specific fix and send v2 after checking
the exact page_table_check paths.

Thanks for the review.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] mm/page_table_check: widen map counters
  2026-07-18 10:21       ` tt roxy
@ 2026-07-19 15:20         ` Pasha Tatashin
  0 siblings, 0 replies; 7+ messages in thread
From: Pasha Tatashin @ 2026-07-19 15:20 UTC (permalink / raw)
  To: tt roxy
  Cc: Andrew Morton, Ren Wei, linux-mm, pasha.tatashin, vega,
	Vlastimil Babka, Suren Baghdasaryan, Michal Hocko,
	Brendan Jackman, Johannes Weiner

On 07-18 18:21, tt roxy wrote:
> On Sat, Jul 18, 2026 at 1:31 PM Andrew Morton <akpm@linux-foundation.org> wrote:
> >
> > On Fri, 17 Jul 2026 22:11:08 -0700 Andrew Morton <akpm@linux-foundation.org> wrote:
> >
> > > Probably adding __aligned(sizeof(atomic64_t)) will address?
> >
> > err, no.  I think page_ext code will need alteration for this.
> 
> Thanks Andrew and Matthew.
> 
> Agreed. Widening the counters is not the right direction: it changes the
> page_ext storage/alignment requirements, and normal page mapcount is still
> 32-bit as Matthew pointed out.

Also, double page table check overhead. So, I agree let's address the 
special case instead of widening page_ext.

Thanks,
Pasha

> 
> I'll rework this around a zero-page-specific fix and send v2 after checking
> the exact page_table_check paths.
> 
> Thanks for the review.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/1] mm/page_table_check: widen map counters
  2026-07-18  4:27 ` [PATCH 1/1] mm/page_table_check: widen map counters Ren Wei
  2026-07-18  5:11   ` Andrew Morton
  2026-07-18  5:17   ` Matthew Wilcox
@ 2026-09-01 23:50   ` Andrew Morton
  2 siblings, 0 replies; 7+ messages in thread
From: Andrew Morton @ 2026-09-01 23:50 UTC (permalink / raw)
  To: Ren Wei; +Cc: linux-mm, pasha.tatashin, vega, roxy520tt

On Sat, 18 Jul 2026 12:27:20 +0800 Ren Wei <enjou1224z@gmail.com> wrote:

> From: Zhiling Zou <roxy520tt@gmail.com>
> 
> page_table_check_set() and page_table_check_clear() store per-page
> anonymous and file map counts in signed atomic_t counters. A page can
> have more than INT_MAX read-only mappings while still being mapped
> legally.
> 
> The global zero page is one example: repeated read faults on private
> anonymous mappings install read-only PTEs that are accounted as file
> mappings. Once file_map_count wraps, the next set or clear observes a
> negative count and trips BUG_ON(), allowing an unprivileged user to panic
> a kernel with CONFIG_PAGE_TABLE_CHECK enabled.
> 
> Use atomic64_t for both counters so page_table_check can keep the same
> type-conflict checks without overflowing at INT_MAX mappings.
> 
> Fixes: df4e817b7108 ("mm: page table check")
> Cc: stable@vger.kernel.org
> Reported-by: Vega <vega@nebusec.ai>
> Assisted-by: Codex:gpt-5.4
> Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
> Reviewed-by: Ren Wei <enjou1224z@gmail.com>

Thanks.

I've merged Zhiling's "mm/page_table_check: prevent map count
overflow", which appears to address the same issue. 
https://lore.kernel.org/1f8848512d2e3ded944f8d595c29faee8fdaeab0.1784645969.git.roxy520tt@gmail.com

But the patch I merged is very different from the below.  I assume the
patch I merged is the one which you want because it was sent three days
later.  Correct?


However my question regarding the possibly missing barrier remains
unaddressed:

	https://lore.kernel.org/all/20260721135614.7aa2d8d9a8a732a66ba623c3@linux-foundation.org/


> --- a/mm/page_table_check.c
> +++ b/mm/page_table_check.c
> @@ -14,8 +14,8 @@
>  #define pr_fmt(fmt)	"page_table_check: " fmt
>  
>  struct page_table_check {
> -	atomic_t anon_map_count;
> -	atomic_t file_map_count;
> +	atomic64_t anon_map_count;
> +	atomic64_t file_map_count;
>  };
>  
>  static bool __page_table_check_enabled __initdata =
> @@ -79,11 +79,11 @@ static void page_table_check_clear(unsigned long pfn, unsigned long pgcnt)
>  		struct page_table_check *ptc = get_page_table_check(page_ext);
>  
>  		if (anon) {
> -			BUG_ON(atomic_read(&ptc->file_map_count));
> -			BUG_ON(atomic_dec_return(&ptc->anon_map_count) < 0);
> +			BUG_ON(atomic64_read(&ptc->file_map_count));
> +			BUG_ON(atomic64_dec_return(&ptc->anon_map_count) < 0);
>  		} else {
> -			BUG_ON(atomic_read(&ptc->anon_map_count));
> -			BUG_ON(atomic_dec_return(&ptc->file_map_count) < 0);
> +			BUG_ON(atomic64_read(&ptc->anon_map_count));
> +			BUG_ON(atomic64_dec_return(&ptc->file_map_count) < 0);
>  		}
>  	}
>  	rcu_read_unlock();
> @@ -114,11 +114,11 @@ static void page_table_check_set(unsigned long pfn, unsigned long pgcnt,
>  		struct page_table_check *ptc = get_page_table_check(page_ext);
>  
>  		if (anon) {
> -			BUG_ON(atomic_read(&ptc->file_map_count));
> -			BUG_ON(atomic_inc_return(&ptc->anon_map_count) > 1 && rw);
> +			BUG_ON(atomic64_read(&ptc->file_map_count));
> +			BUG_ON(atomic64_inc_return(&ptc->anon_map_count) > 1 && rw);
>  		} else {
> -			BUG_ON(atomic_read(&ptc->anon_map_count));
> -			BUG_ON(atomic_inc_return(&ptc->file_map_count) < 0);
> +			BUG_ON(atomic64_read(&ptc->anon_map_count));
> +			BUG_ON(atomic64_inc_return(&ptc->file_map_count) < 0);
>  		}
>  	}
>  	rcu_read_unlock();
> @@ -139,8 +139,8 @@ void __page_table_check_zero(struct page *page, unsigned int order)
>  	for_each_page_ext(page, 1 << order, page_ext, iter) {
>  		struct page_table_check *ptc = get_page_table_check(page_ext);
>  
> -		BUG_ON(atomic_read(&ptc->anon_map_count));
> -		BUG_ON(atomic_read(&ptc->file_map_count));
> +		BUG_ON(atomic64_read(&ptc->anon_map_count));
> +		BUG_ON(atomic64_read(&ptc->file_map_count));
>  	}
>  	rcu_read_unlock();
>  }
> -- 
> 2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-09-01 23:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1784337674.git.roxy520tt@gmail.com>
2026-07-18  4:27 ` [PATCH 1/1] mm/page_table_check: widen map counters Ren Wei
2026-07-18  5:11   ` Andrew Morton
2026-07-18  5:31     ` Andrew Morton
2026-07-18 10:21       ` tt roxy
2026-07-19 15:20         ` Pasha Tatashin
2026-07-18  5:17   ` Matthew Wilcox
2026-09-01 23:50   ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox