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.
6 * Functions for working with userspace's address space. The user_mem ones need
7 * to involve some form of pinning (TODO), and that global static needs to go. */
9 #include <ros/common.h>
10 #include <arch/uaccess.h>
19 static int string_copy_from_user(char *dst, const char *src)
22 const char *top = src + valid_user_rbytes_from(src);
24 for (;; dst++, src++) {
25 if (unlikely(src >= top))
27 error = __get_user(dst, src, 1);
37 static int string_copy_to_user(char *dst, const char *src)
40 char *top = dst + valid_user_rwbytes_from(dst);
42 for (;; dst++, src++) {
43 if (unlikely(dst >= top))
45 error = __put_user(dst, src, 1);
55 int strcpy_from_user(struct proc *p, char *dst, const char *src)
57 uintptr_t prev = switch_to(p);
58 int error = string_copy_from_user(dst, src);
65 int strcpy_to_user(struct proc *p, char *dst, const char *src)
67 uintptr_t prev = switch_to(p);
68 int error = string_copy_to_user(dst, src);
75 int memcpy_from_user(struct proc *p, void *dest, const void *va, size_t len)
77 uintptr_t prev = switch_to(p);
78 int error = copy_from_user(dest, va, len);
85 int memcpy_to_user(struct proc *p, void *dest, const void *src, size_t len)
87 uintptr_t prev = switch_to(p);
88 int error = copy_to_user(dest, src, len);
95 /* Same as above, but sets errno */
96 int memcpy_from_user_errno(struct proc *p, void *dst, const void *src, int len)
98 int error = memcpy_from_user(p, dst, src, len);
100 if (unlikely(error < 0))
106 /* Same as above, but sets errno */
107 int memcpy_to_user_errno(struct proc *p, void *dst, const void *src, int len)
109 int error = memcpy_to_user(p, dst, src, len);
111 if (unlikely(error < 0))
117 /* Helpers for FSs that don't care if they copy to the user or the kernel.
119 * TODO: (KFOP) Probably shouldn't do this. Either memcpy directly, or split
120 * out the is_user_r(w)addr from copy_{to,from}_user(). Or throw from the fault
121 * handler. Right now, we ignore the ret/errors completely. */
122 int memcpy_to_safe(void *dst, const void *src, size_t amt)
126 if (!is_ktask(per_cpu_info[core_id()].cur_kthread))
127 error = memcpy_to_user(current, dst, src, amt);
129 memcpy(dst, src, amt);
133 int memcpy_from_safe(void *dst, const void *src, size_t amt)
137 if (!is_ktask(per_cpu_info[core_id()].cur_kthread))
138 error = memcpy_from_user(current, dst, src, amt);
140 memcpy(dst, src, amt);
144 /* Creates a buffer (kmalloc) and safely copies into it from va. Can return an
145 * error code. Check its response with IS_ERR(). Must be paired with
146 * user_memdup_free() if this succeeded. */
147 void *user_memdup(struct proc *p, const void *va, int len)
151 if (len < 0 || (kva = kmalloc(len, 0)) == NULL)
152 return ERR_PTR(-ENOMEM);
153 if (memcpy_from_user(p, kva, va, len)) {
155 return ERR_PTR(-EFAULT);
160 void *user_memdup_errno(struct proc *p, const void *va, int len)
162 void *kva = user_memdup(p, va, len);
165 set_errno(-PTR_ERR(kva));
171 void user_memdup_free(struct proc *p, void *va)
176 /* Same as memdup, but just does strings, and needs to know the actual strlen.
177 * Still needs memdup_free()d. This will enforce that the string is null
178 * terminated. The parameter strlen does not include the \0, though it can if
179 * someone else is playing it safe. Since strlen() doesn't count the \0, we'll
180 * play it safe here. */
181 char *user_strdup(struct proc *p, const char *u_string, size_t strlen)
183 char *k_string = user_memdup(p, u_string, strlen + 1);
185 if (!IS_ERR(k_string))
186 k_string[strlen] = '\0';
190 /* user_strdup, but this handles the errno. 0 on failure, ptr on success */
191 char *user_strdup_errno(struct proc *p, const char *u_string, size_t strlen)
193 void *k_string = user_strdup(p, u_string, strlen);
194 if (IS_ERR(k_string)) {
195 set_errno(-PTR_ERR(k_string));
201 void *kmalloc_errno(int len)
205 if (len < 0 || (kva = kmalloc(len, 0)) == NULL)
210 /* Returns true if uva and kva both resolve to the same phys addr. If uva is
211 * unmapped, it will return FALSE. This is probably what you want, since after
212 * all uva isn't kva. */
213 bool uva_is_kva(struct proc *p, void *uva, void *kva)
216 assert(kva); /* catch bugs */
218 /* Check offsets first */
219 if (PGOFF(uva) != PGOFF(kva))
221 /* Check to see if it is the same physical page */
222 u_page = page_lookup(p->env_pgdir, uva, 0);
225 return (kva2page(kva) == u_page) ? TRUE : FALSE;
228 /* Given a proc and a user virtual address, gives us the KVA. Useful for
229 * debugging. Returns 0 if the page is unmapped (page lookup fails). This
230 * doesn't play nice with Jumbo pages. */
231 uintptr_t uva2kva(struct proc *p, void *uva, size_t len, int prot)
234 uintptr_t offset = PGOFF(uva);
238 if (prot & PROT_WRITE) {
239 if (!is_user_rwaddr(uva, len))
242 if (!is_user_raddr(uva, len))
245 u_page = page_lookup(p->env_pgdir, uva, 0);
248 return (uintptr_t)page2kva(u_page) + offset;
251 /* Helper, copies a pathname from the process into the kernel. Returns a string
252 * on success, which you must free with free_path. Returns 0 on failure and
254 char *copy_in_path(struct proc *p, const char *path, size_t path_l)
256 struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
259 /* PATH_MAX includes the \0 */
260 if (path_l > PATH_MAX) {
261 set_errno(ENAMETOOLONG);
264 t_path = user_strdup_errno(p, path, path_l);
270 /* Helper, frees a path that was allocated with copy_in_path. */
271 void free_path(struct proc *p, char *t_path)
273 user_memdup_free(p, t_path);