From: Greg Kroah-Hartman Date: Wed, 25 May 2022 13:35:34 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v5.18.1~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=01a4f724cc30ac32c2d927b8268b73d690cdb046;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: lockdown-also-lock-down-previous-kgdb-use.patch --- diff --git a/queue-5.10/lockdown-also-lock-down-previous-kgdb-use.patch b/queue-5.10/lockdown-also-lock-down-previous-kgdb-use.patch new file mode 100644 index 00000000000..0791a7607ed --- /dev/null +++ b/queue-5.10/lockdown-also-lock-down-previous-kgdb-use.patch @@ -0,0 +1,196 @@ +From eadb2f47a3ced5c64b23b90fd2a3463f63726066 Mon Sep 17 00:00:00 2001 +From: Daniel Thompson +Date: Mon, 23 May 2022 19:11:02 +0100 +Subject: lockdown: also lock down previous kgdb use + +From: Daniel Thompson + +commit eadb2f47a3ced5c64b23b90fd2a3463f63726066 upstream. + +KGDB and KDB allow read and write access to kernel memory, and thus +should be restricted during lockdown. An attacker with access to a +serial port (for example, via a hypervisor console, which some cloud +vendors provide over the network) could trigger the debugger so it is +important that the debugger respect the lockdown mode when/if it is +triggered. + +Fix this by integrating lockdown into kdb's existing permissions +mechanism. Unfortunately kgdb does not have any permissions mechanism +(although it certainly could be added later) so, for now, kgdb is simply +and brutally disabled by immediately exiting the gdb stub without taking +any action. + +For lockdowns established early in the boot (e.g. the normal case) then +this should be fine but on systems where kgdb has set breakpoints before +the lockdown is enacted than "bad things" will happen. + +CVE: CVE-2022-21499 +Co-developed-by: Stephen Brennan +Signed-off-by: Stephen Brennan +Reviewed-by: Douglas Anderson +Signed-off-by: Daniel Thompson +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/security.h | 2 + + kernel/debug/debug_core.c | 24 +++++++++++++++++ + kernel/debug/kdb/kdb_main.c | 62 +++++++++++++++++++++++++++++++++++++++++--- + security/security.c | 2 + + 4 files changed, 87 insertions(+), 3 deletions(-) + +--- a/include/linux/security.h ++++ b/include/linux/security.h +@@ -121,10 +121,12 @@ enum lockdown_reason { + LOCKDOWN_DEBUGFS, + LOCKDOWN_XMON_WR, + LOCKDOWN_BPF_WRITE_USER, ++ LOCKDOWN_DBG_WRITE_KERNEL, + LOCKDOWN_INTEGRITY_MAX, + LOCKDOWN_KCORE, + LOCKDOWN_KPROBES, + LOCKDOWN_BPF_READ, ++ LOCKDOWN_DBG_READ_KERNEL, + LOCKDOWN_PERF, + LOCKDOWN_TRACEFS, + LOCKDOWN_XMON_RW, +--- a/kernel/debug/debug_core.c ++++ b/kernel/debug/debug_core.c +@@ -56,6 +56,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -756,6 +757,29 @@ cpu_master_loop: + continue; + kgdb_connected = 0; + } else { ++ /* ++ * This is a brutal way to interfere with the debugger ++ * and prevent gdb being used to poke at kernel memory. ++ * This could cause trouble if lockdown is applied when ++ * there is already an active gdb session. For now the ++ * answer is simply "don't do that". Typically lockdown ++ * *will* be applied before the debug core gets started ++ * so only developers using kgdb for fairly advanced ++ * early kernel debug can be biten by this. Hopefully ++ * they are sophisticated enough to take care of ++ * themselves, especially with help from the lockdown ++ * message printed on the console! ++ */ ++ if (security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL)) { ++ if (IS_ENABLED(CONFIG_KGDB_KDB)) { ++ /* Switch back to kdb if possible... */ ++ dbg_kdb_mode = 1; ++ continue; ++ } else { ++ /* ... otherwise just bail */ ++ break; ++ } ++ } + error = gdb_serial_stub(ks); + } + +--- a/kernel/debug/kdb/kdb_main.c ++++ b/kernel/debug/kdb/kdb_main.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include "kdb_private.h" + + #undef MODULE_PARAM_PREFIX +@@ -197,10 +198,62 @@ struct task_struct *kdb_curr_task(int cp + } + + /* +- * Check whether the flags of the current command and the permissions +- * of the kdb console has allow a command to be run. ++ * Update the permissions flags (kdb_cmd_enabled) to match the ++ * current lockdown state. ++ * ++ * Within this function the calls to security_locked_down() are "lazy". We ++ * avoid calling them if the current value of kdb_cmd_enabled already excludes ++ * flags that might be subject to lockdown. Additionally we deliberately check ++ * the lockdown flags independently (even though read lockdown implies write ++ * lockdown) since that results in both simpler code and clearer messages to ++ * the user on first-time debugger entry. ++ * ++ * The permission masks during a read+write lockdown permits the following ++ * flags: INSPECT, SIGNAL, REBOOT (and ALWAYS_SAFE). ++ * ++ * The INSPECT commands are not blocked during lockdown because they are ++ * not arbitrary memory reads. INSPECT covers the backtrace family (sometimes ++ * forcing them to have no arguments) and lsmod. These commands do expose ++ * some kernel state but do not allow the developer seated at the console to ++ * choose what state is reported. SIGNAL and REBOOT should not be controversial, ++ * given these are allowed for root during lockdown already. ++ */ ++static void kdb_check_for_lockdown(void) ++{ ++ const int write_flags = KDB_ENABLE_MEM_WRITE | ++ KDB_ENABLE_REG_WRITE | ++ KDB_ENABLE_FLOW_CTRL; ++ const int read_flags = KDB_ENABLE_MEM_READ | ++ KDB_ENABLE_REG_READ; ++ ++ bool need_to_lockdown_write = false; ++ bool need_to_lockdown_read = false; ++ ++ if (kdb_cmd_enabled & (KDB_ENABLE_ALL | write_flags)) ++ need_to_lockdown_write = ++ security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL); ++ ++ if (kdb_cmd_enabled & (KDB_ENABLE_ALL | read_flags)) ++ need_to_lockdown_read = ++ security_locked_down(LOCKDOWN_DBG_READ_KERNEL); ++ ++ /* De-compose KDB_ENABLE_ALL if required */ ++ if (need_to_lockdown_write || need_to_lockdown_read) ++ if (kdb_cmd_enabled & KDB_ENABLE_ALL) ++ kdb_cmd_enabled = KDB_ENABLE_MASK & ~KDB_ENABLE_ALL; ++ ++ if (need_to_lockdown_write) ++ kdb_cmd_enabled &= ~write_flags; ++ ++ if (need_to_lockdown_read) ++ kdb_cmd_enabled &= ~read_flags; ++} ++ ++/* ++ * Check whether the flags of the current command, the permissions of the kdb ++ * console and the lockdown state allow a command to be run. + */ +-static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions, ++static bool kdb_check_flags(kdb_cmdflags_t flags, int permissions, + bool no_args) + { + /* permissions comes from userspace so needs massaging slightly */ +@@ -1194,6 +1247,9 @@ static int kdb_local(kdb_reason_t reason + kdb_curr_task(raw_smp_processor_id()); + + KDB_DEBUG_STATE("kdb_local 1", reason); ++ ++ kdb_check_for_lockdown(); ++ + kdb_go_count = 0; + if (reason == KDB_REASON_DEBUG) { + /* special case below */ +--- a/security/security.c ++++ b/security/security.c +@@ -59,10 +59,12 @@ const char *const lockdown_reasons[LOCKD + [LOCKDOWN_DEBUGFS] = "debugfs access", + [LOCKDOWN_XMON_WR] = "xmon write access", + [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM", ++ [LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM", + [LOCKDOWN_INTEGRITY_MAX] = "integrity", + [LOCKDOWN_KCORE] = "/proc/kcore access", + [LOCKDOWN_KPROBES] = "use of kprobes", + [LOCKDOWN_BPF_READ] = "use of bpf to read kernel RAM", ++ [LOCKDOWN_DBG_READ_KERNEL] = "use of kgdb/kdb to read kernel RAM", + [LOCKDOWN_PERF] = "unsafe use of perf", + [LOCKDOWN_TRACEFS] = "use of tracefs", + [LOCKDOWN_XMON_RW] = "xmon read and write access", diff --git a/queue-5.10/series b/queue-5.10/series new file mode 100644 index 00000000000..171495bc682 --- /dev/null +++ b/queue-5.10/series @@ -0,0 +1 @@ +lockdown-also-lock-down-previous-kgdb-use.patch