From e95621f381ab930a1b7f2be1bfe3259ead616346 Mon Sep 17 00:00:00 2001 From: marius Date: Sun, 24 Aug 2008 20:53:36 +0000 Subject: There's a race in kmem(4) between checking whether a page is resident in the kernel and copying it out, causing a panic when faulting on a nofault entry. Handle this case gracefully by letting the kernel copy functions return EFAULT instead. As such this change addresses the same problem as r154721 does for i386. MFC after: 3 days --- sys/sparc64/sparc64/trap.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sys/sparc64') diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index 44eed95..c1a81cd 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -388,6 +388,7 @@ trap_pfault(struct thread *td, struct trapframe *tf) struct proc *p; vm_offset_t va; vm_prot_t prot; + vm_map_entry_t entry; u_long ctx; int flags; int type; @@ -461,6 +462,19 @@ trap_pfault(struct thread *td, struct trapframe *tf) KASSERT(tf->tf_tstate & TSTATE_PRIV, ("trap_pfault: fault on nucleus context from user mode")); + if (tf->tf_tpc >= (u_long)copy_nofault_begin && + tf->tf_tpc <= (u_long)copy_nofault_end) { + vm_map_lock_read(kernel_map); + if (vm_map_lookup_entry(kernel_map, va, &entry) && + (entry->eflags & MAP_ENTRY_NOFAULT) != 0) { + tf->tf_tpc = (u_long)copy_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + vm_map_unlock_read(kernel_map); + return (0); + } + vm_map_unlock_read(kernel_map); + } + /* * We don't have to worry about process locking or stacks in * the kernel. -- cgit v1.1