.. | .. |
---|
45 | 45 | #include <linux/proc_fs.h> |
---|
46 | 46 | #include <linux/uaccess.h> |
---|
47 | 47 | #include <linux/slab.h> |
---|
| 48 | +#include <linux/security.h> |
---|
48 | 49 | #include "kdb_private.h" |
---|
49 | 50 | |
---|
50 | 51 | #undef MODULE_PARAM_PREFIX |
---|
.. | .. |
---|
62 | 63 | /* |
---|
63 | 64 | * Kernel debugger state flags |
---|
64 | 65 | */ |
---|
65 | | -int kdb_flags; |
---|
| 66 | +unsigned int kdb_flags; |
---|
66 | 67 | |
---|
67 | 68 | /* |
---|
68 | 69 | * kdb_lock protects updates to kdb_initial_cpu. Used to |
---|
.. | .. |
---|
73 | 74 | int kdb_state; /* General KDB state */ |
---|
74 | 75 | |
---|
75 | 76 | struct task_struct *kdb_current_task; |
---|
76 | | -EXPORT_SYMBOL(kdb_current_task); |
---|
77 | 77 | struct pt_regs *kdb_current_regs; |
---|
78 | 78 | |
---|
79 | 79 | const char *kdb_diemsg; |
---|
.. | .. |
---|
198 | 198 | } |
---|
199 | 199 | |
---|
200 | 200 | /* |
---|
201 | | - * Check whether the flags of the current command and the permissions |
---|
202 | | - * 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. |
---|
203 | 220 | */ |
---|
204 | | -static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions, |
---|
| 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 = |
---|
| 234 | + security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL); |
---|
| 235 | + |
---|
| 236 | + if (kdb_cmd_enabled & (KDB_ENABLE_ALL | read_flags)) |
---|
| 237 | + need_to_lockdown_read = |
---|
| 238 | + security_locked_down(LOCKDOWN_DBG_READ_KERNEL); |
---|
| 239 | + |
---|
| 240 | + /* De-compose KDB_ENABLE_ALL if required */ |
---|
| 241 | + if (need_to_lockdown_write || need_to_lockdown_read) |
---|
| 242 | + if (kdb_cmd_enabled & KDB_ENABLE_ALL) |
---|
| 243 | + kdb_cmd_enabled = KDB_ENABLE_MASK & ~KDB_ENABLE_ALL; |
---|
| 244 | + |
---|
| 245 | + if (need_to_lockdown_write) |
---|
| 246 | + kdb_cmd_enabled &= ~write_flags; |
---|
| 247 | + |
---|
| 248 | + if (need_to_lockdown_read) |
---|
| 249 | + kdb_cmd_enabled &= ~read_flags; |
---|
| 250 | +} |
---|
| 251 | + |
---|
| 252 | +/* |
---|
| 253 | + * Check whether the flags of the current command, the permissions of the kdb |
---|
| 254 | + * console and the lockdown state allow a command to be run. |
---|
| 255 | + */ |
---|
| 256 | +static bool kdb_check_flags(kdb_cmdflags_t flags, int permissions, |
---|
205 | 257 | bool no_args) |
---|
206 | 258 | { |
---|
207 | 259 | /* permissions comes from userspace so needs massaging slightly */ |
---|
.. | .. |
---|
400 | 452 | return KDB_ARGCOUNT; |
---|
401 | 453 | |
---|
402 | 454 | /* |
---|
| 455 | + * Censor sensitive variables |
---|
| 456 | + */ |
---|
| 457 | + if (strcmp(argv[1], "PROMPT") == 0 && |
---|
| 458 | + !kdb_check_flags(KDB_ENABLE_MEM_READ, kdb_cmd_enabled, false)) |
---|
| 459 | + return KDB_NOPERM; |
---|
| 460 | + |
---|
| 461 | + /* |
---|
403 | 462 | * Check for internal variables |
---|
404 | 463 | */ |
---|
405 | 464 | if (strcmp(argv[1], "KDBDEBUG") == 0) { |
---|
.. | .. |
---|
412 | 471 | argv[2]); |
---|
413 | 472 | return 0; |
---|
414 | 473 | } |
---|
415 | | - kdb_flags = (kdb_flags & |
---|
416 | | - ~(KDB_DEBUG_FLAG_MASK << KDB_DEBUG_FLAG_SHIFT)) |
---|
| 474 | + kdb_flags = (kdb_flags & ~KDB_DEBUG(MASK)) |
---|
417 | 475 | | (debugflags << KDB_DEBUG_FLAG_SHIFT); |
---|
418 | 476 | |
---|
419 | 477 | return 0; |
---|
.. | .. |
---|
658 | 716 | */ |
---|
659 | 717 | struct defcmd_set { |
---|
660 | 718 | int count; |
---|
661 | | - int usable; |
---|
| 719 | + bool usable; |
---|
662 | 720 | char *name; |
---|
663 | 721 | char *usage; |
---|
664 | 722 | char *help; |
---|
.. | .. |
---|
666 | 724 | }; |
---|
667 | 725 | static struct defcmd_set *defcmd_set; |
---|
668 | 726 | static int defcmd_set_count; |
---|
669 | | -static int defcmd_in_progress; |
---|
| 727 | +static bool defcmd_in_progress; |
---|
670 | 728 | |
---|
671 | 729 | /* Forward references */ |
---|
672 | 730 | static int kdb_exec_defcmd(int argc, const char **argv); |
---|
.. | .. |
---|
676 | 734 | struct defcmd_set *s = defcmd_set + defcmd_set_count - 1; |
---|
677 | 735 | char **save_command = s->command; |
---|
678 | 736 | if (strcmp(argv0, "endefcmd") == 0) { |
---|
679 | | - defcmd_in_progress = 0; |
---|
| 737 | + defcmd_in_progress = false; |
---|
680 | 738 | if (!s->count) |
---|
681 | | - s->usable = 0; |
---|
| 739 | + s->usable = false; |
---|
682 | 740 | if (s->usable) |
---|
683 | 741 | /* macros are always safe because when executed each |
---|
684 | 742 | * internal command re-enters kdb_parse() and is |
---|
.. | .. |
---|
695 | 753 | if (!s->command) { |
---|
696 | 754 | kdb_printf("Could not allocate new kdb_defcmd table for %s\n", |
---|
697 | 755 | cmdstr); |
---|
698 | | - s->usable = 0; |
---|
| 756 | + s->usable = false; |
---|
699 | 757 | return KDB_NOTIMP; |
---|
700 | 758 | } |
---|
701 | 759 | memcpy(s->command, save_command, s->count * sizeof(*(s->command))); |
---|
.. | .. |
---|
737 | 795 | defcmd_set_count * sizeof(*defcmd_set)); |
---|
738 | 796 | s = defcmd_set + defcmd_set_count; |
---|
739 | 797 | memset(s, 0, sizeof(*s)); |
---|
740 | | - s->usable = 1; |
---|
| 798 | + s->usable = true; |
---|
741 | 799 | s->name = kdb_strdup(argv[1], GFP_KDB); |
---|
742 | 800 | if (!s->name) |
---|
743 | 801 | goto fail_name; |
---|
.. | .. |
---|
756 | 814 | s->help[strlen(s->help)-1] = '\0'; |
---|
757 | 815 | } |
---|
758 | 816 | ++defcmd_set_count; |
---|
759 | | - defcmd_in_progress = 1; |
---|
| 817 | + defcmd_in_progress = true; |
---|
760 | 818 | kfree(save_defcmd_set); |
---|
761 | 819 | return 0; |
---|
762 | 820 | fail_help: |
---|
.. | .. |
---|
830 | 888 | cp++; |
---|
831 | 889 | while (isspace(*cp)) |
---|
832 | 890 | cp++; |
---|
833 | | - if (strncmp(cp, "grep ", 5)) { |
---|
| 891 | + if (!str_has_prefix(cp, "grep ")) { |
---|
834 | 892 | kdb_printf("invalid 'pipe', see grephelp\n"); |
---|
835 | 893 | return; |
---|
836 | 894 | } |
---|
.. | .. |
---|
1102 | 1160 | switch (*cmd) { |
---|
1103 | 1161 | case CTRL_P: |
---|
1104 | 1162 | if (cmdptr != cmd_tail) |
---|
1105 | | - cmdptr = (cmdptr-1) % KDB_CMD_HISTORY_COUNT; |
---|
1106 | | - strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN); |
---|
| 1163 | + cmdptr = (cmdptr + KDB_CMD_HISTORY_COUNT - 1) % |
---|
| 1164 | + KDB_CMD_HISTORY_COUNT; |
---|
| 1165 | + strscpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN); |
---|
1107 | 1166 | return 1; |
---|
1108 | 1167 | case CTRL_N: |
---|
1109 | 1168 | if (cmdptr != cmd_head) |
---|
1110 | 1169 | cmdptr = (cmdptr+1) % KDB_CMD_HISTORY_COUNT; |
---|
1111 | | - strncpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN); |
---|
| 1170 | + strscpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN); |
---|
1112 | 1171 | return 1; |
---|
1113 | 1172 | } |
---|
1114 | 1173 | return 0; |
---|
.. | .. |
---|
1139 | 1198 | console_loglevel = old_lvl; |
---|
1140 | 1199 | } |
---|
1141 | 1200 | |
---|
1142 | | -void kdb_set_current_task(struct task_struct *p) |
---|
| 1201 | +static void kdb_set_current_task(struct task_struct *p) |
---|
1143 | 1202 | { |
---|
1144 | 1203 | kdb_current_task = p; |
---|
1145 | 1204 | |
---|
.. | .. |
---|
1188 | 1247 | kdb_curr_task(raw_smp_processor_id()); |
---|
1189 | 1248 | |
---|
1190 | 1249 | KDB_DEBUG_STATE("kdb_local 1", reason); |
---|
| 1250 | + |
---|
| 1251 | + kdb_check_for_lockdown(); |
---|
| 1252 | + |
---|
1191 | 1253 | kdb_go_count = 0; |
---|
1192 | 1254 | if (reason == KDB_REASON_DEBUG) { |
---|
1193 | 1255 | /* special case below */ |
---|
.. | .. |
---|
1299 | 1361 | *(cmd_hist[cmd_head]) = '\0'; |
---|
1300 | 1362 | |
---|
1301 | 1363 | do_full_getstr: |
---|
1302 | | -#if defined(CONFIG_SMP) |
---|
| 1364 | + /* PROMPT can only be set if we have MEM_READ permission. */ |
---|
1303 | 1365 | snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), |
---|
1304 | 1366 | raw_smp_processor_id()); |
---|
1305 | | -#else |
---|
1306 | | - snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT")); |
---|
1307 | | -#endif |
---|
1308 | 1367 | if (defcmd_in_progress) |
---|
1309 | 1368 | strncat(kdb_prompt_str, "[defcmd]", CMD_BUFLEN); |
---|
1310 | 1369 | |
---|
.. | .. |
---|
1315 | 1374 | if (*cmdbuf != '\n') { |
---|
1316 | 1375 | if (*cmdbuf < 32) { |
---|
1317 | 1376 | if (cmdptr == cmd_head) { |
---|
1318 | | - strncpy(cmd_hist[cmd_head], cmd_cur, |
---|
| 1377 | + strscpy(cmd_hist[cmd_head], cmd_cur, |
---|
1319 | 1378 | CMD_BUFLEN); |
---|
1320 | 1379 | *(cmd_hist[cmd_head] + |
---|
1321 | 1380 | strlen(cmd_hist[cmd_head])-1) = '\0'; |
---|
.. | .. |
---|
1325 | 1384 | cmdbuf = cmd_cur; |
---|
1326 | 1385 | goto do_full_getstr; |
---|
1327 | 1386 | } else { |
---|
1328 | | - strncpy(cmd_hist[cmd_head], cmd_cur, |
---|
| 1387 | + strscpy(cmd_hist[cmd_head], cmd_cur, |
---|
1329 | 1388 | CMD_BUFLEN); |
---|
1330 | 1389 | } |
---|
1331 | 1390 | |
---|
.. | .. |
---|
1493 | 1552 | char cbuf[32]; |
---|
1494 | 1553 | char *c = cbuf; |
---|
1495 | 1554 | int i; |
---|
| 1555 | + int j; |
---|
1496 | 1556 | unsigned long word; |
---|
1497 | 1557 | |
---|
1498 | 1558 | memset(cbuf, '\0', sizeof(cbuf)); |
---|
.. | .. |
---|
1538 | 1598 | wc.word = word; |
---|
1539 | 1599 | #define printable_char(c) \ |
---|
1540 | 1600 | ({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.'; }) |
---|
1541 | | - switch (bytesperword) { |
---|
1542 | | - case 8: |
---|
| 1601 | + for (j = 0; j < bytesperword; j++) |
---|
1543 | 1602 | *c++ = printable_char(*cp++); |
---|
1544 | | - *c++ = printable_char(*cp++); |
---|
1545 | | - *c++ = printable_char(*cp++); |
---|
1546 | | - *c++ = printable_char(*cp++); |
---|
1547 | | - addr += 4; |
---|
1548 | | - case 4: |
---|
1549 | | - *c++ = printable_char(*cp++); |
---|
1550 | | - *c++ = printable_char(*cp++); |
---|
1551 | | - addr += 2; |
---|
1552 | | - case 2: |
---|
1553 | | - *c++ = printable_char(*cp++); |
---|
1554 | | - addr++; |
---|
1555 | | - case 1: |
---|
1556 | | - *c++ = printable_char(*cp++); |
---|
1557 | | - addr++; |
---|
1558 | | - break; |
---|
1559 | | - } |
---|
| 1603 | + addr += bytesperword; |
---|
1560 | 1604 | #undef printable_char |
---|
1561 | 1605 | } |
---|
1562 | 1606 | } |
---|
.. | .. |
---|
2093 | 2137 | } |
---|
2094 | 2138 | |
---|
2095 | 2139 | if (KDB_DEBUG(MASK)) |
---|
2096 | | - kdb_printf("KDBFLAGS=0x%x\n", kdb_flags); |
---|
| 2140 | + kdb_printf("KDBDEBUG=0x%x\n", |
---|
| 2141 | + (kdb_flags & KDB_DEBUG(MASK)) >> KDB_DEBUG_FLAG_SHIFT); |
---|
2097 | 2142 | |
---|
2098 | 2143 | return 0; |
---|
2099 | 2144 | } |
---|
.. | .. |
---|
2310 | 2355 | if (kdb_task_state(p, mask_I)) |
---|
2311 | 2356 | ++idle; |
---|
2312 | 2357 | } |
---|
2313 | | - kdb_do_each_thread(g, p) { |
---|
| 2358 | + for_each_process_thread(g, p) { |
---|
2314 | 2359 | if (kdb_task_state(p, mask_M)) |
---|
2315 | 2360 | ++daemon; |
---|
2316 | | - } kdb_while_each_thread(g, p); |
---|
| 2361 | + } |
---|
2317 | 2362 | if (idle || daemon) { |
---|
2318 | 2363 | if (idle) |
---|
2319 | 2364 | kdb_printf("%d idle process%s (state I)%s\n", |
---|
.. | .. |
---|
2337 | 2382 | int cpu; |
---|
2338 | 2383 | unsigned long tmp; |
---|
2339 | 2384 | |
---|
2340 | | - if (!p || probe_kernel_read(&tmp, (char *)p, sizeof(unsigned long))) |
---|
| 2385 | + if (!p || |
---|
| 2386 | + copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long))) |
---|
2341 | 2387 | return; |
---|
2342 | 2388 | |
---|
2343 | 2389 | cpu = kdb_process_cpu(p); |
---|
.. | .. |
---|
2380 | 2426 | } |
---|
2381 | 2427 | kdb_printf("\n"); |
---|
2382 | 2428 | /* Now the real tasks */ |
---|
2383 | | - kdb_do_each_thread(g, p) { |
---|
| 2429 | + for_each_process_thread(g, p) { |
---|
2384 | 2430 | if (KDB_FLAG(CMD_INTERRUPT)) |
---|
2385 | 2431 | return 0; |
---|
2386 | 2432 | if (kdb_task_state(p, mask)) |
---|
2387 | 2433 | kdb_ps1(p); |
---|
2388 | | - } kdb_while_each_thread(g, p); |
---|
| 2434 | + } |
---|
2389 | 2435 | |
---|
2390 | 2436 | return 0; |
---|
2391 | 2437 | } |
---|
.. | .. |
---|
2537 | 2583 | kdb_printf("machine %s\n", init_uts_ns.name.machine); |
---|
2538 | 2584 | kdb_printf("nodename %s\n", init_uts_ns.name.nodename); |
---|
2539 | 2585 | kdb_printf("domainname %s\n", init_uts_ns.name.domainname); |
---|
2540 | | - kdb_printf("ccversion %s\n", __stringify(CCVERSION)); |
---|
2541 | 2586 | |
---|
2542 | 2587 | now = __ktime_get_real_seconds(); |
---|
2543 | 2588 | time64_to_tm(now, 0, &tm); |
---|