Blame SOURCES/CVE-2022-2585.patch

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