Permit supervisor to access user VA space for certain functions only.

This is done by setting SUM (permit Supervisor User Memory access)
bit in sstatus register.

The functions we allow access for are routines in assembly that
explicitly handle crossing the user kernel boundary.

Approved by:	re (kib)
Sponsored by:	DARPA, AFRL
This commit is contained in:
br 2018-09-05 11:34:58 +00:00
parent 95fb6bf7ba
commit 54f3f3f9dc
6 changed files with 49 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -63,4 +63,12 @@
ld tmp, TD_PCB(tmp); /* Load the pcb */ \
sd handler, PCB_ONFAULT(tmp) /* Set the handler */
#define ENTER_USER_ACCESS(tmp) \
li tmp, SSTATUS_SUM; \
csrs sstatus, tmp
#define EXIT_USER_ACCESS(tmp) \
li tmp, SSTATUS_SUM; \
csrc sstatus, tmp
#endif /* _MACHINE_ASM_H_ */

View File

@ -35,6 +35,7 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <machine/riscvreg.h>
#include <sys/errno.h>
#include "assym.inc"
@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$");
*/
ENTRY(copyio_fault)
SET_FAULT_HANDLER(x0, a1) /* Clear the handler */
EXIT_USER_ACCESS(a1)
copyio_fault_nopcb:
li a0, EFAULT
ret
@ -62,6 +64,7 @@ ENTRY(copyout)
la a6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(a6, a7) /* Set the handler */
ENTER_USER_ACCESS(a7)
1: lb a4, 0(a0) /* Load from kaddr */
addi a0, a0, 1
@ -70,6 +73,7 @@ ENTRY(copyout)
addi a2, a2, -1 /* len-- */
bnez a2, 1b
EXIT_USER_ACCESS(a7)
SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
2: li a0, 0 /* return 0 */
@ -89,6 +93,7 @@ ENTRY(copyin)
la a6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(a6, a7) /* Set the handler */
ENTER_USER_ACCESS(a7)
1: lb a4, 0(a0) /* Load from uaddr */
addi a0, a0, 1
@ -97,6 +102,7 @@ ENTRY(copyin)
addi a2, a2, -1 /* len-- */
bnez a2, 1b
EXIT_USER_ACCESS(a7)
SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
2: li a0, 0 /* return 0 */
@ -114,6 +120,7 @@ ENTRY(copyinstr)
la a6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(a6, a7) /* Set the handler */
ENTER_USER_ACCESS(a7)
li a7, VM_MAXUSER_ADDRESS
1: bgt a0, a7, copyio_fault
@ -125,8 +132,9 @@ ENTRY(copyinstr)
addi a2, a2, -1 /* len-- */
addi a5, a5, 1 /* count++ */
bnez a2, 1b
2: SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
2: EXIT_USER_ACCESS(a7)
SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
3: beqz a3, 4f /* Check if done != NULL */
addi a5, a5, 1 /* count++ */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -116,11 +116,8 @@ __FBSDID("$FreeBSD$");
.macro load_registers el
ld t0, (TF_SSTATUS)(sp)
.if \el == 0
/*
* Ensure user interrupts will be enabled on eret
* and supervisor mode can access userspace on trap.
*/
li t1, (SSTATUS_SPIE | SSTATUS_SUM)
/* Ensure user interrupts will be enabled on eret */
li t1, SSTATUS_SPIE
or t0, t0, t1
.else
/*

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -62,9 +62,6 @@ _start:
mv s10, a0 /* s10 = hart id */
mv s11, a1 /* s11 = dtbp */
li t0, SSTATUS_SUM
csrs sstatus, t0
/* Direct secondary cores to mpentry */
bnez s10, mpentry

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -36,6 +36,7 @@
__FBSDID("$FreeBSD$");
#include <machine/setjmp.h>
#include <machine/riscvreg.h>
#include "assym.inc"
@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$");
*/
ENTRY(fsu_fault)
SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */
EXIT_USER_ACCESS(a1)
fsu_fault_nopcb:
li a0, -1
ret
@ -57,11 +59,13 @@ ENTRY(casueword32)
bgt a0, a4, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a4) /* And set it */
ENTER_USER_ACCESS(a4)
1: lr.w a4, 0(a0) /* Load-exclusive the data */
bne a4, a1, 2f /* If not equal then exit */
sc.w a5, a3, 0(a0) /* Store the new data */
bnez a5, 1b /* Retry on failure */
2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
2: EXIT_USER_ACCESS(a5)
SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
sw a4, 0(a2) /* Store the read data */
li a0, 0 /* Success */
ret /* Return */
@ -75,11 +79,13 @@ ENTRY(casueword)
bgt a0, a4, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a4) /* And set it */
ENTER_USER_ACCESS(a4)
1: lr.d a4, 0(a0) /* Load-exclusive the data */
bne a4, a1, 2f /* If not equal then exit */
sc.d a5, a3, 0(a0) /* Store the new data */
bnez a5, 1b /* Retry on failure */
2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
2: EXIT_USER_ACCESS(a5)
SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
sd a4, 0(a2) /* Store the read data */
li a0, 0 /* Success */
ret /* Return */
@ -93,7 +99,9 @@ ENTRY(fubyte)
bgt a0, a1, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a1) /* And set it */
ENTER_USER_ACCESS(a1)
lb a0, 0(a0) /* Try loading the data */
EXIT_USER_ACCESS(a1)
SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */
ret /* Return */
END(fubyte)
@ -106,7 +114,9 @@ ENTRY(fuword16)
bgt a0, a1, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a1) /* And set it */
ENTER_USER_ACCESS(a1)
lh a0, 0(a0) /* Try loading the data */
EXIT_USER_ACCESS(a1)
SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */
ret /* Return */
END(fuword16)
@ -119,7 +129,9 @@ ENTRY(fueword32)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ENTER_USER_ACCESS(a2)
lw a0, 0(a0) /* Try loading the data */
EXIT_USER_ACCESS(a2)
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
sw a0, 0(a1) /* Save the data in kernel space */
li a0, 0 /* Success */
@ -136,7 +148,9 @@ EENTRY(fueword64)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ENTER_USER_ACCESS(a2)
ld a0, 0(a0) /* Try loading the data */
EXIT_USER_ACCESS(a2)
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
sd a0, 0(a1) /* Save the data in kernel space */
li a0, 0 /* Success */
@ -152,7 +166,9 @@ ENTRY(subyte)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ENTER_USER_ACCESS(a2)
sb a1, 0(a0) /* Try storing the data */
EXIT_USER_ACCESS(a2)
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
@ -166,7 +182,9 @@ ENTRY(suword16)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ENTER_USER_ACCESS(a2)
sh a1, 0(a0) /* Try storing the data */
EXIT_USER_ACCESS(a2)
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
@ -180,7 +198,9 @@ ENTRY(suword32)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ENTER_USER_ACCESS(a2)
sw a1, 0(a0) /* Try storing the data */
EXIT_USER_ACCESS(a2)
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
@ -195,7 +215,9 @@ EENTRY(suword64)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ENTER_USER_ACCESS(a2)
sd a1, 0(a0) /* Try storing the data */
EXIT_USER_ACCESS(a2)
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -105,7 +105,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
tf->tf_a[0] = 0;
tf->tf_a[1] = 0;
tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */
tf->tf_sstatus |= (SSTATUS_SUM); /* Supervisor can access userspace. */
tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */
td2->td_frame = tf;