@@ -876,6 +876,34 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
876876 return res ;
877877}
878878
879+ /*
880+ * The ffd.file pointer may be in the process of being torn down due to
881+ * being closed, but we may not have finished eventpoll_release() yet.
882+ *
883+ * Normally, even with the atomic_long_inc_not_zero, the file may have
884+ * been free'd and then gotten re-allocated to something else (since
885+ * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU).
886+ *
887+ * But for epoll, users hold the ep->mtx mutex, and as such any file in
888+ * the process of being free'd will block in eventpoll_release_file()
889+ * and thus the underlying file allocation will not be free'd, and the
890+ * file re-use cannot happen.
891+ *
892+ * For the same reason we can avoid a rcu_read_lock() around the
893+ * operation - 'ffd.file' cannot go away even if the refcount has
894+ * reached zero (but we must still not call out to ->poll() functions
895+ * etc).
896+ */
897+ static struct file * epi_fget (const struct epitem * epi )
898+ {
899+ struct file * file ;
900+
901+ file = epi -> ffd .file ;
902+ if (!atomic_long_inc_not_zero (& file -> f_count ))
903+ file = NULL ;
904+ return file ;
905+ }
906+
879907/*
880908 * Differs from ep_eventpoll_poll() in that internal callers already have
881909 * the ep->mtx so we need to start from depth=1, such that mutex_lock_nested()
@@ -884,14 +912,22 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
884912static __poll_t ep_item_poll (const struct epitem * epi , poll_table * pt ,
885913 int depth )
886914{
887- struct file * file = epi -> ffd . file ;
915+ struct file * file = epi_fget ( epi ) ;
888916 __poll_t res ;
889917
918+ /*
919+ * We could return EPOLLERR | EPOLLHUP or something, but let's
920+ * treat this more as "file doesn't exist, poll didn't happen".
921+ */
922+ if (!file )
923+ return 0 ;
924+
890925 pt -> _key = epi -> event .events ;
891926 if (!is_file_epoll (file ))
892927 res = vfs_poll (file , pt );
893928 else
894929 res = __ep_eventpoll_poll (file , pt , depth );
930+ fput (file );
895931 return res & epi -> event .events ;
896932}
897933
0 commit comments