Commit aa9291355e19f804570466756ed7d874cd2e99ff
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'for_linus-3.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb
Pull kgdb/kdb fixes from Jason Wessel: "These have been around since 3.17 and in kgdb-next for the last 9 weeks and some will go back to -stable. Summary of changes: Cleanups - kdb: Remove unused command flags, repeat flags and KDB_REPEAT_NONE Fixes - kgdb/kdb: Allow access on a single core, if a CPU round up is deemed impossible, which will allow inspection of the now "trashed" kernel - kdb: Add enable mask for the command groups - kdb: access controls to restrict sensitive commands" * tag 'for_linus-3.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb: kernel/debug/debug_core.c: Logging clean-up kgdb: timeout if secondary CPUs ignore the roundup kdb: Allow access to sensitive commands to be restricted by default kdb: Add enable mask for groups of commands kdb: Categorize kdb commands (similar to SysRq categorization) kdb: Remove KDB_REPEAT_NONE flag kdb: Use KDB_REPEAT_* values as flags kdb: Rename kdb_register_repeat() to kdb_register_flags() kdb: Rename kdb_repeat_t to kdb_cmdflags_t, cmd_repeat to cmd_flags kdb: Remove currently unused kdbtab_t->cmd_flags
Showing 8 changed files Side-by-side Diff
include/linux/kdb.h
... | ... | @@ -13,12 +13,55 @@ |
13 | 13 | * Copyright (C) 2009 Jason Wessel <jason.wessel@windriver.com> |
14 | 14 | */ |
15 | 15 | |
16 | +/* Shifted versions of the command enable bits are be used if the command | |
17 | + * has no arguments (see kdb_check_flags). This allows commands, such as | |
18 | + * go, to have different permissions depending upon whether it is called | |
19 | + * with an argument. | |
20 | + */ | |
21 | +#define KDB_ENABLE_NO_ARGS_SHIFT 10 | |
22 | + | |
16 | 23 | typedef enum { |
17 | - KDB_REPEAT_NONE = 0, /* Do not repeat this command */ | |
18 | - KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */ | |
19 | - KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */ | |
20 | -} kdb_repeat_t; | |
24 | + KDB_ENABLE_ALL = (1 << 0), /* Enable everything */ | |
25 | + KDB_ENABLE_MEM_READ = (1 << 1), | |
26 | + KDB_ENABLE_MEM_WRITE = (1 << 2), | |
27 | + KDB_ENABLE_REG_READ = (1 << 3), | |
28 | + KDB_ENABLE_REG_WRITE = (1 << 4), | |
29 | + KDB_ENABLE_INSPECT = (1 << 5), | |
30 | + KDB_ENABLE_FLOW_CTRL = (1 << 6), | |
31 | + KDB_ENABLE_SIGNAL = (1 << 7), | |
32 | + KDB_ENABLE_REBOOT = (1 << 8), | |
33 | + /* User exposed values stop here, all remaining flags are | |
34 | + * exclusively used to describe a commands behaviour. | |
35 | + */ | |
21 | 36 | |
37 | + KDB_ENABLE_ALWAYS_SAFE = (1 << 9), | |
38 | + KDB_ENABLE_MASK = (1 << KDB_ENABLE_NO_ARGS_SHIFT) - 1, | |
39 | + | |
40 | + KDB_ENABLE_ALL_NO_ARGS = KDB_ENABLE_ALL << KDB_ENABLE_NO_ARGS_SHIFT, | |
41 | + KDB_ENABLE_MEM_READ_NO_ARGS = KDB_ENABLE_MEM_READ | |
42 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
43 | + KDB_ENABLE_MEM_WRITE_NO_ARGS = KDB_ENABLE_MEM_WRITE | |
44 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
45 | + KDB_ENABLE_REG_READ_NO_ARGS = KDB_ENABLE_REG_READ | |
46 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
47 | + KDB_ENABLE_REG_WRITE_NO_ARGS = KDB_ENABLE_REG_WRITE | |
48 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
49 | + KDB_ENABLE_INSPECT_NO_ARGS = KDB_ENABLE_INSPECT | |
50 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
51 | + KDB_ENABLE_FLOW_CTRL_NO_ARGS = KDB_ENABLE_FLOW_CTRL | |
52 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
53 | + KDB_ENABLE_SIGNAL_NO_ARGS = KDB_ENABLE_SIGNAL | |
54 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
55 | + KDB_ENABLE_REBOOT_NO_ARGS = KDB_ENABLE_REBOOT | |
56 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
57 | + KDB_ENABLE_ALWAYS_SAFE_NO_ARGS = KDB_ENABLE_ALWAYS_SAFE | |
58 | + << KDB_ENABLE_NO_ARGS_SHIFT, | |
59 | + KDB_ENABLE_MASK_NO_ARGS = KDB_ENABLE_MASK << KDB_ENABLE_NO_ARGS_SHIFT, | |
60 | + | |
61 | + KDB_REPEAT_NO_ARGS = 0x40000000, /* Repeat the command w/o arguments */ | |
62 | + KDB_REPEAT_WITH_ARGS = 0x80000000, /* Repeat the command with args */ | |
63 | +} kdb_cmdflags_t; | |
64 | + | |
22 | 65 | typedef int (*kdb_func_t)(int, const char **); |
23 | 66 | |
24 | 67 | #ifdef CONFIG_KGDB_KDB |
... | ... | @@ -62,6 +105,7 @@ |
62 | 105 | #define KDB_BADLENGTH (-19) |
63 | 106 | #define KDB_NOBP (-20) |
64 | 107 | #define KDB_BADADDR (-21) |
108 | +#define KDB_NOPERM (-22) | |
65 | 109 | |
66 | 110 | /* |
67 | 111 | * kdb_diemsg |
68 | 112 | |
... | ... | @@ -146,17 +190,17 @@ |
146 | 190 | |
147 | 191 | /* Dynamic kdb shell command registration */ |
148 | 192 | extern int kdb_register(char *, kdb_func_t, char *, char *, short); |
149 | -extern int kdb_register_repeat(char *, kdb_func_t, char *, char *, | |
150 | - short, kdb_repeat_t); | |
193 | +extern int kdb_register_flags(char *, kdb_func_t, char *, char *, | |
194 | + short, kdb_cmdflags_t); | |
151 | 195 | extern int kdb_unregister(char *); |
152 | 196 | #else /* ! CONFIG_KGDB_KDB */ |
153 | 197 | static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; } |
154 | 198 | static inline void kdb_init(int level) {} |
155 | 199 | static inline int kdb_register(char *cmd, kdb_func_t func, char *usage, |
156 | 200 | char *help, short minlen) { return 0; } |
157 | -static inline int kdb_register_repeat(char *cmd, kdb_func_t func, char *usage, | |
158 | - char *help, short minlen, | |
159 | - kdb_repeat_t repeat) { return 0; } | |
201 | +static inline int kdb_register_flags(char *cmd, kdb_func_t func, char *usage, | |
202 | + char *help, short minlen, | |
203 | + kdb_cmdflags_t flags) { return 0; } | |
160 | 204 | static inline int kdb_unregister(char *cmd) { return 0; } |
161 | 205 | #endif /* CONFIG_KGDB_KDB */ |
162 | 206 | enum { |
kernel/debug/debug_core.c
... | ... | @@ -27,6 +27,9 @@ |
27 | 27 | * version 2. This program is licensed "as is" without any warranty of any |
28 | 28 | * kind, whether express or implied. |
29 | 29 | */ |
30 | + | |
31 | +#define pr_fmt(fmt) "KGDB: " fmt | |
32 | + | |
30 | 33 | #include <linux/pid_namespace.h> |
31 | 34 | #include <linux/clocksource.h> |
32 | 35 | #include <linux/serial_core.h> |
... | ... | @@ -196,8 +199,8 @@ |
196 | 199 | return err; |
197 | 200 | err = kgdb_arch_remove_breakpoint(&tmp); |
198 | 201 | if (err) |
199 | - printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " | |
200 | - "memory destroyed at: %lx", addr); | |
202 | + pr_err("Critical breakpoint error, kernel memory destroyed at: %lx\n", | |
203 | + addr); | |
201 | 204 | return err; |
202 | 205 | } |
203 | 206 | |
... | ... | @@ -256,8 +259,8 @@ |
256 | 259 | error = kgdb_arch_set_breakpoint(&kgdb_break[i]); |
257 | 260 | if (error) { |
258 | 261 | ret = error; |
259 | - printk(KERN_INFO "KGDB: BP install failed: %lx", | |
260 | - kgdb_break[i].bpt_addr); | |
262 | + pr_info("BP install failed: %lx\n", | |
263 | + kgdb_break[i].bpt_addr); | |
261 | 264 | continue; |
262 | 265 | } |
263 | 266 | |
... | ... | @@ -319,8 +322,8 @@ |
319 | 322 | continue; |
320 | 323 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); |
321 | 324 | if (error) { |
322 | - printk(KERN_INFO "KGDB: BP remove failed: %lx\n", | |
323 | - kgdb_break[i].bpt_addr); | |
325 | + pr_info("BP remove failed: %lx\n", | |
326 | + kgdb_break[i].bpt_addr); | |
324 | 327 | ret = error; |
325 | 328 | } |
326 | 329 | |
... | ... | @@ -367,7 +370,7 @@ |
367 | 370 | goto setundefined; |
368 | 371 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); |
369 | 372 | if (error) |
370 | - printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", | |
373 | + pr_err("breakpoint remove failed: %lx\n", | |
371 | 374 | kgdb_break[i].bpt_addr); |
372 | 375 | setundefined: |
373 | 376 | kgdb_break[i].state = BP_UNDEFINED; |
374 | 377 | |
... | ... | @@ -400,9 +403,9 @@ |
400 | 403 | if (print_wait) { |
401 | 404 | #ifdef CONFIG_KGDB_KDB |
402 | 405 | if (!dbg_kdb_mode) |
403 | - printk(KERN_CRIT "KGDB: waiting... or $3#33 for KDB\n"); | |
406 | + pr_crit("waiting... or $3#33 for KDB\n"); | |
404 | 407 | #else |
405 | - printk(KERN_CRIT "KGDB: Waiting for remote debugger\n"); | |
408 | + pr_crit("Waiting for remote debugger\n"); | |
406 | 409 | #endif |
407 | 410 | } |
408 | 411 | return 1; |
... | ... | @@ -430,8 +433,7 @@ |
430 | 433 | exception_level = 0; |
431 | 434 | kgdb_skipexception(ks->ex_vector, ks->linux_regs); |
432 | 435 | dbg_activate_sw_breakpoints(); |
433 | - printk(KERN_CRIT "KGDB: re-enter error: breakpoint removed %lx\n", | |
434 | - addr); | |
436 | + pr_crit("re-enter error: breakpoint removed %lx\n", addr); | |
435 | 437 | WARN_ON_ONCE(1); |
436 | 438 | |
437 | 439 | return 1; |
... | ... | @@ -444,7 +446,7 @@ |
444 | 446 | panic("Recursive entry to debugger"); |
445 | 447 | } |
446 | 448 | |
447 | - printk(KERN_CRIT "KGDB: re-enter exception: ALL breakpoints killed\n"); | |
449 | + pr_crit("re-enter exception: ALL breakpoints killed\n"); | |
448 | 450 | #ifdef CONFIG_KGDB_KDB |
449 | 451 | /* Allow kdb to debug itself one level */ |
450 | 452 | return 0; |
... | ... | @@ -471,6 +473,7 @@ |
471 | 473 | int cpu; |
472 | 474 | int trace_on = 0; |
473 | 475 | int online_cpus = num_online_cpus(); |
476 | + u64 time_left; | |
474 | 477 | |
475 | 478 | kgdb_info[ks->cpu].enter_kgdb++; |
476 | 479 | kgdb_info[ks->cpu].exception_state |= exception_state; |
477 | 480 | |
... | ... | @@ -595,9 +598,13 @@ |
595 | 598 | /* |
596 | 599 | * Wait for the other CPUs to be notified and be waiting for us: |
597 | 600 | */ |
598 | - while (kgdb_do_roundup && (atomic_read(&masters_in_kgdb) + | |
599 | - atomic_read(&slaves_in_kgdb)) != online_cpus) | |
601 | + time_left = loops_per_jiffy * HZ; | |
602 | + while (kgdb_do_roundup && --time_left && | |
603 | + (atomic_read(&masters_in_kgdb) + atomic_read(&slaves_in_kgdb)) != | |
604 | + online_cpus) | |
600 | 605 | cpu_relax(); |
606 | + if (!time_left) | |
607 | + pr_crit("KGDB: Timed out waiting for secondary CPUs.\n"); | |
601 | 608 | |
602 | 609 | /* |
603 | 610 | * At this point the primary processor is completely |
604 | 611 | |
605 | 612 | |
... | ... | @@ -795,15 +802,15 @@ |
795 | 802 | static void sysrq_handle_dbg(int key) |
796 | 803 | { |
797 | 804 | if (!dbg_io_ops) { |
798 | - printk(KERN_CRIT "ERROR: No KGDB I/O module available\n"); | |
805 | + pr_crit("ERROR: No KGDB I/O module available\n"); | |
799 | 806 | return; |
800 | 807 | } |
801 | 808 | if (!kgdb_connected) { |
802 | 809 | #ifdef CONFIG_KGDB_KDB |
803 | 810 | if (!dbg_kdb_mode) |
804 | - printk(KERN_CRIT "KGDB or $3#33 for KDB\n"); | |
811 | + pr_crit("KGDB or $3#33 for KDB\n"); | |
805 | 812 | #else |
806 | - printk(KERN_CRIT "Entering KGDB\n"); | |
813 | + pr_crit("Entering KGDB\n"); | |
807 | 814 | #endif |
808 | 815 | } |
809 | 816 | |
... | ... | @@ -945,7 +952,7 @@ |
945 | 952 | { |
946 | 953 | kgdb_break_asap = 0; |
947 | 954 | |
948 | - printk(KERN_CRIT "kgdb: Waiting for connection from remote gdb...\n"); | |
955 | + pr_crit("Waiting for connection from remote gdb...\n"); | |
949 | 956 | kgdb_breakpoint(); |
950 | 957 | } |
951 | 958 | |
... | ... | @@ -964,8 +971,7 @@ |
964 | 971 | if (dbg_io_ops) { |
965 | 972 | spin_unlock(&kgdb_registration_lock); |
966 | 973 | |
967 | - printk(KERN_ERR "kgdb: Another I/O driver is already " | |
968 | - "registered with KGDB.\n"); | |
974 | + pr_err("Another I/O driver is already registered with KGDB\n"); | |
969 | 975 | return -EBUSY; |
970 | 976 | } |
971 | 977 | |
... | ... | @@ -981,8 +987,7 @@ |
981 | 987 | |
982 | 988 | spin_unlock(&kgdb_registration_lock); |
983 | 989 | |
984 | - printk(KERN_INFO "kgdb: Registered I/O driver %s.\n", | |
985 | - new_dbg_io_ops->name); | |
990 | + pr_info("Registered I/O driver %s\n", new_dbg_io_ops->name); | |
986 | 991 | |
987 | 992 | /* Arm KGDB now. */ |
988 | 993 | kgdb_register_callbacks(); |
... | ... | @@ -1017,8 +1022,7 @@ |
1017 | 1022 | |
1018 | 1023 | spin_unlock(&kgdb_registration_lock); |
1019 | 1024 | |
1020 | - printk(KERN_INFO | |
1021 | - "kgdb: Unregistered I/O driver %s, debugger disabled.\n", | |
1025 | + pr_info("Unregistered I/O driver %s, debugger disabled\n", | |
1022 | 1026 | old_dbg_io_ops->name); |
1023 | 1027 | } |
1024 | 1028 | EXPORT_SYMBOL_GPL(kgdb_unregister_io_module); |
kernel/debug/kdb/kdb_bp.c
... | ... | @@ -531,22 +531,29 @@ |
531 | 531 | for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) |
532 | 532 | bp->bp_free = 1; |
533 | 533 | |
534 | - kdb_register_repeat("bp", kdb_bp, "[<vaddr>]", | |
535 | - "Set/Display breakpoints", 0, KDB_REPEAT_NO_ARGS); | |
536 | - kdb_register_repeat("bl", kdb_bp, "[<vaddr>]", | |
537 | - "Display breakpoints", 0, KDB_REPEAT_NO_ARGS); | |
534 | + kdb_register_flags("bp", kdb_bp, "[<vaddr>]", | |
535 | + "Set/Display breakpoints", 0, | |
536 | + KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); | |
537 | + kdb_register_flags("bl", kdb_bp, "[<vaddr>]", | |
538 | + "Display breakpoints", 0, | |
539 | + KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); | |
538 | 540 | if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) |
539 | - kdb_register_repeat("bph", kdb_bp, "[<vaddr>]", | |
540 | - "[datar [length]|dataw [length]] Set hw brk", 0, KDB_REPEAT_NO_ARGS); | |
541 | - kdb_register_repeat("bc", kdb_bc, "<bpnum>", | |
542 | - "Clear Breakpoint", 0, KDB_REPEAT_NONE); | |
543 | - kdb_register_repeat("be", kdb_bc, "<bpnum>", | |
544 | - "Enable Breakpoint", 0, KDB_REPEAT_NONE); | |
545 | - kdb_register_repeat("bd", kdb_bc, "<bpnum>", | |
546 | - "Disable Breakpoint", 0, KDB_REPEAT_NONE); | |
541 | + kdb_register_flags("bph", kdb_bp, "[<vaddr>]", | |
542 | + "[datar [length]|dataw [length]] Set hw brk", 0, | |
543 | + KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); | |
544 | + kdb_register_flags("bc", kdb_bc, "<bpnum>", | |
545 | + "Clear Breakpoint", 0, | |
546 | + KDB_ENABLE_FLOW_CTRL); | |
547 | + kdb_register_flags("be", kdb_bc, "<bpnum>", | |
548 | + "Enable Breakpoint", 0, | |
549 | + KDB_ENABLE_FLOW_CTRL); | |
550 | + kdb_register_flags("bd", kdb_bc, "<bpnum>", | |
551 | + "Disable Breakpoint", 0, | |
552 | + KDB_ENABLE_FLOW_CTRL); | |
547 | 553 | |
548 | - kdb_register_repeat("ss", kdb_ss, "", | |
549 | - "Single Step", 1, KDB_REPEAT_NO_ARGS); | |
554 | + kdb_register_flags("ss", kdb_ss, "", | |
555 | + "Single Step", 1, | |
556 | + KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS); | |
550 | 557 | /* |
551 | 558 | * Architecture dependent initialization. |
552 | 559 | */ |
kernel/debug/kdb/kdb_debugger.c
... | ... | @@ -129,6 +129,10 @@ |
129 | 129 | ks->pass_exception = 1; |
130 | 130 | KDB_FLAG_SET(CATASTROPHIC); |
131 | 131 | } |
132 | + /* set CATASTROPHIC if the system contains unresponsive processors */ | |
133 | + for_each_online_cpu(i) | |
134 | + if (!kgdb_info[i].enter_kgdb) | |
135 | + KDB_FLAG_SET(CATASTROPHIC); | |
132 | 136 | if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) { |
133 | 137 | KDB_STATE_CLEAR(SSBPT); |
134 | 138 | KDB_STATE_CLEAR(DOING_SS); |
kernel/debug/kdb/kdb_main.c
... | ... | @@ -12,6 +12,7 @@ |
12 | 12 | */ |
13 | 13 | |
14 | 14 | #include <linux/ctype.h> |
15 | +#include <linux/types.h> | |
15 | 16 | #include <linux/string.h> |
16 | 17 | #include <linux/kernel.h> |
17 | 18 | #include <linux/kmsg_dump.h> |
... | ... | @@ -23,6 +24,7 @@ |
23 | 24 | #include <linux/vmalloc.h> |
24 | 25 | #include <linux/atomic.h> |
25 | 26 | #include <linux/module.h> |
27 | +#include <linux/moduleparam.h> | |
26 | 28 | #include <linux/mm.h> |
27 | 29 | #include <linux/init.h> |
28 | 30 | #include <linux/kallsyms.h> |
... | ... | @@ -42,6 +44,12 @@ |
42 | 44 | #include <linux/slab.h> |
43 | 45 | #include "kdb_private.h" |
44 | 46 | |
47 | +#undef MODULE_PARAM_PREFIX | |
48 | +#define MODULE_PARAM_PREFIX "kdb." | |
49 | + | |
50 | +static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE; | |
51 | +module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600); | |
52 | + | |
45 | 53 | #define GREP_LEN 256 |
46 | 54 | char kdb_grep_string[GREP_LEN]; |
47 | 55 | int kdb_grepping_flag; |
... | ... | @@ -121,6 +129,7 @@ |
121 | 129 | KDBMSG(BADLENGTH, "Invalid length field"), |
122 | 130 | KDBMSG(NOBP, "No Breakpoint exists"), |
123 | 131 | KDBMSG(BADADDR, "Invalid address"), |
132 | + KDBMSG(NOPERM, "Permission denied"), | |
124 | 133 | }; |
125 | 134 | #undef KDBMSG |
126 | 135 | |
... | ... | @@ -188,6 +197,26 @@ |
188 | 197 | } |
189 | 198 | |
190 | 199 | /* |
200 | + * Check whether the flags of the current command and the permissions | |
201 | + * of the kdb console has allow a command to be run. | |
202 | + */ | |
203 | +static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions, | |
204 | + bool no_args) | |
205 | +{ | |
206 | + /* permissions comes from userspace so needs massaging slightly */ | |
207 | + permissions &= KDB_ENABLE_MASK; | |
208 | + permissions |= KDB_ENABLE_ALWAYS_SAFE; | |
209 | + | |
210 | + /* some commands change group when launched with no arguments */ | |
211 | + if (no_args) | |
212 | + permissions |= permissions << KDB_ENABLE_NO_ARGS_SHIFT; | |
213 | + | |
214 | + flags |= KDB_ENABLE_ALL; | |
215 | + | |
216 | + return permissions & flags; | |
217 | +} | |
218 | + | |
219 | +/* | |
191 | 220 | * kdbgetenv - This function will return the character string value of |
192 | 221 | * an environment variable. |
193 | 222 | * Parameters: |
... | ... | @@ -476,6 +505,15 @@ |
476 | 505 | kdb_symtab_t symtab; |
477 | 506 | |
478 | 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 | + | |
516 | + /* | |
479 | 517 | * Process arguments which follow the following syntax: |
480 | 518 | * |
481 | 519 | * symbol | numeric-address [+/- numeric-offset] |
... | ... | @@ -641,8 +679,13 @@ |
641 | 679 | if (!s->count) |
642 | 680 | s->usable = 0; |
643 | 681 | if (s->usable) |
644 | - kdb_register(s->name, kdb_exec_defcmd, | |
645 | - s->usage, s->help, 0); | |
682 | + /* macros are always safe because when executed each | |
683 | + * internal command re-enters kdb_parse() and is | |
684 | + * safety checked individually. | |
685 | + */ | |
686 | + kdb_register_flags(s->name, kdb_exec_defcmd, s->usage, | |
687 | + s->help, 0, | |
688 | + KDB_ENABLE_ALWAYS_SAFE); | |
646 | 689 | return 0; |
647 | 690 | } |
648 | 691 | if (!s->usable) |
649 | 692 | |
... | ... | @@ -1003,25 +1046,22 @@ |
1003 | 1046 | |
1004 | 1047 | if (i < kdb_max_commands) { |
1005 | 1048 | int result; |
1049 | + | |
1050 | + if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1)) | |
1051 | + return KDB_NOPERM; | |
1052 | + | |
1006 | 1053 | KDB_STATE_SET(CMD); |
1007 | 1054 | result = (*tp->cmd_func)(argc-1, (const char **)argv); |
1008 | 1055 | if (result && ignore_errors && result > KDB_CMD_GO) |
1009 | 1056 | result = 0; |
1010 | 1057 | KDB_STATE_CLEAR(CMD); |
1011 | - switch (tp->cmd_repeat) { | |
1012 | - case KDB_REPEAT_NONE: | |
1013 | - argc = 0; | |
1014 | - if (argv[0]) | |
1015 | - *(argv[0]) = '\0'; | |
1016 | - break; | |
1017 | - case KDB_REPEAT_NO_ARGS: | |
1018 | - argc = 1; | |
1019 | - if (argv[1]) | |
1020 | - *(argv[1]) = '\0'; | |
1021 | - break; | |
1022 | - case KDB_REPEAT_WITH_ARGS: | |
1023 | - break; | |
1024 | - } | |
1058 | + | |
1059 | + if (tp->cmd_flags & KDB_REPEAT_WITH_ARGS) | |
1060 | + return result; | |
1061 | + | |
1062 | + argc = tp->cmd_flags & KDB_REPEAT_NO_ARGS ? 1 : 0; | |
1063 | + if (argv[argc]) | |
1064 | + *(argv[argc]) = '\0'; | |
1025 | 1065 | return result; |
1026 | 1066 | } |
1027 | 1067 | |
1028 | 1068 | |
1029 | 1069 | |
... | ... | @@ -1921,10 +1961,14 @@ |
1921 | 1961 | */ |
1922 | 1962 | static int kdb_sr(int argc, const char **argv) |
1923 | 1963 | { |
1964 | + bool check_mask = | |
1965 | + !kdb_check_flags(KDB_ENABLE_ALL, kdb_cmd_enabled, false); | |
1966 | + | |
1924 | 1967 | if (argc != 1) |
1925 | 1968 | return KDB_ARGCOUNT; |
1969 | + | |
1926 | 1970 | kdb_trap_printk++; |
1927 | - __handle_sysrq(*argv[1], false); | |
1971 | + __handle_sysrq(*argv[1], check_mask); | |
1928 | 1972 | kdb_trap_printk--; |
1929 | 1973 | |
1930 | 1974 | return 0; |
... | ... | @@ -2157,6 +2201,8 @@ |
2157 | 2201 | for (start_cpu = -1, i = 0; i < NR_CPUS; i++) { |
2158 | 2202 | if (!cpu_online(i)) { |
2159 | 2203 | state = 'F'; /* cpu is offline */ |
2204 | + } else if (!kgdb_info[i].enter_kgdb) { | |
2205 | + state = 'D'; /* cpu is online but unresponsive */ | |
2160 | 2206 | } else { |
2161 | 2207 | state = ' '; /* cpu is responding to kdb */ |
2162 | 2208 | if (kdb_task_state_char(KDB_TSK(i)) == 'I') |
... | ... | @@ -2210,7 +2256,7 @@ |
2210 | 2256 | /* |
2211 | 2257 | * Validate cpunum |
2212 | 2258 | */ |
2213 | - if ((cpunum > NR_CPUS) || !cpu_online(cpunum)) | |
2259 | + if ((cpunum > NR_CPUS) || !kgdb_info[cpunum].enter_kgdb) | |
2214 | 2260 | return KDB_BADCPUNUM; |
2215 | 2261 | |
2216 | 2262 | dbg_switch_cpu = cpunum; |
... | ... | @@ -2375,6 +2421,8 @@ |
2375 | 2421 | return 0; |
2376 | 2422 | if (!kt->cmd_name) |
2377 | 2423 | continue; |
2424 | + if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true)) | |
2425 | + continue; | |
2378 | 2426 | if (strlen(kt->cmd_usage) > 20) |
2379 | 2427 | space = "\n "; |
2380 | 2428 | kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name, |
... | ... | @@ -2629,7 +2677,7 @@ |
2629 | 2677 | } |
2630 | 2678 | |
2631 | 2679 | /* |
2632 | - * kdb_register_repeat - This function is used to register a kernel | |
2680 | + * kdb_register_flags - This function is used to register a kernel | |
2633 | 2681 | * debugger command. |
2634 | 2682 | * Inputs: |
2635 | 2683 | * cmd Command name |
... | ... | @@ -2641,12 +2689,12 @@ |
2641 | 2689 | * zero for success, one if a duplicate command. |
2642 | 2690 | */ |
2643 | 2691 | #define kdb_command_extend 50 /* arbitrary */ |
2644 | -int kdb_register_repeat(char *cmd, | |
2645 | - kdb_func_t func, | |
2646 | - char *usage, | |
2647 | - char *help, | |
2648 | - short minlen, | |
2649 | - kdb_repeat_t repeat) | |
2692 | +int kdb_register_flags(char *cmd, | |
2693 | + kdb_func_t func, | |
2694 | + char *usage, | |
2695 | + char *help, | |
2696 | + short minlen, | |
2697 | + kdb_cmdflags_t flags) | |
2650 | 2698 | { |
2651 | 2699 | int i; |
2652 | 2700 | kdbtab_t *kp; |
2653 | 2701 | |
2654 | 2702 | |
2655 | 2703 | |
... | ... | @@ -2694,19 +2742,18 @@ |
2694 | 2742 | kp->cmd_func = func; |
2695 | 2743 | kp->cmd_usage = usage; |
2696 | 2744 | kp->cmd_help = help; |
2697 | - kp->cmd_flags = 0; | |
2698 | 2745 | kp->cmd_minlen = minlen; |
2699 | - kp->cmd_repeat = repeat; | |
2746 | + kp->cmd_flags = flags; | |
2700 | 2747 | |
2701 | 2748 | return 0; |
2702 | 2749 | } |
2703 | -EXPORT_SYMBOL_GPL(kdb_register_repeat); | |
2750 | +EXPORT_SYMBOL_GPL(kdb_register_flags); | |
2704 | 2751 | |
2705 | 2752 | |
2706 | 2753 | /* |
2707 | 2754 | * kdb_register - Compatibility register function for commands that do |
2708 | 2755 | * not need to specify a repeat state. Equivalent to |
2709 | - * kdb_register_repeat with KDB_REPEAT_NONE. | |
2756 | + * kdb_register_flags with flags set to 0. | |
2710 | 2757 | * Inputs: |
2711 | 2758 | * cmd Command name |
2712 | 2759 | * func Function to execute the command |
... | ... | @@ -2721,8 +2768,7 @@ |
2721 | 2768 | char *help, |
2722 | 2769 | short minlen) |
2723 | 2770 | { |
2724 | - return kdb_register_repeat(cmd, func, usage, help, minlen, | |
2725 | - KDB_REPEAT_NONE); | |
2771 | + return kdb_register_flags(cmd, func, usage, help, minlen, 0); | |
2726 | 2772 | } |
2727 | 2773 | EXPORT_SYMBOL_GPL(kdb_register); |
2728 | 2774 | |
2729 | 2775 | |
2730 | 2776 | |
2731 | 2777 | |
2732 | 2778 | |
2733 | 2779 | |
2734 | 2780 | |
2735 | 2781 | |
... | ... | @@ -2764,80 +2810,109 @@ |
2764 | 2810 | for_each_kdbcmd(kp, i) |
2765 | 2811 | kp->cmd_name = NULL; |
2766 | 2812 | |
2767 | - kdb_register_repeat("md", kdb_md, "<vaddr>", | |
2813 | + kdb_register_flags("md", kdb_md, "<vaddr>", | |
2768 | 2814 | "Display Memory Contents, also mdWcN, e.g. md8c1", 1, |
2769 | - KDB_REPEAT_NO_ARGS); | |
2770 | - kdb_register_repeat("mdr", kdb_md, "<vaddr> <bytes>", | |
2771 | - "Display Raw Memory", 0, KDB_REPEAT_NO_ARGS); | |
2772 | - kdb_register_repeat("mdp", kdb_md, "<paddr> <bytes>", | |
2773 | - "Display Physical Memory", 0, KDB_REPEAT_NO_ARGS); | |
2774 | - kdb_register_repeat("mds", kdb_md, "<vaddr>", | |
2775 | - "Display Memory Symbolically", 0, KDB_REPEAT_NO_ARGS); | |
2776 | - kdb_register_repeat("mm", kdb_mm, "<vaddr> <contents>", | |
2777 | - "Modify Memory Contents", 0, KDB_REPEAT_NO_ARGS); | |
2778 | - kdb_register_repeat("go", kdb_go, "[<vaddr>]", | |
2779 | - "Continue Execution", 1, KDB_REPEAT_NONE); | |
2780 | - kdb_register_repeat("rd", kdb_rd, "", | |
2781 | - "Display Registers", 0, KDB_REPEAT_NONE); | |
2782 | - kdb_register_repeat("rm", kdb_rm, "<reg> <contents>", | |
2783 | - "Modify Registers", 0, KDB_REPEAT_NONE); | |
2784 | - kdb_register_repeat("ef", kdb_ef, "<vaddr>", | |
2785 | - "Display exception frame", 0, KDB_REPEAT_NONE); | |
2786 | - kdb_register_repeat("bt", kdb_bt, "[<vaddr>]", | |
2787 | - "Stack traceback", 1, KDB_REPEAT_NONE); | |
2788 | - kdb_register_repeat("btp", kdb_bt, "<pid>", | |
2789 | - "Display stack for process <pid>", 0, KDB_REPEAT_NONE); | |
2790 | - kdb_register_repeat("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]", | |
2791 | - "Backtrace all processes matching state flag", 0, KDB_REPEAT_NONE); | |
2792 | - kdb_register_repeat("btc", kdb_bt, "", | |
2793 | - "Backtrace current process on each cpu", 0, KDB_REPEAT_NONE); | |
2794 | - kdb_register_repeat("btt", kdb_bt, "<vaddr>", | |
2815 | + KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); | |
2816 | + kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>", | |
2817 | + "Display Raw Memory", 0, | |
2818 | + KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); | |
2819 | + kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>", | |
2820 | + "Display Physical Memory", 0, | |
2821 | + KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); | |
2822 | + kdb_register_flags("mds", kdb_md, "<vaddr>", | |
2823 | + "Display Memory Symbolically", 0, | |
2824 | + KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); | |
2825 | + kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>", | |
2826 | + "Modify Memory Contents", 0, | |
2827 | + KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS); | |
2828 | + kdb_register_flags("go", kdb_go, "[<vaddr>]", | |
2829 | + "Continue Execution", 1, | |
2830 | + KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS); | |
2831 | + kdb_register_flags("rd", kdb_rd, "", | |
2832 | + "Display Registers", 0, | |
2833 | + KDB_ENABLE_REG_READ); | |
2834 | + kdb_register_flags("rm", kdb_rm, "<reg> <contents>", | |
2835 | + "Modify Registers", 0, | |
2836 | + KDB_ENABLE_REG_WRITE); | |
2837 | + kdb_register_flags("ef", kdb_ef, "<vaddr>", | |
2838 | + "Display exception frame", 0, | |
2839 | + KDB_ENABLE_MEM_READ); | |
2840 | + kdb_register_flags("bt", kdb_bt, "[<vaddr>]", | |
2841 | + "Stack traceback", 1, | |
2842 | + KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS); | |
2843 | + kdb_register_flags("btp", kdb_bt, "<pid>", | |
2844 | + "Display stack for process <pid>", 0, | |
2845 | + KDB_ENABLE_INSPECT); | |
2846 | + kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]", | |
2847 | + "Backtrace all processes matching state flag", 0, | |
2848 | + KDB_ENABLE_INSPECT); | |
2849 | + kdb_register_flags("btc", kdb_bt, "", | |
2850 | + "Backtrace current process on each cpu", 0, | |
2851 | + KDB_ENABLE_INSPECT); | |
2852 | + kdb_register_flags("btt", kdb_bt, "<vaddr>", | |
2795 | 2853 | "Backtrace process given its struct task address", 0, |
2796 | - KDB_REPEAT_NONE); | |
2797 | - kdb_register_repeat("env", kdb_env, "", | |
2798 | - "Show environment variables", 0, KDB_REPEAT_NONE); | |
2799 | - kdb_register_repeat("set", kdb_set, "", | |
2800 | - "Set environment variables", 0, KDB_REPEAT_NONE); | |
2801 | - kdb_register_repeat("help", kdb_help, "", | |
2802 | - "Display Help Message", 1, KDB_REPEAT_NONE); | |
2803 | - kdb_register_repeat("?", kdb_help, "", | |
2804 | - "Display Help Message", 0, KDB_REPEAT_NONE); | |
2805 | - kdb_register_repeat("cpu", kdb_cpu, "<cpunum>", | |
2806 | - "Switch to new cpu", 0, KDB_REPEAT_NONE); | |
2807 | - kdb_register_repeat("kgdb", kdb_kgdb, "", | |
2808 | - "Enter kgdb mode", 0, KDB_REPEAT_NONE); | |
2809 | - kdb_register_repeat("ps", kdb_ps, "[<flags>|A]", | |
2810 | - "Display active task list", 0, KDB_REPEAT_NONE); | |
2811 | - kdb_register_repeat("pid", kdb_pid, "<pidnum>", | |
2812 | - "Switch to another task", 0, KDB_REPEAT_NONE); | |
2813 | - kdb_register_repeat("reboot", kdb_reboot, "", | |
2814 | - "Reboot the machine immediately", 0, KDB_REPEAT_NONE); | |
2854 | + KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS); | |
2855 | + kdb_register_flags("env", kdb_env, "", | |
2856 | + "Show environment variables", 0, | |
2857 | + KDB_ENABLE_ALWAYS_SAFE); | |
2858 | + kdb_register_flags("set", kdb_set, "", | |
2859 | + "Set environment variables", 0, | |
2860 | + KDB_ENABLE_ALWAYS_SAFE); | |
2861 | + kdb_register_flags("help", kdb_help, "", | |
2862 | + "Display Help Message", 1, | |
2863 | + KDB_ENABLE_ALWAYS_SAFE); | |
2864 | + kdb_register_flags("?", kdb_help, "", | |
2865 | + "Display Help Message", 0, | |
2866 | + KDB_ENABLE_ALWAYS_SAFE); | |
2867 | + kdb_register_flags("cpu", kdb_cpu, "<cpunum>", | |
2868 | + "Switch to new cpu", 0, | |
2869 | + KDB_ENABLE_ALWAYS_SAFE_NO_ARGS); | |
2870 | + kdb_register_flags("kgdb", kdb_kgdb, "", | |
2871 | + "Enter kgdb mode", 0, 0); | |
2872 | + kdb_register_flags("ps", kdb_ps, "[<flags>|A]", | |
2873 | + "Display active task list", 0, | |
2874 | + KDB_ENABLE_INSPECT); | |
2875 | + kdb_register_flags("pid", kdb_pid, "<pidnum>", | |
2876 | + "Switch to another task", 0, | |
2877 | + KDB_ENABLE_INSPECT); | |
2878 | + kdb_register_flags("reboot", kdb_reboot, "", | |
2879 | + "Reboot the machine immediately", 0, | |
2880 | + KDB_ENABLE_REBOOT); | |
2815 | 2881 | #if defined(CONFIG_MODULES) |
2816 | - kdb_register_repeat("lsmod", kdb_lsmod, "", | |
2817 | - "List loaded kernel modules", 0, KDB_REPEAT_NONE); | |
2882 | + kdb_register_flags("lsmod", kdb_lsmod, "", | |
2883 | + "List loaded kernel modules", 0, | |
2884 | + KDB_ENABLE_INSPECT); | |
2818 | 2885 | #endif |
2819 | 2886 | #if defined(CONFIG_MAGIC_SYSRQ) |
2820 | - kdb_register_repeat("sr", kdb_sr, "<key>", | |
2821 | - "Magic SysRq key", 0, KDB_REPEAT_NONE); | |
2887 | + kdb_register_flags("sr", kdb_sr, "<key>", | |
2888 | + "Magic SysRq key", 0, | |
2889 | + KDB_ENABLE_ALWAYS_SAFE); | |
2822 | 2890 | #endif |
2823 | 2891 | #if defined(CONFIG_PRINTK) |
2824 | - kdb_register_repeat("dmesg", kdb_dmesg, "[lines]", | |
2825 | - "Display syslog buffer", 0, KDB_REPEAT_NONE); | |
2892 | + kdb_register_flags("dmesg", kdb_dmesg, "[lines]", | |
2893 | + "Display syslog buffer", 0, | |
2894 | + KDB_ENABLE_ALWAYS_SAFE); | |
2826 | 2895 | #endif |
2827 | 2896 | if (arch_kgdb_ops.enable_nmi) { |
2828 | - kdb_register_repeat("disable_nmi", kdb_disable_nmi, "", | |
2829 | - "Disable NMI entry to KDB", 0, KDB_REPEAT_NONE); | |
2897 | + kdb_register_flags("disable_nmi", kdb_disable_nmi, "", | |
2898 | + "Disable NMI entry to KDB", 0, | |
2899 | + KDB_ENABLE_ALWAYS_SAFE); | |
2830 | 2900 | } |
2831 | - kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", | |
2832 | - "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE); | |
2833 | - kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", | |
2834 | - "Send a signal to a process", 0, KDB_REPEAT_NONE); | |
2835 | - kdb_register_repeat("summary", kdb_summary, "", | |
2836 | - "Summarize the system", 4, KDB_REPEAT_NONE); | |
2837 | - kdb_register_repeat("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]", | |
2838 | - "Display per_cpu variables", 3, KDB_REPEAT_NONE); | |
2839 | - kdb_register_repeat("grephelp", kdb_grep_help, "", | |
2840 | - "Display help on | grep", 0, KDB_REPEAT_NONE); | |
2901 | + kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"", | |
2902 | + "Define a set of commands, down to endefcmd", 0, | |
2903 | + KDB_ENABLE_ALWAYS_SAFE); | |
2904 | + kdb_register_flags("kill", kdb_kill, "<-signal> <pid>", | |
2905 | + "Send a signal to a process", 0, | |
2906 | + KDB_ENABLE_SIGNAL); | |
2907 | + kdb_register_flags("summary", kdb_summary, "", | |
2908 | + "Summarize the system", 4, | |
2909 | + KDB_ENABLE_ALWAYS_SAFE); | |
2910 | + kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]", | |
2911 | + "Display per_cpu variables", 3, | |
2912 | + KDB_ENABLE_MEM_READ); | |
2913 | + kdb_register_flags("grephelp", kdb_grep_help, "", | |
2914 | + "Display help on | grep", 0, | |
2915 | + KDB_ENABLE_ALWAYS_SAFE); | |
2841 | 2916 | } |
2842 | 2917 | |
2843 | 2918 | /* Execute any commands defined in kdb_cmds. */ |
kernel/debug/kdb/kdb_private.h
... | ... | @@ -172,10 +172,9 @@ |
172 | 172 | kdb_func_t cmd_func; /* Function to execute command */ |
173 | 173 | char *cmd_usage; /* Usage String for this command */ |
174 | 174 | char *cmd_help; /* Help message for this command */ |
175 | - short cmd_flags; /* Parsing flags */ | |
176 | 175 | short cmd_minlen; /* Minimum legal # command |
177 | 176 | * chars required */ |
178 | - kdb_repeat_t cmd_repeat; /* Does command auto repeat on enter? */ | |
177 | + kdb_cmdflags_t cmd_flags; /* Command behaviour flags */ | |
179 | 178 | } kdbtab_t; |
180 | 179 | |
181 | 180 | extern int kdb_bt(int, const char **); /* KDB display back trace */ |
kernel/trace/trace_kdb.c
... | ... | @@ -132,8 +132,8 @@ |
132 | 132 | |
133 | 133 | static __init int kdb_ftrace_register(void) |
134 | 134 | { |
135 | - kdb_register_repeat("ftdump", kdb_ftdump, "[skip_#lines] [cpu]", | |
136 | - "Dump ftrace log", 0, KDB_REPEAT_NONE); | |
135 | + kdb_register_flags("ftdump", kdb_ftdump, "[skip_#lines] [cpu]", | |
136 | + "Dump ftrace log", 0, KDB_ENABLE_ALWAYS_SAFE); | |
137 | 137 | return 0; |
138 | 138 | } |
139 | 139 |
lib/Kconfig.kgdb
... | ... | @@ -73,6 +73,31 @@ |
73 | 73 | help |
74 | 74 | KDB frontend for kernel |
75 | 75 | |
76 | +config KDB_DEFAULT_ENABLE | |
77 | + hex "KDB: Select kdb command functions to be enabled by default" | |
78 | + depends on KGDB_KDB | |
79 | + default 0x1 | |
80 | + help | |
81 | + Specifiers which kdb commands are enabled by default. This may | |
82 | + be set to 1 or 0 to enable all commands or disable almost all | |
83 | + commands. | |
84 | + | |
85 | + Alternatively the following bitmask applies: | |
86 | + | |
87 | + 0x0002 - allow arbitrary reads from memory and symbol lookup | |
88 | + 0x0004 - allow arbitrary writes to memory | |
89 | + 0x0008 - allow current register state to be inspected | |
90 | + 0x0010 - allow current register state to be modified | |
91 | + 0x0020 - allow passive inspection (backtrace, process list, lsmod) | |
92 | + 0x0040 - allow flow control management (breakpoint, single step) | |
93 | + 0x0080 - enable signalling of processes | |
94 | + 0x0100 - allow machine to be rebooted | |
95 | + | |
96 | + The config option merely sets the default at boot time. Both | |
97 | + issuing 'echo X > /sys/module/kdb/parameters/cmd_enable' or | |
98 | + setting with kdb.cmd_enable=X kernel command line option will | |
99 | + override the default settings. | |
100 | + | |
76 | 101 | config KDB_KEYBOARD |
77 | 102 | bool "KGDB_KDB: keyboard as input device" |
78 | 103 | depends on VT && KGDB_KDB |