Commit 7a47d187 authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman

memcg: make it work on sparse non-0-node systems

commit 3e8589963773a5c23e2f1fe4bcad0e9a90b7f471 upstream.

We have a single node system with node 0 disabled:
  Scanning NUMA topology in Northbridge 24
  Number of physical nodes 2
  Skipping disabled node 0
  Node 1 MemBase 0000000000000000 Limit 00000000fbff0000
  NODE_DATA(1) allocated [mem 0xfbfda000-0xfbfeffff]

This causes crashes in memcg when system boots:
  BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
  #PF error: [normal kernel read fault]
  RIP: 0010:list_lru_add+0x94/0x170
  Call Trace:

It is reproducible as far as 4.12.  I did not try older kernels.  You have
to have a new enough systemd, e.g.  241 (the reason is unknown -- was not
investigated).  Cannot be reproduced with systemd 234.

The system crashes because the size of lru array is never updated in
memcg_update_all_list_lrus and the reads are past the zero-sized array,
causing dereferences of random memory.

The root cause are list_lru_memcg_aware checks in the list_lru code.  The
test in list_lru_memcg_aware is broken: it assumes node 0 is always
present, but it is not true on some systems as can be seen above.

So fix this by avoiding checks on node 0.  Remember the memcg-awareness by
a bool flag in struct list_lru.

Fixes: 60d3fd32 ("list_lru: introduce per-memcg lists")
Signed-off-by: default avatarJiri Slaby <>
Acked-by: default avatarMichal Hocko <>
Suggested-by: default avatarVladimir Davydov <>
Acked-by: default avatarVladimir Davydov <>
Reviewed-by: default avatarShakeel Butt <>
Cc: Johannes Weiner <>
Cc: Raghavendra K T <>
Cc: <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent 5db0a9c3
......@@ -51,6 +51,7 @@ struct list_lru {
struct list_lru_node *node;
struct list_head list;
bool memcg_aware;
......@@ -42,11 +42,7 @@ static void list_lru_unregister(struct list_lru *lru)
static inline bool list_lru_memcg_aware(struct list_lru *lru)
* This needs node 0 to be always present, even
* in the systems supporting sparse numa ids.
return !!lru->node[0].memcg_lrus;
return lru->memcg_aware;
static inline struct list_lru_one *
......@@ -389,6 +385,8 @@ static int memcg_init_list_lru(struct list_lru *lru, bool memcg_aware)
int i;
lru->memcg_aware = memcg_aware;
if (!memcg_aware)
return 0;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment