--- linux-2.2.10/arch/alpha/mm/fault.c~ Mon Jan 18 02:29:00 1999 +++ linux-2.2.10/arch/alpha/mm/fault.c Sun Jul 18 16:33:21 1999 @@ -163,9 +163,18 @@ if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } - handle_mm_fault(current, vma, address, cause > 0); +survive: + { + int fault = handle_mm_fault(current, vma, address, cause > 0); + if (!fault) + goto do_sigbus; + if (fault < 0) + goto out_of_memory; + } up(&mm->mmap_sem); - goto out; + out_unlock: + unlock_kernel(); + return; /* * Something tried to access memory that isn't in our memory map.. @@ -176,9 +185,10 @@ if (user_mode(regs)) { force_sig(SIGSEGV, current); - goto out; + goto out_unlock; } +no_context: /* Are we prepared to handle this fault as an exception? */ if ((fixup = search_exception_table(regs->pc)) != 0) { unsigned long newpc; @@ -186,7 +196,7 @@ printk("%s: Exception at [<%lx>] (%lx)\n", current->comm, regs->pc, newpc); regs->pc = newpc; - goto out; + goto out_unlock; } /* @@ -197,7 +207,37 @@ "virtual address %016lx\n", address); die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16); do_exit(SIGKILL); - out: - unlock_kernel(); -} +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + if (current->pid == 1) + { + current->policy |= SCHED_YIELD; + schedule(); + goto survive; + } + up(&mm->mmap_sem); + if (user_mode(regs)) + { + printk("VM: killing process %s\n", current->comm); + do_exit(SIGKILL); + } + goto no_context; + +do_sigbus: + up(&mm->mmap_sem); + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + force_sig(SIGBUS, current); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; + goto out_unlock; +} --- linux-2.2.10/arch/alpha/kernel/ptrace.c~ Mon Jan 18 02:29:01 1999 +++ linux-2.2.10/arch/alpha/kernel/ptrace.c Sun Jul 18 16:00:44 1999 @@ -149,13 +149,18 @@ pmd_t * pgmiddle; pte_t * pgtable; unsigned long page; + int fault; DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr)); repeat: pgdir = pgd_offset(vma->vm_mm, addr); if (pgd_none(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 0); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return 0; } if (pgd_bad(*pgdir)) { printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); @@ -164,8 +169,12 @@ } pgmiddle = pmd_offset(pgdir, addr); if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 0); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return 0; } if (pmd_bad(*pgmiddle)) { printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); @@ -174,8 +183,12 @@ } pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 0); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return 0; } page = pte_page(*pgtable); /* this is a hack for non-kernel-mapped video buffers and similar */ @@ -202,12 +215,17 @@ pmd_t *pgmiddle; pte_t *pgtable; unsigned long page; + int fault; repeat: pgdir = pgd_offset(vma->vm_mm, addr); if (!pgd_present(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 1); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return; } if (pgd_bad(*pgdir)) { printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); @@ -216,8 +234,12 @@ } pgmiddle = pmd_offset(pgdir, addr); if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 1); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return; } if (pmd_bad(*pgmiddle)) { printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); @@ -226,13 +248,21 @@ } pgtable = pte_offset(pgmiddle, addr); if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 1); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return; } page = pte_page(*pgtable); if (!pte_write(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; + fault = handle_mm_fault(tsk, vma, addr, 1); + if (fault > 0) + goto repeat; + if (fault < 0) + force_sig(SIGKILL, current); + return; } /* This is a hack for non-kernel-mapped video buffers and similar. */ --- linux-2.2.10/arch/alpha/kernel/signal.c~ Tue Jul 13 00:33:20 1999 +++ linux-2.2.10/arch/alpha/kernel/signal.c Sun Jul 18 16:02:35 1999 @@ -438,6 +438,8 @@ err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); } + if (err) + goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */ @@ -500,6 +502,8 @@ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, set->sig[0], oldsp); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */