FAILED: patch "[PATCH] epoll: Keep a reference on files added to the check list" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a9ed4a6560b8562b7e2e2bed9527e88001f7b682 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Wed, 19 Aug 2020 17:12:17 +0100
Subject: [PATCH] epoll: Keep a reference on files added to the check list
When adding a new fd to an epoll, and that this new fd is an epoll fd itself, we recursively scan the fds attached to it to detect cycles, and add non-epool files to a "check list" that gets subsequently parsed.
However, this check list isn't completely safe when deletions can happen concurrently. To sidestep the issue, make sure that a struct file placed on the check list sees its f_count increased, ensuring that a concurrent deletion won't result in the file disapearing from under our feet.
fs/eventpoll.c +9 -2
@@ -1994,9 +1994,11 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)* not already there, and calling reverse_path_check() * during ep_insert(). */ -if (list_empty (&epi->ffd.file->f_tfile_llink)) +if (list_empty (&epi->ffd.file->f_tfile_llink)) { +get_file (epi->ffd.file);list_add (&epi->ffd.file->f_tfile_llink, &tfile_check_list); + } } }mutex_unlock (&ep->mtx);
@@ -2040,6 +2042,7 @@ static void clear_tfile_check_list(void) file = list_first_entry(&tfile_check_list, struct file, f_tfile_llink);list_del_init (&file->f_tfile_llink); +fput (file); }INIT_LIST_HEAD (&tfile_check_list); }
@@ -2204,13 +2207,17 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,clear_tfile_check_list (); goto error_tgt_fput; } - }else + }else { +get_file (tf.file);list_add (&tf.file->f_tfile_llink, &tfile_check_list); + } error =epoll_mutex_lock (&ep->mtx,0 , nonblock);if (error) { out_del:list_del (&tf.file->f_tfile_llink); +if (!is_file_epoll (tf.file)) +fput (tf.file); goto error_tgt_fput; }if (is_file_epoll (tf.file)) {