Skip to content

Commit b9c9e8c

Browse files
committed
lockdown: also lock down previous kgdb use
jira VULN-1501 cve CVE-2022-21499 commit-author Daniel Thompson <daniel.thompson@linaro.org> commit eadb2f4 upstream-diff: Adapted to use older get_securelevel() APIs 3.10 kernel uses the RHEL 7 securelevel mechanism rather than the Lockdown LSM introduced in 5.4 or the kernel_is_locked_down() bridge used on 4.18.0. 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 <stephen.s.brennan@oracle.com> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> (cherry picked from commit eadb2f4) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 6d8c162 commit b9c9e8c

2 files changed

Lines changed: 81 additions & 3 deletions

File tree

kernel/debug/debug_core.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <linux/smp.h>
5151
#include <linux/mm.h>
5252
#include <linux/rcupdate.h>
53+
#include <linux/security.h>
5354

5455
#include <asm/cacheflush.h>
5556
#include <asm/byteorder.h>
@@ -612,6 +613,29 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
612613
continue;
613614
kgdb_connected = 0;
614615
} else {
616+
/*
617+
* This is a brutal way to interfere with the debugger
618+
* and prevent gdb being used to poke at kernel memory.
619+
* This could cause trouble if lockdown is applied when
620+
* there is already an active gdb session. For now the
621+
* answer is simply "don't do that". Typically lockdown
622+
* *will* be applied before the debug core gets started
623+
* so only developers using kgdb for fairly advanced
624+
* early kernel debug can be biten by this. Hopefully
625+
* they are sophisticated enough to take care of
626+
* themselves, especially with help from the lockdown
627+
* message printed on the console!
628+
*/
629+
if (get_securelevel() > 0) {
630+
if (IS_ENABLED(CONFIG_KGDB_KDB)) {
631+
/* Switch back to kdb if possible... */
632+
dbg_kdb_mode = 1;
633+
continue;
634+
} else {
635+
/* ... otherwise just bail */
636+
break;
637+
}
638+
}
615639
error = gdb_serial_stub(ks);
616640
}
617641

kernel/debug/kdb/kdb_main.c

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <linux/proc_fs.h>
4343
#include <linux/uaccess.h>
4444
#include <linux/slab.h>
45+
#include <linux/security.h>
4546
#include "kdb_private.h"
4647

4748
#undef MODULE_PARAM_PREFIX
@@ -197,10 +198,60 @@ struct task_struct *kdb_curr_task(int cpu)
197198
}
198199

199200
/*
200-
* Check whether the flags of the current command and the permissions
201-
* of the kdb console has allow a command to be run.
201+
* Update the permissions flags (kdb_cmd_enabled) to match the
202+
* current lockdown state.
203+
*
204+
* Within this function the calls to security_locked_down() are "lazy". We
205+
* avoid calling them if the current value of kdb_cmd_enabled already excludes
206+
* flags that might be subject to lockdown. Additionally we deliberately check
207+
* the lockdown flags independently (even though read lockdown implies write
208+
* lockdown) since that results in both simpler code and clearer messages to
209+
* the user on first-time debugger entry.
210+
*
211+
* The permission masks during a read+write lockdown permits the following
212+
* flags: INSPECT, SIGNAL, REBOOT (and ALWAYS_SAFE).
213+
*
214+
* The INSPECT commands are not blocked during lockdown because they are
215+
* not arbitrary memory reads. INSPECT covers the backtrace family (sometimes
216+
* forcing them to have no arguments) and lsmod. These commands do expose
217+
* some kernel state but do not allow the developer seated at the console to
218+
* choose what state is reported. SIGNAL and REBOOT should not be controversial,
219+
* given these are allowed for root during lockdown already.
220+
*/
221+
static void kdb_check_for_lockdown(void)
222+
{
223+
const int write_flags = KDB_ENABLE_MEM_WRITE |
224+
KDB_ENABLE_REG_WRITE |
225+
KDB_ENABLE_FLOW_CTRL;
226+
const int read_flags = KDB_ENABLE_MEM_READ |
227+
KDB_ENABLE_REG_READ;
228+
229+
bool need_to_lockdown_write = false;
230+
bool need_to_lockdown_read = false;
231+
232+
if (kdb_cmd_enabled & (KDB_ENABLE_ALL | write_flags))
233+
need_to_lockdown_write = get_securelevel() > 0;
234+
235+
if (kdb_cmd_enabled & (KDB_ENABLE_ALL | read_flags))
236+
need_to_lockdown_read = get_securelevel() > 0;
237+
238+
/* De-compose KDB_ENABLE_ALL if required */
239+
if (need_to_lockdown_write || need_to_lockdown_read)
240+
if (kdb_cmd_enabled & KDB_ENABLE_ALL)
241+
kdb_cmd_enabled = KDB_ENABLE_MASK & ~KDB_ENABLE_ALL;
242+
243+
if (need_to_lockdown_write)
244+
kdb_cmd_enabled &= ~write_flags;
245+
246+
if (need_to_lockdown_read)
247+
kdb_cmd_enabled &= ~read_flags;
248+
}
249+
250+
/*
251+
* Check whether the flags of the current command, the permissions of the kdb
252+
* console and the lockdown state allow a command to be run.
202253
*/
203-
static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
254+
static bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
204255
bool no_args)
205256
{
206257
/* permissions comes from userspace so needs massaging slightly */
@@ -1178,6 +1229,9 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
11781229
kdb_curr_task(raw_smp_processor_id());
11791230

11801231
KDB_DEBUG_STATE("kdb_local 1", reason);
1232+
1233+
kdb_check_for_lockdown();
1234+
11811235
kdb_go_count = 0;
11821236
if (reason == KDB_REASON_DEBUG) {
11831237
/* special case below */

0 commit comments

Comments
 (0)