History

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

Linus Torvalds committed 6 years ago

Commit d4fce2e2 parents db23baa 3701cb51 file · +31 −41Browse files

Unified · Split

fs/eventpoll.c+31−41
@@ -218,8 +218,7 @@ struct eventpoll { · 217 unmodified lines
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; · 48 unmodified lines
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; · 3 unmodified lines
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) · 1158 unmodified lines
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) · 2 unmodified lines
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, · 55 unmodified lines
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, · 16 unmodified lines
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,6 +1587,8 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event, · 22 unmodified lines
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);
@@ -1595,9 +1596,6 @@ error_remove_epi: · 1 unmodified line
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) · 368 unmodified lines
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) · 34 unmodified lines
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, · 158 unmodified lines
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, · 57 unmodified lines
22632252 error_tgt_fput:
22642253 if (full_check) {
22652254 clear_tfile_check_list();
2255+ loop_check_gen++;
22662256 mutex_unlock(&epmutex);
22672257 }
22682258

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t