Our QA found this problem with KDB:
1. The target boots with KDB enabled kernel.
2. Get KDB prompt by hitting ESC-KDB
3. Set breakpoint (at sys_chmod)
4. "go" on KDB prompt to come out.
5. Verify that chmod invokes KDB.
6. Disable KDB by echo 0 > /proc/sys/kernel/kdb
7. Do chmod again. This results in segmentation fault.
Please note that the system does not crash at this stage. However, if KDB is
enabled again and invoked (by ESC-KDB), it does so with message "Catastrophic
error detected".
I've inlined a patch which fixes the problem by clearing any breakpoints when
kdb is disabled.
Source: MontaVista Software, Inc.
MR: 14547
Type: Defect Fix
Disposition: submitted to kdb mailing list
Signed-off-by: Steven Dake <[EMAIL PROTECTED]>
Description:
If a breakpoint is set, and then KDB is turned off, and then that breakpoint
is executed, the application will crash. Then if KDB is reenabled, it will
suffer a catastrophic error. This patch clears any existing breakpoints
when KDB is disabled by executing echo 0 > /proc/sys/kernel/kdb.
Index: linux-2.6.10/include/linux/kdb.h
===================================================================
--- linux-2.6.10.orig/include/linux/kdb.h
+++ linux-2.6.10/include/linux/kdb.h
@@ -108,6 +108,8 @@ typedef enum {
#ifdef CONFIG_KDB
extern int kdb(kdb_reason_t, int, struct pt_regs *);
+extern void kdb_stateset(int);
+extern void kdb_disableall(void);
#else
#define kdb(reason,error_code,frame) (0)
#endif
Index: linux-2.6.10/kdb/kdb_bp.c
===================================================================
--- linux-2.6.10.orig/kdb/kdb_bp.c
+++ linux-2.6.10/kdb/kdb_bp.c
@@ -217,6 +217,44 @@ kdb_printbp(kdb_bp_t *bp, int i)
}
/*
+ * kdb_clearall
+ *
+ * Clears all existing breakpoints when the debugger is turned off from
+ * echoing 0 to /proc/sys/kernel/kdb.
+ */
+kdb_clearall(void)
+{
+ int bpno;
+ kdb_bp_t *bp;
+
+ for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++, bp++) {
+ if (!bp->bp_enabled) {
+ continue;
+ }
+
+ /*
+ * Since this breakpoint is now disabled, we can
+ * give up the hardware register which is allocated
+ * to it.
+ */
+ if (bp->bp_hardtype) {
+ kdba_freebp(bp->bp_hard);
+ bp->bp_hard = 0;
+ bp->bp_hardtype = 0;
+ }
+
+ kdba_removebp(bp);
+ kdb_printf("KDB turned off through sysctl: clearing breakpoint
%d at " kdb_bfd_vma_fmt "\n",
+ bpno, bp->bp_addr);
+
+ bp->bp_enabled = 0;
+ bp->bp_global = 0;
+ bp->bp_addr = 0;
+ bp->bp_free = 1;
+ }
+}
+
+/*
* kdb_bp
*
* Handle the bp, and bpa commands.
@@ -242,6 +280,7 @@ kdb_printbp(kdb_bp_t *bp, int i)
* bpha Set breakpoint on all cpus, force hardware register
*/
+
static int
kdb_bp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
{
Index: linux-2.6.10/kdb/kdbmain.c
===================================================================
--- linux-2.6.10.orig/kdb/kdbmain.c
+++ linux-2.6.10/kdb/kdbmain.c
@@ -3879,6 +3879,18 @@ kdb_init(void)
kdb_initial_cpu = -1;
}
+void
+kdb_stateset(int state)
+{
+ kdb_on = state;
+ /*
+ * Disable any breakpoints if KDB is turned off
+ */
+ if (kdb_on == 0) {
+ kdb_clearall();
+ }
+}
+
EXPORT_SYMBOL(kdb_register);
EXPORT_SYMBOL(kdb_register_repeat);
EXPORT_SYMBOL(kdb_unregister);
@@ -3894,6 +3906,7 @@ EXPORT_SYMBOL(kdbgetintenv);
EXPORT_SYMBOL(kdbgetaddrarg);
EXPORT_SYMBOL(kdb);
EXPORT_SYMBOL(kdb_on);
+EXPORT_SYMBOL(kdb_stateset);
EXPORT_SYMBOL(kdb_seqno);
EXPORT_SYMBOL(kdb_initial_cpu);
EXPORT_SYMBOL(kdbgetsymval);
Index: linux-2.6.10/kernel/sysctl.c
===================================================================
--- linux-2.6.10.orig/kernel/sysctl.c
+++ linux-2.6.10/kernel/sysctl.c
@@ -47,6 +47,7 @@
#include <asm/processor.h>
#ifdef CONFIG_KDB
#include <linux/kdb.h>
+int kdb_current_state;
static int proc_do_kdb(ctl_table *table, int write, struct file *filp, void
*buffer, size_t *lenp, loff_t *ppos);
#endif /* CONFIG_KDB */
@@ -621,8 +622,8 @@ static ctl_table kern_table[] = {
{
.ctl_name = KERN_KDB,
.procname = "kdb",
- .data = &kdb_on,
- .maxlen = sizeof(kdb_on),
+ .data = &kdb_current_state,
+ .maxlen = sizeof(kdb_current_state),
.mode = 0644,
.proc_handler = &proc_do_kdb,
},
@@ -2344,6 +2345,7 @@ static int proc_do_kdb(ctl_table *table,
void *buffer, size_t *lenp, loff_t *ppos)
{
#ifdef CONFIG_SYSCTL
+ kdb_stateset (kdb_current_state);
if (KDB_FLAG(NO_CONSOLE) && write) {
printk(KERN_ERR "kdb has no working console and has switched
itself off\n");
return -EINVAL;
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.