Blame SOURCES/CVE-2022-2585.patch

358251
From 3b7e363b1d5f3ca329a7056b509a54d081923cd1 Mon Sep 17 00:00:00 2001
358251
From: Yannick Cote <ycote@redhat.com>
358251
Date: Thu, 13 Oct 2022 10:36:30 -0400
358251
Subject: [KPATCH 9.0] kpatch fixes for CVE-2022-2585
358251
358251
Kernels:
358251
5.14.0-70.13.1.el9_0
358251
5.14.0-70.17.1.el9_0
358251
5.14.0-70.22.1.el9_0
358251
5.14.0-70.26.1.el9_0
358251
358251
Changes since last build:
358251
arches: x86_64 ppc64le
358251
exec.o: changed function: begin_new_exec
358251
exit.o: changed function: do_exit
358251
posix-timers.o: new function: kpatch_cve_2022_2585_exit_itimers
358251
---------------------------
358251
358251
Modifications:
358251
- removed changes to .h files, for kpatch locality
358251
- redefine exit_itimers instead of changing it
358251
  (kpatch_cve_2022_2585_exit_itimers())
358251
- use kpatch defined exit_itimers() everywhere it's called in the kernel
358251
358251
commit 84013659b0e8a6965e79f1e7d6108aa2be2230ab
358251
Author: Wander Lairson Costa <wander@redhat.com>
358251
Date:   Thu Aug 25 09:27:13 2022 -0300
358251
358251
    fix race between exit_itimers() and /proc/pid/timers
358251
358251
    Bugzilla: https://bugzilla.redhat.com/2116967
358251
    CVE: CVE-2022-2585
358251
    Y-Commit: a532f4903a5d24d1e5e692628458d3a10184f615
358251
358251
    O-Bugzilla: https://bugzilla.redhat.com/2116968
358251
358251
    commit d5b36a4dbd06c5e8e36ca8ccc552f679069e2946
358251
    Author: Oleg Nesterov <oleg@redhat.com>
358251
    Date:   Mon Jul 11 18:16:25 2022 +0200
358251
358251
        fix race between exit_itimers() and /proc/pid/timers
358251
358251
        As Chris explains, the comment above exit_itimers() is not correct,
358251
        we can race with proc_timers_seq_ops. Change exit_itimers() to clear
358251
        signal->posix_timers with ->siglock held.
358251
358251
        Cc: <stable@vger.kernel.org>
358251
        Reported-by: chris@accessvector.net
358251
        Signed-off-by: Oleg Nesterov <oleg@redhat.com>
358251
        Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
358251
358251
    Signed-off-by: Wander Lairson Costa <wander@redhat.com>
358251
    Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
358251
358251
commit d91003cca875f4b0ca290db6e686ee960125da3a
358251
Author: Wander Lairson Costa <wander@redhat.com>
358251
Date:   Thu Aug 25 09:27:22 2022 -0300
358251
358251
    posix-cpu-timers: Cleanup CPU timers before freeing them during exec
358251
358251
    Bugzilla: https://bugzilla.redhat.com/2116967
358251
    CVE: CVE-2022-2585
358251
    Y-Commit: b89dd8173ef086055a00bd606813e370efe7f0d7
358251
358251
    O-Bugzilla: https://bugzilla.redhat.com/2116968
358251
358251
    commit e362359ace6f87c201531872486ff295df306d13
358251
    Author: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
358251
    Date:   Tue Aug 9 14:07:51 2022 -0300
358251
358251
        posix-cpu-timers: Cleanup CPU timers before freeing them during exec
358251
358251
        Commit 55e8c8eb2c7b ("posix-cpu-timers: Store a reference to a pid not a
358251
        task") started looking up tasks by PID when deleting a CPU timer.
358251
358251
        When a non-leader thread calls execve, it will switch PIDs with the leader
358251
        process. Then, as it calls exit_itimers, posix_cpu_timer_del cannot find
358251
        the task because the timer still points out to the old PID.
358251
358251
        That means that armed timers won't be disarmed, that is, they won't be
358251
        removed from the timerqueue_list. exit_itimers will still release their
358251
        memory, and when that list is later processed, it leads to a
358251
        use-after-free.
358251
358251
        Clean up the timers from the de-threaded task before freeing them. This
358251
        prevents a reported use-after-free.
358251
358251
        Fixes: 55e8c8eb2c7b ("posix-cpu-timers: Store a reference to a pid not a task")
358251
        Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
358251
        Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
358251
        Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
358251
        Cc: <stable@vger.kernel.org>
358251
        Link: https://lore.kernel.org/r/20220809170751.164716-1-cascardo@canonical.com
358251
358251
    Signed-off-by: Wander Lairson Costa <wander@redhat.com>
358251
    Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
358251
358251
Signed-off-by: Yannick Cote <ycote@redhat.com>
358251
---
358251
 fs/exec.c                  |  6 +++++-
358251
 kernel/exit.c              |  4 +++-
358251
 kernel/time/posix-timers.c | 26 +++++++++++++++++++++++++-
358251
 3 files changed, 33 insertions(+), 3 deletions(-)
358251
358251
diff --git a/fs/exec.c b/fs/exec.c
358251
index 2bb8dd6a4e2a..decf9ccef49d 100644
358251
--- a/fs/exec.c
358251
+++ b/fs/exec.c
358251
@@ -1229,6 +1229,7 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
358251
 	perf_event_comm(tsk, exec);
358251
 }
