Subject: port-powerpc/7243: copyin()/copyout() do not always clear the pcb_onfault handler
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mbrinico@nc.com>
List: netbsd-bugs
Date: 03/25/1999 19:43:49
>Number:         7243
>Category:       port-powerpc
>Synopsis:       copyin()/copyout() do not always clear the pcb_onfault handler
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    port-powerpc-maintainer (NetBSD/powerpc Portmasters)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 25 19:50:03 1999
>Last-Modified:
>Originator:     Mark Brinicombe
>Organization:
Network Computer Inc
>Release:        NetBSD-current 1999/03/25
>Environment:
	
System: NetBSD p2.devlab.nc.com 1.3I-NCOS NetBSD 1.3I-NCOS (P2) #1: Wed Mar 17 16:37:17 PST 1999 mark@p2.devlab.nc.com:/usr/export/mark/NCOS/os-src/sys/arch/i386/compile/P2 i386


>Description:
	The copyin() and copyout() functions only clear the pcb_onfault handler
	on a successful copy. In the case where the onfault handler catches
	a fault EFAULT is returned but the onfault handler is not cleared.

>How-To-Repeat:
	Look at the code for copyin() and copyout().
	
>Fix:
	clear the pcb_onfault variable in the EFAULT case.
	
*** trap.c.orig	Thu Mar 25 19:15:36 1999
--- trap.c	Thu Mar 25 19:36:49 1999
***************
*** 396,403 ****
  	size_t l;
  	faultbuf env;
  
! 	if (setfault(env))
  		return EFAULT;
  	while (len > 0) {
  		p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
  		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
--- 396,405 ----
  	size_t l;
  	faultbuf env;
  
! 	if (setfault(env)) {
! 		curpcb->pcb_onfault = 0;
  		return EFAULT;
+ 	}
  	while (len > 0) {
  		p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
  		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
***************
*** 425,432 ****
  	size_t l;
  	faultbuf env;
  
! 	if (setfault(env))
  		return EFAULT;
  	while (len > 0) {
  		p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
  		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
--- 427,436 ----
  	size_t l;
  	faultbuf env;
  
! 	if (setfault(env)) {
! 		curpcb->pcb_onfault = 0;
  		return EFAULT;
+ 	}
  	while (len > 0) {
  		p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
  		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
>Audit-Trail:
>Unformatted: