patch-2.0.35 linux/arch/i386/kernel/traps.c

Next file: linux/arch/m68k/atari/stram.c
Previous file: linux/arch/i386/kernel/setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.34/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
@@ -192,13 +192,36 @@
 DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
 DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
 
+/* signal_return is directly after ret_from_sys_call in entry.S */
+asmlinkage void ret_from_sys_call(void)	__asm__("ret_from_sys_call");
+asmlinkage void signal_return(void)	__asm__("signal_return");
+
 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 {
 	if (regs->eflags & VM_MASK) {
 		handle_vm86_fault((struct vm86_regs *) regs, error_code);
 		return;
 	}
-	die_if_kernel("general protection",regs,error_code);
+
+	/* 
+	 * HACK HACK HACK  :)  Fixing the segment invalid on syscall return
+	 * barfage for 2.0 has been put into the too-hard basket but having
+	 * a user producing endless GPFs is unacceptable as well. - Paul G.
+	 */
+	if ((regs->cs & 3) != 3) {
+		if (regs->eip >= (unsigned long)ret_from_sys_call &&
+		    regs->eip < (unsigned long)signal_return) {
+			static int moancount = 0;
+			if (moancount < 5) {
+				printk(KERN_INFO "Ignoring GPF attempt from program \"%s\" (pid %d).\n",
+					current->comm, current->pid);
+				moancount++;
+			}
+			do_exit(SIGSEGV);
+		}
+		else 
+			die_if_kernel("general protection",regs,error_code);
+	}
 	current->tss.error_code = error_code;
 	current->tss.trap_no = 13;
 	force_sig(SIGSEGV, current);	

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov