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.

Reply via email to