Skip to content

Commit 5161b48

Browse files
Muchun Songakpm00
authored andcommitted
mm: list_lru: fix UAF for memory cgroup
The mem_cgroup_from_slab_obj() is supposed to be called under rcu lock or cgroup_mutex or others which could prevent returned memcg from being freed. Fix it by adding missing rcu read lock. Found by code inspection. [[email protected]: only grab rcu lock when necessary, per Vlastimil] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: 0a97c01 ("list_lru: allow explicit memcg and NUMA node selection") Signed-off-by: Muchun Song <[email protected]> Acked-by: Shakeel Butt <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Nhat Pham <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7d4df2d commit 5161b48

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

mm/list_lru.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
8585
}
8686
#endif /* CONFIG_MEMCG */
8787

88+
/* The caller must ensure the memcg lifetime. */
8889
bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
8990
struct mem_cgroup *memcg)
9091
{
@@ -109,14 +110,22 @@ EXPORT_SYMBOL_GPL(list_lru_add);
109110

110111
bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
111112
{
113+
bool ret;
112114
int nid = page_to_nid(virt_to_page(item));
113-
struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
114-
mem_cgroup_from_slab_obj(item) : NULL;
115115

116-
return list_lru_add(lru, item, nid, memcg);
116+
if (list_lru_memcg_aware(lru)) {
117+
rcu_read_lock();
118+
ret = list_lru_add(lru, item, nid, mem_cgroup_from_slab_obj(item));
119+
rcu_read_unlock();
120+
} else {
121+
ret = list_lru_add(lru, item, nid, NULL);
122+
}
123+
124+
return ret;
117125
}
118126
EXPORT_SYMBOL_GPL(list_lru_add_obj);
119127

128+
/* The caller must ensure the memcg lifetime. */
120129
bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,
121130
struct mem_cgroup *memcg)
122131
{
@@ -139,11 +148,18 @@ EXPORT_SYMBOL_GPL(list_lru_del);
139148

140149
bool list_lru_del_obj(struct list_lru *lru, struct list_head *item)
141150
{
151+
bool ret;
142152
int nid = page_to_nid(virt_to_page(item));
143-
struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
144-
mem_cgroup_from_slab_obj(item) : NULL;
145153

146-
return list_lru_del(lru, item, nid, memcg);
154+
if (list_lru_memcg_aware(lru)) {
155+
rcu_read_lock();
156+
ret = list_lru_del(lru, item, nid, mem_cgroup_from_slab_obj(item));
157+
rcu_read_unlock();
158+
} else {
159+
ret = list_lru_del(lru, item, nid, NULL);
160+
}
161+
162+
return ret;
147163
}
148164
EXPORT_SYMBOL_GPL(list_lru_del_obj);
149165

0 commit comments

Comments
 (0)