perf: Clean up perf_{session,alloc} management
[akaros.git] / kern / include / umem.h
index f6b4265..1bd7c0f 100644 (file)
@@ -5,32 +5,57 @@
  *
  * Functions for working with userspace's address space. */
 
+#pragma once
+
 #include <ros/common.h>
 #include <process.h>
 
 /* Is this a valid user pointer for read/write?  It doesn't care if the address
  * is paged out or even an unmapped region: simply if it is in part of the
- * address space that could be RW user */
-static inline bool is_user_rwaddr(void *addr);
-
-/* Can they use the area in the manner of perm? */
-void *user_mem_check(struct proc *p, const void *DANGEROUS va, size_t len,
-                     int perm);
-/* Kills them if they can't use the area in the manner of perm */
-void *user_mem_assert(struct proc *p, const void *DANGEROUS va, size_t len, 
-                      int perm);
-
-/* Copy from proc p into the kernel's dest from src */
-int memcpy_from_user(struct proc *p, void *dest, const void *DANGEROUS va,
-                     size_t len);
-
-/* Copy to proc p into va from the kernel's src */
-int memcpy_to_user(struct proc *p, void *DANGEROUS va, const void *src,
-                   size_t len);
+ * address space that could be RW user.  Will also check for len bytes. */
+static inline bool is_user_rwaddr(const void *addr, size_t len);
+/* Same deal, but read-only */
+static inline bool is_user_raddr(const void *addr, size_t len);
+
+#include <arch/uaccess.h>
+
+int strcpy_from_user(struct proc *p, char *dst, const char *src);
+int strcpy_to_user(struct proc *p, char *dst, const char *src);
+
+/**
+ * @brief Copies data from a user buffer to a kernel buffer.
+ *
+ * @param p    the process associated with the user program
+ *             from which the buffer is being copied
+ * @param dest the destination address of the kernel buffer
+ * @param va   the address of the userspace buffer from which we are copying
+ * @param len  the length of the userspace buffer
+ *
+ * @return ESUCCESS on success
+ * @return -EFAULT  the page assocaited with 'va' is not present, the user
+ *                  lacks the proper permissions, or there was an invalid 'va'
+ */
+int memcpy_from_user(struct proc *p, void *dest, const void *va, size_t len);
+
+/**
+ * @brief Copies data to a user buffer from a kernel buffer.
+ *
+ * @param p    the process associated with the user program
+ *             to which the buffer is being copied
+ * @param dest the destination address of the user buffer
+ * @param src  the address of the kernel buffer from which we are copying
+ * @param len  the length of the user buffer
+ *
+ * @return ESUCCESS on success
+ * @return -EFAULT  the page assocaited with 'va' is not present, the user
+ *                  lacks the proper permissions, or there was an invalid 'va'
+ */
+int memcpy_to_user(struct proc *p, void *dest, const void *src, size_t len);
+
 /* Same as above, but sets errno */
 int memcpy_from_user_errno(struct proc *p, void *dst, const void *src, int len);
 int memcpy_to_user_errno(struct proc *p, void *dst, const void *src, int len);
-                 
+
 /* Creates a buffer (kmalloc) and safely copies into it from va.  Can return an
  * error code.  Check its response with IS_ERR().  Must be paired with
  * user_memdup_free() if this succeeded. */
@@ -41,11 +66,70 @@ void user_memdup_free(struct proc *p, void *va);
 /* Same as memdup, but just does strings.  still needs memdup_freed */
 char *user_strdup(struct proc *p, const char *u_string, size_t strlen);
 char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen);
+char *copy_in_path(struct proc *p, const char *path, size_t path_l);
+void free_path(struct proc *p, char *t_path);
 void *kmalloc_errno(int len);
 bool uva_is_kva(struct proc *p, void *uva, void *kva);
+uintptr_t uva2kva(struct proc *p, void *uva, size_t len, int prot);
+/* In arch/pmap{64}.c */
+uintptr_t gva2gpa(struct proc *p, uintptr_t cr3, uintptr_t gva);
+
+/* Helper for is_user_r{w,}addr.
+ *
+ * These checks are for addresses that the kernel accesses on behalf of the
+ * user, which are mapped into the user's address space.  One interpretation is
+ * whether or not the user is allowed to refer to this memory, hence the
+ * MMAP_LOWEST_VA check.  But note that the user is allowed to attempt virtual
+ * memory accesses outside of this range.  VMM code may interpose on low memory
+ * PFs to emulate certain instructions.  However, the kernel should never be
+ * given such a pointer.
+ *
+ * Without the MMAP_LOWEST_VA check, the kernel would still PF on a bad user
+ * pointer (say the user gave us 0x10; we have nothing mapped at addr 0).
+ * However, it would be more difficult to detect if the PF was the kernel acting
+ * on behalf of the user or if the kernel itself had a null pointer deref.  By
+ * checking early, the kernel will catch low addresses and error out before page
+ * faulting. */
+static inline bool __is_user_addr(const void *addr, size_t len, uintptr_t lim)
+{
+       if (unlikely((uintptr_t) addr < MMAP_LOWEST_VA))
+               return FALSE;
+       if (unlikely((uintptr_t) addr >= lim))
+               return FALSE;
+       if (unlikely(lim - (uintptr_t) addr < len))
+               return FALSE;
+
+       return TRUE;
+}
+
+static inline size_t __valid_user_bytes_from(const void *addr, uintptr_t lim)
+{
+       if (unlikely((uintptr_t) addr < MMAP_LOWEST_VA))
+               return 0;
+       if (unlikely((uintptr_t) addr >= lim))
+               return 0;
+
+       return (size_t) (lim - (uintptr_t) addr);
+}
+
+/* UWLIM is defined as virtual address below which a process can write */
+static inline bool is_user_rwaddr(const void *addr, size_t len)
+{
+       return __is_user_addr(addr, len, UWLIM);
+}
+
+/* ULIM is defined as virtual address below which a process can read */
+static inline bool is_user_raddr(const void *addr, size_t len)
+{
+       return __is_user_addr(addr, len, ULIM);
+}
+
+static inline size_t valid_user_rwbytes_from(const void *addr)
+{
+       return __valid_user_bytes_from(addr, UWLIM);
+}
 
-/* UTOP is defined as virtual address below which a process can write */
-static inline bool is_user_rwaddr(void *addr)
+static inline size_t valid_user_rbytes_from(const void *addr)
 {
-       return ((uintptr_t)addr < UTOP) ? TRUE : FALSE;
+       return __valid_user_bytes_from(addr, ULIM);
 }