diff options
Diffstat (limited to 'arch/um/kernel/skas')
-rw-r--r-- | arch/um/kernel/skas/uaccess.c | 134 |
1 files changed, 60 insertions, 74 deletions
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index b14422e2c07c..1d8b119f2d0e 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -1,18 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/compiler.h" | 6 | #include "linux/err.h" |
7 | #include "linux/stddef.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/string.h" | ||
10 | #include "linux/fs.h" | ||
11 | #include "linux/hardirq.h" | ||
12 | #include "linux/highmem.h" | 7 | #include "linux/highmem.h" |
8 | #include "linux/mm.h" | ||
9 | #include "asm/current.h" | ||
13 | #include "asm/page.h" | 10 | #include "asm/page.h" |
14 | #include "asm/pgtable.h" | 11 | #include "asm/pgtable.h" |
15 | #include "asm/uaccess.h" | ||
16 | #include "kern_util.h" | 12 | #include "kern_util.h" |
17 | #include "os.h" | 13 | #include "os.h" |
18 | 14 | ||
@@ -27,16 +23,16 @@ static unsigned long maybe_map(unsigned long virt, int is_write) | |||
27 | void *phys = um_virt_to_phys(current, virt, &pte); | 23 | void *phys = um_virt_to_phys(current, virt, &pte); |
28 | int dummy_code; | 24 | int dummy_code; |
29 | 25 | ||
30 | if(IS_ERR(phys) || (is_write && !pte_write(pte))){ | 26 | if (IS_ERR(phys) || (is_write && !pte_write(pte))) { |
31 | err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); | 27 | err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); |
32 | if(err) | 28 | if (err) |
33 | return(-1UL); | 29 | return -1UL; |
34 | phys = um_virt_to_phys(current, virt, NULL); | 30 | phys = um_virt_to_phys(current, virt, NULL); |
35 | } | 31 | } |
36 | if(IS_ERR(phys)) | 32 | if (IS_ERR(phys)) |
37 | phys = (void *) -1; | 33 | phys = (void *) -1; |
38 | 34 | ||
39 | return((unsigned long) phys); | 35 | return (unsigned long) phys; |
40 | } | 36 | } |
41 | 37 | ||
42 | static int do_op_one_page(unsigned long addr, int len, int is_write, | 38 | static int do_op_one_page(unsigned long addr, int len, int is_write, |
@@ -46,17 +42,18 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, | |||
46 | int n; | 42 | int n; |
47 | 43 | ||
48 | addr = maybe_map(addr, is_write); | 44 | addr = maybe_map(addr, is_write); |
49 | if(addr == -1UL) | 45 | if (addr == -1UL) |
50 | return(-1); | 46 | return -1; |
51 | 47 | ||
52 | page = phys_to_page(addr); | 48 | page = phys_to_page(addr); |
53 | addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + (addr & ~PAGE_MASK); | 49 | addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + |
50 | (addr & ~PAGE_MASK); | ||
54 | 51 | ||
55 | n = (*op)(addr, len, arg); | 52 | n = (*op)(addr, len, arg); |
56 | 53 | ||
57 | kunmap_atomic(page, KM_UML_USERCOPY); | 54 | kunmap_atomic(page, KM_UML_USERCOPY); |
58 | 55 | ||
59 | return(n); | 56 | return n; |
60 | } | 57 | } |
61 | 58 | ||
62 | static void do_buffer_op(void *jmpbuf, void *arg_ptr) | 59 | static void do_buffer_op(void *jmpbuf, void *arg_ptr) |
@@ -81,21 +78,21 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
81 | 78 | ||
82 | current->thread.fault_catcher = jmpbuf; | 79 | current->thread.fault_catcher = jmpbuf; |
83 | n = do_op_one_page(addr, size, is_write, op, arg); | 80 | n = do_op_one_page(addr, size, is_write, op, arg); |
84 | if(n != 0){ | 81 | if (n != 0) { |
85 | *res = (n < 0 ? remain : 0); | 82 | *res = (n < 0 ? remain : 0); |
86 | goto out; | 83 | goto out; |
87 | } | 84 | } |
88 | 85 | ||
89 | addr += size; | 86 | addr += size; |
90 | remain -= size; | 87 | remain -= size; |
91 | if(remain == 0){ | 88 | if (remain == 0) { |
92 | *res = 0; | 89 | *res = 0; |
93 | goto out; | 90 | goto out; |
94 | } | 91 | } |
95 | 92 | ||
96 | while(addr < ((addr + remain) & PAGE_MASK)){ | 93 | while(addr < ((addr + remain) & PAGE_MASK)) { |
97 | n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); | 94 | n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg); |
98 | if(n != 0){ | 95 | if (n != 0) { |
99 | *res = (n < 0 ? remain : 0); | 96 | *res = (n < 0 ? remain : 0); |
100 | goto out; | 97 | goto out; |
101 | } | 98 | } |
@@ -103,13 +100,13 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr) | |||
103 | addr += PAGE_SIZE; | 100 | addr += PAGE_SIZE; |
104 | remain -= PAGE_SIZE; | 101 | remain -= PAGE_SIZE; |
105 | } | 102 | } |
106 | if(remain == 0){ | 103 | if (remain == 0) { |
107 | *res = 0; | 104 | *res = 0; |
108 | goto out; | 105 | goto out; |
109 | } | 106 | } |
110 | 107 | ||
111 | n = do_op_one_page(addr, remain, is_write, op, arg); | 108 | n = do_op_one_page(addr, remain, is_write, op, arg); |
112 | if(n != 0) | 109 | if (n != 0) |
113 | *res = (n < 0 ? remain : 0); | 110 | *res = (n < 0 ? remain : 0); |
114 | else *res = 0; | 111 | else *res = 0; |
115 | out: | 112 | out: |
@@ -124,10 +121,10 @@ static int buffer_op(unsigned long addr, int len, int is_write, | |||
124 | 121 | ||
125 | faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, | 122 | faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, |
126 | &res); | 123 | &res); |
127 | if(!faulted) | 124 | if (!faulted) |
128 | return(res); | 125 | return res; |
129 | 126 | ||
130 | return(addr + len - (unsigned long) current->thread.fault_addr); | 127 | return addr + len - (unsigned long) current->thread.fault_addr; |
131 | } | 128 | } |
132 | 129 | ||
133 | static int copy_chunk_from_user(unsigned long from, int len, void *arg) | 130 | static int copy_chunk_from_user(unsigned long from, int len, void *arg) |
@@ -136,19 +133,19 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) | |||
136 | 133 | ||
137 | memcpy((void *) to, (void *) from, len); | 134 | memcpy((void *) to, (void *) from, len); |
138 | *to_ptr += len; | 135 | *to_ptr += len; |
139 | return(0); | 136 | return 0; |
140 | } | 137 | } |
141 | 138 | ||
142 | int copy_from_user(void *to, const void __user *from, int n) | 139 | int copy_from_user(void *to, const void __user *from, int n) |
143 | { | 140 | { |
144 | if(segment_eq(get_fs(), KERNEL_DS)){ | 141 | if (segment_eq(get_fs(), KERNEL_DS)) { |
145 | memcpy(to, (__force void*)from, n); | 142 | memcpy(to, (__force void*)from, n); |
146 | return(0); | 143 | return 0; |
147 | } | 144 | } |
148 | 145 | ||
149 | return(access_ok(VERIFY_READ, from, n) ? | 146 | return access_ok(VERIFY_READ, from, n) ? |
150 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | 147 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): |
151 | n); | 148 | n; |
152 | } | 149 | } |
153 | 150 | ||
154 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) | 151 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) |
@@ -157,19 +154,19 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) | |||
157 | 154 | ||
158 | memcpy((void *) to, (void *) from, len); | 155 | memcpy((void *) to, (void *) from, len); |
159 | *from_ptr += len; | 156 | *from_ptr += len; |
160 | return(0); | 157 | return 0; |
161 | } | 158 | } |
162 | 159 | ||
163 | int copy_to_user(void __user *to, const void *from, int n) | 160 | int copy_to_user(void __user *to, const void *from, int n) |
164 | { | 161 | { |
165 | if(segment_eq(get_fs(), KERNEL_DS)){ | 162 | if (segment_eq(get_fs(), KERNEL_DS)) { |
166 | memcpy((__force void*)to, from, n); | 163 | memcpy((__force void *) to, from, n); |
167 | return(0); | 164 | return 0; |
168 | } | 165 | } |
169 | 166 | ||
170 | return(access_ok(VERIFY_WRITE, to, n) ? | 167 | return access_ok(VERIFY_WRITE, to, n) ? |
171 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | 168 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : |
172 | n); | 169 | n; |
173 | } | 170 | } |
174 | 171 | ||
175 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) | 172 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) |
@@ -181,9 +178,9 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) | |||
181 | n = strnlen(to, len); | 178 | n = strnlen(to, len); |
182 | *to_ptr += n; | 179 | *to_ptr += n; |
183 | 180 | ||
184 | if(n < len) | 181 | if (n < len) |
185 | return(1); | 182 | return 1; |
186 | return(0); | 183 | return 0; |
187 | } | 184 | } |
188 | 185 | ||
189 | int strncpy_from_user(char *dst, const char __user *src, int count) | 186 | int strncpy_from_user(char *dst, const char __user *src, int count) |
@@ -191,41 +188,41 @@ int strncpy_from_user(char *dst, const char __user *src, int count) | |||
191 | int n; | 188 | int n; |
192 | char *ptr = dst; | 189 | char *ptr = dst; |
193 | 190 | ||
194 | if(segment_eq(get_fs(), KERNEL_DS)){ | 191 | if (segment_eq(get_fs(), KERNEL_DS)) { |
195 | strncpy(dst, (__force void*)src, count); | 192 | strncpy(dst, (__force void *) src, count); |
196 | return(strnlen(dst, count)); | 193 | return strnlen(dst, count); |
197 | } | 194 | } |
198 | 195 | ||
199 | if(!access_ok(VERIFY_READ, src, 1)) | 196 | if (!access_ok(VERIFY_READ, src, 1)) |
200 | return(-EFAULT); | 197 | return -EFAULT; |
201 | 198 | ||
202 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, | 199 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, |
203 | &ptr); | 200 | &ptr); |
204 | if(n != 0) | 201 | if (n != 0) |
205 | return(-EFAULT); | 202 | return -EFAULT; |
206 | return(strnlen(dst, count)); | 203 | return strnlen(dst, count); |
207 | } | 204 | } |
208 | 205 | ||
209 | static int clear_chunk(unsigned long addr, int len, void *unused) | 206 | static int clear_chunk(unsigned long addr, int len, void *unused) |
210 | { | 207 | { |
211 | memset((void *) addr, 0, len); | 208 | memset((void *) addr, 0, len); |
212 | return(0); | 209 | return 0; |
213 | } | 210 | } |
214 | 211 | ||
215 | int __clear_user(void __user *mem, int len) | 212 | int __clear_user(void __user *mem, int len) |
216 | { | 213 | { |
217 | return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); | 214 | return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); |
218 | } | 215 | } |
219 | 216 | ||
220 | int clear_user(void __user *mem, int len) | 217 | int clear_user(void __user *mem, int len) |
221 | { | 218 | { |
222 | if(segment_eq(get_fs(), KERNEL_DS)){ | 219 | if (segment_eq(get_fs(), KERNEL_DS)) { |
223 | memset((__force void*)mem, 0, len); | 220 | memset((__force void*)mem, 0, len); |
224 | return(0); | 221 | return 0; |
225 | } | 222 | } |
226 | 223 | ||
227 | return(access_ok(VERIFY_WRITE, mem, len) ? | 224 | return access_ok(VERIFY_WRITE, mem, len) ? |
228 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); | 225 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; |
229 | } | 226 | } |
230 | 227 | ||
231 | static int strnlen_chunk(unsigned long str, int len, void *arg) | 228 | static int strnlen_chunk(unsigned long str, int len, void *arg) |
@@ -235,31 +232,20 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) | |||
235 | n = strnlen((void *) str, len); | 232 | n = strnlen((void *) str, len); |
236 | *len_ptr += n; | 233 | *len_ptr += n; |
237 | 234 | ||
238 | if(n < len) | 235 | if (n < len) |
239 | return(1); | 236 | return 1; |
240 | return(0); | 237 | return 0; |
241 | } | 238 | } |
242 | 239 | ||
243 | int strnlen_user(const void __user *str, int len) | 240 | int strnlen_user(const void __user *str, int len) |
244 | { | 241 | { |
245 | int count = 0, n; | 242 | int count = 0, n; |
246 | 243 | ||
247 | if(segment_eq(get_fs(), KERNEL_DS)) | 244 | if (segment_eq(get_fs(), KERNEL_DS)) |
248 | return(strnlen((__force char*)str, len) + 1); | 245 | return strnlen((__force char*)str, len) + 1; |
249 | 246 | ||
250 | n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); | 247 | n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); |
251 | if(n == 0) | 248 | if (n == 0) |
252 | return(count + 1); | 249 | return count + 1; |
253 | return(-EFAULT); | 250 | return -EFAULT; |
254 | } | 251 | } |
255 | |||
256 | /* | ||
257 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
258 | * Emacs will notice this stuff at the end of the file and automatically | ||
259 | * adjust the settings for this buffer only. This must remain at the end | ||
260 | * of the file. | ||
261 | * --------------------------------------------------------------------------- | ||
262 | * Local variables: | ||
263 | * c-file-style: "linux" | ||
264 | * End: | ||
265 | */ | ||