lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 28 Oct 2017 20:58:26 +0800
From:   Hou Tao <>
To:     <>
CC:     <>, <>,
        <>, <>, <>,
Subject: [RFC][PATCH 7/8] epoll: prevent the double-free of epi in eventpoll_release_file()

After the removal of epmutex, it's possible eventpoll_release_file()
and ep_free() will try to remove the same epi. The removal of epi
is protected by ep->mtx, so there are two possible sequences:

(1) eventpoll_release_file() first, then ep_free()
    there is no double-free, because after the invocation of
    eventpoll_release_file(), the epi will be removed from ep->rbr
    and ep_free() will not be able to free it.
(2) ep_free() first, then eventpoll_release_file()
    double-free is possible because before the invocation of ep_remove()
    in ep_free() eventpoll_release_file may has already got the epi from
    file->f_ep_links. To protect against the double-free case, check
    rb_first_cached() in eventpoll_release_file() to ensure the epi
    has not been removed by ep_free()

Signed-off-by: Hou Tao <>
 fs/eventpoll.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 27b743b..cd7a9f4 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1058,13 +1058,22 @@ void eventpoll_release_file(struct file *file)
 		ep = eventpoll_get_ep(epi->ep);
-		/* Current epi has been removed by ep_free() */
+		/* Current epi had been removed by ep_free() */
 		if (!ep)
 		mutex_lock_nested(&ep->mtx, 0);
-		ep_remove(ep, epi);
+		/*
+		 * If rb_first_cached() returns NULL, it means that the current epi
+		 * had been removed by ep_free(). To prevent epi from double-freeing,
+		 * check the condition before invoking ep_remove().
+		 * If eventpoll_release_file() frees epi firstly, the epi will not
+		 * be freed again because the epi must have been removed from ep->rbr
+		 * when ep_free() is invoked.
+		 */
+		if (rb_first_cached(&ep->rbr))
+			ep_remove(ep, epi);

Powered by blists - more mailing lists