svn commit: r258024 - in head/sys: conf powerpc/aim powerpc/booke powerpc/powerpc

Nathan Whitehorn nwhitehorn at FreeBSD.org
Tue Nov 12 01:15:27 UTC 2013


Author: nwhitehorn
Date: Mon Nov 11 23:37:16 2013
New Revision: 258024
URL: http://svnweb.freebsd.org/changeset/base/258024

Log:
  Use the same implementation of copyinout.c for both AIM and Book-E. This
  fixes some bugs in both implementations related to validity checks on
  mapping bounds.

Added:
  head/sys/powerpc/powerpc/copyinout.c
     - copied, changed from r257990, head/sys/powerpc/aim/copyinout.c
Deleted:
  head/sys/powerpc/aim/copyinout.c
  head/sys/powerpc/booke/copyinout.c
Modified:
  head/sys/conf/files.powerpc

Modified: head/sys/conf/files.powerpc
==============================================================================
--- head/sys/conf/files.powerpc	Mon Nov 11 22:07:56 2013	(r258023)
+++ head/sys/conf/files.powerpc	Mon Nov 11 23:37:16 2013	(r258024)
@@ -86,7 +86,6 @@ libkern/qdivrem.c		optional	powerpc
 libkern/ucmpdi2.c		optional	powerpc
 libkern/udivdi3.c		optional	powerpc
 libkern/umoddi3.c		optional	powerpc
-powerpc/aim/copyinout.c		optional	aim
 powerpc/aim/interrupt.c		optional	aim
 powerpc/aim/locore.S		optional	aim no-obj
 powerpc/aim/machdep.c		optional	aim
@@ -98,7 +97,6 @@ powerpc/aim/mp_cpudep.c		optional	aim sm
 powerpc/aim/slb.c		optional	aim powerpc64
 powerpc/aim/trap.c		optional	aim
 powerpc/aim/uma_machdep.c	optional	aim
-powerpc/booke/copyinout.c	optional	booke
 powerpc/booke/interrupt.c	optional	booke
 powerpc/booke/locore.S		optional	booke no-obj
 powerpc/booke/machdep.c		optional	booke
@@ -173,6 +171,7 @@ powerpc/powerpc/bcopy.c		standard
 powerpc/powerpc/bus_machdep.c	standard
 powerpc/powerpc/busdma_machdep.c standard
 powerpc/powerpc/clock.c		standard
+powerpc/powerpc/copyinout.c	standard
 powerpc/powerpc/copystr.c	standard
 powerpc/powerpc/cpu.c		standard
 powerpc/powerpc/db_disasm.c	optional	ddb

Copied and modified: head/sys/powerpc/powerpc/copyinout.c (from r257990, head/sys/powerpc/aim/copyinout.c)
==============================================================================
--- head/sys/powerpc/aim/copyinout.c	Mon Nov 11 14:08:25 2013	(r257990, copy source)
+++ head/sys/powerpc/powerpc/copyinout.c	Mon Nov 11 23:37:16 2013	(r258024)
@@ -69,9 +69,11 @@ __FBSDID("$FreeBSD$");
 #include <machine/pcb.h>
 #include <machine/sr.h>
 #include <machine/slb.h>
+#include <machine/vmparam.h>
 
 int	setfault(faultbuf);	/* defined in locore.S */
 
+#ifdef AIM
 /*
  * Makes sure that the right segment of userspace is mapped in.
  */
@@ -132,6 +134,43 @@ set_user_sr(pmap_t pm, const void *addr)
 }
 #endif
 
