From: Desmond Cheong Zhi Xi <hidden> Date: 2021-07-07 07:44:39
Hi,
Sorry for the delay between v1 and v2, there was an unrelated issue with Syzbot testing.
Syzbot reports a possible irq lock inversion dependency:
https://syzkaller.appspot.com/bug?id=923cfc6c6348963f99886a0176ef11dcc429547b
While investigating this error, I discovered that multiple similar lock inversion scenarios can occur. Hence, this series addresses potential deadlocks for two classes of locks, one in each patch:
1. Fix potential deadlocks for &fown_struct.lock
2. Fix potential deadlock for &fasync_struct.fa_lock
v2 -> v3:
- Removed WARN_ON_ONCE, keeping elaboration for why read_lock_irq is safe to use in the commit message. As suggested by Greg KH.
v1 -> v2:
- Added WARN_ON_ONCE(irqs_disabled()) before calls to read_lock_irq, and added elaboration in the commit message. As suggested by Jeff Layton.
Best wishes,
Desmond
Desmond Cheong Zhi Xi (2):
fcntl: fix potential deadlocks for &fown_struct.lock
fcntl: fix potential deadlock for &fasync_struct.fa_lock
fs/fcntl.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--
2.25.1
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
From: Desmond Cheong Zhi Xi <hidden> Date: 2021-07-07 07:44:46
Syzbot reports a potential deadlock in do_fcntl:
========================================================
WARNING: possible irq lock inversion dependency detected
5.12.0-syzkaller #0 Not tainted
--------------------------------------------------------
syz-executor132/8391 just changed the state of lock:
ffff888015967bf8 (&f->f_owner.lock){.+..}-{2:2}, at: f_getown_ex fs/fcntl.c:211 [inline]
ffff888015967bf8 (&f->f_owner.lock){.+..}-{2:2}, at: do_fcntl+0x8b4/0x1200 fs/fcntl.c:395
but this lock was taken by another, HARDIRQ-safe lock in the past:
(&dev->event_lock){-...}-{2:2}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this:
Chain exists of:
&dev->event_lock --> &new->fa_lock --> &f->f_owner.lock
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&f->f_owner.lock);
local_irq_disable();
lock(&dev->event_lock);
lock(&new->fa_lock);
<Interrupt>
lock(&dev->event_lock);
*** DEADLOCK ***
This happens because there is a lock hierarchy of
&dev->event_lock --> &new->fa_lock --> &f->f_owner.lock
from the following call chain:
input_inject_event():
spin_lock_irqsave(&dev->event_lock,...);
input_handle_event():
input_pass_values():
input_to_handler():
evdev_events():
evdev_pass_values():
spin_lock(&client->buffer_lock);
__pass_event():
kill_fasync():
kill_fasync_rcu():
read_lock(&fa->fa_lock);
send_sigio():
read_lock_irqsave(&fown->lock,...);
However, since &dev->event_lock is HARDIRQ-safe, interrupts have to be
disabled while grabbing &f->f_owner.lock, otherwise we invert the lock
hierarchy.
Hence, we replace calls to read_lock/read_unlock on &f->f_owner.lock,
with read_lock_irq/read_unlock_irq.
Here read_lock_irq/read_unlock_irq are safe to use because the
functions f_getown_ex and f_getowner_uids are only called from
do_fcntl, and f_getown is only called from do_fnctl and
sock_ioctl. do_fnctl itself is only called from syscalls.
For sock_ioctl, the chain is
compat_sock_ioctl():
compat_sock_ioctl_trans():
sock_ioctl()
Interrupts are not disabled on either path.
Reported-and-tested-by: syzbot+e6d5398a02c516ce5e70@syzkaller.appspotmail.com
Signed-off-by: Desmond Cheong Zhi Xi <redacted>
---
fs/fcntl.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
From: Desmond Cheong Zhi Xi <hidden> Date: 2021-07-07 07:44:52
There is an existing lock hierarchy of
&dev->event_lock --> &fasync_struct.fa_lock --> &f->f_owner.lock
from the following call chain:
input_inject_event():
spin_lock_irqsave(&dev->event_lock,...);
input_handle_event():
input_pass_values():
input_to_handler():
evdev_events():
evdev_pass_values():
spin_lock(&client->buffer_lock);
__pass_event():
kill_fasync():
kill_fasync_rcu():
read_lock(&fa->fa_lock);
send_sigio():
read_lock_irqsave(&fown->lock,...);
&dev->event_lock is HARDIRQ-safe, so interrupts have to be disabled
while grabbing &fasync_struct.fa_lock, otherwise we invert the lock
hierarchy. However, since kill_fasync which calls kill_fasync_rcu is
an exported symbol, it may not necessarily be called with interrupts
disabled.
As kill_fasync_rcu may be called with interrupts disabled (for
example, in the call chain above), we replace calls to
read_lock/read_unlock on &fasync_struct.fa_lock in kill_fasync_rcu
with read_lock_irqsave/read_unlock_irqrestore.
Signed-off-by: Desmond Cheong Zhi Xi <redacted>
---
fs/fcntl.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
@@ -1004,13 +1004,14 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band){while(fa){structfown_struct*fown;+unsignedlongflags;if(fa->magic!=FASYNC_MAGIC){printk(KERN_ERR"kill_fasync: bad magic number in ""fasync_struct!\n");return;}-read_lock(&fa->fa_lock);+read_lock_irqsave(&fa->fa_lock,flags);if(fa->fa_file){fown=&fa->fa_file->f_owner;/* Don't send SIGURG to processes which have not set a
@@ -1019,7 +1020,7 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)if(!(sig==SIGURG&&fown->signum==0))send_sigio(fown,fa->fa_fd,band);}-read_unlock(&fa->fa_lock);+read_unlock_irqrestore(&fa->fa_lock,flags);fa=rcu_dereference(fa->fa_next);}}
--
2.25.1
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
From: Jeff Layton <jlayton@kernel.org> Date: 2021-07-07 17:06:10
On Wed, 2021-07-07 at 15:43 +0800, Desmond Cheong Zhi Xi wrote:
Hi,
Sorry for the delay between v1 and v2, there was an unrelated issue with Syzbot testing.
Syzbot reports a possible irq lock inversion dependency:
https://syzkaller.appspot.com/bug?id=923cfc6c6348963f99886a0176ef11dcc429547b
While investigating this error, I discovered that multiple similar lock inversion scenarios can occur. Hence, this series addresses potential deadlocks for two classes of locks, one in each patch:
1. Fix potential deadlocks for &fown_struct.lock
2. Fix potential deadlock for &fasync_struct.fa_lock
v2 -> v3:
- Removed WARN_ON_ONCE, keeping elaboration for why read_lock_irq is safe to use in the commit message. As suggested by Greg KH.
v1 -> v2:
- Added WARN_ON_ONCE(irqs_disabled()) before calls to read_lock_irq, and added elaboration in the commit message. As suggested by Jeff Layton.
Best wishes,
Desmond
Desmond Cheong Zhi Xi (2):
fcntl: fix potential deadlocks for &fown_struct.lock
fcntl: fix potential deadlock for &fasync_struct.fa_lock
fs/fcntl.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
Looks like these patches are identical to the v1 set, so I'm just going
to leave those in place since linux-next already has them. Let me know
if I've missed something though.
Thanks!
--
Jeff Layton [off-list ref]
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
From: Desmond Cheong Zhi Xi <hidden> Date: 2021-07-08 01:52:26
On 8/7/21 1:06 am, Jeff Layton wrote:
On Wed, 2021-07-07 at 15:43 +0800, Desmond Cheong Zhi Xi wrote:
quoted
Hi,
Sorry for the delay between v1 and v2, there was an unrelated issue with Syzbot testing.
Syzbot reports a possible irq lock inversion dependency:
https://syzkaller.appspot.com/bug?id=923cfc6c6348963f99886a0176ef11dcc429547b
While investigating this error, I discovered that multiple similar lock inversion scenarios can occur. Hence, this series addresses potential deadlocks for two classes of locks, one in each patch:
1. Fix potential deadlocks for &fown_struct.lock
2. Fix potential deadlock for &fasync_struct.fa_lock
v2 -> v3:
- Removed WARN_ON_ONCE, keeping elaboration for why read_lock_irq is safe to use in the commit message. As suggested by Greg KH.
v1 -> v2:
- Added WARN_ON_ONCE(irqs_disabled()) before calls to read_lock_irq, and added elaboration in the commit message. As suggested by Jeff Layton.
Best wishes,
Desmond
Desmond Cheong Zhi Xi (2):
fcntl: fix potential deadlocks for &fown_struct.lock
fcntl: fix potential deadlock for &fasync_struct.fa_lock
fs/fcntl.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
Looks like these patches are identical to the v1 set, so I'm just going
to leave those in place since linux-next already has them. Let me know
if I've missed something though.
Thanks!
Yep, there's no change outside of the commit message. But I think after
the discussion and with config DEBUG_IRQFLAGS, that is fine.
Thanks again, Jeff!
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees