Patch "fcntl: fix potential deadlock for &fasync_struct.fa_lock" has been added to the 5.14-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    fcntl: fix potential deadlock for &fasync_struct.fa_lock

to the 5.14-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     fcntl-fix-potential-deadlock-for-fasync_struct.fa_lo.patch
and it can be found in the queue-5.14 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 1f2069077477b2fe5f47c2341fbbe39eaa11431a
Author: Desmond Cheong Zhi Xi <desmondcheongzx@xxxxxxxxx>
Date:   Fri Jul 2 17:18:31 2021 +0800

    fcntl: fix potential deadlock for &fasync_struct.fa_lock
    
    [ Upstream commit 2f488f698fda820f8e6fa0407630154eceb145d6 ]
    
    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 <desmondcheongzx@xxxxxxxxx>
    Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/fcntl.c b/fs/fcntl.c
index 932ec1e9f5bf..68added37c15 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1004,13 +1004,14 @@ static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band)
 {
 	while (fa) {
 		struct fown_struct *fown;
+		unsigned long flags;
 
 		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);
 	}
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux