Re: [PATCH v2 2/2] mm: multi-gen LRU: fix NULL lruvec->pgdat deref in get_lruvec()

From: Barry Song

Date: Sun Oct 18 2026 - 17:25:52 EST


On Sat, Oct 17, 2026 at 1:09 PM Siddharth Chintamaneni
<sidchintamaneni@xxxxxxxxx> wrote:
>
> Andrew Morton reported that get_lruvec() has the same problem as
> lru_gen_shrink_node(): when memcg is disabled on the command line
> (cgroup_disable=memory), it returns &pgdat->__lruvec directly and so
> bypasses the initialization of lruvec->pgdat. The MGLRU debugfs
> interface calls get_lruvec(), then dereferences the pgdat pointer in
> lru_gen_seq_show() and other paths, so these can hit the same NULL
> dereference.

So userspace must have booted, since otherwise we couldn't read
debugfs. The reachable case is therefore a memory node with no
LRU folios when debugfs is read? So this could happen on a multi-node
system where folios are landed on other nodes but not on this node?

>
> Fixes: ec1c86b25f4b ("mm: multi-gen LRU: groundwork")
> Cc: stable@xxxxxxxxxxxxxxx # 6.2+
> Assisted-by: LLM
> Signed-off-by: Siddharth Chintamaneni <sidchintamaneni@xxxxxxxxx>
> Signed-off-by: Hardik Garg <hargar@xxxxxxxxxxxxxxxxxxx>
> ---
> mm/vmscan.c | 15 ++-------------
> 1 file changed, 2 insertions(+), 13 deletions(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 0c57e4f1eb15..99e9f07fa2e1 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -2745,20 +2745,9 @@ static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid)
> {
> struct pglist_data *pgdat = NODE_DATA(nid);
>
> -#ifdef CONFIG_MEMCG
> - if (memcg) {
> - struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec;
> -
> - /* see the comment in mem_cgroup_lruvec() */
> - if (!lruvec->pgdat)
> - lruvec->pgdat = pgdat;
> -
> - return lruvec;
> - }
> -#endif
> - VM_WARN_ON_ONCE(!mem_cgroup_disabled());
> + VM_WARN_ON_ONCE(!memcg && !mem_cgroup_disabled());
>
> - return &pgdat->__lruvec;
> + return mem_cgroup_lruvec(memcg, pgdat);
> }

I've been struggling to understand why MGLRU needs its own
get_lruvec() when mem_cgroup_lruvec() already exists.
With your patch, it feels like we're one step closer to
getting rid of MGLRU's own variant in the future.

>
> static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc)
> --
> 2.45.4

Best Regards
Barry