bug in kdb - patch to fix

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


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 <sdake at mvista.com>
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.


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]

Add to Google Powered by Linux