AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
uaccess.h
Go to the documentation of this file.
1#ifndef _SYS_UACCESS_H
2#define _SYS_UACCESS_H
3
4/*
5 * User memory. What the kernel reads from it and writes to it goes
6 * through copyin(), copyout() and copyinstr() (or an iobuf, fs/iobuf.h).
7 * The range must be in user space, [0, USER_STACK), and a fault that the
8 * page fault handler can't resolve (the memory isn't mapped, or not that
9 * way) makes them return -EFAULT. The kernel touching user memory any
10 * other way, at an address that turns out bad, is a bug: it panics.
11 *
12 * uaccess_check() is the range check alone.
13 */
14
15#include <core/system.h>
16#include <core/arch.h>
17#include <aquila/errno.h>
18
19/* The first address that isn't in user space. */
20#define UACCESS_LIMIT ((uintptr_t) USER_STACK)
21
27static inline int uaccess_check(const void *ptr, size_t len)
28{
29 uintptr_t addr = (uintptr_t) ptr;
30
31 if (!len)
32 return 0;
33
34 if (!ptr || addr >= UACCESS_LIMIT || len > UACCESS_LIMIT - addr)
35 return -EFAULT;
36
37 return 0;
38}
39
40/* The architecture's copies, which recover from faults. arch_copy_user()
41 * returns how much wasn't copied (0: it all was); arch_copy_user_str()
42 * returns the string's length (max if there was no NUL), or -EFAULT. */
43size_t arch_copy_user(void *dst, const void *src, size_t n);
44long arch_copy_user_str(char *dst, const char *src, size_t max);
45
48static inline int copyin(void *kdst, const void *usrc, size_t n)
49{
50 if (uaccess_check(usrc, n))
51 return -EFAULT;
52
53 return n && arch_copy_user(kdst, usrc, n) ? -EFAULT : 0;
54}
55
58static inline int copyout(void *udst, const void *ksrc, size_t n)
59{
60 if (uaccess_check(udst, n))
61 return -EFAULT;
62
63 return n && arch_copy_user(udst, ksrc, n) ? -EFAULT : 0;
64}
65
68static inline size_t copyin_upto(void *kdst, const void *usrc, size_t n)
69{
70 return uaccess_check(usrc, n) ? 0 : n - arch_copy_user(kdst, usrc, n);
71}
72
75static inline size_t copyout_upto(void *udst, const void *ksrc, size_t n)
76{
77 return uaccess_check(udst, n) ? 0 : n - arch_copy_user(udst, ksrc, n);
78}
79
83static inline long copyinstr(char *kdst, const char *usrc, size_t max)
84{
85 uintptr_t addr = (uintptr_t) usrc;
86
87 if (!usrc || addr >= UACCESS_LIMIT || !max)
88 return -EFAULT;
89
90 /* don't read past the end of user space */
91 size_t room = MIN(max, UACCESS_LIMIT - addr);
92 long len = arch_copy_user_str(kdst, usrc, room);
93
94 if (len < 0)
95 return len;
96
97 if ((size_t) len == room)
98 return room < max ? -EFAULT : -ENAMETOOLONG;
99
100 return len;
101}
102
103#endif /* ! _SYS_UACCESS_H */
#define MIN(a, b)
Definition system.h:11
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
size_t arch_copy_user(void *dst, const void *src, size_t n)
static int copyout(void *udst, const void *ksrc, size_t n)
Copies n bytes from ksrc to user memory at udst.
Definition uaccess.h:58
#define UACCESS_LIMIT
Definition uaccess.h:20
static long copyinstr(char *kdst, const char *usrc, size_t max)
Copies a string from user memory at usrc to kdst (at most max bytes, its NUL included).
Definition uaccess.h:83
static size_t copyout_upto(void *udst, const void *ksrc, size_t n)
Copies as copyout() does, but returns how many bytes were copied before a fault: n if they all were.
Definition uaccess.h:75
static int copyin(void *kdst, const void *usrc, size_t n)
Copies n bytes from user memory at usrc to kdst.
Definition uaccess.h:48
long arch_copy_user_str(char *dst, const char *src, size_t max)
static int uaccess_check(const void *ptr, size_t len)
Checks that [ptr, ptr + len) is in user space.
Definition uaccess.h:27
static size_t copyin_upto(void *kdst, const void *usrc, size_t n)
Copies as copyin() does, but returns how many bytes were copied before a fault (0 for a range that is...
Definition uaccess.h:68