akaros/kern/include/umem.h
<<
>>
Prefs
   1/* Copyright (c) 2009, 2010 The Regents of the University of California
   2 * Barret Rhoden <brho@cs.berkeley.edu>
   3 * Andrew Waterman <waterman@cs.berkeley.edu>
   4 * See LICENSE for details.
   5 *
   6 * Functions for working with userspace's address space. */
   7
   8#pragma once
   9
  10#include <ros/common.h>
  11#include <process.h>
  12
  13/* Is this a valid user pointer for read/write?  It doesn't care if the address
  14 * is paged out or even an unmapped region: simply if it is in part of the
  15 * address space that could be RW user.  Will also check for len bytes. */
  16static inline bool is_user_rwaddr(const void *addr, size_t len);
  17/* Same deal, but read-only */
  18static inline bool is_user_raddr(const void *addr, size_t len);
  19
  20#include <arch/uaccess.h>
  21
  22int strcpy_from_user(struct proc *p, char *dst, const char *src);
  23int strcpy_to_user(struct proc *p, char *dst, const char *src);
  24
  25/**
  26 * @brief Copies data from a user buffer to a kernel buffer.
  27 *
  28 * @param p    the process associated with the user program
  29 *             from which the buffer is being copied
  30 * @param dest the destination address of the kernel buffer
  31 * @param va   the address of the userspace buffer from which we are copying
  32 * @param len  the length of the userspace buffer
  33 *
  34 * @return ESUCCESS on success
  35 * @return -EFAULT  the page assocaited with 'va' is not present, the user
  36 *                  lacks the proper permissions, or there was an invalid 'va'
  37 */
  38int memcpy_from_user(struct proc *p, void *dest, const void *va, size_t len);
  39
  40/**
  41 * @brief Copies data to a user buffer from a kernel buffer.
  42 *
  43 * @param p    the process associated with the user program
  44 *             to which the buffer is being copied
  45 * @param dest the destination address of the user buffer
  46 * @param src  the address of the kernel buffer from which we are copying
  47 * @param len  the length of the user buffer
  48 *
  49 * @return ESUCCESS on success
  50 * @return -EFAULT  the page assocaited with 'va' is not present, the user
  51 *                  lacks the proper permissions, or there was an invalid 'va'
  52 */
  53int memcpy_to_user(struct proc *p, void *dest, const void *src, size_t len);
  54
  55/* Same as above, but sets errno */
  56int memcpy_from_user_errno(struct proc *p, void *dst, const void *src, int len);
  57int memcpy_to_user_errno(struct proc *p, void *dst, const void *src, int len);
  58int memcpy_to_safe(void *dst, const void *src, size_t amt);
  59int memcpy_from_safe(void *dst, const void *src, size_t amt);
  60
  61/* Creates a buffer (kmalloc) and safely copies into it from va.  Can return an
  62 * error code.  Check its response with IS_ERR().  Must be paired with
  63 * user_memdup_free() if this succeeded. */
  64void *user_memdup(struct proc *p, const void *va, int len);
  65/* Same as above, but sets errno */
  66void *user_memdup_errno(struct proc *p, const void *va, int len);
  67void user_memdup_free(struct proc *p, void *va);
  68/* Same as memdup, but just does strings.  still needs memdup_freed */
  69char *user_strdup(struct proc *p, const char *u_string, size_t strlen);
  70char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen);
  71char *copy_in_path(struct proc *p, const char *path, size_t path_l);
  72void free_path(struct proc *p, char *t_path);
  73void *kmalloc_errno(int len);
  74bool uva_is_kva(struct proc *p, void *uva, void *kva);
  75uintptr_t uva2kva(struct proc *p, void *uva, size_t len, int prot);
  76/* In arch/pmap{64}.c */
  77uintptr_t gva2gpa(struct proc *p, uintptr_t cr3, uintptr_t gva);
  78
  79/* Helper for is_user_r{w,}addr.
  80 *
  81 * These checks are for addresses that the kernel accesses on behalf of the
  82 * user, which are mapped into the user's address space.  One interpretation is
  83 * whether or not the user is allowed to refer to this memory, hence the
  84 * MMAP_LOWEST_VA check.  But note that the user is allowed to attempt virtual
  85 * memory accesses outside of this range.  VMM code may interpose on low memory
  86 * PFs to emulate certain instructions.  However, the kernel should never be
  87 * given such a pointer.
  88 *
  89 * Without the MMAP_LOWEST_VA check, the kernel would still PF on a bad user
  90 * pointer (say the user gave us 0x10; we have nothing mapped at addr 0).
  91 * However, it would be more difficult to detect if the PF was the kernel acting
  92 * on behalf of the user or if the kernel itself had a null pointer deref.  By
  93 * checking early, the kernel will catch low addresses and error out before page
  94 * faulting. */
  95static inline bool __is_user_addr(const void *addr, size_t len, uintptr_t lim)
  96{
  97        if (unlikely((uintptr_t) addr < MMAP_LOWEST_VA))
  98                return FALSE;
  99        if (unlikely((uintptr_t) addr >= lim))
 100                return FALSE;
 101        if (unlikely(lim - (uintptr_t) addr < len))
 102                return FALSE;
 103
 104        return TRUE;
 105}
 106
 107static inline size_t __valid_user_bytes_from(const void *addr, uintptr_t lim)
 108{
 109        if (unlikely((uintptr_t) addr < MMAP_LOWEST_VA))
 110                return 0;
 111        if (unlikely((uintptr_t) addr >= lim))
 112                return 0;
 113
 114        return (size_t) (lim - (uintptr_t) addr);
 115}
 116
 117/* UWLIM is defined as virtual address below which a process can write */
 118static inline bool is_user_rwaddr(const void *addr, size_t len)
 119{
 120        return __is_user_addr(addr, len, UWLIM);
 121}
 122
 123/* ULIM is defined as virtual address below which a process can read */
 124static inline bool is_user_raddr(const void *addr, size_t len)
 125{
 126        return __is_user_addr(addr, len, ULIM);
 127}
 128
 129static inline size_t valid_user_rwbytes_from(const void *addr)
 130{
 131        return __valid_user_bytes_from(addr, UWLIM);
 132}
 133
 134static inline size_t valid_user_rbytes_from(const void *addr)
 135{
 136        return __valid_user_bytes_from(addr, ULIM);
 137}
 138