Skip to content

Commit eadb2f4

Browse files
Daniel Thompsontorvalds
authored andcommitted
lockdown: also lock down previous kgdb use
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>
1 parent 6f3f04c commit eadb2f4

File tree

4 files changed

+87
-3
lines changed

4 files changed

+87
-3
lines changed

include/linux/security.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@ enum lockdown_reason {
121121
LOCKDOWN_DEBUGFS,
122122
LOCKDOWN_XMON_WR,
123123
LOCKDOWN_BPF_WRITE_USER,
124+
LOCKDOWN_DBG_WRITE_KERNEL,
124125
LOCKDOWN_INTEGRITY_MAX,
125126
LOCKDOWN_KCORE,
126127
LOCKDOWN_KPROBES,
127128
LOCKDOWN_BPF_READ_KERNEL,
129+
LOCKDOWN_DBG_READ_KERNEL,
128130
LOCKDOWN_PERF,
129131
LOCKDOWN_TRACEFS,
130132
LOCKDOWN_XMON_RW,

kernel/debug/debug_core.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <linux/vmacache.h>
5454
#include <linux/rcupdate.h>
5555
#include <linux/irq.h>
56+
#include <linux/security.h>
5657

5758
#include <asm/cacheflush.h>
5859
#include <asm/byteorder.h>
@@ -752,6 +753,29 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
752753
continue;
753754
kgdb_connected = 0;
754755
} else {
756+
/*
757+
* This is a brutal way to interfere with the debugger
758+
* and prevent gdb being used to poke at kernel memory.
759+
* This could cause trouble if lockdown is applied when
760+
* there is already an active gdb session. For now the
761+
* answer is simply "don't do that". Typically lockdown
762+
* *will* be applied before the debug core gets started
763+
* so only developers using kgdb for fairly advanced
764+
* early kernel debug can be biten by this. Hopefully
765+
* they are sophisticated enough to take care of
766+
* themselves, especially with help from the lockdown
767+
* message printed on the console!
768+
*/
769+
if (security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL)) {
770+
if (IS_ENABLED(CONFIG_KGDB_KDB)) {
771+
/* Switch back to kdb if possible... */
772+
dbg_kdb_mode = 1;
773+
continue;
774+
} else {
775+
/* ... otherwise just bail */
776+
break;
777+
}
778+
}
755779
error = gdb_serial_stub(ks);
756780
}
757781

kernel/debug/kdb/kdb_main.c

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <linux/proc_fs.h>
4646
#include <linux/uaccess.h>
4747
#include <linux/slab.h>
48+
#include <linux/security.h>
4849
#include "kdb_private.h"
4950

5051
#undef MODULE_PARAM_PREFIX
@@ -166,10 +167,62 @@ struct task_struct *kdb_curr_task(int cpu)
166167
}
167168

168169
/*
169-
* Check whether the flags of the current command and the permissions
170-
* of the kdb console has allow a command to be run.
170+
* Update the permissions flags (kdb_cmd_enabled) to match the
171+
* current lockdown state.
172+
*
173+
* Within this function the calls to security_locked_down() are "lazy". We
174+
* avoid calling them if the current value of kdb_cmd_enabled already excludes
175+
* flags that might be subject to lockdown. Additionally we deliberately check
176+
* the lockdown flags independently (even though read lockdown implies write
177+
* lockdown) since that results in both simpler code and clearer messages to
178+
* the user on first-time debugger entry.
179+
*
180+
* The permission masks during a read+write lockdown permits the following
181+
* flags: INSPECT, SIGNAL, REBOOT (and ALWAYS_SAFE).
182+
*
183+
* The INSPECT commands are not blocked during lockdown because they are
184+
* not arbitrary memory reads. INSPECT covers the backtrace family (sometimes
185+
* forcing them to have no arguments) and lsmod. These commands do expose
186+
* some kernel state but do not allow the developer seated at the console to
187+
* choose what state is reported. SIGNAL and REBOOT should not be controversial,
188+
* given these are allowed for root during lockdown already.
189+
*/
190+
static void kdb_check_for_lockdown(void)
191+
{
192+
const int write_flags = KDB_ENABLE_MEM_WRITE |
193+
KDB_ENABLE_REG_WRITE |
194+
KDB_ENABLE_FLOW_CTRL;
195+
const int read_flags = KDB_ENABLE_MEM_READ |
196+
KDB_ENABLE_REG_READ;
197+
198+
bool need_to_lockdown_write = false;
199+
bool need_to_lockdown_read = false;
200+
201+
if (kdb_cmd_enabled & (KDB_ENABLE_ALL | write_flags))
202+
need_to_lockdown_write =
203+
security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL);
204+
205+
if (kdb_cmd_enabled & (KDB_ENABLE_ALL | read_flags))
206+
need_to_lockdown_read =
207+
security_locked_down(LOCKDOWN_DBG_READ_KERNEL);
208+
209+
/* De-compose KDB_ENABLE_ALL if required */
210+
if (need_to_lockdown_write || need_to_lockdown_read)
211+
if (kdb_cmd_enabled & KDB_ENABLE_ALL)
212+
kdb_cmd_enabled = KDB_ENABLE_MASK & ~KDB_ENABLE_ALL;
213+
214+
if (need_to_lockdown_write)
215+
kdb_cmd_enabled &= ~write_flags;
216+
217+
if (need_to_lockdown_read)
218+
kdb_cmd_enabled &= ~read_flags;
219+
}
220+
221+
/*
222+
* Check whether the flags of the current command, the permissions of the kdb
223+
* console and the lockdown state allow a command to be run.
171224
*/
172-
static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
225+
static bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
173226
bool no_args)
174227
{
175228
/* permissions comes from userspace so needs massaging slightly */
@@ -1180,6 +1233,9 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
11801233
kdb_curr_task(raw_smp_processor_id());
11811234

11821235
KDB_DEBUG_STATE("kdb_local 1", reason);
1236+
1237+
kdb_check_for_lockdown();
1238+
11831239
kdb_go_count = 0;
11841240
if (reason == KDB_REASON_DEBUG) {
11851241
/* special case below */

security/security.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
5959
[LOCKDOWN_DEBUGFS] = "debugfs access",
6060
[LOCKDOWN_XMON_WR] = "xmon write access",
6161
[LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
62+
[LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",
6263
[LOCKDOWN_INTEGRITY_MAX] = "integrity",
6364
[LOCKDOWN_KCORE] = "/proc/kcore access",
6465
[LOCKDOWN_KPROBES] = "use of kprobes",
6566
[LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
67+
[LOCKDOWN_DBG_READ_KERNEL] = "use of kgdb/kdb to read kernel RAM",
6668
[LOCKDOWN_PERF] = "unsafe use of perf",
6769
[LOCKDOWN_TRACEFS] = "use of tracefs",
6870
[LOCKDOWN_XMON_RW] = "xmon read and write access",

0 commit comments

Comments
 (0)