diff options
author | Andrew Waterman <andrew@sifive.com> | 2021-02-10 17:03:03 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2021-03-25 22:21:06 -0700 |
commit | 817e7d0dfea820a369a5b5c2d5d729942b7daf42 (patch) | |
tree | a725081a6966d928cb9ddacdd2172251ef1691f9 /pk/usermem.c | |
parent | b7f64fe5584094a6fe65d94d5e2382ff9289cbda (diff) | |
download | pk-817e7d0dfea820a369a5b5c2d5d729942b7daf42.zip pk-817e7d0dfea820a369a5b5c2d5d729942b7daf42.tar.gz pk-817e7d0dfea820a369a5b5c2d5d729942b7daf42.tar.bz2 |
pk: only access user memory through explicit accessors
Enforced with sstatus.SUM.
Diffstat (limited to 'pk/usermem.c')
-rw-r--r-- | pk/usermem.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/pk/usermem.c b/pk/usermem.c new file mode 100644 index 0000000..b65e515 --- /dev/null +++ b/pk/usermem.c @@ -0,0 +1,66 @@ +// See LICENSE for license details. + +#include "usermem.h" +#include "mmap.h" +#include <string.h> +#include <stdint.h> + +void memset_user(void* dst, int ch, size_t n) +{ + if ((uintptr_t)dst + n < (uintptr_t)dst || !is_uva(dst + n - 1)) + handle_page_fault((uintptr_t)dst, PROT_WRITE); + + uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM); + + memset(dst, ch, n); + + write_csr(sstatus, sstatus); +} + +void memcpy_to_user(void* dst, const void* src, size_t n) +{ + if ((uintptr_t)dst + n < (uintptr_t)dst || !is_uva(dst + n - 1)) + handle_page_fault((uintptr_t)dst, PROT_WRITE); + + uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM); + + memcpy(dst, src, n); + + write_csr(sstatus, sstatus); +} + +void memcpy_from_user(void* dst, const void* src, size_t n) +{ + if ((uintptr_t)src + n < (uintptr_t)src || !is_uva(src + n - 1)) + handle_page_fault((uintptr_t)src, PROT_READ); + + uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM); + + memcpy(dst, src, n); + + write_csr(sstatus, sstatus); +} + +bool strcpy_from_user(char* dst, const char* src, size_t n) +{ + uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM); + + while (n > 0) { + if (!is_uva(src)) + handle_page_fault((uintptr_t)src, PROT_READ); + + char ch = *(volatile const char*)src; + *dst = ch; + + if (ch == 0) + return true; + + src++; + dst++; + n--; + } + + write_csr(sstatus, sstatus); + + return false; +} |