From c17b58ebffbfa862b3f1815e208db340bd1664eb Mon Sep 17 00:00:00 2001 From: Yannick Cote Date: Tue, 1 Feb 2022 14:14:41 -0500 Subject: [KPATCH CVE-2020-0466] epoll: kpatch fixes for CVE-2020-0466 Kernels: 3.10.0-1160.15.2.el7 3.10.0-1160.21.1.el7 3.10.0-1160.24.1.el7 3.10.0-1160.25.1.el7 3.10.0-1160.31.1.el7 3.10.0-1160.36.2.el7 3.10.0-1160.41.1.el7 3.10.0-1160.42.2.el7 3.10.0-1160.45.1.el7 3.10.0-1160.49.1.el7 3.10.0-1160.53.1.el7 Changes since last build: [x86_64]: eventpoll.o: changed function: SyS_epoll_ctl eventpoll.o: changed function: clear_tfile_check_list eventpoll.o: changed function: ep_loop_check_proc [ppc64le]: eventpoll.o: changed function: SyS_epoll_ctl eventpoll.o: changed function: ep_loop_check_proc --------------------------- Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-7/-/merge_requests/22 Approved-by: Artem Savkov (@artem.savkov) Kernels: 3.10.0-1160.21.1.el7 3.10.0-1160.24.1.el7 3.10.0-1160.25.1.el7 3.10.0-1160.31.1.el7 3.10.0-1160.36.2.el7 3.10.0-1160.41.1.el7 3.10.0-1160.42.2.el7 3.10.0-1160.45.1.el7 3.10.0-1160.49.1.el7 3.10.0-1160.53.1.el7 Modifications: none commit f771ed0537c55c506dc846cb8f3da60f6383a2b3 Author: Carlos Maiolino Date: Sat Dec 18 09:23:31 2021 +0100 epoll: Keep a reference on files added to the check list Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2042760 Tested: Sanity check only CVE: CVE-2020-0466 Conflicts: - RHEL7 has no support for non-blocking do_epoll_ctl(), so the original patch got this part stripped. When adding a new fd to an epoll, and that this new fd is an epoll fd itself, we recursively scan the fds attached to it to detect cycles, and add non-epool files to a "check list" that gets subsequently parsed. However, this check list isn't completely safe when deletions can happen concurrently. To sidestep the issue, make sure that a struct file placed on the check list sees its f_count increased, ensuring that a concurrent deletion won't result in the file disapearing from under our feet. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Signed-off-by: Al Viro (cherry picked from commit a9ed4a6560b8562b7e2e2bed9527e88001f7b682) Signed-off-by: Carlos Maiolino commit 0875a380011a7ff7f4504b72890c29fec420d1cd Author: Carlos Maiolino Date: Sat Dec 18 09:23:47 2021 +0100 fix regression in "epoll: Keep a reference on files added to the check list" Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2042760 Tested: Sanity check only CVE: CVE-2020-0466 epoll_loop_check_proc() can run into a file already committed to destruction; we can't grab a reference on those and don't need to add them to the set for reverse path check anyway. Tested-by: Marc Zyngier Fixes: a9ed4a6560b8 ("epoll: Keep a reference on files added to the check list") Signed-off-by: Al Viro (cherry picked from commit 77f4689de17c0887775bb77896f4cc11a39bf848) Signed-off-by: Carlos Maiolino Signed-off-by: Yannick Cote --- fs/eventpoll.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6731b99a481f..ca0eb701eeb4 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1750,9 +1750,11 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests) * not already there, and calling reverse_path_check() * during ep_insert(). */ - if (list_empty(&epi->ffd.file->f_tfile_llink)) - list_add(&epi->ffd.file->f_tfile_llink, - &tfile_check_list); + if (list_empty(&epi->ffd.file->f_tfile_llink)) { + if (get_file_rcu(epi->ffd.file)) + list_add(&epi->ffd.file->f_tfile_llink, + &tfile_check_list); + } } } mutex_unlock(&ep->mtx); @@ -1796,6 +1798,7 @@ static void clear_tfile_check_list(void) file = list_first_entry(&tfile_check_list, struct file, f_tfile_llink); list_del_init(&file->f_tfile_llink); + fput(file); } INIT_LIST_HEAD(&tfile_check_list); } @@ -1951,9 +1954,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, clear_tfile_check_list(); goto error_tgt_fput; } - } else + } else { + get_file(tf.file); list_add(&tf.file->f_tfile_llink, &tfile_check_list); + } mutex_lock_nested(&ep->mtx, 0); if (is_file_epoll(tf.file)) { tep = tf.file->private_data; -- 2.26.3