Skip to content

Commit cde04a3

Browse files
committed
kdb: Add enable mask for groups of commands
jira VULN-1501 cve-pre CVE-2022-21499 commit-author Anton Vorontsov <anton.vorontsov@linaro.org> commit 420c2b1 Currently all kdb commands are enabled whenever kdb is deployed. This makes it difficult to deploy kdb to help debug certain types of systems. Android phones provide one example; the FIQ debugger found on some Android devices has a deliberately weak set of commands to allow the debugger to enabled very late in the production cycle. Certain kiosk environments offer another interesting case where an engineer might wish to probe the system state using passive inspection commands without providing sufficient power for a passer by to root it. Without any restrictions, obtaining the root rights via KDB is a matter of a few commands, and works everywhere. For example, log in as a normal user: cbou:~$ id uid=1001(cbou) gid=1001(cbou) groups=1001(cbou) Now enter KDB (for example via sysrq): Entering kdb (current=0xffff8800065bc740, pid 920) due to Keyboard Entry kdb> ps 23 sleeping system daemon (state M) processes suppressed, use 'ps A' to see all. Task Addr Pid Parent [*] cpu State Thread Command 0xffff8800065bc740 920 919 1 0 R 0xffff8800065bca20 *bash 0xffff880007078000 1 0 0 0 S 0xffff8800070782e0 init [...snip...] 0xffff8800065be3c0 918 1 0 0 S 0xffff8800065be6a0 getty 0xffff8800065b9c80 919 1 0 0 S 0xffff8800065b9f60 login 0xffff8800065bc740 920 919 1 0 R 0xffff8800065bca20 *bash All we need is the offset of cred pointers. We can look up the offset in the distro's kernel source, but it is unnecessary. We can just start dumping init's task_struct, until we see the process name: kdb> md 0xffff880007078000 0xffff880007078000 0000000000000001 ffff88000703c000 ................ 0xffff880007078010 0040210000000002 0000000000000000 .....!@......... [...snip...] 0xffff8800070782b0 ffff8800073e0580 ffff8800073e0580 ..>.......>..... 0xffff8800070782c0 0000000074696e69 0000000000000000 init............ ^ Here, 'init'. Creds are just above it, so the offset is 0x02b0. Now we set up init's creds for our non-privileged shell: kdb> mm 0xffff8800065bc740+0x02b0 0xffff8800073e0580 0xffff8800065bc9f0 = 0xffff8800073e0580 kdb> mm 0xffff8800065bc740+0x02b8 0xffff8800073e0580 0xffff8800065bc9f8 = 0xffff8800073e0580 And thus gaining the root: kdb> go cbou:~$ id uid=0(root) gid=0(root) groups=0(root) cbou:~$ bash root:~# p.s. No distro enables kdb by default (although, with a nice KDB-over-KMS feature availability, I would expect at least some would enable it), so it's not actually some kind of a major issue. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Jason Wessel <jason.wessel@windriver.com> Signed-off-by: Jason Wessel <jason.wessel@windriver.com> (cherry picked from commit 420c2b1) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 3e82e39 commit cde04a3

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

include/linux/kdb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ extern atomic_t kdb_event;
105105
#define KDB_BADLENGTH (-19)
106106
#define KDB_NOBP (-20)
107107
#define KDB_BADADDR (-21)
108+
#define KDB_NOPERM (-22)
108109

109110
/*
110111
* kdb_diemsg

kernel/debug/kdb/kdb_main.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
#include <linux/ctype.h>
15+
#include <linux/types.h>
1516
#include <linux/string.h>
1617
#include <linux/kernel.h>
1718
#include <linux/kmsg_dump.h>
@@ -23,6 +24,7 @@
2324
#include <linux/vmalloc.h>
2425
#include <linux/atomic.h>
2526
#include <linux/module.h>
27+
#include <linux/moduleparam.h>
2628
#include <linux/mm.h>
2729
#include <linux/init.h>
2830
#include <linux/kallsyms.h>
@@ -42,6 +44,12 @@
4244
#include <linux/slab.h>
4345
#include "kdb_private.h"
4446

47+
#undef MODULE_PARAM_PREFIX
48+
#define MODULE_PARAM_PREFIX "kdb."
49+
50+
static int kdb_cmd_enabled;
51+
module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
52+
4553
#define GREP_LEN 256
4654
char kdb_grep_string[GREP_LEN];
4755
int kdb_grepping_flag;
@@ -121,6 +129,7 @@ static kdbmsg_t kdbmsgs[] = {
121129
KDBMSG(BADLENGTH, "Invalid length field"),
122130
KDBMSG(NOBP, "No Breakpoint exists"),
123131
KDBMSG(BADADDR, "Invalid address"),
132+
KDBMSG(NOPERM, "Permission denied"),
124133
};
125134
#undef KDBMSG
126135

@@ -495,6 +504,15 @@ int kdbgetaddrarg(int argc, const char **argv, int *nextarg,
495504
char *cp;
496505
kdb_symtab_t symtab;
497506

507+
/*
508+
* If the enable flags prohibit both arbitrary memory access
509+
* and flow control then there are no reasonable grounds to
510+
* provide symbol lookup.
511+
*/
512+
if (!kdb_check_flags(KDB_ENABLE_MEM_READ | KDB_ENABLE_FLOW_CTRL,
513+
kdb_cmd_enabled, false))
514+
return KDB_NOPERM;
515+
498516
/*
499517
* Process arguments which follow the following syntax:
500518
*
@@ -1028,6 +1046,10 @@ int kdb_parse(const char *cmdstr)
10281046

10291047
if (i < kdb_max_commands) {
10301048
int result;
1049+
1050+
if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
1051+
return KDB_NOPERM;
1052+
10311053
KDB_STATE_SET(CMD);
10321054
result = (*tp->cmd_func)(argc-1, (const char **)argv);
10331055
if (result && ignore_errors && result > KDB_CMD_GO)
@@ -1939,10 +1961,14 @@ static int kdb_rm(int argc, const char **argv)
19391961
*/
19401962
static int kdb_sr(int argc, const char **argv)
19411963
{
1964+
bool check_mask =
1965+
!kdb_check_flags(KDB_ENABLE_ALL, kdb_cmd_enabled, false);
1966+
19421967
if (argc != 1)
19431968
return KDB_ARGCOUNT;
1969+
19441970
kdb_trap_printk++;
1945-
__handle_sysrq(*argv[1], false);
1971+
__handle_sysrq(*argv[1], check_mask);
19461972
kdb_trap_printk--;
19471973

19481974
return 0;
@@ -2393,6 +2419,8 @@ static int kdb_help(int argc, const char **argv)
23932419
return 0;
23942420
if (!kt->cmd_name)
23952421
continue;
2422+
if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
2423+
continue;
23962424
if (strlen(kt->cmd_usage) > 20)
23972425
space = "\n ";
23982426
kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,

0 commit comments

Comments
 (0)