Linux cgroups development
 help / color / mirror / Atom feed
* [PATCH] mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host
@ 2026-05-04 12:55 Jose Fernandez (Anthropic)
  0 siblings, 0 replies; 4+ messages in thread
From: Jose Fernandez (Anthropic) @ 2026-05-04 12:55 UTC (permalink / raw)
  To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
	Muchun Song, Andrew Morton, Hugh Dickins, David Hildenbrand,
	Barry Song
  Cc: cgroups, linux-mm, linux-kernel, Kairui Song, stable,
	syzbot+e12bd9ca48157add237a, Jose Fernandez (Anthropic)

lookup_swap_cgroup_id() passes swap_cgroup_ctrl[type].map to
__swap_cgroup_id_lookup() without checking that the type was ever
registered via swap_cgroup_swapon(). On a swapless host every
ctrl->map is NULL, so __swap_cgroup_id_lookup() dereferences
NULL + a scaled swp_offset().

Since commit bea67dcc5eea ("mm: attempt to batch free swap entries
for zap_pte_range()"), zap_pte_range() -> swap_pte_batch() calls
lookup_swap_cgroup_id() on any non-present, non-none PTE that
decodes as a real swap entry, without first validating it against
swap_info[]. A single PTE corrupted into a type-0 swap entry takes
the host down at process exit.

We hit this in production on a swapless 6.12.58 host: ~1s of
"get_swap_device: Bad swap file entry 3f800204222bb" (do_swap_page()
being correctly defensive about the same entry) followed by

  BUG: unable to handle page fault for address: 000003f800204220
  RIP: 0010:lookup_swap_cgroup_id+0x2b/0x60
  Call Trace:
   swap_pte_batch+0xbf/0x230
   zap_pte_range+0x4c8/0x780
   unmap_page_range+0x190/0x3e0
   exit_mmap+0xd9/0x3c0
   do_exit+0x20c/0x4b0

syzbot has reported the identical stack.

The source of the PTE corruption is a separate bug; this change
makes the teardown path as robust as the fault path already is.
Every other caller of lookup_swap_cgroup_id() is downstream of a
get_swap_device() that has already validated the entry, so the new
branch is cold.

Fixes: bea67dcc5eea ("mm: attempt to batch free swap entries for zap_pte_range()")
Cc: stable@vger.kernel.org
Reported-by: syzbot+e12bd9ca48157add237a@syzkaller.appspotmail.com
Link: https://lore.kernel.org/r/69859728.050a0220.3b3015.0033.GAE@google.com
Assisted-by: Claude:unspecified
Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
---
 mm/swap_cgroup.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c
index de779fed8c210..95c38e54dd587 100644
--- a/mm/swap_cgroup.c
+++ b/mm/swap_cgroup.c
@@ -124,6 +124,8 @@ unsigned short lookup_swap_cgroup_id(swp_entry_t ent)
 		return 0;
 
 	ctrl = &swap_cgroup_ctrl[swp_type(ent)];
+	if (unlikely(!ctrl->map))
+		return 0;
 	return __swap_cgroup_id_lookup(ctrl->map, swp_offset(ent));
 }
 

---
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
change-id: 20260504-swap-cgroup-fix-7-0-ed0fcdb8f103

Best regards,
--  
Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>


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

