pthread: Fix null attr for pthread_mutex_init()
[akaros.git] / kern / include / umem.h
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. */
16 static inline bool is_user_rwaddr(const void *addr, size_t len);
17 /* Same deal, but read-only */
18 static inline bool is_user_raddr(const void *addr, size_t len);
19
20 #include <arch/uaccess.h>
21
22 int strcpy_from_user(struct proc *p, char *dst, const char *src);
23 int 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  */
38 int 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  */
53 int memcpy_to_user(struct proc *p, void *dest, const void *src, size_t len);
54
55 /* Same as above, but sets errno */
56 int memcpy_from_user_errno(struct proc *p, void *dst, const void *src, int len);
57 int memcpy_to_user_errno(struct proc *p, void *dst, const void *src, int len);
58
59 /* Creates a buffer (kmalloc) and safely copies into it from va.  Can return an
60  * error code.  Check its response with IS_ERR().  Must be paired with
61  * user_memdup_free() if this succeeded. */
62 void *user_memdup(struct proc *p, const void *va, int len);
63 /* Same as above, but sets errno */
64 void *user_memdup_errno(struct proc *p, const void *va, int len);
65 void user_memdup_free(struct proc *p, void *va);
66 /* Same as memdup, but just does strings.  still needs memdup_freed */
67 char *user_strdup(struct proc *p, const char *u_string, size_t strlen);
68 char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen);
69 char *copy_in_path(struct proc *p, const char *path, size_t path_l);
70 void free_path(struct proc *p, char *t_path);
71 void *kmalloc_errno(int len);
72 bool uva_is_kva(struct proc *p, void *uva, void *kva);
73 uintptr_t uva2kva(struct proc *p, void *uva, size_t len, int prot);
74 /* In arch/pmap{64}.c */
75 uintptr_t gva2gpa(struct proc *p, uintptr_t cr3, uintptr_t gva);
76
77 /* Helper for is_user_r{w,}addr.
78  *
79  * These checks are for addresses that the kernel accesses on behalf of the
80  * user, which are mapped into the user's address space.  One interpretation is
81  * whether or not the user is allowed to refer to this memory, hence the
82  * MMAP_LOWEST_VA check.  But note that the user is allowed to attempt virtual
83  * memory accesses outside of this range.  VMM code may interpose on low memory
84  * PFs to emulate certain instructions.  However, the kernel should never be
85  * given such a pointer.
86  *
87  * Without the MMAP_LOWEST_VA check, the kernel would still PF on a bad user
88  * pointer (say the user gave us 0x10; we have nothing mapped at addr 0).
89  * However, it would be more difficult to detect if the PF was the kernel acting
90  * on behalf of the user or if the kernel itself had a null pointer deref.  By
91  * checking early, the kernel will catch low addresses and error out before page
92  * faulting. */
93 static inline bool __is_user_addr(const void *addr, size_t len, uintptr_t lim)
94 {
95         if (unlikely((uintptr_t) addr < MMAP_LOWEST_VA))
96                 return FALSE;
97         if (unlikely((uintptr_t) addr >= lim))
98                 return FALSE;
99         if (unlikely(lim - (uintptr_t) addr < len))
100                 return FALSE;
101
102         return TRUE;
103 }
104
105 static inline size_t __valid_user_bytes_from(const void *addr, uintptr_t lim)
106 {
107         if (unlikely((uintptr_t) addr < MMAP_LOWEST_VA))
108                 return 0;
109         if (unlikely((uintptr_t) addr >= lim))
110                 return 0;
111
112         return (size_t) (lim - (uintptr_t) addr);
113 }
114
115 /* UWLIM is defined as virtual address below which a process can write */
116 static inline bool is_user_rwaddr(const void *addr, size_t len)
117 {
118         return __is_user_addr(addr, len, UWLIM);
119 }
120
121 /* ULIM is defined as virtual address below which a process can read */
122 static inline bool is_user_raddr(const void *addr, size_t len)
123 {
124         return __is_user_addr(addr, len, ULIM);
125 }
126
127 static inline size_t valid_user_rwbytes_from(const void *addr)
128 {
129         return __valid_user_bytes_from(addr, UWLIM);
130 }
131
132 static inline size_t valid_user_rbytes_from(const void *addr)
133 {
134         return __valid_user_bytes_from(addr, ULIM);
135 }