Blame SOURCES/CVE-2022-2585.patch

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