* Re: [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist
[not found] ` <b9a674c1-860c-4448-aeb2-bf07a78c6fbf@suse.cz>
@ 2024-11-04 11:45 ` Peter Zijlstra
2024-11-04 11:47 ` Peter Zijlstra
2024-11-04 12:16 ` Marco Elver
0 siblings, 2 replies; 14+ messages in thread
From: Peter Zijlstra @ 2024-11-04 11:45 UTC (permalink / raw)
To: Vlastimil Babka
Cc: syzbot, Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, Sebastian Andrzej Siewior,
Marco Elver, Andrey Konovalov, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, peterz, juri.lelli, vincent.guittot, dietmar.eggemann,
bsegall, mgorman, vschneid, tj, cl, penberg, rientjes,
iamjoonsoo.kim, vbabka, roman.gushchin, 42.hyeyoo, rcu
On Mon, Nov 04, 2024 at 12:25:03PM +0100, Vlastimil Babka wrote:
> On 11/4/24 12:11, Vlastimil Babka wrote:
> >> __alloc_pages_noprof+0x292/0x710 mm/page_alloc.c:4771
> >> alloc_pages_mpol_noprof+0x3e8/0x680 mm/mempolicy.c:2265
> >> stack_depot_save_flags+0x666/0x830 lib/stackdepot.c:627
> >> kasan_save_stack+0x4f/0x60 mm/kasan/common.c:48
> >> __kasan_record_aux_stack+0xac/0xc0 mm/kasan/generic.c:544
> >> task_work_add+0xd9/0x490 kernel/task_work.c:77
> >
> > It seems the decision if stack depot is allowed to allocate here depends on
> > TWAF_NO_ALLOC added only recently. So does it mean it doesn't work as intended?
>
> I guess __run_posix_cpu_timers() needs to pass TWAF_NO_ALLOC too?
Yeah, or we just accept that kasan_record_aux_stack() is a horrible
thing and shouldn't live in functions that try their bestest to
locklessly setup async work at all.
That thing has only ever caused trouble :/
Also see 156172a13ff0.
How about we do the below at the very least?
---
include/linux/kasan.h | 2 --
include/linux/task_work.h | 1 -
kernel/irq_work.c | 2 +-
kernel/rcu/tiny.c | 2 +-
kernel/rcu/tree.c | 4 ++--
kernel/sched/core.c | 2 +-
kernel/task_work.c | 12 +-----------
kernel/workqueue.c | 2 +-
mm/kasan/generic.c | 16 +++-------------
mm/slub.c | 2 +-
10 files changed, 11 insertions(+), 34 deletions(-)
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 00a3bf7c0d8f..1a623818e8b3 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
void kasan_cache_shrink(struct kmem_cache *cache);
void kasan_cache_shutdown(struct kmem_cache *cache);
void kasan_record_aux_stack(void *ptr);
-void kasan_record_aux_stack_noalloc(void *ptr);
#else /* CONFIG_KASAN_GENERIC */
@@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
static inline void kasan_record_aux_stack(void *ptr) {}
-static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
#endif /* CONFIG_KASAN_GENERIC */
diff --git a/include/linux/task_work.h b/include/linux/task_work.h
index 2964171856e0..db1690e01346 100644
--- a/include/linux/task_work.h
+++ b/include/linux/task_work.h
@@ -21,7 +21,6 @@ enum task_work_notify_mode {
TWA_NMI_CURRENT,
TWA_FLAGS = 0xff00,
- TWAF_NO_ALLOC = 0x0100,
};
static inline bool task_work_pending(struct task_struct *task)
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index 2f4fb336dda1..73f7e1fd4ab4 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
if (!irq_work_claim(work))
return false;
- kasan_record_aux_stack_noalloc(work);
+ kasan_record_aux_stack(work);
preempt_disable();
if (cpu != smp_processor_id()) {
diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
index b3b3ce34df63..4b3f31911465 100644
--- a/kernel/rcu/tiny.c
+++ b/kernel/rcu/tiny.c
@@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
void kvfree_call_rcu(struct rcu_head *head, void *ptr)
{
if (head)
- kasan_record_aux_stack_noalloc(ptr);
+ kasan_record_aux_stack(ptr);
__kvfree_call_rcu(head, ptr);
}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index b1f883fcd918..7eae9bd818a9 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
}
head->func = func;
head->next = NULL;
- kasan_record_aux_stack_noalloc(head);
+ kasan_record_aux_stack(head);
local_irq_save(flags);
rdp = this_cpu_ptr(&rcu_data);
lazy = lazy_in && !rcu_async_should_hurry();
@@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
return;
}
- kasan_record_aux_stack_noalloc(ptr);
+ kasan_record_aux_stack(ptr);
success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
if (!success) {
run_page_cache_worker(krcp);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5de31c312189..dafc668a156e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -10519,7 +10519,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
return;
/* No page allocation under rq lock */
- task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
+ task_work_add(curr, work, TWA_RESUME);
}
void sched_mm_cid_exit_signals(struct task_struct *t)
diff --git a/kernel/task_work.c b/kernel/task_work.c
index c969f1f26be5..2ffd5a6db91b 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -64,17 +64,7 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
if (!IS_ENABLED(CONFIG_IRQ_WORK))
return -EINVAL;
} else {
- /*
- * Record the work call stack in order to print it in KASAN
- * reports.
- *
- * Note that stack allocation can fail if TWAF_NO_ALLOC flag
- * is set and new page is needed to expand the stack buffer.
- */
- if (flags & TWAF_NO_ALLOC)
- kasan_record_aux_stack_noalloc(work);
- else
- kasan_record_aux_stack(work);
+ kasan_record_aux_stack(work);
}
head = READ_ONCE(task->task_works);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9949ffad8df0..65b8314b2d53 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
debug_work_activate(work);
/* record the work call stack in order to print it in KASAN reports */
- kasan_record_aux_stack_noalloc(work);
+ kasan_record_aux_stack(work);
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 6310a180278b..ac9f6682bb2f 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -521,12 +521,12 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
sizeof(struct kasan_free_meta) : 0);
}
-static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
+void kasan_record_aux_stack(void *addr)
{
struct slab *slab = kasan_addr_to_slab(addr);
struct kmem_cache *cache;
struct kasan_alloc_meta *alloc_meta;
- void *object;
+ void *object
if (is_kfence_address(addr) || !slab)
return;
@@ -538,17 +538,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
return;
alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
- alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
-}
-
-void kasan_record_aux_stack(void *addr)
-{
- return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
-}
-
-void kasan_record_aux_stack_noalloc(void *addr)
-{
- return __kasan_record_aux_stack(addr, 0);
+ alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
}
void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
diff --git a/mm/slub.c b/mm/slub.c
index 5b832512044e..b8c4bf3fe0d0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
* We have to do this manually because the rcu_head is
* not located inside the object.
*/
- kasan_record_aux_stack_noalloc(x);
+ kasan_record_aux_stack(x);
delayed_free->object = x;
call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist
2024-11-04 11:45 ` [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist Peter Zijlstra
@ 2024-11-04 11:47 ` Peter Zijlstra
2024-11-13 14:18 ` Sebastian Andrzej Siewior
2024-11-04 12:16 ` Marco Elver
1 sibling, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2024-11-04 11:47 UTC (permalink / raw)
To: Vlastimil Babka
Cc: syzbot, Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, Sebastian Andrzej Siewior,
Marco Elver, Andrey Konovalov, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, juri.lelli, vincent.guittot, dietmar.eggemann, bsegall,
mgorman, vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
roman.gushchin, 42.hyeyoo, rcu
On Mon, Nov 04, 2024 at 12:45:06PM +0100, Peter Zijlstra wrote:
> diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> index 6310a180278b..ac9f6682bb2f 100644
> --- a/mm/kasan/generic.c
> +++ b/mm/kasan/generic.c
> @@ -521,12 +521,12 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> sizeof(struct kasan_free_meta) : 0);
> }
>
> -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> +void kasan_record_aux_stack(void *addr)
> {
> struct slab *slab = kasan_addr_to_slab(addr);
> struct kmem_cache *cache;
> struct kasan_alloc_meta *alloc_meta;
> - void *object;
> + void *object
Clearly I'm still struggling to type ... *sigh*
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist
2024-11-04 11:45 ` [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist Peter Zijlstra
2024-11-04 11:47 ` Peter Zijlstra
@ 2024-11-04 12:16 ` Marco Elver
2024-11-19 15:57 ` [PATCH] kasan: Remove kasan_record_aux_stack_noalloc() Sebastian Andrzej Siewior
1 sibling, 1 reply; 14+ messages in thread
From: Marco Elver @ 2024-11-04 12:16 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Vlastimil Babka, syzbot, Liam.Howlett, akpm, jannh, linux-kernel,
linux-mm, lorenzo.stoakes, syzkaller-bugs,
Sebastian Andrzej Siewior, Andrey Konovalov, kasan-dev,
Andrey Ryabinin, Alexander Potapenko, Waiman Long, dvyukov,
vincenzo.frascino, paulmck, frederic, neeraj.upadhyay, joel, josh,
boqun.feng, urezki, rostedt, mathieu.desnoyers, jiangshanlai,
qiang.zhang1211, mingo, juri.lelli, vincent.guittot,
dietmar.eggemann, bsegall, mgorman, vschneid, tj, cl, penberg,
rientjes, iamjoonsoo.kim, roman.gushchin, 42.hyeyoo, rcu
On Mon, 4 Nov 2024 at 12:45, Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Mon, Nov 04, 2024 at 12:25:03PM +0100, Vlastimil Babka wrote:
> > On 11/4/24 12:11, Vlastimil Babka wrote:
>
> > >> __alloc_pages_noprof+0x292/0x710 mm/page_alloc.c:4771
> > >> alloc_pages_mpol_noprof+0x3e8/0x680 mm/mempolicy.c:2265
> > >> stack_depot_save_flags+0x666/0x830 lib/stackdepot.c:627
> > >> kasan_save_stack+0x4f/0x60 mm/kasan/common.c:48
> > >> __kasan_record_aux_stack+0xac/0xc0 mm/kasan/generic.c:544
> > >> task_work_add+0xd9/0x490 kernel/task_work.c:77
> > >
> > > It seems the decision if stack depot is allowed to allocate here depends on
> > > TWAF_NO_ALLOC added only recently. So does it mean it doesn't work as intended?
> >
> > I guess __run_posix_cpu_timers() needs to pass TWAF_NO_ALLOC too?
>
> Yeah, or we just accept that kasan_record_aux_stack() is a horrible
> thing and shouldn't live in functions that try their bestest to
> locklessly setup async work at all.
>
> That thing has only ever caused trouble :/
>
> Also see 156172a13ff0.
>
> How about we do the below at the very least?
I'd be in favor, it simplifies things. And stack depot should be able
to replenish its pool sufficiently in the "non-aux" cases i.e. regular
allocations.
Worst case we fail to record some aux stacks, but I think that's only
really bad if there's a bug around one of these allocations. In
general the probabilities of this being a regression are extremely
small - same as I argued back in
https://lore.kernel.org/all/20210913112609.2651084-1-elver@google.com/
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist
2024-11-04 11:47 ` Peter Zijlstra
@ 2024-11-13 14:18 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 14+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-11-13 14:18 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Vlastimil Babka, syzbot, Liam.Howlett, akpm, jannh, linux-kernel,
linux-mm, lorenzo.stoakes, syzkaller-bugs, Marco Elver,
Andrey Konovalov, kasan-dev, Andrey Ryabinin, Alexander Potapenko,
Waiman Long, dvyukov, vincenzo.frascino, paulmck, frederic,
neeraj.upadhyay, joel, josh, boqun.feng, urezki, rostedt,
mathieu.desnoyers, jiangshanlai, qiang.zhang1211, mingo,
juri.lelli, vincent.guittot, dietmar.eggemann, bsegall, mgorman,
vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
roman.gushchin, 42.hyeyoo, rcu
On 2024-11-04 12:47:26 [+0100], Peter Zijlstra wrote:
> On Mon, Nov 04, 2024 at 12:45:06PM +0100, Peter Zijlstra wrote:
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 6310a180278b..ac9f6682bb2f 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -521,12 +521,12 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> > sizeof(struct kasan_free_meta) : 0);
> > }
> >
> > -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> > +void kasan_record_aux_stack(void *addr)
> > {
> > struct slab *slab = kasan_addr_to_slab(addr);
> > struct kmem_cache *cache;
> > struct kasan_alloc_meta *alloc_meta;
> > - void *object;
> > + void *object
>
> Clearly I'm still struggling to type ... *sigh*
Should I put all this in a patch or is already been done?
Sebastian
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-04 12:16 ` Marco Elver
@ 2024-11-19 15:57 ` Sebastian Andrzej Siewior
2024-11-19 16:22 ` Waiman Long
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-11-19 15:57 UTC (permalink / raw)
To: Marco Elver, Peter Zijlstra
Cc: Vlastimil Babka, syzbot, Liam.Howlett, akpm, jannh, linux-kernel,
linux-mm, lorenzo.stoakes, syzkaller-bugs, Andrey Konovalov,
kasan-dev, Andrey Ryabinin, Alexander Potapenko, Waiman Long,
dvyukov, vincenzo.frascino, paulmck, frederic, neeraj.upadhyay,
joel, josh, boqun.feng, urezki, rostedt, mathieu.desnoyers,
jiangshanlai, qiang.zhang1211, mingo, juri.lelli, vincent.guittot,
dietmar.eggemann, bsegall, mgorman, vschneid, tj, cl, penberg,
rientjes, iamjoonsoo.kim, Thomas Gleixner, roman.gushchin,
42.hyeyoo, rcu
From: Peter Zijlstra <peterz@infradead.org>
kasan_record_aux_stack_noalloc() was introduced to record a stack trace
without allocating memory in the process. It has been added to callers
which were invoked while a raw_spinlock_t was held.
More and more callers were identified and changed over time. Is it a
good thing to have this while functions try their best to do a
locklessly setup? The only downside of having kasan_record_aux_stack()
not allocate any memory is that we end up without a stacktrace if
stackdepot runs out of memory and at the same stacktrace was not
recorded before. Marco Elver said in
https://lore.kernel.org/all/20210913112609.2651084-1-elver@google.com/
that this is rare.
Make the kasan_record_aux_stack_noalloc() behaviour default as
kasan_record_aux_stack().
[bigeasy: Dressed the diff as patch. ]
Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/67275485.050a0220.3c8d68.0a37.GAE@google.com
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
Didn't add a Fixes tag, didn't want to put
7cb3007ce2da2 ("kasan: generic: introduce kasan_record_aux_stack_noalloc()")
there.
include/linux/kasan.h | 2 --
include/linux/task_work.h | 3 ---
kernel/irq_work.c | 2 +-
kernel/rcu/tiny.c | 2 +-
kernel/rcu/tree.c | 4 ++--
kernel/sched/core.c | 2 +-
kernel/task_work.c | 14 +-------------
kernel/workqueue.c | 2 +-
mm/kasan/generic.c | 14 ++------------
mm/slub.c | 2 +-
10 files changed, 10 insertions(+), 37 deletions(-)
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 00a3bf7c0d8f0..1a623818e8b39 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
void kasan_cache_shrink(struct kmem_cache *cache);
void kasan_cache_shutdown(struct kmem_cache *cache);
void kasan_record_aux_stack(void *ptr);
-void kasan_record_aux_stack_noalloc(void *ptr);
#else /* CONFIG_KASAN_GENERIC */
@@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
static inline void kasan_record_aux_stack(void *ptr) {}
-static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
#endif /* CONFIG_KASAN_GENERIC */
diff --git a/include/linux/task_work.h b/include/linux/task_work.h
index 2964171856e00..0646804860ff1 100644
--- a/include/linux/task_work.h
+++ b/include/linux/task_work.h
@@ -19,9 +19,6 @@ enum task_work_notify_mode {
TWA_SIGNAL,
TWA_SIGNAL_NO_IPI,
TWA_NMI_CURRENT,
-
- TWA_FLAGS = 0xff00,
- TWAF_NO_ALLOC = 0x0100,
};
static inline bool task_work_pending(struct task_struct *task)
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index 2f4fb336dda17..73f7e1fd4ab4d 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
if (!irq_work_claim(work))
return false;
- kasan_record_aux_stack_noalloc(work);
+ kasan_record_aux_stack(work);
preempt_disable();
if (cpu != smp_processor_id()) {
diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
index b3b3ce34df631..4b3f319114650 100644
--- a/kernel/rcu/tiny.c
+++ b/kernel/rcu/tiny.c
@@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
void kvfree_call_rcu(struct rcu_head *head, void *ptr)
{
if (head)
- kasan_record_aux_stack_noalloc(ptr);
+ kasan_record_aux_stack(ptr);
__kvfree_call_rcu(head, ptr);
}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index b1f883fcd9185..7eae9bd818a90 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
}
head->func = func;
head->next = NULL;
- kasan_record_aux_stack_noalloc(head);
+ kasan_record_aux_stack(head);
local_irq_save(flags);
rdp = this_cpu_ptr(&rcu_data);
lazy = lazy_in && !rcu_async_should_hurry();
@@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
return;
}
- kasan_record_aux_stack_noalloc(ptr);
+ kasan_record_aux_stack(ptr);
success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
if (!success) {
run_page_cache_worker(krcp);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a1c353a62c568..3717360a940d2 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -10485,7 +10485,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
return;
/* No page allocation under rq lock */
- task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
+ task_work_add(curr, work, TWA_RESUME);
}
void sched_mm_cid_exit_signals(struct task_struct *t)
diff --git a/kernel/task_work.c b/kernel/task_work.c
index c969f1f26be58..d1efec571a4a4 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -55,26 +55,14 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
enum task_work_notify_mode notify)
{
struct callback_head *head;
- int flags = notify & TWA_FLAGS;
- notify &= ~TWA_FLAGS;
if (notify == TWA_NMI_CURRENT) {
if (WARN_ON_ONCE(task != current))
return -EINVAL;
if (!IS_ENABLED(CONFIG_IRQ_WORK))
return -EINVAL;
} else {
- /*
- * Record the work call stack in order to print it in KASAN
- * reports.
- *
- * Note that stack allocation can fail if TWAF_NO_ALLOC flag
- * is set and new page is needed to expand the stack buffer.
- */
- if (flags & TWAF_NO_ALLOC)
- kasan_record_aux_stack_noalloc(work);
- else
- kasan_record_aux_stack(work);
+ kasan_record_aux_stack(work);
}
head = READ_ONCE(task->task_works);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9949ffad8df09..65b8314b2d538 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
debug_work_activate(work);
/* record the work call stack in order to print it in KASAN reports */
- kasan_record_aux_stack_noalloc(work);
+ kasan_record_aux_stack(work);
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 6310a180278b6..b18b5944997f8 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -521,7 +521,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
sizeof(struct kasan_free_meta) : 0);
}
-static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
+void kasan_record_aux_stack(void *addr)
{
struct slab *slab = kasan_addr_to_slab(addr);
struct kmem_cache *cache;
@@ -538,17 +538,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
return;
alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
- alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
-}
-
-void kasan_record_aux_stack(void *addr)
-{
- return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
-}
-
-void kasan_record_aux_stack_noalloc(void *addr)
-{
- return __kasan_record_aux_stack(addr, 0);
+ alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
}
void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
diff --git a/mm/slub.c b/mm/slub.c
index 5b832512044e3..b8c4bf3fe0d07 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
* We have to do this manually because the rcu_head is
* not located inside the object.
*/
- kasan_record_aux_stack_noalloc(x);
+ kasan_record_aux_stack(x);
delayed_free->object = x;
call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
--
2.45.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-19 15:57 ` [PATCH] kasan: Remove kasan_record_aux_stack_noalloc() Sebastian Andrzej Siewior
@ 2024-11-19 16:22 ` Waiman Long
2024-11-19 16:37 ` Marco Elver
2024-11-19 19:36 ` Andrey Konovalov
2 siblings, 0 replies; 14+ messages in thread
From: Waiman Long @ 2024-11-19 16:22 UTC (permalink / raw)
To: Sebastian Andrzej Siewior, Marco Elver, Peter Zijlstra
Cc: Vlastimil Babka, syzbot, Liam.Howlett, akpm, jannh, linux-kernel,
linux-mm, lorenzo.stoakes, syzkaller-bugs, Andrey Konovalov,
kasan-dev, Andrey Ryabinin, Alexander Potapenko, dvyukov,
vincenzo.frascino, paulmck, frederic, neeraj.upadhyay, joel, josh,
boqun.feng, urezki, rostedt, mathieu.desnoyers, jiangshanlai,
qiang.zhang1211, mingo, juri.lelli, vincent.guittot,
dietmar.eggemann, bsegall, mgorman, vschneid, tj, cl, penberg,
rientjes, iamjoonsoo.kim, Thomas Gleixner, roman.gushchin,
42.hyeyoo, rcu
On 11/19/24 10:57 AM, Sebastian Andrzej Siewior wrote:
> From: Peter Zijlstra <peterz@infradead.org>
>
> kasan_record_aux_stack_noalloc() was introduced to record a stack trace
> without allocating memory in the process. It has been added to callers
> which were invoked while a raw_spinlock_t was held.
> More and more callers were identified and changed over time. Is it a
> good thing to have this while functions try their best to do a
> locklessly setup? The only downside of having kasan_record_aux_stack()
> not allocate any memory is that we end up without a stacktrace if
> stackdepot runs out of memory and at the same stacktrace was not
> recorded before. Marco Elver said in
> https://lore.kernel.org/all/20210913112609.2651084-1-elver@google.com/
> that this is rare.
>
> Make the kasan_record_aux_stack_noalloc() behaviour default as
> kasan_record_aux_stack().
>
> [bigeasy: Dressed the diff as patch. ]
>
> Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/67275485.050a0220.3c8d68.0a37.GAE@google.com
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>
> Didn't add a Fixes tag, didn't want to put
> 7cb3007ce2da2 ("kasan: generic: introduce kasan_record_aux_stack_noalloc()")
>
> there.
Right now task_work_add() is the only caller of
kasan_record_aux_stack(). So it essentially make all its callers use the
noalloc version of kasan_record_aux_stack().
Acked-by: Waiman Long <longman@redhat.com>
> include/linux/kasan.h | 2 --
> include/linux/task_work.h | 3 ---
> kernel/irq_work.c | 2 +-
> kernel/rcu/tiny.c | 2 +-
> kernel/rcu/tree.c | 4 ++--
> kernel/sched/core.c | 2 +-
> kernel/task_work.c | 14 +-------------
> kernel/workqueue.c | 2 +-
> mm/kasan/generic.c | 14 ++------------
> mm/slub.c | 2 +-
> 10 files changed, 10 insertions(+), 37 deletions(-)
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 00a3bf7c0d8f0..1a623818e8b39 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> void kasan_cache_shrink(struct kmem_cache *cache);
> void kasan_cache_shutdown(struct kmem_cache *cache);
> void kasan_record_aux_stack(void *ptr);
> -void kasan_record_aux_stack_noalloc(void *ptr);
>
> #else /* CONFIG_KASAN_GENERIC */
>
> @@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
> static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> static inline void kasan_record_aux_stack(void *ptr) {}
> -static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
>
> #endif /* CONFIG_KASAN_GENERIC */
>
> diff --git a/include/linux/task_work.h b/include/linux/task_work.h
> index 2964171856e00..0646804860ff1 100644
> --- a/include/linux/task_work.h
> +++ b/include/linux/task_work.h
> @@ -19,9 +19,6 @@ enum task_work_notify_mode {
> TWA_SIGNAL,
> TWA_SIGNAL_NO_IPI,
> TWA_NMI_CURRENT,
> -
> - TWA_FLAGS = 0xff00,
> - TWAF_NO_ALLOC = 0x0100,
> };
>
> static inline bool task_work_pending(struct task_struct *task)
> diff --git a/kernel/irq_work.c b/kernel/irq_work.c
> index 2f4fb336dda17..73f7e1fd4ab4d 100644
> --- a/kernel/irq_work.c
> +++ b/kernel/irq_work.c
> @@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
> if (!irq_work_claim(work))
> return false;
>
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> preempt_disable();
> if (cpu != smp_processor_id()) {
> diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
> index b3b3ce34df631..4b3f319114650 100644
> --- a/kernel/rcu/tiny.c
> +++ b/kernel/rcu/tiny.c
> @@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
> void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> {
> if (head)
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
>
> __kvfree_call_rcu(head, ptr);
> }
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index b1f883fcd9185..7eae9bd818a90 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
> }
> head->func = func;
> head->next = NULL;
> - kasan_record_aux_stack_noalloc(head);
> + kasan_record_aux_stack(head);
> local_irq_save(flags);
> rdp = this_cpu_ptr(&rcu_data);
> lazy = lazy_in && !rcu_async_should_hurry();
> @@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> return;
> }
>
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
> success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
> if (!success) {
> run_page_cache_worker(krcp);
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index a1c353a62c568..3717360a940d2 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -10485,7 +10485,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
> return;
>
> /* No page allocation under rq lock */
> - task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
> + task_work_add(curr, work, TWA_RESUME);
> }
>
> void sched_mm_cid_exit_signals(struct task_struct *t)
> diff --git a/kernel/task_work.c b/kernel/task_work.c
> index c969f1f26be58..d1efec571a4a4 100644
> --- a/kernel/task_work.c
> +++ b/kernel/task_work.c
> @@ -55,26 +55,14 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
> enum task_work_notify_mode notify)
> {
> struct callback_head *head;
> - int flags = notify & TWA_FLAGS;
>
> - notify &= ~TWA_FLAGS;
> if (notify == TWA_NMI_CURRENT) {
> if (WARN_ON_ONCE(task != current))
> return -EINVAL;
> if (!IS_ENABLED(CONFIG_IRQ_WORK))
> return -EINVAL;
> } else {
> - /*
> - * Record the work call stack in order to print it in KASAN
> - * reports.
> - *
> - * Note that stack allocation can fail if TWAF_NO_ALLOC flag
> - * is set and new page is needed to expand the stack buffer.
> - */
> - if (flags & TWAF_NO_ALLOC)
> - kasan_record_aux_stack_noalloc(work);
> - else
> - kasan_record_aux_stack(work);
> + kasan_record_aux_stack(work);
> }
>
> head = READ_ONCE(task->task_works);
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 9949ffad8df09..65b8314b2d538 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
> debug_work_activate(work);
>
> /* record the work call stack in order to print it in KASAN reports */
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> /* we own @work, set data and link */
> set_work_pwq(work, pwq, extra_flags);
> diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> index 6310a180278b6..b18b5944997f8 100644
> --- a/mm/kasan/generic.c
> +++ b/mm/kasan/generic.c
> @@ -521,7 +521,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> sizeof(struct kasan_free_meta) : 0);
> }
>
> -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> +void kasan_record_aux_stack(void *addr)
> {
> struct slab *slab = kasan_addr_to_slab(addr);
> struct kmem_cache *cache;
> @@ -538,17 +538,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> return;
>
> alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
> - alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
> -}
> -
> -void kasan_record_aux_stack(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
> -}
> -
> -void kasan_record_aux_stack_noalloc(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, 0);
> + alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
> }
>
> void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
> diff --git a/mm/slub.c b/mm/slub.c
> index 5b832512044e3..b8c4bf3fe0d07 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
> * We have to do this manually because the rcu_head is
> * not located inside the object.
> */
> - kasan_record_aux_stack_noalloc(x);
> + kasan_record_aux_stack(x);
>
> delayed_free->object = x;
> call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-19 15:57 ` [PATCH] kasan: Remove kasan_record_aux_stack_noalloc() Sebastian Andrzej Siewior
2024-11-19 16:22 ` Waiman Long
@ 2024-11-19 16:37 ` Marco Elver
2024-11-19 19:36 ` Andrey Konovalov
2 siblings, 0 replies; 14+ messages in thread
From: Marco Elver @ 2024-11-19 16:37 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Peter Zijlstra, Vlastimil Babka, syzbot, Liam.Howlett, akpm,
jannh, linux-kernel, linux-mm, lorenzo.stoakes, syzkaller-bugs,
Andrey Konovalov, kasan-dev, Andrey Ryabinin, Alexander Potapenko,
Waiman Long, dvyukov, vincenzo.frascino, paulmck, frederic,
neeraj.upadhyay, joel, josh, boqun.feng, urezki, rostedt,
mathieu.desnoyers, jiangshanlai, qiang.zhang1211, mingo,
juri.lelli, vincent.guittot, dietmar.eggemann, bsegall, mgorman,
vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
On Tue, 19 Nov 2024 at 16:57, Sebastian Andrzej Siewior
<bigeasy@linutronix.de> wrote:
>
> From: Peter Zijlstra <peterz@infradead.org>
The patch title is misleading - it might suggest the opposite of what
it's doing. I think this might be clearer:
"kasan: Make kasan_record_aux_stack_noalloc() the default behaviour"
Which is also more or less what you say below.
> kasan_record_aux_stack_noalloc() was introduced to record a stack trace
> without allocating memory in the process. It has been added to callers
> which were invoked while a raw_spinlock_t was held.
> More and more callers were identified and changed over time. Is it a
> good thing to have this while functions try their best to do a
> locklessly setup? The only downside of having kasan_record_aux_stack()
> not allocate any memory is that we end up without a stacktrace if
> stackdepot runs out of memory and at the same stacktrace was not
> recorded before. Marco Elver said in
> https://lore.kernel.org/all/20210913112609.2651084-1-elver@google.com/
> that this is rare.
>
> Make the kasan_record_aux_stack_noalloc() behaviour default as
> kasan_record_aux_stack().
>
> [bigeasy: Dressed the diff as patch. ]
>
> Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/67275485.050a0220.3c8d68.0a37.GAE@google.com
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Marco Elver <elver@google.com>
As I wrote in https://lore.kernel.org/all/CANpmjNPmQYJ7pv1N3cuU8cP18u7PP_uoZD8YxwZd4jtbof9nVQ@mail.gmail.com/:
> I'd be in favor, it simplifies things. And stack depot should be
> able to replenish its pool sufficiently in the "non-aux" cases
> i.e. regular allocations. Worst case we fail to record some
> aux stacks, but I think that's only really bad if there's a bug
> around one of these allocations. In general the probabilities
> of this being a regression are extremely small [...]
Good riddance.
Thanks,
-- Marco
> ---
>
> Didn't add a Fixes tag, didn't want to put
> 7cb3007ce2da2 ("kasan: generic: introduce kasan_record_aux_stack_noalloc()")
>
> there.
>
> include/linux/kasan.h | 2 --
> include/linux/task_work.h | 3 ---
> kernel/irq_work.c | 2 +-
> kernel/rcu/tiny.c | 2 +-
> kernel/rcu/tree.c | 4 ++--
> kernel/sched/core.c | 2 +-
> kernel/task_work.c | 14 +-------------
> kernel/workqueue.c | 2 +-
> mm/kasan/generic.c | 14 ++------------
> mm/slub.c | 2 +-
> 10 files changed, 10 insertions(+), 37 deletions(-)
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 00a3bf7c0d8f0..1a623818e8b39 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> void kasan_cache_shrink(struct kmem_cache *cache);
> void kasan_cache_shutdown(struct kmem_cache *cache);
> void kasan_record_aux_stack(void *ptr);
> -void kasan_record_aux_stack_noalloc(void *ptr);
>
> #else /* CONFIG_KASAN_GENERIC */
>
> @@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
> static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> static inline void kasan_record_aux_stack(void *ptr) {}
> -static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
>
> #endif /* CONFIG_KASAN_GENERIC */
>
> diff --git a/include/linux/task_work.h b/include/linux/task_work.h
> index 2964171856e00..0646804860ff1 100644
> --- a/include/linux/task_work.h
> +++ b/include/linux/task_work.h
> @@ -19,9 +19,6 @@ enum task_work_notify_mode {
> TWA_SIGNAL,
> TWA_SIGNAL_NO_IPI,
> TWA_NMI_CURRENT,
> -
> - TWA_FLAGS = 0xff00,
> - TWAF_NO_ALLOC = 0x0100,
> };
>
> static inline bool task_work_pending(struct task_struct *task)
> diff --git a/kernel/irq_work.c b/kernel/irq_work.c
> index 2f4fb336dda17..73f7e1fd4ab4d 100644
> --- a/kernel/irq_work.c
> +++ b/kernel/irq_work.c
> @@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
> if (!irq_work_claim(work))
> return false;
>
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> preempt_disable();
> if (cpu != smp_processor_id()) {
> diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
> index b3b3ce34df631..4b3f319114650 100644
> --- a/kernel/rcu/tiny.c
> +++ b/kernel/rcu/tiny.c
> @@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
> void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> {
> if (head)
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
>
> __kvfree_call_rcu(head, ptr);
> }
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index b1f883fcd9185..7eae9bd818a90 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
> }
> head->func = func;
> head->next = NULL;
> - kasan_record_aux_stack_noalloc(head);
> + kasan_record_aux_stack(head);
> local_irq_save(flags);
> rdp = this_cpu_ptr(&rcu_data);
> lazy = lazy_in && !rcu_async_should_hurry();
> @@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> return;
> }
>
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
> success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
> if (!success) {
> run_page_cache_worker(krcp);
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index a1c353a62c568..3717360a940d2 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -10485,7 +10485,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
> return;
>
> /* No page allocation under rq lock */
> - task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
> + task_work_add(curr, work, TWA_RESUME);
> }
>
> void sched_mm_cid_exit_signals(struct task_struct *t)
> diff --git a/kernel/task_work.c b/kernel/task_work.c
> index c969f1f26be58..d1efec571a4a4 100644
> --- a/kernel/task_work.c
> +++ b/kernel/task_work.c
> @@ -55,26 +55,14 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
> enum task_work_notify_mode notify)
> {
> struct callback_head *head;
> - int flags = notify & TWA_FLAGS;
>
> - notify &= ~TWA_FLAGS;
> if (notify == TWA_NMI_CURRENT) {
> if (WARN_ON_ONCE(task != current))
> return -EINVAL;
> if (!IS_ENABLED(CONFIG_IRQ_WORK))
> return -EINVAL;
> } else {
> - /*
> - * Record the work call stack in order to print it in KASAN
> - * reports.
> - *
> - * Note that stack allocation can fail if TWAF_NO_ALLOC flag
> - * is set and new page is needed to expand the stack buffer.
> - */
> - if (flags & TWAF_NO_ALLOC)
> - kasan_record_aux_stack_noalloc(work);
> - else
> - kasan_record_aux_stack(work);
> + kasan_record_aux_stack(work);
> }
>
> head = READ_ONCE(task->task_works);
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 9949ffad8df09..65b8314b2d538 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
> debug_work_activate(work);
>
> /* record the work call stack in order to print it in KASAN reports */
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> /* we own @work, set data and link */
> set_work_pwq(work, pwq, extra_flags);
> diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> index 6310a180278b6..b18b5944997f8 100644
> --- a/mm/kasan/generic.c
> +++ b/mm/kasan/generic.c
> @@ -521,7 +521,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> sizeof(struct kasan_free_meta) : 0);
> }
>
> -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> +void kasan_record_aux_stack(void *addr)
> {
> struct slab *slab = kasan_addr_to_slab(addr);
> struct kmem_cache *cache;
> @@ -538,17 +538,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> return;
>
> alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
> - alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
> -}
> -
> -void kasan_record_aux_stack(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
> -}
> -
> -void kasan_record_aux_stack_noalloc(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, 0);
> + alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
> }
>
> void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
> diff --git a/mm/slub.c b/mm/slub.c
> index 5b832512044e3..b8c4bf3fe0d07 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
> * We have to do this manually because the rcu_head is
> * not located inside the object.
> */
> - kasan_record_aux_stack_noalloc(x);
> + kasan_record_aux_stack(x);
>
> delayed_free->object = x;
> call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
> --
> 2.45.2
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-19 15:57 ` [PATCH] kasan: Remove kasan_record_aux_stack_noalloc() Sebastian Andrzej Siewior
2024-11-19 16:22 ` Waiman Long
2024-11-19 16:37 ` Marco Elver
@ 2024-11-19 19:36 ` Andrey Konovalov
2024-11-22 11:32 ` Sebastian Andrzej Siewior
2024-11-22 15:54 ` [PATCH v2] kasan: Make kasan_record_aux_stack_noalloc() the default behaviour Sebastian Andrzej Siewior
2 siblings, 2 replies; 14+ messages in thread
From: Andrey Konovalov @ 2024-11-19 19:36 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Marco Elver, Peter Zijlstra, Vlastimil Babka, syzbot,
Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, juri.lelli, vincent.guittot, dietmar.eggemann, bsegall,
mgorman, vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
On Tue, Nov 19, 2024 at 4:57 PM Sebastian Andrzej Siewior
<bigeasy@linutronix.de> wrote:
>
> From: Peter Zijlstra <peterz@infradead.org>
>
> kasan_record_aux_stack_noalloc() was introduced to record a stack trace
> without allocating memory in the process. It has been added to callers
> which were invoked while a raw_spinlock_t was held.
> More and more callers were identified and changed over time. Is it a
> good thing to have this while functions try their best to do a
> locklessly setup? The only downside of having kasan_record_aux_stack()
> not allocate any memory is that we end up without a stacktrace if
> stackdepot runs out of memory and at the same stacktrace was not
> recorded before. Marco Elver said in
> https://lore.kernel.org/all/20210913112609.2651084-1-elver@google.com/
> that this is rare.
>
> Make the kasan_record_aux_stack_noalloc() behaviour default as
> kasan_record_aux_stack().
>
> [bigeasy: Dressed the diff as patch. ]
>
> Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/67275485.050a0220.3c8d68.0a37.GAE@google.com
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>
> Didn't add a Fixes tag, didn't want to put
> 7cb3007ce2da2 ("kasan: generic: introduce kasan_record_aux_stack_noalloc()")
>
> there.
>
> include/linux/kasan.h | 2 --
> include/linux/task_work.h | 3 ---
> kernel/irq_work.c | 2 +-
> kernel/rcu/tiny.c | 2 +-
> kernel/rcu/tree.c | 4 ++--
> kernel/sched/core.c | 2 +-
> kernel/task_work.c | 14 +-------------
> kernel/workqueue.c | 2 +-
> mm/kasan/generic.c | 14 ++------------
> mm/slub.c | 2 +-
> 10 files changed, 10 insertions(+), 37 deletions(-)
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 00a3bf7c0d8f0..1a623818e8b39 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> void kasan_cache_shrink(struct kmem_cache *cache);
> void kasan_cache_shutdown(struct kmem_cache *cache);
> void kasan_record_aux_stack(void *ptr);
> -void kasan_record_aux_stack_noalloc(void *ptr);
>
> #else /* CONFIG_KASAN_GENERIC */
>
> @@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
> static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> static inline void kasan_record_aux_stack(void *ptr) {}
> -static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
>
> #endif /* CONFIG_KASAN_GENERIC */
>
> diff --git a/include/linux/task_work.h b/include/linux/task_work.h
> index 2964171856e00..0646804860ff1 100644
> --- a/include/linux/task_work.h
> +++ b/include/linux/task_work.h
> @@ -19,9 +19,6 @@ enum task_work_notify_mode {
> TWA_SIGNAL,
> TWA_SIGNAL_NO_IPI,
> TWA_NMI_CURRENT,
> -
> - TWA_FLAGS = 0xff00,
> - TWAF_NO_ALLOC = 0x0100,
> };
>
> static inline bool task_work_pending(struct task_struct *task)
> diff --git a/kernel/irq_work.c b/kernel/irq_work.c
> index 2f4fb336dda17..73f7e1fd4ab4d 100644
> --- a/kernel/irq_work.c
> +++ b/kernel/irq_work.c
> @@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
> if (!irq_work_claim(work))
> return false;
>
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> preempt_disable();
> if (cpu != smp_processor_id()) {
> diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
> index b3b3ce34df631..4b3f319114650 100644
> --- a/kernel/rcu/tiny.c
> +++ b/kernel/rcu/tiny.c
> @@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
> void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> {
> if (head)
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
>
> __kvfree_call_rcu(head, ptr);
> }
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index b1f883fcd9185..7eae9bd818a90 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
> }
> head->func = func;
> head->next = NULL;
> - kasan_record_aux_stack_noalloc(head);
> + kasan_record_aux_stack(head);
> local_irq_save(flags);
> rdp = this_cpu_ptr(&rcu_data);
> lazy = lazy_in && !rcu_async_should_hurry();
> @@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> return;
> }
>
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
> success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
> if (!success) {
> run_page_cache_worker(krcp);
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index a1c353a62c568..3717360a940d2 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -10485,7 +10485,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
> return;
>
> /* No page allocation under rq lock */
> - task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
> + task_work_add(curr, work, TWA_RESUME);
> }
>
> void sched_mm_cid_exit_signals(struct task_struct *t)
> diff --git a/kernel/task_work.c b/kernel/task_work.c
> index c969f1f26be58..d1efec571a4a4 100644
> --- a/kernel/task_work.c
> +++ b/kernel/task_work.c
> @@ -55,26 +55,14 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
> enum task_work_notify_mode notify)
> {
> struct callback_head *head;
> - int flags = notify & TWA_FLAGS;
>
> - notify &= ~TWA_FLAGS;
> if (notify == TWA_NMI_CURRENT) {
> if (WARN_ON_ONCE(task != current))
> return -EINVAL;
> if (!IS_ENABLED(CONFIG_IRQ_WORK))
> return -EINVAL;
> } else {
> - /*
> - * Record the work call stack in order to print it in KASAN
> - * reports.
> - *
> - * Note that stack allocation can fail if TWAF_NO_ALLOC flag
> - * is set and new page is needed to expand the stack buffer.
> - */
> - if (flags & TWAF_NO_ALLOC)
> - kasan_record_aux_stack_noalloc(work);
> - else
> - kasan_record_aux_stack(work);
> + kasan_record_aux_stack(work);
> }
>
> head = READ_ONCE(task->task_works);
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 9949ffad8df09..65b8314b2d538 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
> debug_work_activate(work);
>
> /* record the work call stack in order to print it in KASAN reports */
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> /* we own @work, set data and link */
> set_work_pwq(work, pwq, extra_flags);
> diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> index 6310a180278b6..b18b5944997f8 100644
> --- a/mm/kasan/generic.c
> +++ b/mm/kasan/generic.c
> @@ -521,7 +521,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> sizeof(struct kasan_free_meta) : 0);
> }
>
> -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
Could you add a comment here that notes the usage, something like:
"This function avoids dynamic memory allocations and thus can be
called from contexts that do not allow allocating memory."
> +void kasan_record_aux_stack(void *addr)
> {
> struct slab *slab = kasan_addr_to_slab(addr);
> struct kmem_cache *cache;
> @@ -538,17 +538,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> return;
>
> alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
> - alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
> -}
> -
> -void kasan_record_aux_stack(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
> -}
> -
> -void kasan_record_aux_stack_noalloc(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, 0);
> + alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
> }
>
> void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
> diff --git a/mm/slub.c b/mm/slub.c
> index 5b832512044e3..b8c4bf3fe0d07 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
> * We have to do this manually because the rcu_head is
> * not located inside the object.
> */
> - kasan_record_aux_stack_noalloc(x);
> + kasan_record_aux_stack(x);
>
> delayed_free->object = x;
> call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
> --
> 2.45.2
>
Otherwise,
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Thank you!
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-19 19:36 ` Andrey Konovalov
@ 2024-11-22 11:32 ` Sebastian Andrzej Siewior
2024-11-22 15:01 ` Marco Elver
2024-11-22 15:54 ` [PATCH v2] kasan: Make kasan_record_aux_stack_noalloc() the default behaviour Sebastian Andrzej Siewior
1 sibling, 1 reply; 14+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-11-22 11:32 UTC (permalink / raw)
To: Andrey Konovalov
Cc: Marco Elver, Peter Zijlstra, Vlastimil Babka, syzbot,
Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, juri.lelli, vincent.guittot, dietmar.eggemann, bsegall,
mgorman, vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
On 2024-11-19 20:36:56 [+0100], Andrey Konovalov wrote:
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 6310a180278b6..b18b5944997f8 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -521,7 +521,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> > sizeof(struct kasan_free_meta) : 0);
> > }
> >
> > -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
>
> Could you add a comment here that notes the usage, something like:
>
> "This function avoids dynamic memory allocations and thus can be
> called from contexts that do not allow allocating memory."
>
> > +void kasan_record_aux_stack(void *addr)
> > {
…
Added but would prefer to add a pointer to stack_depot_save_flags()
which has this Context: paragraph. Would that work?
Now looking at it, it says:
| * Context: Any context, but setting STACK_DEPOT_FLAG_CAN_ALLOC is required if
| * alloc_pages() cannot be used from the current context. Currently
| * this is the case for contexts where neither %GFP_ATOMIC nor
| * %GFP_NOWAIT can be used (NMI, raw_spin_lock).
If I understand this correctly then STACK_DEPOT_FLAG_CAN_ALLOC must not
be specified if invoked from NMI. This will stop
stack_depot_save_flags() from allocating memory the function will still
acquire pool_lock, right?
Do we need to update the comment saying that it must not be used from
NMI or do we make it jump over the locked section in the NMI case?
Sebastian
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-22 11:32 ` Sebastian Andrzej Siewior
@ 2024-11-22 15:01 ` Marco Elver
2024-11-22 15:29 ` Sebastian Andrzej Siewior
0 siblings, 1 reply; 14+ messages in thread
From: Marco Elver @ 2024-11-22 15:01 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Andrey Konovalov, Peter Zijlstra, Vlastimil Babka, syzbot,
Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, juri.lelli, vincent.guittot, dietmar.eggemann, bsegall,
mgorman, vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
On Fri, Nov 22, 2024 at 12:32PM +0100, Sebastian Andrzej Siewior wrote:
> On 2024-11-19 20:36:56 [+0100], Andrey Konovalov wrote:
> > > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > > index 6310a180278b6..b18b5944997f8 100644
> > > --- a/mm/kasan/generic.c
> > > +++ b/mm/kasan/generic.c
> > > @@ -521,7 +521,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> > > sizeof(struct kasan_free_meta) : 0);
> > > }
> > >
> > > -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> >
> > Could you add a comment here that notes the usage, something like:
> >
> > "This function avoids dynamic memory allocations and thus can be
> > called from contexts that do not allow allocating memory."
> >
> > > +void kasan_record_aux_stack(void *addr)
> > > {
> …
> Added but would prefer to add a pointer to stack_depot_save_flags()
> which has this Context: paragraph. Would that work?
> Now looking at it, it says:
> | * Context: Any context, but setting STACK_DEPOT_FLAG_CAN_ALLOC is required if
> | * alloc_pages() cannot be used from the current context. Currently
> | * this is the case for contexts where neither %GFP_ATOMIC nor
> | * %GFP_NOWAIT can be used (NMI, raw_spin_lock).
>
> If I understand this correctly then STACK_DEPOT_FLAG_CAN_ALLOC must not
> be specified if invoked from NMI. This will stop
> stack_depot_save_flags() from allocating memory the function will still
> acquire pool_lock, right?
> Do we need to update the comment saying that it must not be used from
> NMI or do we make it jump over the locked section in the NMI case?
Good point. It was meant to also be usable from NMI, because it's very
likely to succeed, and should just take the lock-less fast path once the
stack is in the depot.
But I think we need a fix like this for initial saving of a stack trace:
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 5ed34cc963fc..245d5b416699 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -630,7 +630,15 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
prealloc = page_address(page);
}
- raw_spin_lock_irqsave(&pool_lock, flags);
+ if (in_nmi()) {
+ /* We can never allocate in NMI context. */
+ WARN_ON_ONCE(can_alloc);
+ /* Best effort; bail if we fail to take the lock. */
+ if (!raw_spin_trylock_irqsave(&pool_lock, flags))
+ goto exit;
+ } else {
+ raw_spin_lock_irqsave(&pool_lock, flags);
+ }
printk_deferred_enter();
/* Try to find again, to avoid concurrently inserting duplicates. */
If that looks reasonable, I'll turn it into a patch.
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] kasan: Remove kasan_record_aux_stack_noalloc().
2024-11-22 15:01 ` Marco Elver
@ 2024-11-22 15:29 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 14+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-11-22 15:29 UTC (permalink / raw)
To: Marco Elver
Cc: Andrey Konovalov, Peter Zijlstra, Vlastimil Babka, syzbot,
Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, juri.lelli, vincent.guittot, dietmar.eggemann, bsegall,
mgorman, vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
On 2024-11-22 16:01:29 [+0100], Marco Elver wrote:
> > Do we need to update the comment saying that it must not be used from
> > NMI or do we make it jump over the locked section in the NMI case?
>
> Good point. It was meant to also be usable from NMI, because it's very
> likely to succeed, and should just take the lock-less fast path once the
> stack is in the depot.
>
> But I think we need a fix like this for initial saving of a stack trace:
>
>
> diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> index 5ed34cc963fc..245d5b416699 100644
> --- a/lib/stackdepot.c
> +++ b/lib/stackdepot.c
> @@ -630,7 +630,15 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
> prealloc = page_address(page);
> }
>
> - raw_spin_lock_irqsave(&pool_lock, flags);
> + if (in_nmi()) {
> + /* We can never allocate in NMI context. */
> + WARN_ON_ONCE(can_alloc);
> + /* Best effort; bail if we fail to take the lock. */
> + if (!raw_spin_trylock_irqsave(&pool_lock, flags))
> + goto exit;
> + } else {
> + raw_spin_lock_irqsave(&pool_lock, flags);
> + }
> printk_deferred_enter();
>
> /* Try to find again, to avoid concurrently inserting duplicates. */
>
>
> If that looks reasonable, I'll turn it into a patch.
Yes, looks reasonable.
Sebastian
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2] kasan: Make kasan_record_aux_stack_noalloc() the default behaviour
2024-11-19 19:36 ` Andrey Konovalov
2024-11-22 11:32 ` Sebastian Andrzej Siewior
@ 2024-11-22 15:54 ` Sebastian Andrzej Siewior
2024-11-22 18:04 ` Waiman Long
1 sibling, 1 reply; 14+ messages in thread
From: Sebastian Andrzej Siewior @ 2024-11-22 15:54 UTC (permalink / raw)
To: Andrey Konovalov
Cc: Marco Elver, Peter Zijlstra, Vlastimil Babka, syzbot,
Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, Waiman Long, dvyukov, vincenzo.frascino,
paulmck, frederic, neeraj.upadhyay, joel, josh, boqun.feng,
urezki, rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211,
mingo, juri.lelli, vincent.guittot, dietmar.eggemann, bsegall,
mgorman, vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
From: Peter Zijlstra <peterz@infradead.org>
kasan_record_aux_stack_noalloc() was introduced to record a stack trace
without allocating memory in the process. It has been added to callers
which were invoked while a raw_spinlock_t was held.
More and more callers were identified and changed over time. Is it a
good thing to have this while functions try their best to do a
locklessly setup? The only downside of having kasan_record_aux_stack()
not allocate any memory is that we end up without a stacktrace if
stackdepot runs out of memory and at the same stacktrace was not
recorded before To quote Marco Elver from
https://lore.kernel.org/all/CANpmjNPmQYJ7pv1N3cuU8cP18u7PP_uoZD8YxwZd4jtbof9nVQ@mail.gmail.com/
| I'd be in favor, it simplifies things. And stack depot should be
| able to replenish its pool sufficiently in the "non-aux" cases
| i.e. regular allocations. Worst case we fail to record some
| aux stacks, but I think that's only really bad if there's a bug
| around one of these allocations. In general the probabilities
| of this being a regression are extremely small [...]
Make the kasan_record_aux_stack_noalloc() behaviour default as
kasan_record_aux_stack().
[bigeasy: Dressed the diff as patch. ]
Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/67275485.050a0220.3c8d68.0a37.GAE@google.com
Acked-by: Waiman Long <longman@redhat.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Reviewed-by: Marco Elver <elver@google.com>
Fixes: 7cb3007ce2da2 ("kasan: generic: introduce kasan_record_aux_stack_noalloc()")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
v1…v2:
- Renamed the patch as per Marco.
- Added comment to kasan_record_aux_stack() as per Andrey.
- Added fixes tag since Waiman that it is the only user.
- Added Marco's quote from the mail to the commit description.
include/linux/kasan.h | 2 --
include/linux/task_work.h | 3 ---
kernel/irq_work.c | 2 +-
kernel/rcu/tiny.c | 2 +-
kernel/rcu/tree.c | 4 ++--
kernel/sched/core.c | 2 +-
kernel/task_work.c | 14 +-------------
kernel/workqueue.c | 2 +-
mm/kasan/generic.c | 18 ++++++------------
mm/slub.c | 2 +-
10 files changed, 14 insertions(+), 37 deletions(-)
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 00a3bf7c0d8f0..1a623818e8b39 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
void kasan_cache_shrink(struct kmem_cache *cache);
void kasan_cache_shutdown(struct kmem_cache *cache);
void kasan_record_aux_stack(void *ptr);
-void kasan_record_aux_stack_noalloc(void *ptr);
#else /* CONFIG_KASAN_GENERIC */
@@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
static inline void kasan_record_aux_stack(void *ptr) {}
-static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
#endif /* CONFIG_KASAN_GENERIC */
diff --git a/include/linux/task_work.h b/include/linux/task_work.h
index 2964171856e00..0646804860ff1 100644
--- a/include/linux/task_work.h
+++ b/include/linux/task_work.h
@@ -19,9 +19,6 @@ enum task_work_notify_mode {
TWA_SIGNAL,
TWA_SIGNAL_NO_IPI,
TWA_NMI_CURRENT,
-
- TWA_FLAGS = 0xff00,
- TWAF_NO_ALLOC = 0x0100,
};
static inline bool task_work_pending(struct task_struct *task)
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index 2f4fb336dda17..73f7e1fd4ab4d 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
if (!irq_work_claim(work))
return false;
- kasan_record_aux_stack_noalloc(work);
+ kasan_record_aux_stack(work);
preempt_disable();
if (cpu != smp_processor_id()) {
diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
index b3b3ce34df631..4b3f319114650 100644
--- a/kernel/rcu/tiny.c
+++ b/kernel/rcu/tiny.c
@@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
void kvfree_call_rcu(struct rcu_head *head, void *ptr)
{
if (head)
- kasan_record_aux_stack_noalloc(ptr);
+ kasan_record_aux_stack(ptr);
__kvfree_call_rcu(head, ptr);
}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index b1f883fcd9185..7eae9bd818a90 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
}
head->func = func;
head->next = NULL;
- kasan_record_aux_stack_noalloc(head);
+ kasan_record_aux_stack(head);
local_irq_save(flags);
rdp = this_cpu_ptr(&rcu_data);
lazy = lazy_in && !rcu_async_should_hurry();
@@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
return;
}
- kasan_record_aux_stack_noalloc(ptr);
+ kasan_record_aux_stack(ptr);
success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
if (!success) {
run_page_cache_worker(krcp);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a1c353a62c568..3717360a940d2 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -10485,7 +10485,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
return;
/* No page allocation under rq lock */
- task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
+ task_work_add(curr, work, TWA_RESUME);
}
void sched_mm_cid_exit_signals(struct task_struct *t)
diff --git a/kernel/task_work.c b/kernel/task_work.c
index c969f1f26be58..d1efec571a4a4 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -55,26 +55,14 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
enum task_work_notify_mode notify)
{
struct callback_head *head;
- int flags = notify & TWA_FLAGS;
- notify &= ~TWA_FLAGS;
if (notify == TWA_NMI_CURRENT) {
if (WARN_ON_ONCE(task != current))
return -EINVAL;
if (!IS_ENABLED(CONFIG_IRQ_WORK))
return -EINVAL;
} else {
- /*
- * Record the work call stack in order to print it in KASAN
- * reports.
- *
- * Note that stack allocation can fail if TWAF_NO_ALLOC flag
- * is set and new page is needed to expand the stack buffer.
- */
- if (flags & TWAF_NO_ALLOC)
- kasan_record_aux_stack_noalloc(work);
- else
- kasan_record_aux_stack(work);
+ kasan_record_aux_stack(work);
}
head = READ_ONCE(task->task_works);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9949ffad8df09..65b8314b2d538 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
debug_work_activate(work);
/* record the work call stack in order to print it in KASAN reports */
- kasan_record_aux_stack_noalloc(work);
+ kasan_record_aux_stack(work);
/* we own @work, set data and link */
set_work_pwq(work, pwq, extra_flags);
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 6310a180278b6..2242249c2d50d 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -521,7 +521,11 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
sizeof(struct kasan_free_meta) : 0);
}
-static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
+/*
+ * This function avoids dynamic memory allocations and thus can be called from
+ * contexts that do not allow allocating memory.
+ */
+void kasan_record_aux_stack(void *addr)
{
struct slab *slab = kasan_addr_to_slab(addr);
struct kmem_cache *cache;
@@ -538,17 +542,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
return;
alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
- alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
-}
-
-void kasan_record_aux_stack(void *addr)
-{
- return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
-}
-
-void kasan_record_aux_stack_noalloc(void *addr)
-{
- return __kasan_record_aux_stack(addr, 0);
+ alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
}
void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
diff --git a/mm/slub.c b/mm/slub.c
index 5b832512044e3..b8c4bf3fe0d07 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
* We have to do this manually because the rcu_head is
* not located inside the object.
*/
- kasan_record_aux_stack_noalloc(x);
+ kasan_record_aux_stack(x);
delayed_free->object = x;
call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
--
2.45.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2] kasan: Make kasan_record_aux_stack_noalloc() the default behaviour
2024-11-22 15:54 ` [PATCH v2] kasan: Make kasan_record_aux_stack_noalloc() the default behaviour Sebastian Andrzej Siewior
@ 2024-11-22 18:04 ` Waiman Long
0 siblings, 0 replies; 14+ messages in thread
From: Waiman Long @ 2024-11-22 18:04 UTC (permalink / raw)
To: Sebastian Andrzej Siewior, Andrey Konovalov
Cc: Marco Elver, Peter Zijlstra, Vlastimil Babka, syzbot,
Liam.Howlett, akpm, jannh, linux-kernel, linux-mm,
lorenzo.stoakes, syzkaller-bugs, kasan-dev, Andrey Ryabinin,
Alexander Potapenko, dvyukov, vincenzo.frascino, paulmck,
frederic, neeraj.upadhyay, joel, josh, boqun.feng, urezki,
rostedt, mathieu.desnoyers, jiangshanlai, qiang.zhang1211, mingo,
juri.lelli, vincent.guittot, dietmar.eggemann, bsegall, mgorman,
vschneid, tj, cl, penberg, rientjes, iamjoonsoo.kim,
Thomas Gleixner, roman.gushchin, 42.hyeyoo, rcu
On 11/22/24 10:54 AM, Sebastian Andrzej Siewior wrote:
> From: Peter Zijlstra <peterz@infradead.org>
>
> kasan_record_aux_stack_noalloc() was introduced to record a stack trace
> without allocating memory in the process. It has been added to callers
> which were invoked while a raw_spinlock_t was held.
> More and more callers were identified and changed over time. Is it a
> good thing to have this while functions try their best to do a
> locklessly setup? The only downside of having kasan_record_aux_stack()
> not allocate any memory is that we end up without a stacktrace if
> stackdepot runs out of memory and at the same stacktrace was not
> recorded before To quote Marco Elver from
> https://lore.kernel.org/all/CANpmjNPmQYJ7pv1N3cuU8cP18u7PP_uoZD8YxwZd4jtbof9nVQ@mail.gmail.com/
>
> | I'd be in favor, it simplifies things. And stack depot should be
> | able to replenish its pool sufficiently in the "non-aux" cases
> | i.e. regular allocations. Worst case we fail to record some
> | aux stacks, but I think that's only really bad if there's a bug
> | around one of these allocations. In general the probabilities
> | of this being a regression are extremely small [...]
>
> Make the kasan_record_aux_stack_noalloc() behaviour default as
> kasan_record_aux_stack().
>
> [bigeasy: Dressed the diff as patch. ]
>
> Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/67275485.050a0220.3c8d68.0a37.GAE@google.com
> Acked-by: Waiman Long <longman@redhat.com>
> Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
> Reviewed-by: Marco Elver <elver@google.com>
> Fixes: 7cb3007ce2da2 ("kasan: generic: introduce kasan_record_aux_stack_noalloc()")
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> v1…v2:
> - Renamed the patch as per Marco.
> - Added comment to kasan_record_aux_stack() as per Andrey.
> - Added fixes tag since Waiman that it is the only user.
> - Added Marco's quote from the mail to the commit description.
>
> include/linux/kasan.h | 2 --
> include/linux/task_work.h | 3 ---
> kernel/irq_work.c | 2 +-
> kernel/rcu/tiny.c | 2 +-
> kernel/rcu/tree.c | 4 ++--
> kernel/sched/core.c | 2 +-
> kernel/task_work.c | 14 +-------------
> kernel/workqueue.c | 2 +-
> mm/kasan/generic.c | 18 ++++++------------
> mm/slub.c | 2 +-
> 10 files changed, 14 insertions(+), 37 deletions(-)
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index 00a3bf7c0d8f0..1a623818e8b39 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -488,7 +488,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> void kasan_cache_shrink(struct kmem_cache *cache);
> void kasan_cache_shutdown(struct kmem_cache *cache);
> void kasan_record_aux_stack(void *ptr);
> -void kasan_record_aux_stack_noalloc(void *ptr);
>
> #else /* CONFIG_KASAN_GENERIC */
>
> @@ -506,7 +505,6 @@ static inline void kasan_cache_create(struct kmem_cache *cache,
> static inline void kasan_cache_shrink(struct kmem_cache *cache) {}
> static inline void kasan_cache_shutdown(struct kmem_cache *cache) {}
> static inline void kasan_record_aux_stack(void *ptr) {}
> -static inline void kasan_record_aux_stack_noalloc(void *ptr) {}
>
> #endif /* CONFIG_KASAN_GENERIC */
>
> diff --git a/include/linux/task_work.h b/include/linux/task_work.h
> index 2964171856e00..0646804860ff1 100644
> --- a/include/linux/task_work.h
> +++ b/include/linux/task_work.h
> @@ -19,9 +19,6 @@ enum task_work_notify_mode {
> TWA_SIGNAL,
> TWA_SIGNAL_NO_IPI,
> TWA_NMI_CURRENT,
> -
> - TWA_FLAGS = 0xff00,
> - TWAF_NO_ALLOC = 0x0100,
> };
>
> static inline bool task_work_pending(struct task_struct *task)
> diff --git a/kernel/irq_work.c b/kernel/irq_work.c
> index 2f4fb336dda17..73f7e1fd4ab4d 100644
> --- a/kernel/irq_work.c
> +++ b/kernel/irq_work.c
> @@ -147,7 +147,7 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
> if (!irq_work_claim(work))
> return false;
>
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> preempt_disable();
> if (cpu != smp_processor_id()) {
> diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
> index b3b3ce34df631..4b3f319114650 100644
> --- a/kernel/rcu/tiny.c
> +++ b/kernel/rcu/tiny.c
> @@ -250,7 +250,7 @@ EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
> void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> {
> if (head)
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
>
> __kvfree_call_rcu(head, ptr);
> }
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index b1f883fcd9185..7eae9bd818a90 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -3083,7 +3083,7 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in)
> }
> head->func = func;
> head->next = NULL;
> - kasan_record_aux_stack_noalloc(head);
> + kasan_record_aux_stack(head);
> local_irq_save(flags);
> rdp = this_cpu_ptr(&rcu_data);
> lazy = lazy_in && !rcu_async_should_hurry();
> @@ -3807,7 +3807,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
> return;
> }
>
> - kasan_record_aux_stack_noalloc(ptr);
> + kasan_record_aux_stack(ptr);
> success = add_ptr_to_bulk_krc_lock(&krcp, &flags, ptr, !head);
> if (!success) {
> run_page_cache_worker(krcp);
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index a1c353a62c568..3717360a940d2 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -10485,7 +10485,7 @@ void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
> return;
>
> /* No page allocation under rq lock */
> - task_work_add(curr, work, TWA_RESUME | TWAF_NO_ALLOC);
> + task_work_add(curr, work, TWA_RESUME);
> }
>
> void sched_mm_cid_exit_signals(struct task_struct *t)
> diff --git a/kernel/task_work.c b/kernel/task_work.c
> index c969f1f26be58..d1efec571a4a4 100644
> --- a/kernel/task_work.c
> +++ b/kernel/task_work.c
> @@ -55,26 +55,14 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
> enum task_work_notify_mode notify)
> {
> struct callback_head *head;
> - int flags = notify & TWA_FLAGS;
>
> - notify &= ~TWA_FLAGS;
> if (notify == TWA_NMI_CURRENT) {
> if (WARN_ON_ONCE(task != current))
> return -EINVAL;
> if (!IS_ENABLED(CONFIG_IRQ_WORK))
> return -EINVAL;
> } else {
> - /*
> - * Record the work call stack in order to print it in KASAN
> - * reports.
> - *
> - * Note that stack allocation can fail if TWAF_NO_ALLOC flag
> - * is set and new page is needed to expand the stack buffer.
> - */
> - if (flags & TWAF_NO_ALLOC)
> - kasan_record_aux_stack_noalloc(work);
> - else
> - kasan_record_aux_stack(work);
> + kasan_record_aux_stack(work);
> }
>
> head = READ_ONCE(task->task_works);
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 9949ffad8df09..65b8314b2d538 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -2180,7 +2180,7 @@ static void insert_work(struct pool_workqueue *pwq, struct work_struct *work,
> debug_work_activate(work);
>
> /* record the work call stack in order to print it in KASAN reports */
> - kasan_record_aux_stack_noalloc(work);
> + kasan_record_aux_stack(work);
>
> /* we own @work, set data and link */
> set_work_pwq(work, pwq, extra_flags);
> diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> index 6310a180278b6..2242249c2d50d 100644
> --- a/mm/kasan/generic.c
> +++ b/mm/kasan/generic.c
> @@ -521,7 +521,11 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
> sizeof(struct kasan_free_meta) : 0);
> }
>
> -static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> +/*
> + * This function avoids dynamic memory allocations and thus can be called from
> + * contexts that do not allow allocating memory.
> + */
> +void kasan_record_aux_stack(void *addr)
> {
> struct slab *slab = kasan_addr_to_slab(addr);
> struct kmem_cache *cache;
> @@ -538,17 +542,7 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags)
> return;
>
> alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
> - alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags);
> -}
> -
> -void kasan_record_aux_stack(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, STACK_DEPOT_FLAG_CAN_ALLOC);
> -}
> -
> -void kasan_record_aux_stack_noalloc(void *addr)
> -{
> - return __kasan_record_aux_stack(addr, 0);
> + alloc_meta->aux_stack[0] = kasan_save_stack(0, 0);
> }
>
> void kasan_save_alloc_info(struct kmem_cache *cache, void *object, gfp_t flags)
> diff --git a/mm/slub.c b/mm/slub.c
> index 5b832512044e3..b8c4bf3fe0d07 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -2300,7 +2300,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
> * We have to do this manually because the rcu_head is
> * not located inside the object.
> */
> - kasan_record_aux_stack_noalloc(x);
> + kasan_record_aux_stack(x);
>
> delayed_free->object = x;
> call_rcu(&delayed_free->head, slab_free_after_rcu_debug);
LGTM
Reviewed-by: Waiman Long <longman@redhat.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist
[not found] <67275485.050a0220.3c8d68.0a37.GAE@google.com>
[not found] ` <ee48b6e9-3f7a-49aa-ae5b-058b5ada2172@suse.cz>
@ 2024-12-15 10:12 ` syzbot
1 sibling, 0 replies; 14+ messages in thread
From: syzbot @ 2024-12-15 10:12 UTC (permalink / raw)
To: 42.hyeyoo, akpm, andreyknvl, bigeasy, boqun.feng, bsegall, cl,
dietmar.eggemann, dvyukov, elver, frederic, glider,
iamjoonsoo.kim, jannh, jiangshanlai, joel, josh, juri.lelli,
kasan-dev, liam.howlett, linux-kernel, linux-mm, llong, longman,
lorenzo.stoakes, mathieu.desnoyers, mgorman, mingo,
neeraj.upadhyay, paulmck, penberg, peterz, qiang.zhang1211, rcu,
rientjes, roman.gushchin, rostedt, ryabinin.a.a, syzkaller-bugs,
tglx, tj, urezki, vbabka, vincent.guittot, vincenzo.frascino,
vschneid
syzbot has found a reproducer for the following issue on:
HEAD commit: a0e3919a2df2 Merge tag 'usb-6.13-rc3' of git://git.kernel...
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15a4c344580000
kernel config: https://syzkaller.appspot.com/x/.config?x=b874549ac3d0b012
dashboard link: https://syzkaller.appspot.com/bug?extid=39f85d612b7c20d8db48
compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=139407e8580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=179407e8580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/694eb7d9bffc/disk-a0e3919a.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/1350ab6a6022/vmlinux-a0e3919a.xz
kernel image: https://storage.googleapis.com/syzbot-assets/f64266879922/bzImage-a0e3919a.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+39f85d612b7c20d8db48@syzkaller.appspotmail.com
=============================
[ BUG: Invalid wait context ]
6.13.0-rc2-syzkaller-00333-ga0e3919a2df2 #0 Not tainted
-----------------------------
syz-executor300/5884 is trying to lock:
ffff88813fffc298 (&zone->lock){-.-.}-{3:3}, at: rmqueue_bulk mm/page_alloc.c:2307 [inline]
ffff88813fffc298 (&zone->lock){-.-.}-{3:3}, at: __rmqueue_pcplist+0x6bb/0x1600 mm/page_alloc.c:3001
other info that might help us debug this:
context-{2:2}
5 locks held by syz-executor300/5884:
#0: ffff888036701f20 (&mm->mmap_lock){++++}-{4:4}, at: mmap_read_lock include/linux/mmap_lock.h:144 [inline]
#0: ffff888036701f20 (&mm->mmap_lock){++++}-{4:4}, at: __mm_populate+0x21d/0x380 mm/gup.c:2014
#1: ffffffff8e1bb500 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:337 [inline]
#1: ffffffff8e1bb500 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:849 [inline]
#1: ffffffff8e1bb500 (rcu_read_lock){....}-{1:3}, at: count_memcg_events_mm.constprop.0+0x3a/0x340 include/linux/memcontrol.h:994
#2: ffffffff8e1bb500 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:337 [inline]
#2: ffffffff8e1bb500 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:849 [inline]
#2: ffffffff8e1bb500 (rcu_read_lock){....}-{1:3}, at: ieee80211_rx_napi+0xa6/0x400 net/mac80211/rx.c:5491
#3: ffff888067a68168 (&rdev->bss_lock){+.-.}-{3:3}, at: spin_lock_bh include/linux/spinlock.h:356 [inline]
#3: ffff888067a68168 (&rdev->bss_lock){+.-.}-{3:3}, at: cfg80211_inform_single_bss_data+0x791/0x1de0 net/wireless/scan.c:2329
#4: ffff8880b8644c58 (&pcp->lock){+.+.}-{3:3}, at: spin_trylock include/linux/spinlock.h:361 [inline]
#4: ffff8880b8644c58 (&pcp->lock){+.+.}-{3:3}, at: rmqueue_pcplist mm/page_alloc.c:3030 [inline]
#4: ffff8880b8644c58 (&pcp->lock){+.+.}-{3:3}, at: rmqueue mm/page_alloc.c:3074 [inline]
#4: ffff8880b8644c58 (&pcp->lock){+.+.}-{3:3}, at: get_page_from_freelist+0x350/0x2f80 mm/page_alloc.c:3471
stack backtrace:
CPU: 0 UID: 0 PID: 5884 Comm: syz-executor300 Not tainted 6.13.0-rc2-syzkaller-00333-ga0e3919a2df2 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/25/2024
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
print_lock_invalid_wait_context kernel/locking/lockdep.c:4826 [inline]
check_wait_context kernel/locking/lockdep.c:4898 [inline]
__lock_acquire+0x878/0x3c40 kernel/locking/lockdep.c:5176
lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5849
__raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline]
_raw_spin_lock_irqsave+0x3a/0x60 kernel/locking/spinlock.c:162
rmqueue_bulk mm/page_alloc.c:2307 [inline]
__rmqueue_pcplist+0x6bb/0x1600 mm/page_alloc.c:3001
rmqueue_pcplist mm/page_alloc.c:3043 [inline]
rmqueue mm/page_alloc.c:3074 [inline]
get_page_from_freelist+0x3d2/0x2f80 mm/page_alloc.c:3471
__alloc_pages_noprof+0x223/0x25b0 mm/page_alloc.c:4751
alloc_pages_mpol_noprof+0x2c9/0x610 mm/mempolicy.c:2269
stack_depot_save_flags+0x8e0/0x9e0 lib/stackdepot.c:627
kasan_save_stack+0x42/0x60 mm/kasan/common.c:48
__kasan_record_aux_stack+0xba/0xd0 mm/kasan/generic.c:544
task_work_add+0xc0/0x3b0 kernel/task_work.c:77
__run_posix_cpu_timers kernel/time/posix-cpu-timers.c:1223 [inline]
run_posix_cpu_timers+0x69f/0x7d0 kernel/time/posix-cpu-timers.c:1422
update_process_times+0x1a1/0x2d0 kernel/time/timer.c:2526
tick_sched_handle kernel/time/tick-sched.c:276 [inline]
tick_nohz_handler+0x376/0x530 kernel/time/tick-sched.c:297
__run_hrtimer kernel/time/hrtimer.c:1739 [inline]
__hrtimer_run_queues+0x5fb/0xae0 kernel/time/hrtimer.c:1803
hrtimer_interrupt+0x392/0x8e0 kernel/time/hrtimer.c:1865
local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1038 [inline]
__sysvec_apic_timer_interrupt+0x10f/0x400 arch/x86/kernel/apic/apic.c:1055
instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline]
sysvec_apic_timer_interrupt+0x52/0xc0 arch/x86/kernel/apic/apic.c:1049
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702
RIP: 0010:__sanitizer_cov_trace_switch+0x4f/0x90 kernel/kcov.c:351
Code: 83 f8 10 75 2f 41 bd 03 00 00 00 4c 8b 75 00 31 db 4d 85 f6 74 1e 48 8b 74 dd 10 4c 89 e2 4c 89 ef 48 83 c3 01 48 8b 4c 24 28 <e8> 8c fd ff ff 49 39 de 75 e2 5b 5d 41 5c 41 5d 41 5e c3 cc cc cc
RSP: 0018:ffffc90000007098 EFLAGS: 00000212
RAX: 0000000000000000 RBX: 0000000000000020 RCX: ffffffff8aaf7a17
RDX: 0000000000000000 RSI: 00000000000000f4 RDI: 0000000000000001
RBP: ffffffff8cc04980 R08: 0000000000000001 R09: 00000000000000e8
R10: 0000000000000000 R11: 0000000000000004 R12: 0000000000000000
R13: 0000000000000001 R14: 0000000000000020 R15: dffffc0000000000
_ieee802_11_parse_elems_full+0x297/0x4340 net/mac80211/parse.c:293
ieee802_11_parse_elems_full+0x9ca/0x1680 net/mac80211/parse.c:984
ieee802_11_parse_elems_crc net/mac80211/ieee80211_i.h:2384 [inline]
ieee802_11_parse_elems net/mac80211/ieee80211_i.h:2391 [inline]
ieee80211_inform_bss+0xfd/0x1100 net/mac80211/scan.c:79
rdev_inform_bss net/wireless/rdev-ops.h:418 [inline]
cfg80211_inform_single_bss_data+0x8f6/0x1de0 net/wireless/scan.c:2334
cfg80211_inform_bss_data+0x205/0x3ba0 net/wireless/scan.c:3189
cfg80211_inform_bss_frame_data+0x272/0x7a0 net/wireless/scan.c:3284
ieee80211_bss_info_update+0x311/0xab0 net/mac80211/scan.c:226
ieee80211_scan_rx+0x474/0xac0 net/mac80211/scan.c:340
__ieee80211_rx_handle_packet net/mac80211/rx.c:5232 [inline]
ieee80211_rx_list+0x1bd7/0x2970 net/mac80211/rx.c:5469
ieee80211_rx_napi+0xdd/0x400 net/mac80211/rx.c:5492
ieee80211_rx include/net/mac80211.h:5166 [inline]
ieee80211_handle_queued_frames+0xd5/0x130 net/mac80211/main.c:441
tasklet_action_common+0x251/0x3f0 kernel/softirq.c:811
handle_softirqs+0x213/0x8f0 kernel/softirq.c:561
__do_softirq kernel/softirq.c:595 [inline]
invoke_softirq kernel/softirq.c:435 [inline]
__irq_exit_rcu+0x109/0x170 kernel/softirq.c:662
irq_exit_rcu+0x9/0x30 kernel/softirq.c:678
instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline]
sysvec_apic_timer_interrupt+0xa4/0xc0 arch/x86/kernel/apic/apic.c:1049
</IRQ>
<TASK>
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702
RIP: 0010:rcu_read_unlock include/linux/rcupdate.h:878 [inline]
RIP: 0010:count_memcg_events_mm.constprop.0+0x108/0x340 include/linux/memcontrol.h:998
Code: ba 01 00 00 00 89 de 48 89 ef e8 c3 13 22 00 9c 5b 81 e3 00 02 00 00 31 ff 48 89 de e8 91 2d b7 ff 48 85 db 0f 85 06 02 00 00 <e8> 13 2b b7 ff e8 9e 50 46 09 31 ff 89 c3 89 c6 e8 43 2d b7 ff 85
RSP: 0018:ffffc90002ee7a90 EFLAGS: 00000293
RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffff81e2da5e
RDX: ffff88803650a440 RSI: ffffffff81e2da68 RDI: 0000000000000007
RBP: ffff888035a04000 R08: 0000000000000007 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000200
R13: ffff8880223138d8 R14: 0000000000000000 R15: ffff88803650a440
count_memcg_event_mm include/linux/memcontrol.h:1004 [inline]
mm_account_fault mm/memory.c:5978 [inline]
handle_mm_fault+0x5cc/0xaa0 mm/memory.c:6138
faultin_page mm/gup.c:1196 [inline]
__get_user_pages+0x8d9/0x3b50 mm/gup.c:1494
populate_vma_page_range+0x27f/0x3a0 mm/gup.c:1932
__mm_populate+0x1d6/0x380 mm/gup.c:2035
mm_populate include/linux/mm.h:3386 [inline]
vm_mmap_pgoff+0x293/0x360 mm/util.c:585
ksys_mmap_pgoff+0x7d/0x5c0 mm/mmap.c:542
__do_sys_mmap arch/x86/kernel/sys_x86_64.c:89 [inline]
__se_sys_mmap arch/x86/kernel/sys_x86_64.c:82 [inline]
__x64_sys_mmap+0x125/0x190 arch/x86/kernel/sys_x86_64.c:82
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f9a0d37bde9
Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 c1 1f 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f9a0cb00148 EFLAGS: 00000246 ORIG_RAX: 0000000000000009
RAX: ffffffffffffffda RBX: 00007f9a0d4031f8 RCX: 00007f9a0d37bde9
RDX: b635773f06ebbeee RSI: 0000000000b36000 RDI: 0000000020000000
RBP: 00007f9a0d4031f0 R08: 00000000ffffffff R09: 0000000002000000
R10: 0000000000008031 R11: 0000000000000246 R12: 00007f9a0d4031fc
R13: 000000000000006e R14: 00007ffd73f9daf0 R15: 00007ffd73f9dbd8
</TASK>
----------------
Code disassembly (best guess):
0: 83 f8 10 cmp $0x10,%eax
3: 75 2f jne 0x34
5: 41 bd 03 00 00 00 mov $0x3,%r13d
b: 4c 8b 75 00 mov 0x0(%rbp),%r14
f: 31 db xor %ebx,%ebx
11: 4d 85 f6 test %r14,%r14
14: 74 1e je 0x34
16: 48 8b 74 dd 10 mov 0x10(%rbp,%rbx,8),%rsi
1b: 4c 89 e2 mov %r12,%rdx
1e: 4c 89 ef mov %r13,%rdi
21: 48 83 c3 01 add $0x1,%rbx
25: 48 8b 4c 24 28 mov 0x28(%rsp),%rcx
* 2a: e8 8c fd ff ff call 0xfffffdbb <-- trapping instruction
2f: 49 39 de cmp %rbx,%r14
32: 75 e2 jne 0x16
34: 5b pop %rbx
35: 5d pop %rbp
36: 41 5c pop %r12
38: 41 5d pop %r13
3a: 41 5e pop %r14
3c: c3 ret
3d: cc int3
3e: cc int3
3f: cc int3
---
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2024-12-15 10:12 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <67275485.050a0220.3c8d68.0a37.GAE@google.com>
[not found] ` <ee48b6e9-3f7a-49aa-ae5b-058b5ada2172@suse.cz>
[not found] ` <b9a674c1-860c-4448-aeb2-bf07a78c6fbf@suse.cz>
2024-11-04 11:45 ` [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist Peter Zijlstra
2024-11-04 11:47 ` Peter Zijlstra
2024-11-13 14:18 ` Sebastian Andrzej Siewior
2024-11-04 12:16 ` Marco Elver
2024-11-19 15:57 ` [PATCH] kasan: Remove kasan_record_aux_stack_noalloc() Sebastian Andrzej Siewior
2024-11-19 16:22 ` Waiman Long
2024-11-19 16:37 ` Marco Elver
2024-11-19 19:36 ` Andrey Konovalov
2024-11-22 11:32 ` Sebastian Andrzej Siewior
2024-11-22 15:01 ` Marco Elver
2024-11-22 15:29 ` Sebastian Andrzej Siewior
2024-11-22 15:54 ` [PATCH v2] kasan: Make kasan_record_aux_stack_noalloc() the default behaviour Sebastian Andrzej Siewior
2024-11-22 18:04 ` Waiman Long
2024-12-15 10:12 ` [syzbot] [mm?] WARNING: locking bug in __rmqueue_pcplist syzbot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox