| .. | .. |
|---|
| 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); |
|---|