From: Davide Libenzi This fixes a bug that might happen having a thread doing epoll_wait() with another thread doing epoll_ctl(EPOLL_CTL_DEL) and close(). The fast check inside eventpoll_release() is good to not effect performace of code not using epoll, but it requires get_file() to be called ( that can be avoided by dropping the fast check ). I opted to keep the fast check and to have epoll to call get_file() before the event send loop. I tested it on UP and 2SMP with a bug-exploiting program provided by @pivia.com ( thx to them ) and it looks fine. I also update the 2.4.20 epoll patch with this fix : http://www.xmailserver.org/linux-patches/epoll-lt-2.4.20-0.5.diff 25-akpm/fs/eventpoll.c | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletion(-) diff -puN fs/eventpoll.c~epoll-cross-thread-deletion-fix fs/eventpoll.c --- 25/fs/eventpoll.c~epoll-cross-thread-deletion-fix Mon Apr 7 12:27:47 2003 +++ 25-akpm/fs/eventpoll.c Mon Apr 7 12:27:47 2003 @@ -1342,6 +1342,13 @@ static int ep_collect_ready_items(struct ep_use_epitem(epi); /* + * We need to increase the usage count of the "struct file" because + * another thread might call close() on this target and make the file + * to vanish before we will be able to call f_op->poll(). + */ + get_file(epi->file); + + /* * This is initialized in this way so that the default * behaviour of the reinjecting code will be to push back * the item inside the ready list. @@ -1386,6 +1393,14 @@ static int ep_send_events(struct eventpo revents = epi->file->f_op->poll(epi->file, NULL); /* + * Release the file usage before checking the event mask. + * In case this call will lead to the file removal, its + * ->event.events member has been already set to zero and + * this will make the event to be dropped. + */ + fput(epi->file); + + /* * Set the return event set for the current file descriptor. * Note that only the task task was successfully able to link * the item to its "txlist" will write this field. @@ -1398,8 +1413,17 @@ static int ep_send_events(struct eventpo eventbuf++; if (eventbuf == EP_MAX_BUF_EVENTS) { if (__copy_to_user(&events[eventcnt], event, - eventbuf * sizeof(struct epoll_event))) + eventbuf * sizeof(struct epoll_event))) { + /* + * We need to complete the loop to decrement the file + * usage before returning from this function. + */ + for (lnk = lnk->next; lnk != txlist; lnk = lnk->next) { + epi = list_entry(lnk, struct epitem, txlink); + fput(epi->file); + } return -EFAULT; + } eventcnt += eventbuf; eventbuf = 0; } _