* [PATCH] mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host
@ 2026-08-14  7:47 mambaxin
  2026-08-14 11:23 ` Barry Song
  0 siblings, 1 reply; 4+ messages in thread
From: mambaxin @ 2026-08-14  7:47 UTC (permalink / raw)
  To: hannes, mhocko, roman.gushchin, shakeelb, muchun.song, akpm,
	david, v-songbaohua, hughd, cgroups, linux-mm, linux-kernel
  Cc: gregkh, jose.fernandez, stable, syzbot+e12bd9ca48157add237a,
	Barry Song, David Hildenbrand, Kairui Song, Shakeel Butt,
	Sasha Levin, chenxin

From: "Jose Fernandez (Anthropic)" <jose.fernandez@linux.dev>

[ Upstream commit 63b02a9409cb5180398491b093e48bcb5315f5fb ]

lookup_swap_cgroup_id() passes swap_cgroup_ctrl[type].map to
__swap_cgroup_id_lookup() without checking that the type was ever
registered via swap_cgroup_swapon().  On a swapless host every ctrl->map
is NULL, so __swap_cgroup_id_lookup() dereferences NULL + a scaled
swp_offset().

Since commit bea67dcc5eea ("mm: attempt to batch free swap entries for
zap_pte_range()"), zap_pte_range() -> swap_pte_batch() calls
lookup_swap_cgroup_id() on any non-present, non-none PTE that decodes as a
real swap entry, without first validating it against swap_info[].  A
single PTE corrupted into a type-0 swap entry takes the host down at
process exit.

We hit this in production on a swapless 6.12.58 host: ~1s of
"get_swap_device: Bad swap file entry 3f800204222bb" (do_swap_page() being
correctly defensive about the same entry) followed by

  BUG: unable to handle page fault for address: 000003f800204220
  RIP: 0010:lookup_swap_cgroup_id+0x2b/0x60
  Call Trace:
   swap_pte_batch+0xbf/0x230
   zap_pte_range+0x4c8/0x780
   unmap_page_range+0x190/0x3e0
   exit_mmap+0xd9/0x3c0
   do_exit+0x20c/0x4b0

syzbot has reported the identical stack.

The source of the PTE corruption is a separate bug; this change makes the
teardown path as robust as the fault path already is.  Every other caller
of lookup_swap_cgroup_id() is downstream of a get_swap_device() that has
already validated the entry, so the new branch is cold.

Link: https://lore.kernel.org/20260504-swap-cgroup-fix-7-0-v1-1-f53ff41ee553@linux.dev
Fixes: bea67dcc5eea ("mm: attempt to batch free swap entries for zap_pte_range()")
Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
Reported-by: syzbot+e12bd9ca48157add237a@syzkaller.appspotmail.com
Link: https://lore.kernel.org/r/69859728.050a0220.3b3015.0033.GAE@google.com
Assisted-by: Claude:unspecified
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kairui Song <ryncsn@gmail.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: chenxin <chenxinxin@xiaomi.com>
---
 mm/swap_cgroup.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c
index db6c4a26cf59..2d0425f4a6b9 100644
--- a/mm/swap_cgroup.c
+++ b/mm/swap_cgroup.c
@@ -161,6 +161,11 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id,
  */
 unsigned short lookup_swap_cgroup_id(swp_entry_t ent)
 {
+	struct swap_cgroup_ctrl *ctrl;
+
+	ctrl = &swap_cgroup_ctrl[swp_type(ent)];
+	if (unlikely(!ctrl->map))
+		return 0;
 	return lookup_swap_cgroup(ent, NULL)->id;
 }
 
-- 
2.50.1


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

* Re: [PATCH] mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host
  2026-08-14  7:47 [PATCH] mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host mambaxin
@ 2026-08-14 11:23 ` Barry Song
  2026-08-15  0:36   ` Shakeel Butt
  0 siblings, 1 reply; 4+ messages in thread
From: Barry Song @ 2026-08-14 11:23 UTC (permalink / raw)
  To: mambaxin
  Cc: hannes, mhocko, roman.gushchin, shakeelb, muchun.song, akpm,
	david, v-songbaohua, hughd, cgroups, linux-mm, linux-kernel,
	gregkh, jose.fernandez, stable, syzbot+e12bd9ca48157add237a,
	David Hildenbrand, Kairui Song, Shakeel Butt, Sasha Levin,
	chenxin

On Fri, Aug 14, 2026 at 3:48 PM <mambaxin@163.com> wrote:
>
> From: "Jose Fernandez (Anthropic)" <jose.fernandez@linux.dev>
>
> [ Upstream commit 63b02a9409cb5180398491b093e48bcb5315f5fb ]
>
> lookup_swap_cgroup_id() passes swap_cgroup_ctrl[type].map to
> __swap_cgroup_id_lookup() without checking that the type was ever
> registered via swap_cgroup_swapon().  On a swapless host every ctrl->map
> is NULL, so __swap_cgroup_id_lookup() dereferences NULL + a scaled
> swp_offset().
>
> Since commit bea67dcc5eea ("mm: attempt to batch free swap entries for
> zap_pte_range()"), zap_pte_range() -> swap_pte_batch() calls
> lookup_swap_cgroup_id() on any non-present, non-none PTE that decodes as a
> real swap entry, without first validating it against swap_info[].  A
> single PTE corrupted into a type-0 swap entry takes the host down at
> process exit.

Thanks for the patch. However, we have a strict check to ensure that
this is only done for valid swap entries:

static inline int swap_pte_batch(pte_t *start_ptep, int max_nr, pte_t pte)
{
        pte_t expected_pte = pte_next_swp_offset(pte);
        const pte_t *end_ptep = start_ptep + max_nr;
        pte_t *ptep = start_ptep + 1;

        VM_WARN_ON(max_nr < 1);
        VM_WARN_ON(!softleaf_is_swap(softleaf_from_pte(pte)));

        while (ptep < end_ptep) {
                pte = ptep_get(ptep);

                if (!pte_same(pte, expected_pte))
                        break;
                expected_pte = pte_next_swp_offset(expected_pte);
                ptep++;
        }

        return ptep - start_ptep;
}

I don't know why this can happen on a swapless system.

>
> We hit this in production on a swapless 6.12.58 host: ~1s of
> "get_swap_device: Bad swap file entry 3f800204222bb" (do_swap_page() being
> correctly defensive about the same entry) followed by
>
>   BUG: unable to handle page fault for address: 000003f800204220
>   RIP: 0010:lookup_swap_cgroup_id+0x2b/0x60
>   Call Trace:
>    swap_pte_batch+0xbf/0x230
>    zap_pte_range+0x4c8/0x780
>    unmap_page_range+0x190/0x3e0
>    exit_mmap+0xd9/0x3c0
>    do_exit+0x20c/0x4b0
>
> syzbot has reported the identical stack.
>
> The source of the PTE corruption is a separate bug; this change makes the
> teardown path as robust as the fault path already is.  Every other caller
> of lookup_swap_cgroup_id() is downstream of a get_swap_device() that has
> already validated the entry, so the new branch is cold.

If the source is PTE corruption, I think we should fix the corruption
itself rather than work around it here.

Best Regards
Barry

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

* Re: [PATCH] mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host
  2026-08-14 11:23 ` Barry Song
