Skip to content

Commit a9ed4a6

Browse files
Marc ZyngierAl Viro
authored andcommitted
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. Cc: [email protected] Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 9123e3a commit a9ed4a6

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

fs/eventpoll.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,9 +1994,11 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
19941994
* not already there, and calling reverse_path_check()
19951995
* during ep_insert().
19961996
*/
1997-
if (list_empty(&epi->ffd.file->f_tfile_llink))
1997+
if (list_empty(&epi->ffd.file->f_tfile_llink)) {
1998+
get_file(epi->ffd.file);
19981999
list_add(&epi->ffd.file->f_tfile_llink,
19992000
&tfile_check_list);
2001+
}
20002002
}
20012003
}
20022004
mutex_unlock(&ep->mtx);
@@ -2040,6 +2042,7 @@ static void clear_tfile_check_list(void)
20402042
file = list_first_entry(&tfile_check_list, struct file,
20412043
f_tfile_llink);
20422044
list_del_init(&file->f_tfile_llink);
2045+
fput(file);
20432046
}
20442047
INIT_LIST_HEAD(&tfile_check_list);
20452048
}
@@ -2204,13 +2207,17 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
22042207
clear_tfile_check_list();
22052208
goto error_tgt_fput;
22062209
}
2207-
} else
2210+
} else {
2211+
get_file(tf.file);
22082212
list_add(&tf.file->f_tfile_llink,
22092213
&tfile_check_list);
2214+
}
22102215
error = epoll_mutex_lock(&ep->mtx, 0, nonblock);
22112216
if (error) {
22122217
out_del:
22132218
list_del(&tf.file->f_tfile_llink);
2219+
if (!is_file_epoll(tf.file))
2220+
fput(tf.file);
22142221
goto error_tgt_fput;
22152222
}
22162223
if (is_file_epoll(tf.file)) {

0 commit comments

Comments
 (0)