[PATCH v10 0/2] kernel/fork: beware of __put_task_struct calling context

From: Wander Lairson Costa
Date: Wed Jun 14 2023 - 08:25:48 EST


Under PREEMPT_RT, __put_task_struct() indirectly acquires sleeping
locks. Therefore, it can't be called from an non-preemptible context.

Instead of calling __put_task_struct() directly, we defer it using
call_rcu(). A more natural approach would use a workqueue, but since
in PREEMPT_RT, we can't allocate dynamic memory from atomic context,
the code would become more complex because we would need to put the
work_struct instance in the task_struct and initialize it when we
allocate a new task_struct.

Changelog
=========

v1:
* Initial implementation fixing the splat.

v2:
* Isolate the logic in its own function.
* Fix two more cases caught in review.

v3:
* Change __put_task_struct() to handle the issue internally.

v4:
* Explain why call_rcu() is safe to call from interrupt context.

v5:
* Explain why __put_task_struct() doesn't conflict with
put_task_sruct_rcu_user.

v6:
* As per Sebastian's review, revert back the implementation of v2
with a distinct function.
* Add a check in put_task_struct() to warning when called from a
non-sleepable context.
* Address more call sites.

v7:
* Fix typos.
* Add an explanation why the new function doesn't conflict with
delayed_free_task().

v8:
* Bring back v5.
* Fix coding style.

v9:
* Reorganize to not need ___put_task_struct() by Oleg's suggestion.

v10:
* Add a patch preventing a splat when compile with
CONFIG_PROVE_RAW_LOCK_NESTING.

Reported-by: Hu Chunyu <chuhu@xxxxxxxxxx>
Suggested-by: Oleg Nesterov <oleg@xxxxxxxxxx>
Suggested-by: Valentin Schneider <vschneid@xxxxxxxxxx>
Suggested-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Cc: Paul McKenney <paulmck@xxxxxxxxxx>
Cc: Steven Rostedt <rostedt@xxxxxxxxxxx>
Cc: Luis Goncalves <lgoncalv@xxxxxxxxxx>

Wander Lairson Costa (2):
kernel/fork: beware of __put_task_struct calling context
sched: avoid false lockdep splat in put_task_struct()

include/linux/sched/task.h | 38 +++++++++++++++++++++++++++++++++++++-
kernel/fork.c | 8 ++++++++
2 files changed, 45 insertions(+), 1 deletion(-)

--
2.40.1