@ 2026-08-15  0:36   ` Shakeel Butt
  0 siblings, 0 replies; 4+ messages in thread
From: Shakeel Butt @ 2026-08-15  0:36 UTC (permalink / raw)
  To: Barry Song
  Cc: mambaxin, hannes, mhocko, roman.gushchin, shakeelb, muchun.song,
	akpm, david, v-songbaohua, hughd, cgroups, linux-mm, linux-kernel,
	gregkh, jose.fernandez, stable, syzbot+e12bd9ca48157add237a,
	David Hildenbrand, Kairui Song, Sasha Levin, chenxin

On Fri, Aug 14, 2026 at 07:23:41PM +0800, Barry Song wrote:
> On Fri, Aug 14, 2026 at 3:48 PM <mambaxin@163.com> wrote:
> >
> > From: "Jose Fernandez (Anthropic)" <jose.fernandez@linux.dev>
> >
> > [ Upstream commit 63b02a9409cb5180398491b093e48bcb5315f5fb ]
> >
> > lookup_swap_cgroup_id() passes swap_cgroup_ctrl[type].map to
> > __swap_cgroup_id_lookup() without checking that the type was ever
> > registered via swap_cgroup_swapon().  On a swapless host every ctrl->map
> > is NULL, so __swap_cgroup_id_lookup() dereferences NULL + a scaled
> > swp_offset().
> >
> > Since commit bea67dcc5eea ("mm: attempt to batch free swap entries for
> > zap_pte_range()"), zap_pte_range() -> swap_pte_batch() calls
> > lookup_swap_cgroup_id() on any non-present, non-none PTE that decodes as a
> > real swap entry, without first validating it against swap_info[].  A
> > single PTE corrupted into a type-0 swap entry takes the host down at
> > process exit.
> 
> Thanks for the patch. However, we have a strict check to ensure that
> this is only done for valid swap entries:

This patch is already in the upstream linus tree.

Mambaxin, what do you want to do with this patch? Are you requesting to backport
this to stable tree? Which one? It already had stable CCed, so I would expect
the stable tree maintainers would pick this up automatically.


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

end of thread, other threads:[~2026-08-15  0:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-14  7:47 [PATCH] mm: swap_cgroup: fix NULL deref in lookup_swap_cgroup_id on swapless host mambaxin
2026-08-14 11:23 ` Barry Song
2026-08-15  0:36   ` Shakeel Butt
  -- strict thread matches above, loose matches on Subject: below --
2026-05-04 12:55 Jose Fernandez (Anthropic)

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