Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Oct 2015 17:40:40 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r289372 - in head/sys/arm: arm include
Message-ID:  <201510151740.t9FHeeEY076864@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Thu Oct 15 17:40:39 2015
New Revision: 289372
URL: https://svnweb.freebsd.org/changeset/base/289372

Log:
  ARM userspace accessors, e.g. {s,f}uword(9), copy{in,out}(9),
  casuword(9) and others, use LDRT and STRT instructions to access
  memory with the privileges of userspace.  If the *RT instruction
  faults on the kernel address, then additional checks must be done to
  not confuse the VM system with invalid kernel-mode faults.
  
  Put ARM on line with other FreeBSD architectures and disallow usermode
  buffers which intersect with the kernel address space in advance,
  before any accesses are performed.  In other words, vm_fault(9) is no
  longer called when e.g. suword(9) stores to invalid (i.e. not
  userspace) address.
  
  Also, switch ARM to use fueword(9) and casueword(9).
  
  Note: there is a pending patch in D3617, which adds the special
  processing for faults from LDRT and STRT.  The addition of the
  processing is useful for potential other uses of the instructions and
  for completeness, but standard userspace accessors are better served
  by not allowing such faults beforehand.
  
  Reviewed by:	andrew
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D3816
  MFC after:	2 weeks

Modified:
  head/sys/arm/arm/bcopyinout.S
  head/sys/arm/arm/bcopyinout_xscale.S
  head/sys/arm/arm/copystr.S
  head/sys/arm/arm/fusu.S
  head/sys/arm/arm/genassym.c
  head/sys/arm/include/param.h

Modified: head/sys/arm/arm/bcopyinout.S
==============================================================================
--- head/sys/arm/arm/bcopyinout.S	Thu Oct 15 17:36:56 2015	(r289371)
+++ head/sys/arm/arm/bcopyinout.S	Thu Oct 15 17:40:39 2015	(r289372)
@@ -94,6 +94,15 @@ ENTRY(copyin)
 	moveq	r0, #0
 	RETeq
 
+	adds	r3, r0, r2
+	movcs	r0, #EFAULT
+	RETc(cs)
+
+	ldr	r12, =(VM_MAXUSER_ADDRESS + 1)
+	cmp	r3, r12
+	movcs	r0, #EFAULT
+	RETc(cs)
+
 	ldr	r3, .L_arm_memcpy
 	ldr	r3, [r3]
 	cmp	r3, #0
@@ -332,6 +341,15 @@ ENTRY(copyout)
 	moveq	r0, #0
 	RETeq
 
+	adds	r3, r1, r2
+	movcs	r0, #EFAULT
+	RETc(cs)
+
+	ldr	r12, =(VM_MAXUSER_ADDRESS + 1)
+	cmp	r3, r12
+	movcs	r0, #EFAULT
+	RETc(cs)
+
 	ldr	r3, .L_arm_memcpy
 	ldr	r3, [r3]
 	cmp	r3, #0

Modified: head/sys/arm/arm/bcopyinout_xscale.S
==============================================================================
--- head/sys/arm/arm/bcopyinout_xscale.S	Thu Oct 15 17:36:56 2015	(r289371)
+++ head/sys/arm/arm/bcopyinout_xscale.S	Thu Oct 15 17:40:39 2015	(r289372)
@@ -67,6 +67,15 @@ ENTRY(copyin)
 	movle	r0, #0x00
 	movle	pc, lr			/* Bail early if length is <= 0 */
 
+	adds	r3, r0, r2
+	movcs	r0, #EFAULT
+	RETc(cs)
+
+	ldr	r12, =(VM_MAXUSER_ADDRESS + 1)
+	cmp	r3, r12
+	movcs	r0, #EFAULT
+	RETc(cs)
+
 	ldr	r3, .L_arm_memcpy
 	ldr	r3, [r3]
 	cmp	r3, #0
@@ -509,6 +518,15 @@ ENTRY(copyout)
 	movle	r0, #0x00
 	movle	pc, lr			/* Bail early if length is <= 0 */
 
+	adds	r3, r1, r2
+	movcs	r0, #EFAULT
+	RETc(cs)
+
+	ldr	r12, =(VM_MAXUSER_ADDRESS + 1)
+	cmp	r3, r12
+	movcs	r0, #EFAULT
+	RETc(cs)
+
 	ldr	r3, .L_arm_memcpy
 	ldr	r3, [r3]
 	cmp	r3, #0

Modified: head/sys/arm/arm/copystr.S
==============================================================================
--- head/sys/arm/arm/copystr.S	Thu Oct 15 17:36:56 2015	(r289371)
+++ head/sys/arm/arm/copystr.S	Thu Oct 15 17:40:39 2015	(r289372)
@@ -113,6 +113,8 @@ ENTRY(copyinstr)
 	moveq	r0, #ENAMETOOLONG
 	beq	2f
 
