Patch "mm, slub: prevent kmalloc_node crashes and memory leaks" has been added to the 4.9-stable tree
Subsystems (2)
[email protected]
AppliedThis is a note to let you know that I've just added the patch titled
mm, slub: prevent kmalloc_node crashes and memory leaks
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
mm-slub-prevent-kmalloc_node-crashes-and-memory-leaks.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From 0715e6c516f106ed553828a671d30ad9a3431536 Mon Sep 17 00:00:00 2001
From: Vlastimil Babka <[email protected]>
Date: Sat, 21 Mar 2020 18:22:37 -0700
Subject: mm, slub: prevent kmalloc_node crashes and memory leaks
From: Vlastimil Babka <[email protected]>
commit 0715e6c516f106ed553828a671d30ad9a3431536 upstream.
Sachin reports [1] a crash in SLUB __slab_alloc():
BUG: Kernel NULL pointer dereference on read at 0x000073b0
Faulting instruction address: 0xc0000000003d55f4
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
Modules linked in:
CPU: 19 PID: 1 Comm: systemd Not tainted 5.6.0-rc2-next-20200218-autotest #1
NIP: c0000000003d55f4 LR: c0000000003d5b94 CTR: 0000000000000000
REGS: c0000008b37836d0 TRAP: 0300 Not tainted (5.6.0-rc2-next-20200218-autotest)
MSR: 8000000000009033 <SF,EE,ME,IR,DR,RI,LE> CR: 24004844 XER: 00000000
CFAR: c00000000000dec4 DAR: 00000000000073b0 DSISR: 40000000 IRQMASK: 1
GPR00: c0000000003d5b94 c0000008b3783960 c00000000155d400 c0000008b301f500
GPR04: 0000000000000dc0 0000000000000002 c0000000003443d8 c0000008bb398620
GPR08: 00000008ba2f0000 0000000000000001 0000000000000000 0000000000000000
GPR12: 0000000024004844 c00000001ec52a00 0000000000000000 0000000000000000
GPR16: c0000008a1b20048 c000000001595898 c000000001750c18 0000000000000002
GPR20: c000000001750c28 c000000001624470 0000000fffffffe0 5deadbeef0000122
GPR24: 0000000000000001 0000000000000dc0 0000000000000002 c0000000003443d8
GPR28: c0000008b301f500 c0000008bb398620 0000000000000000 c00c000002287180
NIP ___slab_alloc+0x1f4/0x760
LR __slab_alloc+0x34/0x60
Call Trace:
___slab_alloc+0x334/0x760 (unreliable)
__slab_alloc+0x34/0x60
__kmalloc_node+0x110/0x490
kvmalloc_node+0x58/0x110
mem_cgroup_css_online+0x108/0x270
online_css+0x48/0xd0
cgroup_apply_control_enable+0x2ec/0x4d0
cgroup_mkdir+0x228/0x5f0
kernfs_iop_mkdir+0x90/0xf0
vfs_mkdir+0x110/0x230
do_mkdirat+0xb0/0x1a0
system_call+0x5c/0x68This is a PowerPC platform with following NUMA topology:
available: 2 nodes (0-1)
node 0 cpus:
node 0 size: 0 MB
node 0 free: 0 MB
node 1 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 node 1 size: 35247 MB
node 1 free: 30907 MB
node distances:
node 0 1
0: 10 40
1: 40 10possible numa nodes: 0-31
This only happens with a mmotm patch "mm/memcontrol.c: allocate shrinker_map on appropriate NUMA node" [2] which effectively calls kmalloc_node for each possible node. SLUB however only allocates kmem_cache_node on online N_NORMAL_MEMORY nodes, and relies on node_to_mem_node to return such valid node for other nodes since commit a561ce00b09e ("slub: fall back to node_to_mem_node() node if allocating on memoryless node"). This is however not true in this configuration where the _node_numa_mem_ array is not initialized for nodes 0 and 2-31, thus it contains zeroes and get_partial() ends up accessing non-allocated kmem_cache_node.
A related issue was reported by Bharata (originally by Ramachandran) [3] where a similar PowerPC configuration, but with mainline kernel without patch [2] ends up allocating large amounts of pages by kmalloc-1k kmalloc-512. This seems to have the same underlying issue with node_to_mem_node() not behaving as expected, and might probably also lead to an infinite loop with CONFIG_SLUB_CPU_PARTIAL [4].
This patch should fix both issues by not relying on node_to_mem_node() anymore and instead simply falling back to NUMA_NO_NODE, when kmalloc_node(node) is attempted for a node that's not online, or has no usable memory. The "usable memory" condition is also changed from node_present_pages() to N_NORMAL_MEMORY node state, as that is exactly the condition that SLUB uses to allocate kmem_cache_node structures. The check in get_partial() is removed completely, as the checks in ___slab_alloc() are now sufficient to prevent get_partial() being reached with an invalid node.
[1] https://lore.kernel.org/linux-next/[email protected]/
[2] https://lore.kernel.org/linux-mm/[email protected]/
[3] https://lore.kernel.org/linux-mm/[email protected]/
[4] https://lore.kernel.org/linux-mm/[email protected]/
--- mm/slub.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
mm/slub.c +17 -9
@@ -1909,8 +1909,6 @@ static void *get_partial(struct kmem_cacif (node ==NUMA_NO_NODE ) searchnode =numa_mem_id (); -else if (!node_present_pages (node)) - searchnode =node_to_mem_node (node); object =get_partial_node (s,get_node (s, searchnode), c, flags);if (object || node !=NUMA_NO_NODE )
@@ -2506,17 +2504,27 @@ static void *___slab_alloc(struct kmem_cstruct page *page; page = c->page; -if (!page) +if (!page) { +/* +* if the node is not online or has no normal memory, just +* ignore the node constraint +*/ +if (unlikely (node !=NUMA_NO_NODE && + !node_state (node,N_NORMAL_MEMORY ))) + node =NUMA_NO_NODE ; goto new_slab; + } redo:if (unlikely (!node_match (page, node))) { -int searchnode = node; - -if (node !=NUMA_NO_NODE && !node_present_pages (node)) - searchnode =node_to_mem_node (node); - -if (unlikely (!node_match (page, searchnode))) { +/* +* same as above but node_match() being false already +* implies node != NUMA_NO_NODE +*/ +if (!node_state (node,N_NORMAL_MEMORY )) { + node =NUMA_NO_NODE ; + goto redo; + }else {stat (s,ALLOC_NODE_MISMATCH );deactivate_slab (s, page, c->freelist); c->page =NULL ;
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/mm-slub-prevent-kmalloc_node-crashes-and-memory-leaks.patch