patch-2.4.20 linux-2.4.20/arch/sparc64/mm/fault.c

Next file: linux-2.4.20/arch/sparc64/mm/init.c
Previous file: linux-2.4.20/arch/sparc64/lib/blockops.S
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/arch/sparc64/mm/fault.c linux-2.4.20/arch/sparc64/mm/fault.c
@@ -129,8 +129,8 @@
 	return tally;
 }
 
-void unhandled_fault(unsigned long address, struct task_struct *tsk,
-                     struct pt_regs *regs)
+static void unhandled_fault(unsigned long address, struct task_struct *tsk,
+			    struct pt_regs *regs)
 {
 	if ((unsigned long) address < PAGE_SIZE) {
 		printk(KERN_ALERT "Unable to handle kernel NULL "
@@ -147,6 +147,19 @@
 	die_if_kernel("Oops", regs);
 }
 
+extern void show_trace_raw(struct task_struct *, unsigned long);
+
+static void bad_kernel_pc(struct pt_regs *regs)
+{
+	unsigned long ksp;
+
+	printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
+	       regs->tpc);
+	__asm__("mov %%sp, %0" : "=r" (ksp));
+	show_trace_raw(current, ksp);
+	unhandled_fault(regs->tpc, current, regs);
+}
+
 /*
  * We now make sure that mmap_sem is held in all paths that call 
  * this. Additionally, to prevent kswapd from ripping ptes from
@@ -211,7 +224,7 @@
 		if (!regs->tpc || (regs->tpc & 0x3))
 			return 0;
 		if (regs->tstate & TSTATE_PRIV) {
-			insn = *(unsigned int *)regs->tpc;
+			insn = *(unsigned int *) regs->tpc;
 		} else {
 			insn = get_user_insn(regs->tpc);
 		}
@@ -302,6 +315,20 @@
 	    (fault_code & FAULT_CODE_DTLB))
 		BUG();
 
+	if (regs->tstate & TSTATE_PRIV) {
+		unsigned long tpc = regs->tpc;
+		extern unsigned int _etext;
+
+		/* Sanity check the PC. */
+		if ((tpc >= KERNBASE && tpc < (unsigned long) &_etext) ||
+		    (tpc >= MODULES_VADDR && tpc < MODULES_END)) {
+			/* Valid, no problems... */
+		} else {
+			bad_kernel_pc(regs);
+			return;
+		}
+	}
+
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)