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_ */
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to