* [PATCH] fs/fcntl: fix SOFTIRQ-unsafe lock order in send_sigio()
@ 2026-05-23 8:02 w15303746062
2026-05-23 11:08 ` Jeff Layton
0 siblings, 1 reply; 4+ messages in thread
From: w15303746062 @ 2026-05-23 8:02 UTC (permalink / raw)
To: jlayton, chuck.lever, viro, brauner
Cc: alex.aring, jack, linux-fsdevel, linux-kernel, Mingyu Wang
From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
A SOFTIRQ-safe to SOFTIRQ-unsafe lock order deadlock can occur in
send_sigio() when a process group receives a SIGIO.
When FASYNC is configured for a process group (PIDTYPE_PGID),
send_sigio() uses read_lock(&tasklist_lock) to traverse the task
list. However, send_sigio() is often called from softirq context
(e.g., input_inject_event -> kill_fasync), where it already holds
SOFTIRQ-safe locks like &dev->event_lock and &f_owner->lock.
The deadlock is caused by the rwlock writer fairness mechanism:
1. CPU 0 (process context) holds read_lock(&tasklist_lock) in do_wait().
2. CPU 1 (process context) attempts write_lock(&tasklist_lock) in
fork() or exit() and spins, which blocks all new readers.
3. CPU 0 is interrupted by a softirq (e.g., keyboard input event).
4. The softirq calls send_sigio() and attempts to acquire
read_lock(&tasklist_lock), deadlocking because CPU 1 is waiting.
Since PID hashing and do_each_pid_task() traversals are already
RCU-protected, the read_lock on tasklist_lock is no longer strictly
required for safe traversal. Fix this by replacing tasklist_lock with
rcu_read_lock(), aligning the process group signaling path with the
single-PID path.
Lockdep splat:
=====================================================
WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected
[...]
Chain exists of:
&dev->event_lock --> &f_owner->lock --> tasklist_lock
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(tasklist_lock);
local_irq_disable();
lock(&dev->event_lock);
lock(&f_owner->lock);
<Interrupt>
lock(&dev->event_lock);
*** DEADLOCK ***
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
---
fs/fcntl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index beab8080badf..a6c764ede282 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -929,11 +929,11 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
send_sigio_to_task(p, fown, fd, band, type);
rcu_read_unlock();
} else {
- read_lock(&tasklist_lock);
+ rcu_read_lock();
do_each_pid_task(pid, type, p) {
send_sigio_to_task(p, fown, fd, band, type);
} while_each_pid_task(pid, type, p);
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
}
out_unlock_fown:
read_unlock_irqrestore(&fown->lock, flags);
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] fs/fcntl: fix SOFTIRQ-unsafe lock order in send_sigio()
2026-05-23 8:02 [PATCH] fs/fcntl: fix SOFTIRQ-unsafe lock order in send_sigio() w15303746062
@ 2026-05-23 11:08 ` Jeff Layton
2026-05-23 13:52 ` [PATCH v2] fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling w15303746062
0 siblings, 1 reply; 4+ messages in thread
From: Jeff Layton @ 2026-05-23 11:08 UTC (permalink / raw)
To: w15303746062, chuck.lever, viro, brauner
Cc: alex.aring, jack, linux-fsdevel, linux-kernel, Mingyu Wang
On Sat, 2026-05-23 at 16:02 +0800, w15303746062@163.com wrote:
> From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
>
> A SOFTIRQ-safe to SOFTIRQ-unsafe lock order deadlock can occur in
> send_sigio() when a process group receives a SIGIO.
>
> When FASYNC is configured for a process group (PIDTYPE_PGID),
> send_sigio() uses read_lock(&tasklist_lock) to traverse the task
> list. However, send_sigio() is often called from softirq context
> (e.g., input_inject_event -> kill_fasync), where it already holds
> SOFTIRQ-safe locks like &dev->event_lock and &f_owner->lock.
>
> The deadlock is caused by the rwlock writer fairness mechanism:
> 1. CPU 0 (process context) holds read_lock(&tasklist_lock) in do_wait().
> 2. CPU 1 (process context) attempts write_lock(&tasklist_lock) in
> fork() or exit() and spins, which blocks all new readers.
> 3. CPU 0 is interrupted by a softirq (e.g., keyboard input event).
> 4. The softirq calls send_sigio() and attempts to acquire
> read_lock(&tasklist_lock), deadlocking because CPU 1 is waiting.
>
> Since PID hashing and do_each_pid_task() traversals are already
> RCU-protected, the read_lock on tasklist_lock is no longer strictly
> required for safe traversal. Fix this by replacing tasklist_lock with
> rcu_read_lock(), aligning the process group signaling path with the
> single-PID path.
>
> Lockdep splat:
> =====================================================
> WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected
> [...]
> Chain exists of:
> &dev->event_lock --> &f_owner->lock --> tasklist_lock
>
> Possible interrupt unsafe locking scenario:
> CPU0 CPU1
> ---- ----
> lock(tasklist_lock);
> local_irq_disable();
> lock(&dev->event_lock);
> lock(&f_owner->lock);
> <Interrupt>
> lock(&dev->event_lock);
>
> *** DEADLOCK ***
>
> Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
> ---
> fs/fcntl.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/fcntl.c b/fs/fcntl.c
> index beab8080badf..a6c764ede282 100644
> --- a/fs/fcntl.c
> +++ b/fs/fcntl.c
> @@ -929,11 +929,11 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
> send_sigio_to_task(p, fown, fd, band, type);
> rcu_read_unlock();
> } else {
> - read_lock(&tasklist_lock);
> + rcu_read_lock();
> do_each_pid_task(pid, type, p) {
> send_sigio_to_task(p, fown, fd, band, type);
> } while_each_pid_task(pid, type, p);
> - read_unlock(&tasklist_lock);
> + rcu_read_unlock();
> }
> out_unlock_fown:
> read_unlock_irqrestore(&fown->lock, flags);
This looks good to me. Sashiko seems to think that send_sigurg has the
same problem though. Care to look into fixing that one too?
https://sashiko.dev/#/patchset/20260523080255.585201-1-w15303746062%40163.com
You can add:
Reviewed-by: Jeff Layton <jlayton@kernel.org>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling
2026-05-23 11:08 ` Jeff Layton
@ 2026-05-23 13:52 ` w15303746062
2026-05-28 12:40 ` Christian Brauner
0 siblings, 1 reply; 4+ messages in thread
From: w15303746062 @ 2026-05-23 13:52 UTC (permalink / raw)
To: jlayton, chuck.lever, viro, brauner
Cc: alex.aring, jack, linux-fsdevel, linux-kernel, Mingyu Wang
From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
A SOFTIRQ-safe to SOFTIRQ-unsafe lock order deadlock can occur in
send_sigio() and send_sigurg() when a process group receives a signal.
When FASYNC is configured for a process group (PIDTYPE_PGID), both
functions use read_lock(&tasklist_lock) to traverse the task list.
However, they are frequently called from softirq context:
- send_sigio() via input_inject_event -> kill_fasync
- send_sigurg() via tcp_check_urg -> sk_send_sigurg (NET_RX_SOFTIRQ)
The deadlock is caused by the rwlock writer fairness mechanism:
1. CPU 0 (process context) holds read_lock(&tasklist_lock) in do_wait().
2. CPU 1 (process context) attempts write_lock(&tasklist_lock) in
fork() or exit() and spins, which blocks all new readers.
3. CPU 0 is interrupted by a softirq (e.g., TCP URG packet reception).
4. The softirq calls send_sigurg() and attempts to acquire
read_lock(&tasklist_lock), deadlocking because CPU 1 is waiting.
Since PID hashing and do_each_pid_task() traversals are already
RCU-protected, the read_lock on tasklist_lock is no longer strictly
required for safe traversal. Fix this by replacing tasklist_lock with
rcu_read_lock(), aligning the process group signaling path with the
single-PID path. This also mitigates a potential remote denial of
service vector via TCP URG packets.
Lockdep splat:
=====================================================
WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected
[...]
Chain exists of:
&dev->event_lock --> &f_owner->lock --> tasklist_lock
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(tasklist_lock);
local_irq_disable();
lock(&dev->event_lock);
lock(&f_owner->lock);
<Interrupt>
lock(&dev->event_lock);
*** DEADLOCK ***
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
---
Changes in v2:
- Also apply the RCU replacement to send_sigurg() to fix an identical
deadlock vector triggered by TCP URG packets.
- Add Reviewed-by tag from Jeff Layton.
fs/fcntl.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index beab8080badf..92d643a14196 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -929,11 +929,11 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
send_sigio_to_task(p, fown, fd, band, type);
rcu_read_unlock();
} else {
- read_lock(&tasklist_lock);
+ rcu_read_lock();
do_each_pid_task(pid, type, p) {
send_sigio_to_task(p, fown, fd, band, type);
} while_each_pid_task(pid, type, p);
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
}
out_unlock_fown:
read_unlock_irqrestore(&fown->lock, flags);
@@ -975,11 +975,11 @@ int send_sigurg(struct file *file)
send_sigurg_to_task(p, fown, type);
rcu_read_unlock();
} else {
- read_lock(&tasklist_lock);
+ rcu_read_lock();
do_each_pid_task(pid, type, p) {
send_sigurg_to_task(p, fown, type);
} while_each_pid_task(pid, type, p);
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
}
out_unlock_fown:
read_unlock_irqrestore(&fown->lock, flags);
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2] fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling
2026-05-23 13:52 ` [PATCH v2] fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling w15303746062
@ 2026-05-28 12:40 ` Christian Brauner
0 siblings, 0 replies; 4+ messages in thread
From: Christian Brauner @ 2026-05-28 12:40 UTC (permalink / raw)
To: w15303746062
Cc: Christian Brauner, jlayton, chuck.lever, viro, alex.aring, jack,
linux-fsdevel, linux-kernel, Mingyu Wang
On Sat, 23 May 2026 21:52:10 +0800, w15303746062@163.com wrote:
> A SOFTIRQ-safe to SOFTIRQ-unsafe lock order deadlock can occur in
> send_sigio() and send_sigurg() when a process group receives a signal.
>
> When FASYNC is configured for a process group (PIDTYPE_PGID), both
> functions use read_lock(&tasklist_lock) to traverse the task list.
> However, they are frequently called from softirq context:
> - send_sigio() via input_inject_event -> kill_fasync
> - send_sigurg() via tcp_check_urg -> sk_send_sigurg (NET_RX_SOFTIRQ)
>
> [...]
Applied to the vfs-7.2.misc branch of the vfs/vfs.git tree.
Patches in the vfs-7.2.misc branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-7.2.misc
[1/1] fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling
https://git.kernel.org/vfs/vfs/c/00633c468382
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-05-28 12:40 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-23 8:02 [PATCH] fs/fcntl: fix SOFTIRQ-unsafe lock order in send_sigio() w15303746062
2026-05-23 11:08 ` Jeff Layton
2026-05-23 13:52 ` [PATCH v2] fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling w15303746062
2026-05-28 12:40 ` Christian Brauner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox