* [PATCH] mm: list_lru: fix UAF for memory cgroup
@ 2024-07-18 8:36 Muchun Song
2024-07-18 10:30 ` Vlastimil Babka
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Muchun Song @ 2024-07-18 8:36 UTC (permalink / raw)
To: akpm; +Cc: hannes, muchun.song, nphamcs, linux-mm, linux-kernel, Muchun Song
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.
Fixes: 0a97c01cd20bb ("list_lru: allow explicit memcg and NUMA node selection)
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
---
mm/list_lru.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 3fd64736bc458..225da0778a3be 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -85,6 +85,7 @@ list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
}
#endif /* CONFIG_MEMCG_KMEM */
+/* The caller must ensure the memcg lifetime. */
bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
struct mem_cgroup *memcg)
{
@@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
{
+ bool ret;
int nid = page_to_nid(virt_to_page(item));
- struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
- mem_cgroup_from_slab_obj(item) : NULL;
+ struct mem_cgroup *memcg;
- return list_lru_add(lru, item, nid, memcg);
+ rcu_read_lock();
+ memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
+ ret = list_lru_add(lru, item, nid, memcg);
+ rcu_read_unlock();
+
+ return ret;
}
EXPORT_SYMBOL_GPL(list_lru_add_obj);
+/* The caller must ensure the memcg lifetime. */
bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,
struct mem_cgroup *memcg)
{
@@ -139,11 +146,16 @@ EXPORT_SYMBOL_GPL(list_lru_del);
bool list_lru_del_obj(struct list_lru *lru, struct list_head *item)
{
+ bool ret;
int nid = page_to_nid(virt_to_page(item));
- struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
- mem_cgroup_from_slab_obj(item) : NULL;
+ struct mem_cgroup *memcg;
- return list_lru_del(lru, item, nid, memcg);
+ rcu_read_lock();
+ memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
+ ret = list_lru_del(lru, item, nid, memcg);
+ rcu_read_unlock();
+
+ return ret;
}
EXPORT_SYMBOL_GPL(list_lru_del_obj);
--
2.20.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-18 8:36 [PATCH] mm: list_lru: fix UAF for memory cgroup Muchun Song
@ 2024-07-18 10:30 ` Vlastimil Babka
2024-07-18 11:20 ` Muchun Song
2024-07-23 17:52 ` Shakeel Butt
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Vlastimil Babka @ 2024-07-18 10:30 UTC (permalink / raw)
To: Muchun Song, akpm
Cc: hannes, muchun.song, nphamcs, linux-mm, linux-kernel, Michal Hocko
On 7/18/24 10:36 AM, Muchun Song wrote:
> 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.
Was the UAF ever observed, or is this due to code review?
Should there be some lockdep_assert somwhere?
> Fixes: 0a97c01cd20bb ("list_lru: allow explicit memcg and NUMA node selection)
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> ---
> mm/list_lru.c | 24 ++++++++++++++++++------
> 1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/mm/list_lru.c b/mm/list_lru.c
> index 3fd64736bc458..225da0778a3be 100644
> --- a/mm/list_lru.c
> +++ b/mm/list_lru.c
> @@ -85,6 +85,7 @@ list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
> }
> #endif /* CONFIG_MEMCG_KMEM */
>
> +/* The caller must ensure the memcg lifetime. */
> bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
> struct mem_cgroup *memcg)
> {
> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>
> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
> {
> + bool ret;
> int nid = page_to_nid(virt_to_page(item));
> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
> - mem_cgroup_from_slab_obj(item) : NULL;
> + struct mem_cgroup *memcg;
>
> - return list_lru_add(lru, item, nid, memcg);
> + rcu_read_lock();
> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
> + ret = list_lru_add(lru, item, nid, memcg);
> + rcu_read_unlock();
> +
> + return ret;
> }
> EXPORT_SYMBOL_GPL(list_lru_add_obj);
>
> +/* The caller must ensure the memcg lifetime. */
> bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,
> struct mem_cgroup *memcg)
> {
> @@ -139,11 +146,16 @@ EXPORT_SYMBOL_GPL(list_lru_del);
>
> bool list_lru_del_obj(struct list_lru *lru, struct list_head *item)
> {
> + bool ret;
> int nid = page_to_nid(virt_to_page(item));
> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
> - mem_cgroup_from_slab_obj(item) : NULL;
> + struct mem_cgroup *memcg;
>
> - return list_lru_del(lru, item, nid, memcg);
> + rcu_read_lock();
> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
> + ret = list_lru_del(lru, item, nid, memcg);
> + rcu_read_unlock();
> +
> + return ret;
> }
> EXPORT_SYMBOL_GPL(list_lru_del_obj);
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-18 10:30 ` Vlastimil Babka
@ 2024-07-18 11:20 ` Muchun Song
2024-07-23 11:23 ` Muchun Song
0 siblings, 1 reply; 11+ messages in thread
From: Muchun Song @ 2024-07-18 11:20 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Muchun Song, akpm, hannes, nphamcs, linux-mm, linux-kernel, Michal Hocko
> On Jul 18, 2024, at 18:30, Vlastimil Babka <vbabka@suse.cz> wrote:
>
> On 7/18/24 10:36 AM, Muchun Song wrote:
>> 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.
>
> Was the UAF ever observed, or is this due to code review?
Just code review.
Thanks.
> Should there be some lockdep_assert somwhere?
>
It’s a good option to improve this. Maybe mem_cgroup_from_slab_obj() is a good place.
>> Fixes: 0a97c01cd20bb ("list_lru: allow explicit memcg and NUMA node selection)
>> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
>> ---
>> mm/list_lru.c | 24 ++++++++++++++++++------
>> 1 file changed, 18 insertions(+), 6 deletions(-)
>>
>> diff --git a/mm/list_lru.c b/mm/list_lru.c
>> index 3fd64736bc458..225da0778a3be 100644
>> --- a/mm/list_lru.c
>> +++ b/mm/list_lru.c
>> @@ -85,6 +85,7 @@ list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
>> }
>> #endif /* CONFIG_MEMCG_KMEM */
>>
>> +/* The caller must ensure the memcg lifetime. */
>> bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
>> struct mem_cgroup *memcg)
>> {
>> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>>
>> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
>> {
>> + bool ret;
>> int nid = page_to_nid(virt_to_page(item));
>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>> - mem_cgroup_from_slab_obj(item) : NULL;
>> + struct mem_cgroup *memcg;
>>
>> - return list_lru_add(lru, item, nid, memcg);
>> + rcu_read_lock();
>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>> + ret = list_lru_add(lru, item, nid, memcg);
>> + rcu_read_unlock();
>> +
>> + return ret;
>> }
>> EXPORT_SYMBOL_GPL(list_lru_add_obj);
>>
>> +/* The caller must ensure the memcg lifetime. */
>> bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,
>> struct mem_cgroup *memcg)
>> {
>> @@ -139,11 +146,16 @@ EXPORT_SYMBOL_GPL(list_lru_del);
>>
>> bool list_lru_del_obj(struct list_lru *lru, struct list_head *item)
>> {
>> + bool ret;
>> int nid = page_to_nid(virt_to_page(item));
>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>> - mem_cgroup_from_slab_obj(item) : NULL;
>> + struct mem_cgroup *memcg;
>>
>> - return list_lru_del(lru, item, nid, memcg);
>> + rcu_read_lock();
>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>> + ret = list_lru_del(lru, item, nid, memcg);
>> + rcu_read_unlock();
>> +
>> + return ret;
>> }
>> EXPORT_SYMBOL_GPL(list_lru_del_obj);
>>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-18 11:20 ` Muchun Song
@ 2024-07-23 11:23 ` Muchun Song
0 siblings, 0 replies; 11+ messages in thread
From: Muchun Song @ 2024-07-23 11:23 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Muchun Song, Andrew Morton, Johannes Weiner, Nhat Pham,
Linux Memory Management List, LKML, Michal Hocko, Roman Gushchin,
shakeel.butt
> On Jul 18, 2024, at 19:20, Muchun Song <muchun.song@linux.dev> wrote:
>
>
>
>> On Jul 18, 2024, at 18:30, Vlastimil Babka <vbabka@suse.cz> wrote:
>>
>> On 7/18/24 10:36 AM, Muchun Song wrote:
>>> 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.
>>
>> Was the UAF ever observed, or is this due to code review?
>
> Just code review.
>
> Thanks.
>
>> Should there be some lockdep_assert somwhere?
>>
>
> It’s a good option to improve this. Maybe mem_cgroup_from_slab_obj() is a good place.
I added it to obj_cgroup_memcg() [1]. And CC memory cgroup maintainers to this thread.
[1] https://lore.kernel.org/linux-mm/20859F67-A80C-4FD0-990C-40C70905E55B@linux.dev/T/
>
>>> Fixes: 0a97c01cd20bb ("list_lru: allow explicit memcg and NUMA node selection)
>>> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
>>> ---
>>> mm/list_lru.c | 24 ++++++++++++++++++------
>>> 1 file changed, 18 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/mm/list_lru.c b/mm/list_lru.c
>>> index 3fd64736bc458..225da0778a3be 100644
>>> --- a/mm/list_lru.c
>>> +++ b/mm/list_lru.c
>>> @@ -85,6 +85,7 @@ list_lru_from_memcg_idx(struct list_lru *lru, int nid, int idx)
>>> }
>>> #endif /* CONFIG_MEMCG_KMEM */
>>>
>>> +/* The caller must ensure the memcg lifetime. */
>>> bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
>>> struct mem_cgroup *memcg)
>>> {
>>> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>>>
>>> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
>>> {
>>> + bool ret;
>>> int nid = page_to_nid(virt_to_page(item));
>>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>>> - mem_cgroup_from_slab_obj(item) : NULL;
>>> + struct mem_cgroup *memcg;
>>>
>>> - return list_lru_add(lru, item, nid, memcg);
>>> + rcu_read_lock();
>>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>>> + ret = list_lru_add(lru, item, nid, memcg);
>>> + rcu_read_unlock();
>>> +
>>> + return ret;
>>> }
>>> EXPORT_SYMBOL_GPL(list_lru_add_obj);
>>>
>>> +/* The caller must ensure the memcg lifetime. */
>>> bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid,
>>> struct mem_cgroup *memcg)
>>> {
>>> @@ -139,11 +146,16 @@ EXPORT_SYMBOL_GPL(list_lru_del);
>>>
>>> bool list_lru_del_obj(struct list_lru *lru, struct list_head *item)
>>> {
>>> + bool ret;
>>> int nid = page_to_nid(virt_to_page(item));
>>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>>> - mem_cgroup_from_slab_obj(item) : NULL;
>>> + struct mem_cgroup *memcg;
>>>
>>> - return list_lru_del(lru, item, nid, memcg);
>>> + rcu_read_lock();
>>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>>> + ret = list_lru_del(lru, item, nid, memcg);
>>> + rcu_read_unlock();
>>> +
>>> + return ret;
>>> }
>>> EXPORT_SYMBOL_GPL(list_lru_del_obj);
>>>
>>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-18 8:36 [PATCH] mm: list_lru: fix UAF for memory cgroup Muchun Song
2024-07-18 10:30 ` Vlastimil Babka
@ 2024-07-23 17:52 ` Shakeel Butt
2024-07-24 0:45 ` Andrew Morton
2024-07-31 20:28 ` Andrew Morton
3 siblings, 0 replies; 11+ messages in thread
From: Shakeel Butt @ 2024-07-23 17:52 UTC (permalink / raw)
To: Muchun Song; +Cc: akpm, hannes, muchun.song, nphamcs, linux-mm, linux-kernel
On Thu, Jul 18, 2024 at 04:36:07PM GMT, Muchun Song wrote:
> 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.
>
> Fixes: 0a97c01cd20bb ("list_lru: allow explicit memcg and NUMA node selection)
> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Yup I noticed these as well while reviewing Kairui's patches.
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-18 8:36 [PATCH] mm: list_lru: fix UAF for memory cgroup Muchun Song
2024-07-18 10:30 ` Vlastimil Babka
2024-07-23 17:52 ` Shakeel Butt
@ 2024-07-24 0:45 ` Andrew Morton
2024-07-24 2:23 ` Muchun Song
2024-07-31 20:28 ` Andrew Morton
3 siblings, 1 reply; 11+ messages in thread
From: Andrew Morton @ 2024-07-24 0:45 UTC (permalink / raw)
To: Muchun Song; +Cc: hannes, muchun.song, nphamcs, linux-mm, linux-kernel
On Thu, 18 Jul 2024 16:36:07 +0800 Muchun Song <songmuchun@bytedance.com> wrote:
> 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.
"or others" is rather vague. What others?
> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>
> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
> {
> + bool ret;
> int nid = page_to_nid(virt_to_page(item));
> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
> - mem_cgroup_from_slab_obj(item) : NULL;
> + struct mem_cgroup *memcg;
>
> - return list_lru_add(lru, item, nid, memcg);
> + rcu_read_lock();
> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
> + ret = list_lru_add(lru, item, nid, memcg);
> + rcu_read_unlock();
We don't need rcu_read_lock() to evaluate NULL.
memcg = NULL;
if (list_lru_memcg_aware(lru)) {
rcu_read_lock();
memcg = mem_cgroup_from_slab_obj(item);
rcu_read_unlock();
}
Seems worthwhile?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-24 0:45 ` Andrew Morton
@ 2024-07-24 2:23 ` Muchun Song
2024-07-31 10:06 ` Vlastimil Babka (SUSE)
0 siblings, 1 reply; 11+ messages in thread
From: Muchun Song @ 2024-07-24 2:23 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Johannes Weiner, Nhat Pham,
Linux Memory Management List, LKML
> On Jul 24, 2024, at 08:45, Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Thu, 18 Jul 2024 16:36:07 +0800 Muchun Song <songmuchun@bytedance.com> wrote:
>
>> 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.
>
> "or others" is rather vague. What others?
Like objcg_lock. I have added this one into obj_cgroup_memcg().
>
>> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>>
>> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
>> {
>> + bool ret;
>> int nid = page_to_nid(virt_to_page(item));
>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>> - mem_cgroup_from_slab_obj(item) : NULL;
>> + struct mem_cgroup *memcg;
>>
>> - return list_lru_add(lru, item, nid, memcg);
>> + rcu_read_lock();
>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>> + ret = list_lru_add(lru, item, nid, memcg);
>> + rcu_read_unlock();
>
> We don't need rcu_read_lock() to evaluate NULL.
>
> memcg = NULL;
> if (list_lru_memcg_aware(lru)) {
> rcu_read_lock();
> memcg = mem_cgroup_from_slab_obj(item);
> rcu_read_unlock();
Actually, the access to memcg is in list_lru_add(), so the rcu lock should
also cover this function rather than only mem_cgroup_from_slab_obj().
Something like:
memcg = NULL;
if (list_lru_memcg_aware(lru)) {
rcu_read_lock();
memcg = mem_cgroup_from_slab_obj(item);
}
ret = list_lru_add(lru, item, nid, memcg);
if (list_lru_memcg_aware(lru))
rcu_read_unlock();
Not concise. I don't know if this is good.
> }
>
> Seems worthwhile?
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-24 2:23 ` Muchun Song
@ 2024-07-31 10:06 ` Vlastimil Babka (SUSE)
2024-08-01 2:42 ` Muchun Song
0 siblings, 1 reply; 11+ messages in thread
From: Vlastimil Babka (SUSE) @ 2024-07-31 10:06 UTC (permalink / raw)
To: Muchun Song, Andrew Morton
Cc: Muchun Song, Johannes Weiner, Nhat Pham,
Linux Memory Management List, LKML
On 7/24/24 4:23 AM, Muchun Song wrote:
>
>
>> On Jul 24, 2024, at 08:45, Andrew Morton <akpm@linux-foundation.org> wrote:
>>
>> On Thu, 18 Jul 2024 16:36:07 +0800 Muchun Song <songmuchun@bytedance.com> wrote:
>>
>>> 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.
>>
>> "or others" is rather vague. What others?
>
> Like objcg_lock. I have added this one into obj_cgroup_memcg().
>
>>
>>> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>>>
>>> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
>>> {
>>> + bool ret;
>>> int nid = page_to_nid(virt_to_page(item));
>>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>>> - mem_cgroup_from_slab_obj(item) : NULL;
>>> + struct mem_cgroup *memcg;
>>>
>>> - return list_lru_add(lru, item, nid, memcg);
>>> + rcu_read_lock();
>>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>>> + ret = list_lru_add(lru, item, nid, memcg);
>>> + rcu_read_unlock();
>>
>> We don't need rcu_read_lock() to evaluate NULL.
>>
>> memcg = NULL;
>> if (list_lru_memcg_aware(lru)) {
>> rcu_read_lock();
>> memcg = mem_cgroup_from_slab_obj(item);
>> rcu_read_unlock();
>
> Actually, the access to memcg is in list_lru_add(), so the rcu lock should
> also cover this function rather than only mem_cgroup_from_slab_obj().
> Something like:
>
> memcg = NULL;
> if (list_lru_memcg_aware(lru)) {
> rcu_read_lock();
> memcg = mem_cgroup_from_slab_obj(item);
> }
> ret = list_lru_add(lru, item, nid, memcg);
> if (list_lru_memcg_aware(lru))
> rcu_read_unlock();
>
> Not concise. I don't know if this is good.
At such point, it's probably best to just:
if (list_lru_memcg_aware(lru)) {
rcu_read_lock();
ret = list_lru_add(lru, item, nid, mem_cgroup_from_slab_obj(item));
rcu_read_unlock();
} else {
list_lru_add(lru, item, nid, NULL);
}
?
>
>> }
>>
>> Seems worthwhile?
>>
>>
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-18 8:36 [PATCH] mm: list_lru: fix UAF for memory cgroup Muchun Song
` (2 preceding siblings ...)
2024-07-24 0:45 ` Andrew Morton
@ 2024-07-31 20:28 ` Andrew Morton
2024-08-01 2:42 ` Muchun Song
3 siblings, 1 reply; 11+ messages in thread
From: Andrew Morton @ 2024-07-31 20:28 UTC (permalink / raw)
To: Muchun Song
Cc: hannes, muchun.song, nphamcs, linux-mm, linux-kernel,
Vlastimil Babka, shakeel.butt
On Thu, 18 Jul 2024 16:36:07 +0800 Muchun Song <songmuchun@bytedance.com> wrote:
> 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.
>
Well I grabbed this, but the review led me to expect a v2.
Should it have cc:stable?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-31 20:28 ` Andrew Morton
@ 2024-08-01 2:42 ` Muchun Song
0 siblings, 0 replies; 11+ messages in thread
From: Muchun Song @ 2024-08-01 2:42 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Johannes Weiner, Nhat Pham,
Linux Memory Management List, LKML, Vlastimil Babka,
Shakeel Butt
> On Aug 1, 2024, at 04:28, Andrew Morton <akpm@linux-foundation.org> wrote:
>
> On Thu, 18 Jul 2024 16:36:07 +0800 Muchun Song <songmuchun@bytedance.com> wrote:
>
>> 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.
>>
>
> Well I grabbed this, but the review led me to expect a v2.
Will do.
>
> Should it have cc:stable?
Yes.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] mm: list_lru: fix UAF for memory cgroup
2024-07-31 10:06 ` Vlastimil Babka (SUSE)
@ 2024-08-01 2:42 ` Muchun Song
0 siblings, 0 replies; 11+ messages in thread
From: Muchun Song @ 2024-08-01 2:42 UTC (permalink / raw)
To: Vlastimil Babka (SUSE)
Cc: Andrew Morton, Muchun Song, Johannes Weiner, Nhat Pham,
Linux Memory Management List, LKML
> On Jul 31, 2024, at 18:06, Vlastimil Babka (SUSE) <vbabka@kernel.org> wrote:
>
> On 7/24/24 4:23 AM, Muchun Song wrote:
>>
>>
>>> On Jul 24, 2024, at 08:45, Andrew Morton <akpm@linux-foundation.org> wrote:
>>>
>>> On Thu, 18 Jul 2024 16:36:07 +0800 Muchun Song <songmuchun@bytedance.com> wrote:
>>>
>>>> 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.
>>>
>>> "or others" is rather vague. What others?
>>
>> Like objcg_lock. I have added this one into obj_cgroup_memcg().
>>
>>>
>>>> @@ -109,14 +110,20 @@ EXPORT_SYMBOL_GPL(list_lru_add);
>>>>
>>>> bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
>>>> {
>>>> + bool ret;
>>>> int nid = page_to_nid(virt_to_page(item));
>>>> - struct mem_cgroup *memcg = list_lru_memcg_aware(lru) ?
>>>> - mem_cgroup_from_slab_obj(item) : NULL;
>>>> + struct mem_cgroup *memcg;
>>>>
>>>> - return list_lru_add(lru, item, nid, memcg);
>>>> + rcu_read_lock();
>>>> + memcg = list_lru_memcg_aware(lru) ? mem_cgroup_from_slab_obj(item) : NULL;
>>>> + ret = list_lru_add(lru, item, nid, memcg);
>>>> + rcu_read_unlock();
>>>
>>> We don't need rcu_read_lock() to evaluate NULL.
>>>
>>> memcg = NULL;
>>> if (list_lru_memcg_aware(lru)) {
>>> rcu_read_lock();
>>> memcg = mem_cgroup_from_slab_obj(item);
>>> rcu_read_unlock();
>>
>> Actually, the access to memcg is in list_lru_add(), so the rcu lock should
>> also cover this function rather than only mem_cgroup_from_slab_obj().
>> Something like:
>>
>> memcg = NULL;
>> if (list_lru_memcg_aware(lru)) {
>> rcu_read_lock();
>> memcg = mem_cgroup_from_slab_obj(item);
>> }
>> ret = list_lru_add(lru, item, nid, memcg);
>> if (list_lru_memcg_aware(lru))
>> rcu_read_unlock();
>>
>> Not concise. I don't know if this is good.
>
> At such point, it's probably best to just:
>
> if (list_lru_memcg_aware(lru)) {
> rcu_read_lock();
> ret = list_lru_add(lru, item, nid, mem_cgroup_from_slab_obj(item));
> rcu_read_unlock();
> } else {
> list_lru_add(lru, item, nid, NULL);
> }
Good. Will update v2.
Thanks.
>
> ?
>
>>
>>> }
>>>
>>> Seems worthwhile?
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2024-08-01 2:43 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-18 8:36 [PATCH] mm: list_lru: fix UAF for memory cgroup Muchun Song
2024-07-18 10:30 ` Vlastimil Babka
2024-07-18 11:20 ` Muchun Song
2024-07-23 11:23 ` Muchun Song
2024-07-23 17:52 ` Shakeel Butt
2024-07-24 0:45 ` Andrew Morton
2024-07-24 2:23 ` Muchun Song
2024-07-31 10:06 ` Vlastimil Babka (SUSE)
2024-08-01 2:42 ` Muchun Song
2024-07-31 20:28 ` Andrew Morton
2024-08-01 2:42 ` Muchun Song
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox