Skip to content

Commit d4fce2e

Browse files
committed
Merge branch 'work.epoll' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull epoll fixes from Al Viro: "Several race fixes in epoll" * 'work.epoll' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: ep_create_wakeup_source(): dentry name can change under you... epoll: EPOLL_CTL_ADD: close the race in decision to take fast path epoll: replace ->visited/visited_list with generation count epoll: do not insert into poll queues until all sanity checks are done
2 parents db23baa + 3701cb5 commit d4fce2e

File tree

1 file changed

+31
-41
lines changed

1 file changed

+31
-41
lines changed

fs/eventpoll.c

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ struct eventpoll {
218218
struct file *file;
219219

220220
/* used to optimize loop detection check */
221-
struct list_head visited_list_link;
222-
int visited;
221+
u64 gen;
223222

224223
#ifdef CONFIG_NET_RX_BUSY_POLL
225224
/* used to track busy poll napi_id */
@@ -274,6 +273,8 @@ static long max_user_watches __read_mostly;
274273
*/
275274
static DEFINE_MUTEX(epmutex);
276275

276+
static u64 loop_check_gen = 0;
277+
277278
/* Used to check for epoll file descriptor inclusion loops */
278279
static struct nested_calls poll_loop_ncalls;
279280

@@ -283,9 +284,6 @@ static struct kmem_cache *epi_cache __read_mostly;
283284
/* Slab cache used to allocate "struct eppoll_entry" */
284285
static struct kmem_cache *pwq_cache __read_mostly;
285286

286-
/* Visited nodes during ep_loop_check(), so we can unset them when we finish */
287-
static LIST_HEAD(visited_list);
288-
289287
/*
290288
* List of files with newly added links, where we may need to limit the number
291289
* of emanating paths. Protected by the epmutex.
@@ -1450,7 +1448,7 @@ static int reverse_path_check(void)
14501448

14511449
static int ep_create_wakeup_source(struct epitem *epi)
14521450
{
1453-
const char *name;
1451+
struct name_snapshot n;
14541452
struct wakeup_source *ws;
14551453

14561454
if (!epi->ep->ws) {
@@ -1459,8 +1457,9 @@ static int ep_create_wakeup_source(struct epitem *epi)
14591457
return -ENOMEM;
14601458
}
14611459

1462-
name = epi->ffd.file->f_path.dentry->d_name.name;
1463-
ws = wakeup_source_register(NULL, name);
1460+
take_dentry_name_snapshot(&n, epi->ffd.file->f_path.dentry);
1461+
ws = wakeup_source_register(NULL, n.name.name);
1462+
release_dentry_name_snapshot(&n);
14641463

14651464
if (!ws)
14661465
return -ENOMEM;
@@ -1522,6 +1521,22 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
15221521
RCU_INIT_POINTER(epi->ws, NULL);
15231522
}
15241523

1524+
/* Add the current item to the list of active epoll hook for this file */
1525+
spin_lock(&tfile->f_lock);
1526+
list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links);
1527+
spin_unlock(&tfile->f_lock);
1528+
1529+
/*
1530+
* Add the current item to the RB tree. All RB tree operations are
1531+
* protected by "mtx", and ep_insert() is called with "mtx" held.
1532+
*/
1533+
ep_rbtree_insert(ep, epi);
1534+
1535+
/* now check if we've created too many backpaths */
1536+
error = -EINVAL;
1537+
if (full_check && reverse_path_check())
1538+
goto error_remove_epi;
1539+
15251540
/* Initialize the poll table using the queue callback */
15261541
epq.epi = epi;
15271542
init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
@@ -1544,22 +1559,6 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
15441559
if (epi->nwait < 0)
15451560
goto error_unregister;
15461561

1547-
/* Add the current item to the list of active epoll hook for this file */
1548-
spin_lock(&tfile->f_lock);
1549-
list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links);
1550-
spin_unlock(&tfile->f_lock);
1551-
1552-
/*
1553-
* Add the current item to the RB tree. All RB tree operations are
1554-
* protected by "mtx", and ep_insert() is called with "mtx" held.
1555-
*/
1556-
ep_rbtree_insert(ep, epi);
1557-
1558-
/* now check if we've created too many backpaths */
1559-
error = -EINVAL;
1560-
if (full_check && reverse_path_check())
1561-
goto error_remove_epi;
1562-
15631562
/* We have to drop the new item inside our item list to keep track of it */
15641563
write_lock_irq(&ep->lock);
15651564

@@ -1588,16 +1587,15 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
15881587

15891588
return 0;
15901589

1590+
error_unregister:
1591+
ep_unregister_pollwait(ep, epi);
15911592
error_remove_epi:
15921593
spin_lock(&tfile->f_lock);
15931594
list_del_rcu(&epi->fllink);
15941595
spin_unlock(&tfile->f_lock);
15951596

15961597
rb_erase_cached(&epi->rbn, &ep->rbr);
15971598

1598-
error_unregister:
1599-
ep_unregister_pollwait(ep, epi);
1600-
16011599
/*
16021600
* We need to do this because an event could have been arrived on some
16031601
* allocated wait queue. Note that we don't care about the ep->ovflist
@@ -1972,13 +1970,12 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
19721970
struct epitem *epi;
19731971

19741972
mutex_lock_nested(&ep->mtx, call_nests + 1);
1975-
ep->visited = 1;
1976-
list_add(&ep->visited_list_link, &visited_list);
1973+
ep->gen = loop_check_gen;
19771974
for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
19781975
epi = rb_entry(rbp, struct epitem, rbn);
19791976
if (unlikely(is_file_epoll(epi->ffd.file))) {
19801977
ep_tovisit = epi->ffd.file->private_data;
1981-
if (ep_tovisit->visited)
1978+
if (ep_tovisit->gen == loop_check_gen)
19821979
continue;
19831980
error = ep_call_nested(&poll_loop_ncalls,
19841981
ep_loop_check_proc, epi->ffd.file,
@@ -2019,18 +2016,8 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
20192016
*/
20202017
static int ep_loop_check(struct eventpoll *ep, struct file *file)
20212018
{
2022-
int ret;
2023-
struct eventpoll *ep_cur, *ep_next;
2024-
2025-
ret = ep_call_nested(&poll_loop_ncalls,
2019+
return ep_call_nested(&poll_loop_ncalls,
20262020
ep_loop_check_proc, file, ep, current);
2027-
/* clear visited list */
2028-
list_for_each_entry_safe(ep_cur, ep_next, &visited_list,
2029-
visited_list_link) {
2030-
ep_cur->visited = 0;
2031-
list_del(&ep_cur->visited_list_link);
2032-
}
2033-
return ret;
20342021
}
20352022

20362023
static void clear_tfile_check_list(void)
@@ -2195,11 +2182,13 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
21952182
goto error_tgt_fput;
21962183
if (op == EPOLL_CTL_ADD) {
21972184
if (!list_empty(&f.file->f_ep_links) ||
2185+
ep->gen == loop_check_gen ||
21982186
is_file_epoll(tf.file)) {
21992187
mutex_unlock(&ep->mtx);
22002188
error = epoll_mutex_lock(&epmutex, 0, nonblock);
22012189
if (error)
22022190
goto error_tgt_fput;
2191+
loop_check_gen++;
22032192
full_check = 1;
22042193
if (is_file_epoll(tf.file)) {
22052194
error = -ELOOP;
@@ -2263,6 +2252,7 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
22632252
error_tgt_fput:
22642253
if (full_check) {
22652254
clear_tfile_check_list();
2255+
loop_check_gen++;
22662256
mutex_unlock(&epmutex);
22672257
}
22682258

0 commit comments

Comments
 (0)