Skip to content

Commit 4957d56

Browse files
Marc Zyngiergregkh
authored andcommitted
epoll: Keep a reference on files added to the check list
commit a9ed4a6 upstream. 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. Cc: [email protected] Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Al Viro <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2ff3c97 commit 4957d56

File tree

1 file changed

+7
-2
lines changed

1 file changed

+7
-2
lines changed

fs/eventpoll.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,9 +1890,11 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
18901890
* not already there, and calling reverse_path_check()
18911891
* during ep_insert().
18921892
*/
1893-
if (list_empty(&epi->ffd.file->f_tfile_llink))
1893+
if (list_empty(&epi->ffd.file->f_tfile_llink)) {
1894+
get_file(epi->ffd.file);
18941895
list_add(&epi->ffd.file->f_tfile_llink,
18951896
&tfile_check_list);
1897+
}
18961898
}
18971899
}
18981900
mutex_unlock(&ep->mtx);
@@ -1936,6 +1938,7 @@ static void clear_tfile_check_list(void)
19361938
file = list_first_entry(&tfile_check_list, struct file,
19371939
f_tfile_llink);
19381940
list_del_init(&file->f_tfile_llink);
1941+
fput(file);
19391942
}
19401943
INIT_LIST_HEAD(&tfile_check_list);
19411944
}
@@ -2095,9 +2098,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
20952098
clear_tfile_check_list();
20962099
goto error_tgt_fput;
20972100
}
2098-
} else
2101+
} else {
2102+
get_file(tf.file);
20992103
list_add(&tf.file->f_tfile_llink,
21002104
&tfile_check_list);
2105+
}
21012106
mutex_lock_nested(&ep->mtx, 0);
21022107
if (is_file_epoll(tf.file)) {
21032108
tep = tf.file->private_data;

0 commit comments

Comments
 (0)