]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
epoll: annotate racy check
authorChristian Brauner <brauner@kernel.org>
Wed, 25 Sep 2024 09:05:16 +0000 (11:05 +0200)
committerChristian Brauner <brauner@kernel.org>
Tue, 22 Oct 2024 09:16:56 +0000 (11:16 +0200)
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>
fs/eventpoll.c
include/linux/eventpoll.h

index 1ae4542f0bd88b07e323d0dd75be6c0fe9fff54f..90fbab6b6f0363705222892f79e8e667340698f2 100644 (file)
@@ -823,7 +823,8 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
        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);
@@ -1603,7 +1604,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;
 
        /*