+static __inline int
+map_user_ptr(pmap_t pm, const void *uaddr, void **kaddr, size_t ulen,
+    size_t *klen)
+{
+	size_t l;
+
+	*kaddr = (char *)USER_ADDR + ((uintptr_t)uaddr & ~SEGMENT_MASK);
+
+	l = ((char *)USER_ADDR + SEGMENT_LENGTH) - (char *)(*kaddr);
+	if (l > ulen)
+		l = ulen;
+	if (klen)
+		*klen = l;
+	else if (l != ulen)
+		return (EFAULT);
+
+	set_user_sr(pm, uaddr);
+
+	return (0);
+}
+#else /* Book-E uses a combined kernel/user mapping */
+static __inline int
+map_user_ptr(pmap_t pm, const void *uaddr, void **kaddr, size_t ulen,
+    size_t *klen)
+{
+
+	if ((uintptr_t)uaddr + ulen > VM_MAXUSER_ADDRESS + PAGE_SIZE)
+		return (EFAULT);
+
+	*kaddr = (void *)(uintptr_t)uaddr;
+	if (klen)
+		*klen = ulen;
+
+	return (0);
+}
+#endif
+
 int
 copyout(const void *kaddr, void *udaddr, size_t len)
 {
@@ -154,13 +193,10 @@ copyout(const void *kaddr, void *udaddr,
 	up = udaddr;
 
 	while (len > 0) {
-		p = (char *)USER_ADDR + ((uintptr_t)up & ~SEGMENT_MASK);
-
-		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
-		if (l > len)
-			l = len;
-
-		set_user_sr(pm,up);
+		if (map_user_ptr(pm, udaddr, (void **)&p, len, &l)) {
+			td->td_pcb->pcb_onfault = NULL;
+			return (-1);
+		}
 
 		bcopy(kp, p, l);
 
@@ -195,13 +231,10 @@ copyin(const void *udaddr, void *kaddr, 
 	up = udaddr;
 
 	while (len > 0) {
-		p = (char *)USER_ADDR + ((uintptr_t)up & ~SEGMENT_MASK);
-
-		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
-		if (l > len)
-			l = len;
-
-		set_user_sr(pm,up);
+		if (map_user_ptr(pm, udaddr, (void **)&p, len, &l)) {
+			td->td_pcb->pcb_onfault = NULL;
+			return (-1);
+		}
 
 		bcopy(p, kp, l);
 
@@ -269,14 +302,16 @@ subyte(void *addr, int byte)
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (char *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
-	set_user_sr(pm,addr);
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
 
 	*p = (char)byte;
 
@@ -295,14 +330,16 @@ suword32(void *addr, int word)
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (int *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
-	set_user_sr(pm,addr);
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
 
 	*p = word;
 
@@ -321,14 +358,16 @@ suword(void *addr, long word)
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (long *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
-	set_user_sr(pm,addr);
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
 
 	*p = word;
 
@@ -361,14 +400,16 @@ fubyte(const void *addr)
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (u_char *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
-	set_user_sr(pm,addr);
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
 
 	val = *p;
 
@@ -387,14 +428,16 @@ fuword32(const void *addr)
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (int32_t *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
-	set_user_sr(pm,addr);
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
 
 	val = *p;
 
@@ -413,14 +456,16 @@ fuword(const void *addr)
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (long *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
-	set_user_sr(pm,addr);
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
 
 	val = *p;
 
@@ -446,15 +491,18 @@ casuword32(volatile uint32_t *addr, uint
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (uint32_t *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
-
-	set_user_sr(pm,(const void *)(vm_offset_t)addr);
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
+	if (map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, sizeof(*p),
+	    NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
 	__asm __volatile (
 		"1:\tlwarx %0, 0, %2\n\t"	/* load old value */
 		"cmplw %3, %0\n\t"		/* compare */
@@ -491,15 +539,18 @@ casuword(volatile u_long *addr, u_long o
 
 	td = curthread;
 	pm = &td->td_proc->p_vmspace->vm_pmap;
-	p = (u_long *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK));
-
-	set_user_sr(pm,(const void *)(vm_offset_t)addr);
 
 	if (setfault(env)) {
 		td->td_pcb->pcb_onfault = NULL;
 		return (-1);
 	}
 
+	if (map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, sizeof(*p),
+	    NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
 	__asm __volatile (
 		"1:\tldarx %0, 0, %2\n\t"	/* load old value */
 		"cmpld %3, %0\n\t"		/* compare */


More information about the svn-src-all mailing list