]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
epoll: annotate racy check
authorChristian Brauner <brauner@kernel.org>
Wed, 25 Sep 2024 09:05:16 +0000 (11:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Dec 2024 18:51:34 +0000 (19:51 +0100)
[ Upstream commit 6474353a5e3d0b2cf610153cea0c61f576a36d0a ]

Epoll relies on a racy fastpath check during __fput() in
eventpoll_release() to avoid the hit of pointlessly acquiring a
semaphore. Annotate that race by using WRITE_ONCE() and READ_ONCE().

Link: https://lore.kernel.org/r/66edfb3c.050a0220.3195df.001a.GAE@google.com
Link: https://lore.kernel.org/r/20240925-fungieren-anbauen-79b334b00542@brauner
Reviewed-by: Jan Kara <jack@suse.cz>
Reported-by: syzbot+3b6b32dc50537a49bb4a@syzkaller.appspotmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/eventpoll.c
include/linux/eventpoll.h

index b60edddf17870b3377f27639c6f4e136a2dca52b..7413b4a6ba282001a14eef5f83c8264e751f0b20 100644 (file)
@@ -696,7 +696,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        to_free = NULL;
        head = file->f_ep;
        if (head->first == &epi->fllink && !epi->fllink.next) {
-               file->f_ep = NULL;
+               /* See eventpoll_release() for details. */
+               WRITE_ONCE(file->f_ep, NULL);
                if (!is_file_epoll(file)) {
                        struct epitems_head *v;
                        v = container_of(head, struct epitems_head, epitems);
@@ -1460,7 +1461,8 @@ allocate:
                        spin_unlock(&file->f_lock);
                        goto allocate;
                }
-               file->f_ep = head;
+               /* See eventpoll_release() for details. */
+               WRITE_ONCE(file->f_ep, head);
                to_free = NULL;
        }
        hlist_add_head_rcu(&epi->fllink, file->f_ep);
index 3337745d81bd6947c6181bd9f2df3eaf013f0b04..0c0d00fcd131f9ebfdbabdb1917f01e870435595 100644 (file)
@@ -42,7 +42,7 @@ static inline void eventpoll_release(struct file *file)
         * because the file in on the way to be removed and nobody ( but
         * eventpoll ) has still a reference to this file.
         */
-       if (likely(!file->f_ep))
+       if (likely(!READ_ONCE(file->f_ep)))
                return;
 
        /*