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

From: Siddharth Chintamaneni

Date: Mon Oct 19 2026 - 20:24:49 EST


On Mon, 19 Oct 2026 at 16:36, Barry Song <baohua@xxxxxxxxxx> wrote:
>
> On Tue, Oct 20, 2026 at 4:33 AM Siddharth Chintamaneni
> <sidchintamaneni@xxxxxxxxx> wrote:
> >
> > On Sun, 18 Oct 2026 at 14:24, Barry Song <baohua@xxxxxxxxxx> wrote:
> > >
> > > 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?
> > >
> >
> > That is my high level understanding. I'll let Andrew to comment if I
> > am missing something,
> >
>
> I made a silly toy setup by running two numa nodes with one of them has only 4KB
> memory, the other one has 1G-4K:
>
> qemu-system-aarch64 -M virt,gic-version=3,mte=off -cpu cortex-a53 -nographic \
> -smp 4 \
> -m 1G \
> -object memory-backend-ram,id=ram0,size=1048572K \
> -object memory-backend-ram,id=ram1,size=4K \
> -numa node,nodeid=0,memdev=ram0,cpus=0-1 \
> -numa node,nodeid=1,memdev=ram1,cpus=2-3 \
> -kernel arch/arm64/boot/Image \
> -nographic -append "cgroup_disable=memory
> ...
>
> Then I got a machine where node1 is very difficult to have a page in lru.
>
> then i ran the debugfs for mglru:
>
> / # cat /sys/kernel/debug/lru_gen
> memcg 0
> node 0
> 0 14972 0 953
> 1 14972 0 1
> 2 14972 18 3308
> 3 14972 0 0
> node 1
> 0 14972 0 0
> 1 14972 0 0
> 2 14972 0 0
> 3 14972 0 0
>
> now you see node 1 has no page in lru but yet i didn't have any crash.
>
> i think i will need more time to figure out what is the problem and how to
> reproduce it.

I've asked AI to repro the issue with the similar setup

qemu-system-aarch64 -M virt,gic-version=3,mte=off -cpu cortex-a53 -nographic \
-smp 4 -m 1G \
-object memory-backend-ram,id=ram0,size=1048512K \
-object memory-backend-ram,id=ram1,size=64K \
-numa node,nodeid=0,memdev=ram0,cpus=0-1 \
-numa node,nodeid=1,memdev=ram1,cpus=2-3 \
-kernel "$KERNEL" \
-initrd "$INITRD" \
-no-reboot \
-append "console=ttyAMA0 cgroup_disable=memory
initcall_blacklist=kswapd_init panic=-1"

and it was able to repo it. AI identified that kswapd is initializing
the pgdat during boot, so blacklisting kswap_init was able to repro
the crash when reading /sys/kernel/debug/lru_gen

[ 1.347868] Unable to handle kernel access to user memory outside
uaccess routines at virtual address 0000000000005040
[ 1.347920] Mem abort info:
[ 1.347929] ESR = 0x0000000096000005
[ 1.347950] EC = 0x25: DABT (current EL), IL = 32 bits
[ 1.347964] SET = 0, FnV = 0
[ 1.347974] EA = 0, S1PTW = 0
[ 1.347986] FSC = 0x05: level 1 translation fault
[ 1.348249] Data abort info:
[ 1.348277] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
[ 1.348291] CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 1.348302] GCS = 0, Overlay = 0, DirtyBit = 0
[ 1.348345] user pgtable: 64k pages, 48-bit VAs, pgdp=00000000485f6600
[ 1.348369] [0000000000005040] pgd=0800000043640403,
p4d=0800000043640403, pud=0800000043640403, pmd=0800000043620403,
pte=0000000000000000
[ 1.349148] Internal error: Oops: 0000000096000005 [#1] SMP
[ 1.350414] Modules linked in:
[ 1.350896] CPU: 0 UID: 0 PID: 1 Comm: init Not tainted 7.3.0-rc7+
#9 PREEMPT(full)
[ 1.351111] Hardware name: linux,dummy-virt (DT)
[ 1.351411] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 1.351581] pc : lru_gen_seq_show+0x5c/0x460
[ 1.351800] lr : lru_gen_seq_show+0x4c/0x460
[ 1.351898] sp : ffff80008034f9a0
[ 1.351975] x29: ffff80008034fa20 x28: ffff0000035e67e8 x27: 0000000000400cc0
[ 1.352297] x26: 000000007fff0000 x25: ffff0000035e67d8 x24: 0000000000000000
[ 1.352454] x23: ffff80008034fb00 x22: ffff80008034fb28 x21: 0000000000000000
[ 1.352626] x20: ffff0000035e67b0 x19: ffff00003ffc2f20 x18: ffff800080360060
[ 1.352775] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
[ 1.352915] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[ 1.353058] x11: 0000000000000000 x10: 0000000000000000 x9 : ffffa3468a020c5c
[ 1.353226] x8 : ffff000008b07000 x7 : 0000000000000000 x6 : 000000000000003f
[ 1.353367] x5 : 00000000ffffffff x4 : 0000000000000003 x3 : 0000000000001000
[ 1.353511] x2 : ffff00003ffc2f20 x1 : 0000000000004000 x0 : 0000000000000000
[ 1.353732] Call trace:
[ 1.353925] lru_gen_seq_show+0x5c/0x460 (P)
[ 1.354110] seq_read_iter+0xec/0x4c0
[ 1.354213] seq_read+0xfc/0x148
[ 1.354290] full_proxy_read+0x78/0xc0
[ 1.354377] vfs_read+0xd0/0x338
[ 1.354453] ksys_read+0x7c/0x120
[ 1.354528] __arm64_sys_read+0x24/0x40
[ 1.354611] invoke_syscall+0xa8/0x120
[ 1.354695] el0_svc_common.constprop.0+0x4c/0x100
[ 1.354791] do_el0_svc+0x28/0x40
[ 1.354865] el0_svc+0x48/0x2b0
[ 1.354939] el0t_64_sync_handler+0xa8/0xf0
[ 1.355026] el0t_64_sync+0x1b8/0x1c0
[ 1.355250] Code: f9000fe0 f9432661 aa1303e2 91401021 (b9504033)
[ 1.355647] ---[ end trace 0000000000000000 ]---
[ 1.356555] Kernel panic - not syncing: Attempted to kill init!
exitcode=0x0000000b
[ 1.356888] SMP: stopping secondary CPUs
[ 1.357525] Kernel Offset: 0x234609c00000 from 0xffff800080000000
[ 1.357675] PHYS_OFFSET: 0x40000000
[ 1.357762] CPU features: 0x0,00000000,09000020,00100002,0800821b
[ 1.357901] Memory Limit: none