+	ldr	r12, =VM_MAXUSER_ADDRESS
+
 	GET_PCB(r4)
 	ldr	r4, [r4]
 
@@ -124,7 +126,10 @@ ENTRY(copyinstr)
 	adr	r5, .Lcopystrfault
 	str	r5, [r4, #PCB_ONFAULT]
 
-1:	ldrbt	r5, [r0], #0x0001
+1:
+	cmp	r0, r12
+	bcs	.Lcopystrfault
+	ldrbt	r5, [r0], #0x0001
 	add	r6, r6, #0x00000001
 	teq	r5, #0x00000000
 	strb	r5, [r1], #0x0001
@@ -161,6 +166,8 @@ ENTRY(copyoutstr)
 	moveq	r0, #ENAMETOOLONG
 	beq	2f
 
+	ldr	r12, =VM_MAXUSER_ADDRESS
+
 	GET_PCB(r4)
 	ldr	r4, [r4]
 
@@ -172,7 +179,10 @@ ENTRY(copyoutstr)
 	adr	r5, .Lcopystrfault
 	str	r5, [r4, #PCB_ONFAULT]
 
-1:	ldrb	r5, [r0], #0x0001
+1:
+	cmp	r0, r12
+	bcs	.Lcopystrfault
+	ldrb	r5, [r0], #0x0001
 	add	r6, r6, #0x00000001
 	teq	r5, #0x00000000
 	strbt	r5, [r1], #0x0001
@@ -195,9 +205,9 @@ END(copyoutstr)
 
 /* A fault occurred during the copy */
 .Lcopystrfault:
-	mov	r0, #EFAULT
 	mov	r1, #0x00000000
 	str	r1, [r4, #PCB_ONFAULT]
+	mov	r0, #EFAULT
 	RESTORE_REGS
 	RET
 

Modified: head/sys/arm/arm/fusu.S
==============================================================================
--- head/sys/arm/arm/fusu.S	Thu Oct 15 17:36:56 2015	(r289371)
+++ head/sys/arm/arm/fusu.S	Thu Oct 15 17:40:39 2015	(r289372)
@@ -53,49 +53,51 @@ __FBSDID("$FreeBSD$");
 #endif
 
 /*
- * fuword(caddr_t uaddr);
- * Fetch an int from the user's address space.
+ * casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
+ *    uint32_t newval);
  */
 
-ENTRY(casuword)
-EENTRY_NP(casuword32)
-	GET_PCB(r3)
-	ldr	r3, [r3]
+ENTRY(casueword)
+EENTRY_NP(casueword32)
+	stmfd	sp!, {r4, r5, r6}
+
+	ldr	r4, =(VM_MAXUSER_ADDRESS-3)
+	cmp	r0, r4
+	mvncs	r0, #0
+	bcs	2f
+
+	GET_PCB(r6)
+	ldr	r6, [r6]
 
 #ifdef DIAGNOSTIC
-	teq	r3, #0x00000000
+	teq	r6, #0x00000000
+	ldmfdeq	sp!, {r4, r5, r6}
 	beq	.Lfusupcbfault
 #endif
-	stmfd	sp!, {r4, r5}
+
 	adr	r4, .Lcasuwordfault
-	str	r4, [r3, #PCB_ONFAULT]
+	str	r4, [r6, #PCB_ONFAULT]
+
 #if __ARM_ARCH >= 6
 1:
-	cmp     r0, #KERNBASE
-	mvnhs   r0, #0
-	bhs     2f
-
-	ldrex   r5, [r0]
-	cmp     r5, r1
-	movne   r0, r5
-	bne     2f
-	strex   r5, r2, [r0]
-	cmp     r5, #0
-	bne     1b
+	ldrex	r4, [r0]
+	cmp	r4, r1
+	strexeq	r5, r3, [r0]
+	cmpeq	r5, #1
+	beq	1b
 #else
-	ldrt	r5, [r0]
-	cmp	r5, r1
-	movne	r0, r5
-	strteq	r2, [r0]
-#endif
-	moveq	r0, r1
+	ldrt	r4, [r0]
+	cmp	r4, r1
+	strteq	r3, [r0]
+#endif
+	str	r4, [r2]
+	mov	r0, #0
+	str	r0, [r6, #PCB_ONFAULT]
 2:
-	ldmfd	sp!, {r4, r5}
-	mov	r1, #0x00000000
-	str	r1, [r3, #PCB_ONFAULT]
+	ldmfd	sp!, {r4, r5, r6}
 	RET
-EEND(casuword32)
-END(casuword)
+EEND(casueword32)
+END(casueword)
 
 /*
  * Handle faults from casuword.  Clean up and return -1.
@@ -103,18 +105,23 @@ END(casuword)
 
 .Lcasuwordfault:
 	mov	r0, #0x00000000
-	str	r0, [r3, #PCB_ONFAULT]
-	mvn	r0, #0x00000000
-	ldmfd	sp!, {r4, r5}
+	str	r0, [r6, #PCB_ONFAULT]
+	mvn	r0, #0
+	ldmfd	sp!, {r4, r5, r6}
 	RET
 
 /*
- * fuword(caddr_t uaddr);
+ * fueword(caddr_t uaddr, long *val);
  * Fetch an int from the user's address space.
  */
 
-ENTRY(fuword)
-EENTRY_NP(fuword32)
+ENTRY(fueword)
+EENTRY_NP(fueword32)
+	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	GET_PCB(r2)
 	ldr	r2, [r2]
 
@@ -123,14 +130,14 @@ EENTRY_NP(fuword32)
 	beq	.Lfusupcbfault
 #endif
 
-	adr	r1, .Lfusufault
-	str	r1, [r2, #PCB_ONFAULT]
+	adr	r3, .Lfusufault
+	str	r3, [r2, #PCB_ONFAULT]
 
 	ldrt	r3, [r0]
+	str	r3, [r1]
 
-	mov	r1, #0x00000000
-	str	r1, [r2, #PCB_ONFAULT]
-	mov	r0, r3
+	mov	r0, #0x00000000
+	str	r0, [r2, #PCB_ONFAULT]
 	RET
 EEND(fuword32)
 END(fuword)
@@ -141,6 +148,11 @@ END(fuword)
  */
 
 ENTRY(fusword)
+	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	GET_PCB(r2)
 	ldr	r2, [r2]
 
@@ -171,6 +183,11 @@ END(fusword)
  */
 
 ENTRY(fuswintr)
+	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	ldr	r2, Lblock_userspace_access
 	ldr	r2, [r2]
 	teq	r2, #0
@@ -217,6 +234,11 @@ _C_LABEL(block_userspace_access):
  */
 
 ENTRY(fubyte)
+	ldr	r3, =VM_MAXUSER_ADDRESS
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	GET_PCB(r2)
 	ldr	r2, [r2]
 
@@ -282,6 +304,11 @@ fusupcbfaulttext:
 
 ENTRY(suword)
 EENTRY_NP(suword32)
+	ldr	r3, =(VM_MAXUSER_ADDRESS-3)
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	GET_PCB(r2)
 	ldr	r2, [r2]
 
@@ -308,6 +335,11 @@ END(suword)
  */
 
 ENTRY(suswintr)
+	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	ldr	r2, Lblock_userspace_access
 	ldr	r2, [r2]
 	teq	r2, #0
@@ -345,6 +377,11 @@ END(suswintr)
  */
 
 ENTRY(susword)
+	ldr	r3, =(VM_MAXUSER_ADDRESS-1)
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	GET_PCB(r2)
 	ldr	r2, [r2]
 
@@ -376,6 +413,11 @@ END(susword)
  */
 
 ENTRY(subyte)
+	ldr	r3, =VM_MAXUSER_ADDRESS
+	cmp	r0, r3
+	mvncs	r0, #0
+	RETc(cs)
+
 	GET_PCB(r2)
 	ldr	r2, [r2]
 

Modified: head/sys/arm/arm/genassym.c
==============================================================================
--- head/sys/arm/arm/genassym.c	Thu Oct 15 17:36:56 2015	(r289371)
+++ head/sys/arm/arm/genassym.c	Thu Oct 15 17:40:39 2015	(r289372)
@@ -161,6 +161,7 @@ ASSYM(P_VMSPACE, offsetof(struct proc, p
 ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
 ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
 ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid));
+ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
 
 ASSYM(DCACHE_LINE_SIZE, offsetof(struct cpuinfo, dcache_line_size));
 ASSYM(DCACHE_LINE_MASK, offsetof(struct cpuinfo, dcache_line_mask));

Modified: head/sys/arm/include/param.h
==============================================================================
--- head/sys/arm/include/param.h	Thu Oct 15 17:36:56 2015	(r289371)
+++ head/sys/arm/include/param.h	Thu Oct 15 17:40:39 2015	(r289372)
@@ -149,8 +149,4 @@
 
 #define	pgtok(x)		((x) * (PAGE_SIZE / 1024))
 
-#ifdef _KERNEL
-#define	NO_FUEWORD	1
-#endif
-
 #endif /* !_ARM_INCLUDE_PARAM_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510151740.t9FHeeEY076864>