358251
 
358251
+void kpatch_cve_2022_2585_exit_itimers(struct task_struct *tsk);
358251
 /*
358251
  * Calling this is the point of no return. None of the failures will be
358251
  * seen by userspace since either the process is already taking a fatal
358251
@@ -1292,7 +1293,10 @@ int begin_new_exec(struct linux_binprm * bprm)
358251
 	bprm->mm = NULL;
358251
 
358251
 #ifdef CONFIG_POSIX_TIMERS
358251
-	exit_itimers(me->signal);
358251
+	spin_lock_irq(&me->sighand->siglock);
358251
+	posix_cpu_timers_exit(me);
358251
+	spin_unlock_irq(&me->sighand->siglock);
358251
+	kpatch_cve_2022_2585_exit_itimers(me);
358251
 	flush_itimer_signals();
358251
 #endif
358251
 
358251
diff --git a/kernel/exit.c b/kernel/exit.c
358251
index 1731f60de259..d1e618505b7d 100644
358251
--- a/kernel/exit.c
358251
+++ b/kernel/exit.c
358251
@@ -725,6 +725,7 @@ static void check_stack_usage(void)
358251
 static inline void check_stack_usage(void) {}
358251
 #endif
358251
 
358251
+void kpatch_cve_2022_2585_exit_itimers(struct task_struct *tsk);
358251
 void __noreturn do_exit(long code)
358251
 {
358251
 	struct task_struct *tsk = current;
358251
@@ -797,7 +798,8 @@ void __noreturn do_exit(long code)
358251
 
358251
 #ifdef CONFIG_POSIX_TIMERS
358251
 		hrtimer_cancel(&tsk->signal->real_timer);
358251
-		exit_itimers(tsk->signal);
358251
+		kpatch_cve_2022_2585_exit_itimers(tsk);
358251
+
358251
 #endif
358251
 		if (tsk->mm)
358251
 			setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm);
358251
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
358251
index 1cd10b102c51..8a1f61232282 100644
358251
--- a/kernel/time/posix-timers.c
358251
+++ b/kernel/time/posix-timers.c
358251
@@ -1035,7 +1035,7 @@ SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
358251
 /*
358251
  * return timer owned by the process, used by exit_itimers
358251
  */
358251
-static void itimer_delete(struct k_itimer *timer)
358251
+static __always_inline void itimer_delete(struct k_itimer *timer)
358251
 {
358251
 retry_delete:
358251
 	spin_lock_irq(&timer->it_lock);
358251
@@ -1050,6 +1050,30 @@ static void itimer_delete(struct k_itimer *timer)
358251
 	release_posix_timer(timer, IT_ID_SET);
358251
 }
358251
 
358251
+/*
358251
+ * CVE-2022-2585 - kpatch exit_itimers() redefinition
358251
+ * This is called by do_exit or de_thread, only when nobody else can
358251
+ * modify the signal->posix_timers list. Yet we need sighand->siglock
358251
+ * to prevent the race with /proc/pid/timers.
358251
+ */
358251
+void kpatch_cve_2022_2585_exit_itimers(struct task_struct *tsk)
358251
+{
358251
+	struct list_head timers;
358251
+	struct k_itimer *tmr;
358251
+
358251
+	if (list_empty(&tsk->signal->posix_timers))
358251
+		return;
358251
+
358251
+	spin_lock_irq(&tsk->sighand->siglock);
358251
+	list_replace_init(&tsk->signal->posix_timers, &timers);
358251
+	spin_unlock_irq(&tsk->sighand->siglock);
358251
+
358251
+	while (!list_empty(&timers)) {
358251
+		tmr = list_first_entry(&timers, struct k_itimer, list);
358251
+		itimer_delete(tmr);
358251
+	}
358251
+}
358251
+
358251
 /*
358251
  * This is called by do_exit or de_thread, only when there are no more
358251
  * references to the shared signal_struct.
358251
-- 
358251
2.37.3
358251