aboutsummaryrefslogtreecommitdiff
path: root/pk/usermem.c
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2021-02-10 17:03:03 -0800
committerAndrew Waterman <andrew@sifive.com>2021-03-25 22:21:06 -0700
commit817e7d0dfea820a369a5b5c2d5d729942b7daf42 (patch)
treea725081a6966d928cb9ddacdd2172251ef1691f9 /pk/usermem.c
parentb7f64fe5584094a6fe65d94d5e2382ff9289cbda (diff)
downloadpk-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.c66
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;
+}