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