Skip to content

Commit 8c96c51

Browse files
committed
lockdown: also lock down previous kgdb use
jira VULN-3157 cve CVE-2022-21499 commit-author Daniel Thompson <daniel.thompson@linaro.org> commit eadb2f4 upstream-diff: Adapted to use older kernel_is_locked_down() APIs as the Lockdown LSM changes introduced in 5.4 where not backported to this kernel. 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 5bb07aa commit 8c96c51

2 files changed

Lines changed: 81 additions & 3 deletions

File tree

kernel/debug/debug_core.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,29 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
628628
continue;
629629
kgdb_connected = 0;
630630
} else {
631+
/*
632+
* This is a brutal way to interfere with the debugger
633+
* and prevent gdb being used to poke at kernel memory.
634+
* This could cause trouble if lockdown is applied when
635+
* there is already an active gdb session. For now the
636+
* answer is simply "don't do that". Typically lockdown
637+
* *will* be applied before the debug core gets started
638+
* so only developers using kgdb for fairly advanced
639+
* early kernel debug can be biten by this. Hopefully
640+
* they are sophisticated enough to take care of
641+
* themselves, especially with help from the lockdown
642+
* message printed on the console!
643+
*/
644+
if (kernel_is_locked_down("use of kgdb/kdb to write kernel RAM")) {
645+
if (IS_ENABLED(CONFIG_KGDB_KDB)) {
646+
/* Switch back to kdb if possible... */
647+
dbg_kdb_mode = 1;
648+
continue;
649+
} else {
650+
/* ... otherwise just bail */
651+
break;
652+
}
653+
}
631654
error = gdb_serial_stub(ks);
632655
}
633656

kernel/debug/kdb/kdb_main.c

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,62 @@ struct task_struct *kdb_curr_task(int cpu)
168168
}
169169

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

11711223
KDB_DEBUG_STATE("kdb_local 1", reason);
1224+
1225+
kdb_check_for_lockdown();
1226+
11721227
kdb_go_count = 0;
11731228
if (reason == KDB_REASON_DEBUG) {
11741229
/* special case below */

0 commit comments

Comments
 (0)