Commit 579a97f7ff4c0f958a5d8adcba717a205bb58567
1 parent
44f8625d
Linux user memory access API change (initial patch by Thayne Harbaugh)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3583 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
14 changed files
with
977 additions
and
628 deletions
Makefile.target
... | ... | @@ -260,7 +260,7 @@ endif |
260 | 260 | |
261 | 261 | ifdef CONFIG_LINUX_USER |
262 | 262 | OBJS= main.o syscall.o strace.o mmap.o signal.o path.o osdep.o thunk.o \ |
263 | - elfload.o linuxload.o | |
263 | + elfload.o linuxload.o uaccess.o | |
264 | 264 | LIBS+= $(AIOLIBS) |
265 | 265 | ifdef TARGET_HAS_BFLT |
266 | 266 | OBJS+= flatload.o | ... | ... |
arm-semi.c
... | ... | @@ -184,9 +184,11 @@ uint32_t do_arm_semihosting(CPUState *env) |
184 | 184 | args = env->regs[1]; |
185 | 185 | switch (nr) { |
186 | 186 | case SYS_OPEN: |
187 | - s = lock_user_string(ARG(0)); | |
187 | + if (!(s = lock_user_string(ARG(0)))) | |
188 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
189 | + return (uint32_t)-1; | |
188 | 190 | if (ARG(1) >= 12) |
189 | - return (uint32_t)-1; | |
191 | + return (uint32_t)-1; | |
190 | 192 | if (strcmp(s, ":tt") == 0) { |
191 | 193 | if (ARG(1) < 4) |
192 | 194 | return STDIN_FILENO; |
... | ... | @@ -221,7 +223,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
221 | 223 | } |
222 | 224 | } |
223 | 225 | case SYS_WRITE0: |
224 | - s = lock_user_string(args); | |
226 | + if (!(s = lock_user_string(args))) | |
227 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
228 | + return (uint32_t)-1; | |
225 | 229 | len = strlen(s); |
226 | 230 | if (use_gdb_syscalls()) { |
227 | 231 | gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len); |
... | ... | @@ -238,7 +242,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
238 | 242 | gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len); |
239 | 243 | return env->regs[0]; |
240 | 244 | } else { |
241 | - s = lock_user(ARG(1), len, 1); | |
245 | + if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1))) | |
246 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
247 | + return (uint32_t)-1; | |
242 | 248 | ret = set_swi_errno(ts, write(ARG(0), s, len)); |
243 | 249 | unlock_user(s, ARG(1), 0); |
244 | 250 | if (ret == (uint32_t)-1) |
... | ... | @@ -252,7 +258,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
252 | 258 | gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len); |
253 | 259 | return env->regs[0]; |
254 | 260 | } else { |
255 | - s = lock_user(ARG(1), len, 0); | |
261 | + if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0))) | |
262 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
263 | + return (uint32_t)-1; | |
256 | 264 | do |
257 | 265 | ret = set_swi_errno(ts, read(ARG(0), s, len)); |
258 | 266 | while (ret == -1 && errno == EINTR); |
... | ... | @@ -301,7 +309,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
301 | 309 | gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1); |
302 | 310 | ret = env->regs[0]; |
303 | 311 | } else { |
304 | - s = lock_user_string(ARG(0)); | |
312 | + if (!(s = lock_user_string(ARG(0)))) | |
313 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
314 | + return (uint32_t)-1; | |
305 | 315 | ret = set_swi_errno(ts, remove(s)); |
306 | 316 | unlock_user(s, ARG(0), 0); |
307 | 317 | } |
... | ... | @@ -315,9 +325,15 @@ uint32_t do_arm_semihosting(CPUState *env) |
315 | 325 | char *s2; |
316 | 326 | s = lock_user_string(ARG(0)); |
317 | 327 | s2 = lock_user_string(ARG(2)); |
318 | - ret = set_swi_errno(ts, rename(s, s2)); | |
319 | - unlock_user(s2, ARG(2), 0); | |
320 | - unlock_user(s, ARG(0), 0); | |
328 | + if (!s || !s2) | |
329 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
330 | + ret = (uint32_t)-1; | |
331 | + else | |
332 | + ret = set_swi_errno(ts, rename(s, s2)); | |
333 | + if (s2) | |
334 | + unlock_user(s2, ARG(2), 0); | |
335 | + if (s) | |
336 | + unlock_user(s, ARG(0), 0); | |
321 | 337 | return ret; |
322 | 338 | } |
323 | 339 | case SYS_CLOCK: |
... | ... | @@ -329,7 +345,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
329 | 345 | gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1); |
330 | 346 | return env->regs[0]; |
331 | 347 | } else { |
332 | - s = lock_user_string(ARG(0)); | |
348 | + if (!(s = lock_user_string(ARG(0)))) | |
349 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
350 | + return (uint32_t)-1; | |
333 | 351 | ret = set_swi_errno(ts, system(s)); |
334 | 352 | unlock_user(s, ARG(0), 0); |
335 | 353 | } |
... | ... | @@ -346,7 +364,11 @@ uint32_t do_arm_semihosting(CPUState *env) |
346 | 364 | char **arg = ts->info->host_argv; |
347 | 365 | int len = ARG(1); |
348 | 366 | /* lock the buffer on the ARM side */ |
349 | - char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0); | |
367 | + char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0); | |
368 | + | |
369 | + if (!cmdline_buffer) | |
370 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
371 | + return (uint32_t)-1; | |
350 | 372 | |
351 | 373 | s = cmdline_buffer; |
352 | 374 | while (*arg && len > 2) { |
... | ... | @@ -402,7 +424,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
402 | 424 | ts->heap_limit = limit; |
403 | 425 | } |
404 | 426 | |
405 | - ptr = lock_user(ARG(0), 16, 0); | |
427 | + if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0))) | |
428 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
429 | + return (uint32_t)-1; | |
406 | 430 | ptr[0] = tswap32(ts->heap_base); |
407 | 431 | ptr[1] = tswap32(ts->heap_limit); |
408 | 432 | ptr[2] = tswap32(ts->stack_base); |
... | ... | @@ -410,7 +434,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
410 | 434 | unlock_user(ptr, ARG(0), 16); |
411 | 435 | #else |
412 | 436 | limit = ram_size; |
413 | - ptr = lock_user(ARG(0), 16, 0); | |
437 | + if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0))) | |
438 | + /* FIXME - should this error code be -TARGET_EFAULT ? */ | |
439 | + return (uint32_t)-1; | |
414 | 440 | /* TODO: Make this use the limit of the loaded application. */ |
415 | 441 | ptr[0] = tswap32(limit / 2); |
416 | 442 | ptr[1] = tswap32(limit); | ... | ... |
exec.c
... | ... | @@ -2510,13 +2510,19 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, |
2510 | 2510 | if (is_write) { |
2511 | 2511 | if (!(flags & PAGE_WRITE)) |
2512 | 2512 | return; |
2513 | - p = lock_user(addr, len, 0); | |
2513 | + /* XXX: this code should not depend on lock_user */ | |
2514 | + if (!(p = lock_user(VERIFY_WRITE, addr, len, 0))) | |
2515 | + /* FIXME - should this return an error rather than just fail? */ | |
2516 | + return; | |
2514 | 2517 | memcpy(p, buf, len); |
2515 | 2518 | unlock_user(p, addr, len); |
2516 | 2519 | } else { |
2517 | 2520 | if (!(flags & PAGE_READ)) |
2518 | 2521 | return; |
2519 | - p = lock_user(addr, len, 1); | |
2522 | + /* XXX: this code should not depend on lock_user */ | |
2523 | + if (!(p = lock_user(VERIFY_READ, addr, len, 1))) | |
2524 | + /* FIXME - should this return an error rather than just fail? */ | |
2525 | + return; | |
2520 | 2526 | memcpy(buf, p, len); |
2521 | 2527 | unlock_user(p, addr, 0); |
2522 | 2528 | } | ... | ... |
linux-user/elfload.c
... | ... | @@ -677,7 +677,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, |
677 | 677 | for (i = 0 ; i < MAX_ARG_PAGES ; i++) { |
678 | 678 | if (bprm->page[i]) { |
679 | 679 | info->rss++; |
680 | - | |
680 | + /* FIXME - check return value of memcpy_to_target() for failure */ | |
681 | 681 | memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); |
682 | 682 | free(bprm->page[i]); |
683 | 683 | } |
... | ... | @@ -760,6 +760,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, |
760 | 760 | size_t len = strlen(k_platform) + 1; |
761 | 761 | sp -= (len + n - 1) & ~(n - 1); |
762 | 762 | u_platform = sp; |
763 | + /* FIXME - check return value of memcpy_to_target() for failure */ | |
763 | 764 | memcpy_to_target(sp, k_platform, len); |
764 | 765 | } |
765 | 766 | /* | ... | ... |
linux-user/flatload.c
... | ... | @@ -108,7 +108,7 @@ int target_pread(int fd, abi_ulong ptr, abi_ulong len, |
108 | 108 | void *buf; |
109 | 109 | int ret; |
110 | 110 | |
111 | - buf = lock_user(ptr, len, 0); | |
111 | + buf = lock_user(VERIFY_WRITE, ptr, len, 0); | |
112 | 112 | ret = pread(fd, buf, len, offset); |
113 | 113 | unlock_user(buf, ptr, len); |
114 | 114 | return ret; | ... | ... |
linux-user/linuxload.c
... | ... | @@ -13,14 +13,17 @@ |
13 | 13 | #define NGROUPS 32 |
14 | 14 | |
15 | 15 | /* ??? This should really be somewhere else. */ |
16 | -void memcpy_to_target(abi_ulong dest, const void *src, | |
17 | - unsigned long len) | |
16 | +abi_long memcpy_to_target(abi_ulong dest, const void *src, | |
17 | + unsigned long len) | |
18 | 18 | { |
19 | 19 | void *host_ptr; |
20 | 20 | |
21 | - host_ptr = lock_user(dest, len, 0); | |
21 | + host_ptr = lock_user(VERIFY_WRITE, dest, len, 0); | |
22 | + if (!host_ptr) | |
23 | + return -TARGET_EFAULT; | |
22 | 24 | memcpy(host_ptr, src, len); |
23 | 25 | unlock_user(host_ptr, dest, 1); |
26 | + return 0; | |
24 | 27 | } |
25 | 28 | |
26 | 29 | static int in_group_p(gid_t g) | ... | ... |
linux-user/qemu.h
... | ... | @@ -146,8 +146,8 @@ int load_elf_binary_multi(struct linux_binprm *bprm, |
146 | 146 | struct image_info *info); |
147 | 147 | #endif |
148 | 148 | |
149 | -void memcpy_to_target(abi_ulong dest, const void *src, | |
150 | - unsigned long len); | |
149 | +abi_long memcpy_to_target(abi_ulong dest, const void *src, | |
150 | + unsigned long len); | |
151 | 151 | void target_set_brk(abi_ulong new_brk); |
152 | 152 | abi_long do_brk(abi_ulong new_brk); |
153 | 153 | void syscall_init(void); |
... | ... | @@ -179,9 +179,7 @@ void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); |
179 | 179 | void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); |
180 | 180 | long do_sigreturn(CPUState *env); |
181 | 181 | long do_rt_sigreturn(CPUState *env); |
182 | -int do_sigaltstack(const struct target_sigaltstack *uss, | |
183 | - struct target_sigaltstack *uoss, | |
184 | - abi_ulong sp); | |
182 | +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); | |
185 | 183 | |
186 | 184 | #ifdef TARGET_I386 |
187 | 185 | /* vm86.c */ |
... | ... | @@ -207,12 +205,15 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); |
207 | 205 | /* user access */ |
208 | 206 | |
209 | 207 | #define VERIFY_READ 0 |
210 | -#define VERIFY_WRITE 1 | |
208 | +#define VERIFY_WRITE 1 /* implies read access */ | |
211 | 209 | |
212 | 210 | #define access_ok(type,addr,size) \ |
213 | 211 | (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0) |
214 | 212 | |
215 | 213 | /* NOTE __get_user and __put_user use host pointers and don't check access. */ |
214 | +/* These are usually used to access struct data members once the | |
215 | + * struct has been locked - usually with lock_user_struct(). | |
216 | + */ | |
216 | 217 | #define __put_user(x, hptr)\ |
217 | 218 | ({\ |
218 | 219 | int size = sizeof(*hptr);\ |
... | ... | @@ -257,26 +258,44 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); |
257 | 258 | 0;\ |
258 | 259 | }) |
259 | 260 | |
260 | -#define put_user(x,ptr)\ | |
261 | -({\ | |
262 | - int __ret;\ | |
263 | - if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\ | |
264 | - __ret = __put_user(x, ptr);\ | |
265 | - else\ | |
266 | - __ret = -EFAULT;\ | |
267 | - __ret;\ | |
261 | +/* put_user()/get_user() take a guest address and check access */ | |
262 | +/* These are usually used to access an atomic data type, such as an int, | |
263 | + * that has been passed by address. These internally perform locking | |
264 | + * and unlocking on the data type. | |
265 | + */ | |
266 | +#define put_user(x, gaddr, target_type) \ | |
267 | +({ \ | |
268 | + abi_ulong __gaddr = (gaddr); \ | |
269 | + target_type *__hptr; \ | |
270 | + abi_long __ret; \ | |
271 | + if ((__hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0))) { \ | |
272 | + __ret = __put_user((x), __hptr); \ | |
273 | + unlock_user(__hptr, __gaddr, sizeof(target_type)); \ | |
274 | + } else \ | |
275 | + __ret = -TARGET_EFAULT; \ | |
276 | + __ret; \ | |
268 | 277 | }) |
269 | 278 | |
270 | -#define get_user(x,ptr)\ | |
271 | -({\ | |
272 | - int __ret;\ | |
273 | - if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\ | |
274 | - __ret = __get_user(x, ptr);\ | |
275 | - else\ | |
276 | - __ret = -EFAULT;\ | |
277 | - __ret;\ | |
279 | +#define get_user(x, gaddr, target_type) \ | |
280 | +({ \ | |
281 | + abi_ulong __gaddr = (gaddr); \ | |
282 | + target_type *__hptr; \ | |
283 | + abi_long __ret; \ | |
284 | + if ((__hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1))) { \ | |
285 | + __ret = __get_user((x), __hptr); \ | |
286 | + unlock_user(__hptr, __gaddr, 0); \ | |
287 | + } else \ | |
288 | + __ret = -TARGET_EFAULT; \ | |
289 | + __ret; \ | |
278 | 290 | }) |
279 | 291 | |
292 | +/* copy_from_user() and copy_to_user() are usually used to copy data | |
293 | + * buffers between the target and host. These internally perform | |
294 | + * locking/unlocking of the memory. | |
295 | + */ | |
296 | +abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len); | |
297 | +abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len); | |
298 | + | |
280 | 299 | /* Functions for accessing guest memory. The tget and tput functions |
281 | 300 | read/write single values, byteswapping as neccessary. The lock_user |
282 | 301 | gets a pointer to a contiguous area of guest memory, but does not perform |
... | ... | @@ -285,53 +304,61 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); |
285 | 304 | |
286 | 305 | /* Lock an area of guest memory into the host. If copy is true then the |
287 | 306 | host area will have the same contents as the guest. */ |
288 | -static inline void *lock_user(abi_ulong guest_addr, long len, int copy) | |
307 | +static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy) | |
289 | 308 | { |
309 | + if (!access_ok(type, guest_addr, len)) | |
310 | + return NULL; | |
290 | 311 | #ifdef DEBUG_REMAP |
291 | - void *addr; | |
292 | - addr = malloc(len); | |
293 | - if (copy) | |
294 | - memcpy(addr, g2h(guest_addr), len); | |
295 | - else | |
296 | - memset(addr, 0, len); | |
297 | - return addr; | |
312 | + { | |
313 | + void *addr; | |
314 | + addr = malloc(len); | |
315 | + if (copy) | |
316 | + memcpy(addr, g2h(guest_addr), len); | |
317 | + else | |
318 | + memset(addr, 0, len); | |
319 | + return addr; | |
320 | + } | |
298 | 321 | #else |
299 | 322 | return g2h(guest_addr); |
300 | 323 | #endif |
301 | 324 | } |
302 | 325 | |
303 | -/* Unlock an area of guest memory. The first LEN bytes must be flushed back | |
304 | - to guest memory. */ | |
305 | -static inline void unlock_user(void *host_addr, abi_ulong guest_addr, | |
326 | +/* Unlock an area of guest memory. The first LEN bytes must be | |
327 | + flushed back to guest memory. host_ptr = NULL is explicitely | |
328 | + allowed and does nothing. */ | |
329 | +static inline void unlock_user(void *host_ptr, abi_ulong guest_addr, | |
306 | 330 | long len) |
307 | 331 | { |
332 | + | |
308 | 333 | #ifdef DEBUG_REMAP |
309 | - if (host_addr == g2h(guest_addr)) | |
334 | + if (!host_ptr) | |
335 | + return; | |
336 | + if (host_ptr == g2h(guest_addr)) | |
310 | 337 | return; |
311 | 338 | if (len > 0) |
312 | - memcpy(g2h(guest_addr), host_addr, len); | |
313 | - free(host_addr); | |
339 | + memcpy(g2h(guest_ptr), host_ptr, len); | |
340 | + free(host_ptr); | |
314 | 341 | #endif |
315 | 342 | } |
316 | 343 | |
317 | -/* Return the length of a string in target memory. */ | |
318 | -static inline int target_strlen(abi_ulong ptr) | |
319 | -{ | |
320 | - return strlen(g2h(ptr)); | |
321 | -} | |
344 | +/* Return the length of a string in target memory or -TARGET_EFAULT if | |
345 | + access error. */ | |
346 | +abi_long target_strlen(abi_ulong gaddr); | |
322 | 347 | |
323 | 348 | /* Like lock_user but for null terminated strings. */ |
324 | 349 | static inline void *lock_user_string(abi_ulong guest_addr) |
325 | 350 | { |
326 | - long len; | |
327 | - len = target_strlen(guest_addr) + 1; | |
328 | - return lock_user(guest_addr, len, 1); | |
351 | + abi_long len; | |
352 | + len = target_strlen(guest_addr); | |
353 | + if (len < 0) | |
354 | + return NULL; | |
355 | + return lock_user(VERIFY_READ, guest_addr, (long)(len + 1), 1); | |
329 | 356 | } |
330 | 357 | |
331 | 358 | /* Helper macros for locking/ulocking a target struct. */ |
332 | -#define lock_user_struct(host_ptr, guest_addr, copy) \ | |
333 | - host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy) | |
334 | -#define unlock_user_struct(host_ptr, guest_addr, copy) \ | |
359 | +#define lock_user_struct(type, host_ptr, guest_addr, copy) \ | |
360 | + (host_ptr = lock_user(type, guest_addr, sizeof(*host_ptr), copy)) | |
361 | +#define unlock_user_struct(host_ptr, guest_addr, copy) \ | |
335 | 362 | unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) |
336 | 363 | |
337 | 364 | #define tget8(addr) ldub(addr) | ... | ... |
linux-user/signal.c
... | ... | @@ -435,31 +435,32 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
435 | 435 | } |
436 | 436 | |
437 | 437 | /* do_sigaltstack() returns target values and errnos. */ |
438 | -int do_sigaltstack(const struct target_sigaltstack *uss, | |
439 | - struct target_sigaltstack *uoss, | |
440 | - abi_ulong sp) | |
438 | +/* compare linux/kernel/signal.c:do_sigaltstack() */ | |
439 | +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) | |
441 | 440 | { |
442 | 441 | int ret; |
443 | 442 | struct target_sigaltstack oss; |
444 | 443 | |
445 | 444 | /* XXX: test errors */ |
446 | - if(uoss) | |
445 | + if(uoss_addr) | |
447 | 446 | { |
448 | 447 | __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp); |
449 | 448 | __put_user(target_sigaltstack_used.ss_size, &oss.ss_size); |
450 | 449 | __put_user(sas_ss_flags(sp), &oss.ss_flags); |
451 | 450 | } |
452 | 451 | |
453 | - if(uss) | |
452 | + if(uss_addr) | |
454 | 453 | { |
455 | - struct target_sigaltstack ss; | |
454 | + struct target_sigaltstack *uss; | |
455 | + struct target_sigaltstack ss; | |
456 | 456 | |
457 | 457 | ret = -TARGET_EFAULT; |
458 | - if (!access_ok(VERIFY_READ, uss, sizeof(*uss)) | |
458 | + if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1) | |
459 | 459 | || __get_user(ss.ss_sp, &uss->ss_sp) |
460 | 460 | || __get_user(ss.ss_size, &uss->ss_size) |
461 | 461 | || __get_user(ss.ss_flags, &uss->ss_flags)) |
462 | 462 | goto out; |
463 | + unlock_user_struct(uss, uss_addr, 0); | |
463 | 464 | |
464 | 465 | ret = -TARGET_EPERM; |
465 | 466 | if (on_sig_stack(sp)) |
... | ... | @@ -484,11 +485,10 @@ int do_sigaltstack(const struct target_sigaltstack *uss, |
484 | 485 | target_sigaltstack_used.ss_size = ss.ss_size; |
485 | 486 | } |
486 | 487 | |
487 | - if (uoss) { | |
488 | + if (uoss_addr) { | |
488 | 489 | ret = -TARGET_EFAULT; |
489 | - if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss))) | |
490 | + if (copy_to_user(uoss_addr, &oss, sizeof(oss))) | |
490 | 491 | goto out; |
491 | - memcpy(uoss, &oss, sizeof(oss)); | |
492 | 492 | } |
493 | 493 | |
494 | 494 | ret = 0; |
... | ... | @@ -671,6 +671,7 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
671 | 671 | { |
672 | 672 | int err = 0; |
673 | 673 | |
674 | + /* already locked in setup_frame() */ | |
674 | 675 | err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); |
675 | 676 | err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); |
676 | 677 | err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); |
... | ... | @@ -706,7 +707,7 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
706 | 707 | * Determine which stack to use.. |
707 | 708 | */ |
708 | 709 | |
709 | -static inline void * | |
710 | +static inline abi_ulong | |
710 | 711 | get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) |
711 | 712 | { |
712 | 713 | unsigned long esp; |
... | ... | @@ -726,19 +727,22 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) |
726 | 727 | ka->sa.sa_restorer) { |
727 | 728 | esp = (unsigned long) ka->sa.sa_restorer; |
728 | 729 | } |
729 | - return g2h((esp - frame_size) & -8ul); | |
730 | + return (esp - frame_size) & -8ul; | |
730 | 731 | } |
731 | 732 | |
733 | +/* compare linux/arch/i386/kernel/signal.c:setup_frame() */ | |
732 | 734 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
733 | 735 | target_sigset_t *set, CPUX86State *env) |
734 | 736 | { |
737 | + abi_ulong frame_addr; | |
735 | 738 | struct sigframe *frame; |
736 | 739 | int i, err = 0; |
737 | 740 | |
738 | - frame = get_sigframe(ka, env, sizeof(*frame)); | |
741 | + frame_addr = get_sigframe(ka, env, sizeof(*frame)); | |
739 | 742 | |
740 | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | |
743 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
741 | 744 | goto give_sigsegv; |
745 | + | |
742 | 746 | err |= __put_user((/*current->exec_domain |
743 | 747 | && current->exec_domain->signal_invmap |
744 | 748 | && sig < 32 |
... | ... | @@ -786,24 +790,29 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
786 | 790 | cpu_x86_load_seg(env, R_CS, __USER_CS); |
787 | 791 | env->eflags &= ~TF_MASK; |
788 | 792 | |
793 | + unlock_user_struct(frame, frame_addr, 1); | |
794 | + | |
789 | 795 | return; |
790 | 796 | |
791 | 797 | give_sigsegv: |
798 | + unlock_user_struct(frame, frame_addr, 1); | |
792 | 799 | if (sig == TARGET_SIGSEGV) |
793 | 800 | ka->sa._sa_handler = TARGET_SIG_DFL; |
794 | 801 | force_sig(TARGET_SIGSEGV /* , current */); |
795 | 802 | } |
796 | 803 | |
804 | +/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */ | |
797 | 805 | static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
798 | 806 | target_siginfo_t *info, |
799 | 807 | target_sigset_t *set, CPUX86State *env) |
800 | 808 | { |
809 | + abi_ulong frame_addr; | |
801 | 810 | struct rt_sigframe *frame; |
802 | 811 | int i, err = 0; |
803 | 812 | |
804 | - frame = get_sigframe(ka, env, sizeof(*frame)); | |
813 | + frame_addr = get_sigframe(ka, env, sizeof(*frame)); | |
805 | 814 | |
806 | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | |
815 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
807 | 816 | goto give_sigsegv; |
808 | 817 | |
809 | 818 | err |= __put_user((/*current->exec_domain |
... | ... | @@ -859,9 +868,12 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
859 | 868 | cpu_x86_load_seg(env, R_CS, __USER_CS); |
860 | 869 | env->eflags &= ~TF_MASK; |
861 | 870 | |
871 | + unlock_user_struct(frame, frame_addr, 1); | |
872 | + | |
862 | 873 | return; |
863 | 874 | |
864 | 875 | give_sigsegv: |
876 | + unlock_user_struct(frame, frame_addr, 1); | |
865 | 877 | if (sig == TARGET_SIGSEGV) |
866 | 878 | ka->sa._sa_handler = TARGET_SIG_DFL; |
867 | 879 | force_sig(TARGET_SIGSEGV /* , current */); |
... | ... | @@ -918,7 +930,8 @@ badframe: |
918 | 930 | |
919 | 931 | long do_sigreturn(CPUX86State *env) |
920 | 932 | { |
921 | - struct sigframe *frame = (struct sigframe *)g2h(env->regs[R_ESP] - 8); | |
933 | + struct sigframe *frame; | |
934 | + abi_ulong frame_addr = env->regs[R_ESP] - 8; | |
922 | 935 | target_sigset_t target_set; |
923 | 936 | sigset_t set; |
924 | 937 | int eax, i; |
... | ... | @@ -926,6 +939,8 @@ long do_sigreturn(CPUX86State *env) |
926 | 939 | #if defined(DEBUG_SIGNAL) |
927 | 940 | fprintf(stderr, "do_sigreturn\n"); |
928 | 941 | #endif |
942 | + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) | |
943 | + goto badframe; | |
929 | 944 | /* set blocked signals */ |
930 | 945 | if (__get_user(target_set.sig[0], &frame->sc.oldmask)) |
931 | 946 | goto badframe; |
... | ... | @@ -940,9 +955,11 @@ long do_sigreturn(CPUX86State *env) |
940 | 955 | /* restore registers */ |
941 | 956 | if (restore_sigcontext(env, &frame->sc, &eax)) |
942 | 957 | goto badframe; |
958 | + unlock_user_struct(frame, frame_addr, 0); | |
943 | 959 | return eax; |
944 | 960 | |
945 | 961 | badframe: |
962 | + unlock_user_struct(frame, frame_addr, 0); | |
946 | 963 | force_sig(TARGET_SIGSEGV); |
947 | 964 | return 0; |
948 | 965 | } |
... | ... | @@ -963,7 +980,7 @@ long do_rt_sigreturn(CPUX86State *env) |
963 | 980 | if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) |
964 | 981 | goto badframe; |
965 | 982 | |
966 | - if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT) | |
983 | + if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) | |
967 | 984 | goto badframe; |
968 | 985 | |
969 | 986 | return eax; |
... | ... | @@ -1086,7 +1103,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ |
1086 | 1103 | return err; |
1087 | 1104 | } |
1088 | 1105 | |
1089 | -static inline void * | |
1106 | +static inline abi_ulong | |
1090 | 1107 | get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) |
1091 | 1108 | { |
1092 | 1109 | unsigned long sp = regs->regs[13]; |
... | ... | @@ -1099,7 +1116,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) |
1099 | 1116 | /* |
1100 | 1117 | * ATPCS B01 mandates 8-byte alignment |
1101 | 1118 | */ |
1102 | - return g2h((sp - framesize) & ~7); | |
1119 | + return (sp - framesize) & ~7; | |
1103 | 1120 | } |
1104 | 1121 | |
1105 | 1122 | static int |
... | ... | @@ -1167,33 +1184,43 @@ setup_return(CPUState *env, struct emulated_sigaction *ka, |
1167 | 1184 | return 0; |
1168 | 1185 | } |
1169 | 1186 | |
1187 | +/* compare linux/arch/arm/kernel/signal.c:setup_frame() */ | |
1170 | 1188 | static void setup_frame(int usig, struct emulated_sigaction *ka, |
1171 | 1189 | target_sigset_t *set, CPUState *regs) |
1172 | 1190 | { |
1173 | - struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame)); | |
1191 | + struct sigframe *frame; | |
1192 | + abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame)); | |
1174 | 1193 | int i, err = 0; |
1175 | 1194 | |
1195 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
1196 | + return; | |
1197 | + | |
1176 | 1198 | err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); |
1177 | 1199 | |
1178 | 1200 | for(i = 1; i < TARGET_NSIG_WORDS; i++) { |
1179 | 1201 | if (__put_user(set->sig[i], &frame->extramask[i - 1])) |
1180 | - return; | |
1202 | + goto end; | |
1181 | 1203 | } |
1182 | 1204 | |
1183 | 1205 | if (err == 0) |
1184 | 1206 | err = setup_return(regs, ka, &frame->retcode, frame, usig); |
1207 | + | |
1208 | +end: | |
1209 | + unlock_user_struct(frame, frame_addr, 1); | |
1185 | 1210 | // return err; |
1186 | 1211 | } |
1187 | 1212 | |
1213 | +/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */ | |
1188 | 1214 | static void setup_rt_frame(int usig, struct emulated_sigaction *ka, |
1189 | 1215 | target_siginfo_t *info, |
1190 | 1216 | target_sigset_t *set, CPUState *env) |
1191 | 1217 | { |
1192 | - struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame)); | |
1218 | + struct rt_sigframe *frame; | |
1219 | + abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame)); | |
1193 | 1220 | struct target_sigaltstack stack; |
1194 | 1221 | int i, err = 0; |
1195 | 1222 | |
1196 | - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | |
1223 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
1197 | 1224 | return /* 1 */; |
1198 | 1225 | |
1199 | 1226 | __put_user_error(&frame->info, (abi_ulong *)&frame->pinfo, err); |
... | ... | @@ -1207,16 +1234,13 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, |
1207 | 1234 | __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp); |
1208 | 1235 | __put_user(target_sigaltstack_used.ss_size, &stack.ss_size); |
1209 | 1236 | __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags); |
1210 | - if (!access_ok(VERIFY_WRITE, &frame->uc.tuc_stack, sizeof(stack))) | |
1211 | - err = 1; | |
1212 | - else | |
1213 | - memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack)); | |
1237 | + err |= copy_to_user(&frame->uc.tuc_stack, &stack, sizeof(stack)); | |
1214 | 1238 | |
1215 | 1239 | err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/ |
1216 | 1240 | env, set->sig[0]); |
1217 | 1241 | for(i = 0; i < TARGET_NSIG_WORDS; i++) { |
1218 | 1242 | if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) |
1219 | - return; | |
1243 | + goto end; | |
1220 | 1244 | } |
1221 | 1245 | |
1222 | 1246 | if (err == 0) |
... | ... | @@ -1232,6 +1256,9 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, |
1232 | 1256 | env->regs[2] = (abi_ulong)frame->puc; |
1233 | 1257 | } |
1234 | 1258 | |
1259 | +end: | |
1260 | + unlock_user_struct(frame, frame_addr, 1); | |
1261 | + | |
1235 | 1262 | // return err; |
1236 | 1263 | } |
1237 | 1264 | |
... | ... | @@ -1338,7 +1365,7 @@ long do_rt_sigreturn(CPUState *env) |
1338 | 1365 | if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) |
1339 | 1366 | goto badframe; |
1340 | 1367 | |
1341 | - if (do_sigaltstack(&frame->uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT) | |
1368 | + if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) | |
1342 | 1369 | goto badframe; |
1343 | 1370 | |
1344 | 1371 | #if 0 |
... | ... | @@ -1788,8 +1815,8 @@ void sparc64_set_context(CPUSPARCState *env) |
1788 | 1815 | abi_ulong *src, *dst; |
1789 | 1816 | |
1790 | 1817 | grp = &ucp->uc_mcontext.mc_gregs; |
1791 | - err = get_user(pc, &((*grp)[MC_PC])); | |
1792 | - err |= get_user(npc, &((*grp)[MC_NPC])); | |
1818 | + err = __get_user(pc, &((*grp)[MC_PC])); | |
1819 | + err |= __get_user(npc, &((*grp)[MC_NPC])); | |
1793 | 1820 | if (err || ((pc | npc) & 3)) |
1794 | 1821 | goto do_sigsegv; |
1795 | 1822 | if (env->regwptr[UREG_I1]) { |
... | ... | @@ -1797,14 +1824,14 @@ void sparc64_set_context(CPUSPARCState *env) |
1797 | 1824 | sigset_t set; |
1798 | 1825 | |
1799 | 1826 | if (TARGET_NSIG_WORDS == 1) { |
1800 | - if (get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) | |
1827 | + if (__get_user(target_set.sig[0], &ucp->uc_sigmask.sig[0])) | |
1801 | 1828 | goto do_sigsegv; |
1802 | 1829 | } else { |
1803 | 1830 | src = &ucp->uc_sigmask; |
1804 | 1831 | dst = &target_set; |
1805 | 1832 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); |
1806 | 1833 | i++, dst++, src++) |
1807 | - err |= get_user(dst, src); | |
1834 | + err |= __get_user(dst, src); | |
1808 | 1835 | if (err) |
1809 | 1836 | goto do_sigsegv; |
1810 | 1837 | } |
... | ... | @@ -1813,44 +1840,44 @@ void sparc64_set_context(CPUSPARCState *env) |
1813 | 1840 | } |
1814 | 1841 | env->pc = pc; |
1815 | 1842 | env->npc = npc; |
1816 | - err |= get_user(env->y, &((*grp)[MC_Y])); | |
1817 | - err |= get_user(tstate, &((*grp)[MC_TSTATE])); | |
1843 | + err |= __get_user(env->y, &((*grp)[MC_Y])); | |
1844 | + err |= __get_user(tstate, &((*grp)[MC_TSTATE])); | |
1818 | 1845 | env->asi = (tstate >> 24) & 0xff; |
1819 | 1846 | PUT_CCR(env, tstate >> 32); |
1820 | 1847 | PUT_CWP64(env, tstate & 0x1f); |
1821 | - err |= get_user(env->gregs[1], (&(*grp)[MC_G1])); | |
1822 | - err |= get_user(env->gregs[2], (&(*grp)[MC_G2])); | |
1823 | - err |= get_user(env->gregs[3], (&(*grp)[MC_G3])); | |
1824 | - err |= get_user(env->gregs[4], (&(*grp)[MC_G4])); | |
1825 | - err |= get_user(env->gregs[5], (&(*grp)[MC_G5])); | |
1826 | - err |= get_user(env->gregs[6], (&(*grp)[MC_G6])); | |
1827 | - err |= get_user(env->gregs[7], (&(*grp)[MC_G7])); | |
1828 | - err |= get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0])); | |
1829 | - err |= get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1])); | |
1830 | - err |= get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2])); | |
1831 | - err |= get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3])); | |
1832 | - err |= get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4])); | |
1833 | - err |= get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5])); | |
1834 | - err |= get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6])); | |
1835 | - err |= get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7])); | |
1836 | - | |
1837 | - err |= get_user(fp, &(ucp->uc_mcontext.mc_fp)); | |
1838 | - err |= get_user(i7, &(ucp->uc_mcontext.mc_i7)); | |
1839 | - err |= put_user(fp, | |
1840 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | |
1841 | - err |= put_user(i7, | |
1842 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | |
1843 | - | |
1844 | - err |= get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); | |
1845 | - err |= get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); | |
1848 | + err |= __get_user(env->gregs[1], (&(*grp)[MC_G1])); | |
1849 | + err |= __get_user(env->gregs[2], (&(*grp)[MC_G2])); | |
1850 | + err |= __get_user(env->gregs[3], (&(*grp)[MC_G3])); | |
1851 | + err |= __get_user(env->gregs[4], (&(*grp)[MC_G4])); | |
1852 | + err |= __get_user(env->gregs[5], (&(*grp)[MC_G5])); | |
1853 | + err |= __get_user(env->gregs[6], (&(*grp)[MC_G6])); | |
1854 | + err |= __get_user(env->gregs[7], (&(*grp)[MC_G7])); | |
1855 | + err |= __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0])); | |
1856 | + err |= __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1])); | |
1857 | + err |= __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2])); | |
1858 | + err |= __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3])); | |
1859 | + err |= __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4])); | |
1860 | + err |= __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5])); | |
1861 | + err |= __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6])); | |
1862 | + err |= __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7])); | |
1863 | + | |
1864 | + err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); | |
1865 | + err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); | |
1866 | + err |= __put_user(fp, | |
1867 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | |
1868 | + err |= __put_user(i7, | |
1869 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | |
1870 | + | |
1871 | + err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); | |
1872 | + err |= __get_user(env->fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); | |
1846 | 1873 | src = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); |
1847 | 1874 | dst = &env->fpr; |
1848 | 1875 | for (i = 0; i < 64; i++, dst++, src++) |
1849 | - err |= get_user(dst, src); | |
1850 | - err |= get_user(env->fsr, | |
1851 | - &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); | |
1852 | - err |= get_user(env->gsr, | |
1853 | - &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); | |
1876 | + err |= __get_user(dst, src); | |
1877 | + err |= __get_user(env->fsr, | |
1878 | + &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); | |
1879 | + err |= __get_user(env->gsr, | |
1880 | + &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); | |
1854 | 1881 | if (err) |
1855 | 1882 | goto do_sigsegv; |
1856 | 1883 | |
... | ... | @@ -1884,52 +1911,52 @@ void sparc64_get_context(CPUSPARCState *env) |
1884 | 1911 | sigprocmask(0, NULL, &set); |
1885 | 1912 | host_to_target_sigset_internal(&target_set, &set); |
1886 | 1913 | if (TARGET_NSIG_WORDS == 1) |
1887 | - err |= put_user(target_set.sig[0], | |
1888 | - (abi_ulong *)&ucp->uc_sigmask); | |
1914 | + err |= __put_user(target_set.sig[0], | |
1915 | + (abi_ulong *)&ucp->uc_sigmask); | |
1889 | 1916 | else { |
1890 | 1917 | src = &target_set; |
1891 | 1918 | dst = &ucp->uc_sigmask; |
1892 | 1919 | for (i = 0; i < sizeof(target_sigset_t) / sizeof(abi_ulong); |
1893 | 1920 | i++, dst++, src++) |
1894 | - err |= put_user(src, dst); | |
1921 | + err |= __put_user(src, dst); | |
1895 | 1922 | if (err) |
1896 | 1923 | goto do_sigsegv; |
1897 | 1924 | } |
1898 | 1925 | |
1899 | - err |= put_user(env->tstate, &((*grp)[MC_TSTATE])); | |
1900 | - err |= put_user(env->pc, &((*grp)[MC_PC])); | |
1901 | - err |= put_user(env->npc, &((*grp)[MC_NPC])); | |
1902 | - err |= put_user(env->y, &((*grp)[MC_Y])); | |
1903 | - err |= put_user(env->gregs[1], &((*grp)[MC_G1])); | |
1904 | - err |= put_user(env->gregs[2], &((*grp)[MC_G2])); | |
1905 | - err |= put_user(env->gregs[3], &((*grp)[MC_G3])); | |
1906 | - err |= put_user(env->gregs[4], &((*grp)[MC_G4])); | |
1907 | - err |= put_user(env->gregs[5], &((*grp)[MC_G5])); | |
1908 | - err |= put_user(env->gregs[6], &((*grp)[MC_G6])); | |
1909 | - err |= put_user(env->gregs[7], &((*grp)[MC_G7])); | |
1910 | - err |= put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0])); | |
1911 | - err |= put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1])); | |
1912 | - err |= put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2])); | |
1913 | - err |= put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3])); | |
1914 | - err |= put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4])); | |
1915 | - err |= put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5])); | |
1916 | - err |= put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); | |
1917 | - err |= put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); | |
1918 | - | |
1919 | - err |= get_user(fp, | |
1920 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | |
1921 | - err |= get_user(i7, | |
1922 | - (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | |
1923 | - err |= put_user(fp, &(mcp->mc_fp)); | |
1924 | - err |= put_user(i7, &(mcp->mc_i7)); | |
1926 | + err |= __put_user(env->tstate, &((*grp)[MC_TSTATE])); | |
1927 | + err |= __put_user(env->pc, &((*grp)[MC_PC])); | |
1928 | + err |= __put_user(env->npc, &((*grp)[MC_NPC])); | |
1929 | + err |= __put_user(env->y, &((*grp)[MC_Y])); | |
1930 | + err |= __put_user(env->gregs[1], &((*grp)[MC_G1])); | |
1931 | + err |= __put_user(env->gregs[2], &((*grp)[MC_G2])); | |
1932 | + err |= __put_user(env->gregs[3], &((*grp)[MC_G3])); | |
1933 | + err |= __put_user(env->gregs[4], &((*grp)[MC_G4])); | |
1934 | + err |= __put_user(env->gregs[5], &((*grp)[MC_G5])); | |
1935 | + err |= __put_user(env->gregs[6], &((*grp)[MC_G6])); | |
1936 | + err |= __put_user(env->gregs[7], &((*grp)[MC_G7])); | |
1937 | + err |= __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0])); | |
1938 | + err |= __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1])); | |
1939 | + err |= __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2])); | |
1940 | + err |= __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3])); | |
1941 | + err |= __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4])); | |
1942 | + err |= __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5])); | |
1943 | + err |= __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); | |
1944 | + err |= __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); | |
1945 | + | |
1946 | + err |= __get_user(fp, | |
1947 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[6]))); | |
1948 | + err |= __get_user(i7, | |
1949 | + (&(((struct target_reg_window *)(TARGET_STACK_BIAS+env->regwptr[UREG_I6]))->ins[7]))); | |
1950 | + err |= __put_user(fp, &(mcp->mc_fp)); | |
1951 | + err |= __put_user(i7, &(mcp->mc_i7)); | |
1925 | 1952 | |
1926 | 1953 | src = &env->fpr; |
1927 | 1954 | dst = &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs); |
1928 | 1955 | for (i = 0; i < 64; i++, dst++, src++) |
1929 | - err |= put_user(src, dst); | |
1930 | - err |= put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); | |
1931 | - err |= put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); | |
1932 | - err |= put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); | |
1956 | + err |= __put_user(src, dst); | |
1957 | + err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); | |
1958 | + err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); | |
1959 | + err |= __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); | |
1933 | 1960 | |
1934 | 1961 | if (err) |
1935 | 1962 | goto do_sigsegv; |
... | ... | @@ -2191,7 +2218,7 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) |
2191 | 2218 | /* |
2192 | 2219 | * Determine which stack to use.. |
2193 | 2220 | */ |
2194 | -static inline void * | |
2221 | +static inline abi_ulong | |
2195 | 2222 | get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) |
2196 | 2223 | { |
2197 | 2224 | unsigned long sp; |
... | ... | @@ -2211,17 +2238,19 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) |
2211 | 2238 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
2212 | 2239 | } |
2213 | 2240 | |
2214 | - return g2h((sp - frame_size) & ~7); | |
2241 | + return (sp - frame_size) & ~7; | |
2215 | 2242 | } |
2216 | 2243 | |
2244 | +/* compare linux/arch/mips/kernel/signal.c:setup_frame() */ | |
2217 | 2245 | static void setup_frame(int sig, struct emulated_sigaction * ka, |
2218 | - target_sigset_t *set, CPUState *regs) | |
2246 | + target_sigset_t *set, CPUState *regs) | |
2219 | 2247 | { |
2220 | 2248 | struct sigframe *frame; |
2249 | + abi_ulong frame_addr; | |
2221 | 2250 | int i; |
2222 | 2251 | |
2223 | - frame = get_sigframe(ka, regs, sizeof(*frame)); | |
2224 | - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | |
2252 | + frame_addr = get_sigframe(ka, regs, sizeof(*frame)); | |
2253 | + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) | |
2225 | 2254 | goto give_sigsegv; |
2226 | 2255 | |
2227 | 2256 | install_sigtramp(frame->sf_code, TARGET_NR_sigreturn); |
... | ... | @@ -2253,9 +2282,11 @@ static void setup_frame(int sig, struct emulated_sigaction * ka, |
2253 | 2282 | * since it returns to userland using eret |
2254 | 2283 | * we cannot do this here, and we must set PC directly */ |
2255 | 2284 | regs->PC[regs->current_tc] = regs->gpr[25][regs->current_tc] = ka->sa._sa_handler; |
2285 | + unlock_user_struct(frame, frame_addr, 1); | |
2256 | 2286 | return; |
2257 | 2287 | |
2258 | 2288 | give_sigsegv: |
2289 | + unlock_user_struct(frame, frame_addr, 1); | |
2259 | 2290 | force_sig(TARGET_SIGSEGV/*, current*/); |
2260 | 2291 | return; |
2261 | 2292 | } |
... | ... | @@ -2263,6 +2294,7 @@ give_sigsegv: |
2263 | 2294 | long do_sigreturn(CPUState *regs) |
2264 | 2295 | { |
2265 | 2296 | struct sigframe *frame; |
2297 | + abi_ulong frame_addr; | |
2266 | 2298 | sigset_t blocked; |
2267 | 2299 | target_sigset_t target_set; |
2268 | 2300 | int i; |
... | ... | @@ -2270,8 +2302,8 @@ long do_sigreturn(CPUState *regs) |
2270 | 2302 | #if defined(DEBUG_SIGNAL) |
2271 | 2303 | fprintf(stderr, "do_sigreturn\n"); |
2272 | 2304 | #endif |
2273 | - frame = (struct sigframe *) regs->gpr[29][regs->current_tc]; | |
2274 | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | |
2305 | + frame_addr = regs->gpr[29][regs->current_tc]; | |
2306 | + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) | |
2275 | 2307 | goto badframe; |
2276 | 2308 | |
2277 | 2309 | for(i = 0; i < TARGET_NSIG_WORDS; i++) { | ... | ... |
linux-user/strace.c
... | ... | @@ -81,14 +81,18 @@ print_fdset(int n, target_ulong target_fds_addr) |
81 | 81 | |
82 | 82 | gemu_log("["); |
83 | 83 | if( target_fds_addr ) { |
84 | - target_long *target_fds; | |
84 | + abi_long *target_fds; | |
85 | 85 | |
86 | - if (!access_ok(VERIFY_READ, target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1))) | |
86 | + target_fds = lock_user(VERIFY_READ, | |
87 | + target_fds_addr, | |
88 | + sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1), | |
89 | + 1); | |
90 | + | |
91 | + if (!target_fds) | |
87 | 92 | return; |
88 | 93 | |
89 | - target_fds = lock_user(target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1), 1); | |
90 | 94 | for (i=n; i>=0; i--) { |
91 | - if ((tswapl(target_fds[i / TARGET_LONG_BITS]) >> (i & (TARGET_LONG_BITS - 1))) & 1) | |
95 | + if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1) | |
92 | 96 | gemu_log("%d,", i ); |
93 | 97 | } |
94 | 98 | unlock_user(target_fds, target_fds_addr, 0); |
... | ... | @@ -102,10 +106,9 @@ print_timeval(target_ulong tv_addr) |
102 | 106 | if( tv_addr ) { |
103 | 107 | struct target_timeval *tv; |
104 | 108 | |
105 | - if (!access_ok(VERIFY_READ, tv_addr, sizeof(*tv))) | |
109 | + tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1); | |
110 | + if (!tv) | |
106 | 111 | return; |
107 | - | |
108 | - tv = lock_user(tv_addr, sizeof(*tv), 1); | |
109 | 112 | gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}", |
110 | 113 | tv->tv_sec, tv->tv_usec); |
111 | 114 | unlock_user(tv, tv_addr, 0); |
... | ... | @@ -165,27 +168,25 @@ print_execve(struct syscallname *name, |
165 | 168 | target_ulong arg_ptr_addr; |
166 | 169 | char *s; |
167 | 170 | |
168 | - if (!access_ok(VERIFY_READ, arg1, 1)) | |
171 | + if (!(s = lock_user_string(arg1))) | |
169 | 172 | return; |
170 | - | |
171 | - s = lock_user_string(arg1); | |
172 | 173 | gemu_log("%s(\"%s\",{", name->name, s); |
173 | 174 | unlock_user(s, arg1, 0); |
174 | 175 | |
175 | 176 | for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(target_ulong)) { |
176 | 177 | target_ulong *arg_ptr, arg_addr, s_addr; |
177 | 178 | |
178 | - if (!access_ok(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong))) | |
179 | + arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong), 1); | |
180 | + if (!arg_ptr) | |
179 | 181 | return; |
180 | - | |
181 | - arg_ptr = lock_user(arg_ptr_addr, sizeof(target_ulong), 1); | |
182 | 182 | arg_addr = tswapl(*arg_ptr); |
183 | 183 | unlock_user(arg_ptr, arg_ptr_addr, 0); |
184 | 184 | if (!arg_addr) |
185 | 185 | break; |
186 | - s = lock_user_string(arg_addr); | |
187 | - gemu_log("\"%s\",", s); | |
188 | - unlock_user(s, s_addr, 0); | |
186 | + if ((s = lock_user_string(arg_addr))) { | |
187 | + gemu_log("\"%s\",", s); | |
188 | + unlock_user(s, s_addr, 0); | |
189 | + } | |
189 | 190 | } |
190 | 191 | |
191 | 192 | gemu_log("NULL})"); | ... | ... |
linux-user/syscall.c
... | ... | @@ -504,12 +504,13 @@ static inline abi_long host_to_target_clock_t(long ticks) |
504 | 504 | #endif |
505 | 505 | } |
506 | 506 | |
507 | -static inline void host_to_target_rusage(abi_ulong target_addr, | |
508 | - const struct rusage *rusage) | |
507 | +static inline abi_long host_to_target_rusage(abi_ulong target_addr, | |
508 | + const struct rusage *rusage) | |
509 | 509 | { |
510 | 510 | struct target_rusage *target_rusage; |
511 | 511 | |
512 | - lock_user_struct(target_rusage, target_addr, 0); | |
512 | + if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) | |
513 | + return -TARGET_EFAULT; | |
513 | 514 | target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); |
514 | 515 | target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); |
515 | 516 | target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); |
... | ... | @@ -529,28 +530,36 @@ static inline void host_to_target_rusage(abi_ulong target_addr, |
529 | 530 | target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); |
530 | 531 | target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); |
531 | 532 | unlock_user_struct(target_rusage, target_addr, 1); |
533 | + | |
534 | + return 0; | |
532 | 535 | } |
533 | 536 | |
534 | -static inline void target_to_host_timeval(struct timeval *tv, | |
535 | - abi_ulong target_addr) | |
537 | +static inline abi_long target_to_host_timeval(struct timeval *tv, | |
538 | + abi_ulong target_addr) | |
536 | 539 | { |
537 | 540 | struct target_timeval *target_tv; |
538 | 541 | |
539 | - lock_user_struct(target_tv, target_addr, 1); | |
542 | + if (!lock_user_struct(VERIFY_READ, target_tv, target_addr, 1)) | |
543 | + return -TARGET_EFAULT; | |
540 | 544 | tv->tv_sec = tswapl(target_tv->tv_sec); |
541 | 545 | tv->tv_usec = tswapl(target_tv->tv_usec); |
542 | 546 | unlock_user_struct(target_tv, target_addr, 0); |
547 | + | |
548 | + return 0; | |
543 | 549 | } |
544 | 550 | |
545 | -static inline void host_to_target_timeval(abi_ulong target_addr, | |
546 | - const struct timeval *tv) | |
551 | +static inline abi_long host_to_target_timeval(abi_ulong target_addr, | |
552 | + const struct timeval *tv) | |
547 | 553 | { |
548 | 554 | struct target_timeval *target_tv; |
549 | 555 | |
550 | - lock_user_struct(target_tv, target_addr, 0); | |
556 | + if (!lock_user_struct(VERIFY_WRITE, target_tv, target_addr, 0)) | |
557 | + return -TARGET_EFAULT; | |
551 | 558 | target_tv->tv_sec = tswapl(tv->tv_sec); |
552 | 559 | target_tv->tv_usec = tswapl(tv->tv_usec); |
553 | 560 | unlock_user_struct(target_tv, target_addr, 1); |
561 | + | |
562 | + return 0; | |
554 | 563 | } |
555 | 564 | |
556 | 565 | |
... | ... | @@ -567,21 +576,33 @@ static abi_long do_select(int n, |
567 | 576 | int ok; |
568 | 577 | |
569 | 578 | if (rfd_p) { |
570 | - target_rfds = lock_user(rfd_p, sizeof(abi_long) * n, 1); | |
579 | + target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1); | |
580 | + if (!target_rfds) { | |
581 | + ret = -TARGET_EFAULT; | |
582 | + goto end; | |
583 | + } | |
571 | 584 | rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); |
572 | 585 | } else { |
573 | 586 | target_rfds = NULL; |
574 | 587 | rfds_ptr = NULL; |
575 | 588 | } |
576 | 589 | if (wfd_p) { |
577 | - target_wfds = lock_user(wfd_p, sizeof(abi_long) * n, 1); | |
590 | + target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1); | |
591 | + if (!target_wfds) { | |
592 | + ret = -TARGET_EFAULT; | |
593 | + goto end; | |
594 | + } | |
578 | 595 | wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); |
579 | 596 | } else { |
580 | 597 | target_wfds = NULL; |
581 | 598 | wfds_ptr = NULL; |
582 | 599 | } |
583 | 600 | if (efd_p) { |
584 | - target_efds = lock_user(efd_p, sizeof(abi_long) * n, 1); | |
601 | + target_efds = lock_user(VERIFY_WRITE, efd_p, sizeof(abi_long) * n, 1); | |
602 | + if (!target_efds) { | |
603 | + ret = -TARGET_EFAULT; | |
604 | + goto end; | |
605 | + } | |
585 | 606 | efds_ptr = target_to_host_fds(&efds, target_efds, n); |
586 | 607 | } else { |
587 | 608 | target_efds = NULL; |
... | ... | @@ -606,38 +627,45 @@ static abi_long do_select(int n, |
606 | 627 | host_to_target_timeval(target_tv, &tv); |
607 | 628 | } |
608 | 629 | } |
609 | - if (target_rfds) | |
610 | - unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0); | |
611 | - if (target_wfds) | |
612 | - unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0); | |
613 | - if (target_efds) | |
614 | - unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0); | |
630 | + | |
631 | +end: | |
632 | + unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0); | |
633 | + unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0); | |
634 | + unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0); | |
615 | 635 | |
616 | 636 | return ret; |
617 | 637 | } |
618 | 638 | |
619 | -static inline void target_to_host_sockaddr(struct sockaddr *addr, | |
620 | - abi_ulong target_addr, | |
621 | - socklen_t len) | |
639 | +static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, | |
640 | + abi_ulong target_addr, | |
641 | + socklen_t len) | |
622 | 642 | { |
623 | 643 | struct target_sockaddr *target_saddr; |
624 | 644 | |
625 | - target_saddr = lock_user(target_addr, len, 1); | |
645 | + target_saddr = lock_user(VERIFY_READ, target_addr, len, 1); | |
646 | + if (!target_saddr) | |
647 | + return -TARGET_EFAULT; | |
626 | 648 | memcpy(addr, target_saddr, len); |
627 | 649 | addr->sa_family = tswap16(target_saddr->sa_family); |
628 | 650 | unlock_user(target_saddr, target_addr, 0); |
651 | + | |
652 | + return 0; | |
629 | 653 | } |
630 | 654 | |
631 | -static inline void host_to_target_sockaddr(abi_ulong target_addr, | |
632 | - struct sockaddr *addr, | |
633 | - socklen_t len) | |
655 | +static inline abi_long host_to_target_sockaddr(abi_ulong target_addr, | |
656 | + struct sockaddr *addr, | |
657 | + socklen_t len) | |
634 | 658 | { |
635 | 659 | struct target_sockaddr *target_saddr; |
636 | 660 | |
637 | - target_saddr = lock_user(target_addr, len, 0); | |
661 | + target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0); | |
662 | + if (!target_saddr) | |
663 | + return -TARGET_EFAULT; | |
638 | 664 | memcpy(target_saddr, addr, len); |
639 | 665 | target_saddr->sa_family = tswap16(addr->sa_family); |
640 | 666 | unlock_user(target_saddr, target_addr, len); |
667 | + | |
668 | + return 0; | |
641 | 669 | } |
642 | 670 | |
643 | 671 | /* ??? Should this also swap msgh->name? */ |
... | ... | @@ -941,35 +969,56 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, |
941 | 969 | return ret; |
942 | 970 | } |
943 | 971 | |
944 | -static void lock_iovec(struct iovec *vec, abi_ulong target_addr, | |
945 | - int count, int copy) | |
972 | +/* FIXME | |
973 | + * lock_iovec()/unlock_iovec() have a return code of 0 for success where | |
974 | + * other lock functions have a return code of 0 for failure. | |
975 | + */ | |
976 | +static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr, | |
977 | + int count, int copy) | |
946 | 978 | { |
947 | 979 | struct target_iovec *target_vec; |
948 | 980 | abi_ulong base; |
949 | - int i; | |
981 | + int i, j; | |
950 | 982 | |
951 | - target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); | |
983 | + target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); | |
984 | + if (!target_vec) | |
985 | + return -TARGET_EFAULT; | |
952 | 986 | for(i = 0;i < count; i++) { |
953 | 987 | base = tswapl(target_vec[i].iov_base); |
954 | 988 | vec[i].iov_len = tswapl(target_vec[i].iov_len); |
955 | - vec[i].iov_base = lock_user(base, vec[i].iov_len, copy); | |
989 | + vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy); | |
990 | + if (!vec[i].iov_base) | |
991 | + goto fail; | |
992 | + } | |
993 | + unlock_user (target_vec, target_addr, 0); | |
994 | + return 0; | |
995 | + fail: | |
996 | + /* failure - unwind locks */ | |
997 | + for (j = 0; j < i; j++) { | |
998 | + base = tswapl(target_vec[j].iov_base); | |
999 | + unlock_user(vec[j].iov_base, base, 0); | |
956 | 1000 | } |
957 | 1001 | unlock_user (target_vec, target_addr, 0); |
1002 | + return -TARGET_EFAULT; | |
958 | 1003 | } |
959 | 1004 | |
960 | -static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, | |
961 | - int count, int copy) | |
1005 | +static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, | |
1006 | + int count, int copy) | |
962 | 1007 | { |
963 | 1008 | struct target_iovec *target_vec; |
964 | 1009 | abi_ulong base; |
965 | 1010 | int i; |
966 | 1011 | |
967 | - target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); | |
1012 | + target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1); | |
1013 | + if (!target_vec) | |
1014 | + return -TARGET_EFAULT; | |
968 | 1015 | for(i = 0;i < count; i++) { |
969 | 1016 | base = tswapl(target_vec[i].iov_base); |
970 | 1017 | unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); |
971 | 1018 | } |
972 | 1019 | unlock_user (target_vec, target_addr, 0); |
1020 | + | |
1021 | + return 0; | |
973 | 1022 | } |
974 | 1023 | |
975 | 1024 | /* do_socket() Must return target values and target errnos. */ |
... | ... | @@ -1033,7 +1082,12 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, |
1033 | 1082 | struct iovec *vec; |
1034 | 1083 | abi_ulong target_vec; |
1035 | 1084 | |
1036 | - lock_user_struct(msgp, target_msg, 1); | |
1085 | + /* FIXME */ | |
1086 | + if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, | |
1087 | + msgp, | |
1088 | + target_msg, | |
1089 | + send ? 1 : 0)) | |
1090 | + return -TARGET_EFAULT; | |
1037 | 1091 | if (msgp->msg_name) { |
1038 | 1092 | msg.msg_namelen = tswap32(msgp->msg_namelen); |
1039 | 1093 | msg.msg_name = alloca(msg.msg_namelen); |
... | ... | @@ -1050,7 +1104,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, |
1050 | 1104 | count = tswapl(msgp->msg_iovlen); |
1051 | 1105 | vec = alloca(count * sizeof(struct iovec)); |
1052 | 1106 | target_vec = tswapl(msgp->msg_iov); |
1053 | - lock_iovec(vec, target_vec, count, send); | |
1107 | + lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send); | |
1054 | 1108 | msg.msg_iovlen = count; |
1055 | 1109 | msg.msg_iov = vec; |
1056 | 1110 | |
... | ... | @@ -1063,6 +1117,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, |
1063 | 1117 | host_to_target_cmsg(msgp, &msg); |
1064 | 1118 | } |
1065 | 1119 | unlock_iovec(vec, target_vec, count, !send); |
1120 | + unlock_user_struct(msgp, target_msg, send ? 0 : 1); | |
1066 | 1121 | return ret; |
1067 | 1122 | } |
1068 | 1123 | |
... | ... | @@ -1137,7 +1192,9 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, |
1137 | 1192 | void *host_msg; |
1138 | 1193 | abi_long ret; |
1139 | 1194 | |
1140 | - host_msg = lock_user(msg, len, 1); | |
1195 | + host_msg = lock_user(VERIFY_READ, msg, len, 1); | |
1196 | + if (!host_msg) | |
1197 | + return -TARGET_EFAULT; | |
1141 | 1198 | if (target_addr) { |
1142 | 1199 | addr = alloca(addrlen); |
1143 | 1200 | target_to_host_sockaddr(addr, target_addr, addrlen); |
... | ... | @@ -1159,7 +1216,9 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, |
1159 | 1216 | void *host_msg; |
1160 | 1217 | abi_long ret; |
1161 | 1218 | |
1162 | - host_msg = lock_user(msg, len, 0); | |
1219 | + host_msg = lock_user(VERIFY_WRITE, msg, len, 0); | |
1220 | + if (!host_msg) | |
1221 | + return -TARGET_EFAULT; | |
1163 | 1222 | if (target_addr) { |
1164 | 1223 | addrlen = tget32(target_addrlen); |
1165 | 1224 | addr = alloca(addrlen); |
... | ... | @@ -1381,13 +1440,14 @@ struct target_semid_ds |
1381 | 1440 | abi_ulong __unused4; |
1382 | 1441 | }; |
1383 | 1442 | |
1384 | -static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip, | |
1385 | - abi_ulong target_addr) | |
1443 | +static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, | |
1444 | + abi_ulong target_addr) | |
1386 | 1445 | { |
1387 | 1446 | struct target_ipc_perm *target_ip; |
1388 | 1447 | struct target_semid_ds *target_sd; |
1389 | 1448 | |
1390 | - lock_user_struct(target_sd, target_addr, 1); | |
1449 | + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) | |
1450 | + return -TARGET_EFAULT; | |
1391 | 1451 | target_ip=&(target_sd->sem_perm); |
1392 | 1452 | host_ip->__key = tswapl(target_ip->__key); |
1393 | 1453 | host_ip->uid = tswapl(target_ip->uid); |
... | ... | @@ -1396,15 +1456,17 @@ static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip, |
1396 | 1456 | host_ip->cgid = tswapl(target_ip->cgid); |
1397 | 1457 | host_ip->mode = tswapl(target_ip->mode); |
1398 | 1458 | unlock_user_struct(target_sd, target_addr, 0); |
1459 | + return 0; | |
1399 | 1460 | } |
1400 | 1461 | |
1401 | -static inline void host_to_target_ipc_perm(abi_ulong target_addr, | |
1402 | - struct ipc_perm *host_ip) | |
1462 | +static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr, | |
1463 | + struct ipc_perm *host_ip) | |
1403 | 1464 | { |
1404 | 1465 | struct target_ipc_perm *target_ip; |
1405 | 1466 | struct target_semid_ds *target_sd; |
1406 | 1467 | |
1407 | - lock_user_struct(target_sd, target_addr, 0); | |
1468 | + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) | |
1469 | + return -TARGET_EFAULT; | |
1408 | 1470 | target_ip = &(target_sd->sem_perm); |
1409 | 1471 | target_ip->__key = tswapl(host_ip->__key); |
1410 | 1472 | target_ip->uid = tswapl(host_ip->uid); |
... | ... | @@ -1413,32 +1475,37 @@ static inline void host_to_target_ipc_perm(abi_ulong target_addr, |
1413 | 1475 | target_ip->cgid = tswapl(host_ip->cgid); |
1414 | 1476 | target_ip->mode = tswapl(host_ip->mode); |
1415 | 1477 | unlock_user_struct(target_sd, target_addr, 1); |
1478 | + return 0; | |
1416 | 1479 | } |
1417 | 1480 | |
1418 | -static inline void target_to_host_semid_ds(struct semid_ds *host_sd, | |
1419 | - abi_ulong target_addr) | |
1481 | +static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, | |
1482 | + abi_ulong target_addr) | |
1420 | 1483 | { |
1421 | 1484 | struct target_semid_ds *target_sd; |
1422 | 1485 | |
1423 | - lock_user_struct(target_sd, target_addr, 1); | |
1486 | + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) | |
1487 | + return -TARGET_EFAULT; | |
1424 | 1488 | target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); |
1425 | 1489 | host_sd->sem_nsems = tswapl(target_sd->sem_nsems); |
1426 | 1490 | host_sd->sem_otime = tswapl(target_sd->sem_otime); |
1427 | 1491 | host_sd->sem_ctime = tswapl(target_sd->sem_ctime); |
1428 | 1492 | unlock_user_struct(target_sd, target_addr, 0); |
1493 | + return 0; | |
1429 | 1494 | } |
1430 | 1495 | |
1431 | -static inline void host_to_target_semid_ds(abi_ulong target_addr, | |
1432 | - struct semid_ds *host_sd) | |
1496 | +static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, | |
1497 | + struct semid_ds *host_sd) | |
1433 | 1498 | { |
1434 | 1499 | struct target_semid_ds *target_sd; |
1435 | 1500 | |
1436 | - lock_user_struct(target_sd, target_addr, 0); | |
1501 | + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) | |
1502 | + return -TARGET_EFAULT; | |
1437 | 1503 | host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); |
1438 | 1504 | target_sd->sem_nsems = tswapl(host_sd->sem_nsems); |
1439 | 1505 | target_sd->sem_otime = tswapl(host_sd->sem_otime); |
1440 | 1506 | target_sd->sem_ctime = tswapl(host_sd->sem_ctime); |
1441 | 1507 | unlock_user_struct(target_sd, target_addr, 1); |
1508 | + return 0; | |
1442 | 1509 | } |
1443 | 1510 | |
1444 | 1511 | union semun { |
... | ... | @@ -1453,67 +1520,75 @@ union target_semun { |
1453 | 1520 | unsigned short int *array; |
1454 | 1521 | }; |
1455 | 1522 | |
1456 | -static inline void target_to_host_semun(int cmd, | |
1457 | - union semun *host_su, | |
1458 | - abi_ulong target_addr, | |
1459 | - struct semid_ds *ds) | |
1523 | +static inline abi_long target_to_host_semun(int cmd, | |
1524 | + union semun *host_su, | |
1525 | + abi_ulong target_addr, | |
1526 | + struct semid_ds *ds) | |
1460 | 1527 | { |
1461 | 1528 | union target_semun *target_su; |
1462 | 1529 | |
1463 | 1530 | switch( cmd ) { |
1464 | 1531 | case IPC_STAT: |
1465 | 1532 | case IPC_SET: |
1466 | - lock_user_struct(target_su, target_addr, 1); | |
1533 | + if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) | |
1534 | + return -TARGET_EFAULT; | |
1467 | 1535 | target_to_host_semid_ds(ds,target_su->buf); |
1468 | 1536 | host_su->buf = ds; |
1469 | 1537 | unlock_user_struct(target_su, target_addr, 0); |
1470 | 1538 | break; |
1471 | 1539 | case GETVAL: |
1472 | 1540 | case SETVAL: |
1473 | - lock_user_struct(target_su, target_addr, 1); | |
1541 | + if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) | |
1542 | + return -TARGET_EFAULT; | |
1474 | 1543 | host_su->val = tswapl(target_su->val); |
1475 | 1544 | unlock_user_struct(target_su, target_addr, 0); |
1476 | 1545 | break; |
1477 | 1546 | case GETALL: |
1478 | 1547 | case SETALL: |
1479 | - lock_user_struct(target_su, target_addr, 1); | |
1548 | + if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) | |
1549 | + return -TARGET_EFAULT; | |
1480 | 1550 | *host_su->array = tswap16(*target_su->array); |
1481 | 1551 | unlock_user_struct(target_su, target_addr, 0); |
1482 | 1552 | break; |
1483 | 1553 | default: |
1484 | 1554 | gemu_log("semun operation not fully supported: %d\n", (int)cmd); |
1485 | 1555 | } |
1556 | + return 0; | |
1486 | 1557 | } |
1487 | 1558 | |
1488 | -static inline void host_to_target_semun(int cmd, | |
1489 | - abi_ulong target_addr, | |
1490 | - union semun *host_su, | |
1491 | - struct semid_ds *ds) | |
1559 | +static inline abi_long host_to_target_semun(int cmd, | |
1560 | + abi_ulong target_addr, | |
1561 | + union semun *host_su, | |
1562 | + struct semid_ds *ds) | |
1492 | 1563 | { |
1493 | 1564 | union target_semun *target_su; |
1494 | 1565 | |
1495 | 1566 | switch( cmd ) { |
1496 | 1567 | case IPC_STAT: |
1497 | 1568 | case IPC_SET: |
1498 | - lock_user_struct(target_su, target_addr, 0); | |
1569 | + if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) | |
1570 | + return -TARGET_EFAULT; | |
1499 | 1571 | host_to_target_semid_ds(target_su->buf,ds); |
1500 | 1572 | unlock_user_struct(target_su, target_addr, 1); |
1501 | 1573 | break; |
1502 | 1574 | case GETVAL: |
1503 | 1575 | case SETVAL: |
1504 | - lock_user_struct(target_su, target_addr, 0); | |
1576 | + if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) | |
1577 | + return -TARGET_EFAULT; | |
1505 | 1578 | target_su->val = tswapl(host_su->val); |
1506 | 1579 | unlock_user_struct(target_su, target_addr, 1); |
1507 | 1580 | break; |
1508 | 1581 | case GETALL: |
1509 | 1582 | case SETALL: |
1510 | - lock_user_struct(target_su, target_addr, 0); | |
1583 | + if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) | |
1584 | + return -TARGET_EFAULT; | |
1511 | 1585 | *target_su->array = tswap16(*host_su->array); |
1512 | 1586 | unlock_user_struct(target_su, target_addr, 1); |
1513 | 1587 | break; |
1514 | 1588 | default: |
1515 | 1589 | gemu_log("semun operation not fully supported: %d\n", (int)cmd); |
1516 | 1590 | } |
1591 | + return 0; | |
1517 | 1592 | } |
1518 | 1593 | |
1519 | 1594 | static inline abi_long do_semctl(int first, int second, int third, |
... | ... | @@ -1580,12 +1655,13 @@ struct target_msqid_ds |
1580 | 1655 | abi_ulong __unused5; |
1581 | 1656 | }; |
1582 | 1657 | |
1583 | -static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, | |
1584 | - abi_ulong target_addr) | |
1658 | +static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, | |
1659 | + abi_ulong target_addr) | |
1585 | 1660 | { |
1586 | 1661 | struct target_msqid_ds *target_md; |
1587 | 1662 | |
1588 | - lock_user_struct(target_md, target_addr, 1); | |
1663 | + if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) | |
1664 | + return -TARGET_EFAULT; | |
1589 | 1665 | target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); |
1590 | 1666 | host_md->msg_stime = tswapl(target_md->msg_stime); |
1591 | 1667 | host_md->msg_rtime = tswapl(target_md->msg_rtime); |
... | ... | @@ -1596,14 +1672,16 @@ static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, |
1596 | 1672 | host_md->msg_lspid = tswapl(target_md->msg_lspid); |
1597 | 1673 | host_md->msg_lrpid = tswapl(target_md->msg_lrpid); |
1598 | 1674 | unlock_user_struct(target_md, target_addr, 0); |
1675 | + return 0; | |
1599 | 1676 | } |
1600 | 1677 | |
1601 | -static inline void host_to_target_msqid_ds(abi_ulong target_addr, | |
1602 | - struct msqid_ds *host_md) | |
1678 | +static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, | |
1679 | + struct msqid_ds *host_md) | |
1603 | 1680 | { |
1604 | 1681 | struct target_msqid_ds *target_md; |
1605 | 1682 | |
1606 | - lock_user_struct(target_md, target_addr, 0); | |
1683 | + if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) | |
1684 | + return -TARGET_EFAULT; | |
1607 | 1685 | host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); |
1608 | 1686 | target_md->msg_stime = tswapl(host_md->msg_stime); |
1609 | 1687 | target_md->msg_rtime = tswapl(host_md->msg_rtime); |
... | ... | @@ -1614,6 +1692,7 @@ static inline void host_to_target_msqid_ds(abi_ulong target_addr, |
1614 | 1692 | target_md->msg_lspid = tswapl(host_md->msg_lspid); |
1615 | 1693 | target_md->msg_lrpid = tswapl(host_md->msg_lrpid); |
1616 | 1694 | unlock_user_struct(target_md, target_addr, 1); |
1695 | + return 0; | |
1617 | 1696 | } |
1618 | 1697 | |
1619 | 1698 | static inline abi_long do_msgctl(int first, int second, abi_long ptr) |
... | ... | @@ -1645,7 +1724,8 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, |
1645 | 1724 | struct msgbuf *host_mb; |
1646 | 1725 | abi_long ret = 0; |
1647 | 1726 | |
1648 | - lock_user_struct(target_mb,msgp,0); | |
1727 | + if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) | |
1728 | + return -TARGET_EFAULT; | |
1649 | 1729 | host_mb = malloc(msgsz+sizeof(long)); |
1650 | 1730 | host_mb->mtype = tswapl(target_mb->mtype); |
1651 | 1731 | memcpy(host_mb->mtext,target_mb->mtext,msgsz); |
... | ... | @@ -1661,18 +1741,30 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, |
1661 | 1741 | int msgflg) |
1662 | 1742 | { |
1663 | 1743 | struct target_msgbuf *target_mb; |
1744 | + char *target_mtext; | |
1664 | 1745 | struct msgbuf *host_mb; |
1665 | 1746 | abi_long ret = 0; |
1666 | 1747 | |
1667 | - lock_user_struct(target_mb, msgp, 0); | |
1748 | + if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) | |
1749 | + return -TARGET_EFAULT; | |
1668 | 1750 | host_mb = malloc(msgsz+sizeof(long)); |
1669 | 1751 | ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); |
1670 | - if (ret > 0) | |
1752 | + if (ret > 0) { | |
1753 | + abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); | |
1754 | + target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); | |
1755 | + if (!target_mtext) { | |
1756 | + ret = -TARGET_EFAULT; | |
1757 | + goto end; | |
1758 | + } | |
1671 | 1759 | memcpy(target_mb->mtext, host_mb->mtext, ret); |
1760 | + unlock_user(target_mtext, target_mtext_addr, ret); | |
1761 | + } | |
1672 | 1762 | target_mb->mtype = tswapl(host_mb->mtype); |
1673 | 1763 | free(host_mb); |
1674 | - unlock_user_struct(target_mb, msgp, 0); | |
1675 | 1764 | |
1765 | +end: | |
1766 | + if (target_mb) | |
1767 | + unlock_user_struct(target_mb, msgp, 1); | |
1676 | 1768 | return ret; |
1677 | 1769 | } |
1678 | 1770 | |
... | ... | @@ -1693,7 +1785,7 @@ static abi_long do_ipc(unsigned int call, int first, |
1693 | 1785 | |
1694 | 1786 | switch (call) { |
1695 | 1787 | case IPCOP_semop: |
1696 | - ret = get_errno(semop(first,(struct sembuf *) ptr, second)); | |
1788 | + ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second)); | |
1697 | 1789 | break; |
1698 | 1790 | |
1699 | 1791 | case IPCOP_semget: |
... | ... | @@ -1723,13 +1815,14 @@ static abi_long do_ipc(unsigned int call, int first, |
1723 | 1815 | |
1724 | 1816 | case IPCOP_msgrcv: |
1725 | 1817 | { |
1818 | + /* XXX: this code is not correct */ | |
1726 | 1819 | struct ipc_kludge |
1727 | 1820 | { |
1728 | 1821 | void *__unbounded msgp; |
1729 | 1822 | long int msgtyp; |
1730 | 1823 | }; |
1731 | 1824 | |
1732 | - struct ipc_kludge *foo = (struct ipc_kludge *) ptr; | |
1825 | + struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr); | |
1733 | 1826 | struct msgbuf *msgp = (struct msgbuf *) foo->msgp; |
1734 | 1827 | |
1735 | 1828 | ret = do_msgrcv(first, (long)msgp, second, 0, third); |
... | ... | @@ -1761,7 +1854,7 @@ static abi_long do_ipc(unsigned int call, int first, |
1761 | 1854 | break; |
1762 | 1855 | } |
1763 | 1856 | } |
1764 | - if (put_user(raddr, (abi_ulong *)third)) | |
1857 | + if (put_user(raddr, third, abi_ulong)) | |
1765 | 1858 | return -TARGET_EFAULT; |
1766 | 1859 | ret = 0; |
1767 | 1860 | break; |
... | ... | @@ -1883,25 +1976,33 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg) |
1883 | 1976 | case IOC_R: |
1884 | 1977 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1885 | 1978 | if (!is_error(ret)) { |
1886 | - argptr = lock_user(arg, target_size, 0); | |
1979 | + argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); | |
1980 | + if (!argptr) | |
1981 | + return -TARGET_EFAULT; | |
1887 | 1982 | thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); |
1888 | 1983 | unlock_user(argptr, arg, target_size); |
1889 | 1984 | } |
1890 | 1985 | break; |
1891 | 1986 | case IOC_W: |
1892 | - argptr = lock_user(arg, target_size, 1); | |
1987 | + argptr = lock_user(VERIFY_READ, arg, target_size, 1); | |
1988 | + if (!argptr) | |
1989 | + return -TARGET_EFAULT; | |
1893 | 1990 | thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); |
1894 | 1991 | unlock_user(argptr, arg, 0); |
1895 | 1992 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1896 | 1993 | break; |
1897 | 1994 | default: |
1898 | 1995 | case IOC_RW: |
1899 | - argptr = lock_user(arg, target_size, 1); | |
1996 | + argptr = lock_user(VERIFY_READ, arg, target_size, 1); | |
1997 | + if (!argptr) | |
1998 | + return -TARGET_EFAULT; | |
1900 | 1999 | thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); |
1901 | 2000 | unlock_user(argptr, arg, 0); |
1902 | 2001 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1903 | 2002 | if (!is_error(ret)) { |
1904 | - argptr = lock_user(arg, target_size, 0); | |
2003 | + argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); | |
2004 | + if (!argptr) | |
2005 | + return -TARGET_EFAULT; | |
1905 | 2006 | thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); |
1906 | 2007 | unlock_user(argptr, arg, target_size); |
1907 | 2008 | } |
... | ... | @@ -2138,8 +2239,10 @@ static int read_ldt(abi_ulong ptr, unsigned long bytecount) |
2138 | 2239 | size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE; |
2139 | 2240 | if (size > bytecount) |
2140 | 2241 | size = bytecount; |
2141 | - p = lock_user(ptr, size, 0); | |
2142 | - /* ??? Shoudl this by byteswapped? */ | |
2242 | + p = lock_user(VERIFY_WRITE, ptr, size, 0); | |
2243 | + if (!p) | |
2244 | + return -EFAULT; | |
2245 | + /* ??? Should this by byteswapped? */ | |
2143 | 2246 | memcpy(p, ldt_table, size); |
2144 | 2247 | unlock_user(p, ptr, size); |
2145 | 2248 | return size; |
... | ... | @@ -2158,7 +2261,8 @@ static int write_ldt(CPUX86State *env, |
2158 | 2261 | |
2159 | 2262 | if (bytecount != sizeof(ldt_info)) |
2160 | 2263 | return -EINVAL; |
2161 | - lock_user_struct(target_ldt_info, ptr, 1); | |
2264 | + if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1)) | |
2265 | + return -EFAULT; | |
2162 | 2266 | ldt_info.entry_number = tswap32(target_ldt_info->entry_number); |
2163 | 2267 | ldt_info.base_addr = tswapl(target_ldt_info->base_addr); |
2164 | 2268 | ldt_info.limit = tswap32(target_ldt_info->limit); |
... | ... | @@ -2365,7 +2469,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) |
2365 | 2469 | |
2366 | 2470 | switch(cmd) { |
2367 | 2471 | case TARGET_F_GETLK: |
2368 | - lock_user_struct(target_fl, arg, 1); | |
2472 | + if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1)) | |
2473 | + return -TARGET_EFAULT; | |
2369 | 2474 | fl.l_type = tswap16(target_fl->l_type); |
2370 | 2475 | fl.l_whence = tswap16(target_fl->l_whence); |
2371 | 2476 | fl.l_start = tswapl(target_fl->l_start); |
... | ... | @@ -2374,7 +2479,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) |
2374 | 2479 | unlock_user_struct(target_fl, arg, 0); |
2375 | 2480 | ret = fcntl(fd, cmd, &fl); |
2376 | 2481 | if (ret == 0) { |
2377 | - lock_user_struct(target_fl, arg, 0); | |
2482 | + if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0)) | |
2483 | + return -TARGET_EFAULT; | |
2378 | 2484 | target_fl->l_type = tswap16(fl.l_type); |
2379 | 2485 | target_fl->l_whence = tswap16(fl.l_whence); |
2380 | 2486 | target_fl->l_start = tswapl(fl.l_start); |
... | ... | @@ -2386,7 +2492,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) |
2386 | 2492 | |
2387 | 2493 | case TARGET_F_SETLK: |
2388 | 2494 | case TARGET_F_SETLKW: |
2389 | - lock_user_struct(target_fl, arg, 1); | |
2495 | + if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1)) | |
2496 | + return -TARGET_EFAULT; | |
2390 | 2497 | fl.l_type = tswap16(target_fl->l_type); |
2391 | 2498 | fl.l_whence = tswap16(target_fl->l_whence); |
2392 | 2499 | fl.l_start = tswapl(target_fl->l_start); |
... | ... | @@ -2397,7 +2504,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) |
2397 | 2504 | break; |
2398 | 2505 | |
2399 | 2506 | case TARGET_F_GETLK64: |
2400 | - lock_user_struct(target_fl64, arg, 1); | |
2507 | + if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1)) | |
2508 | + return -TARGET_EFAULT; | |
2401 | 2509 | fl64.l_type = tswap16(target_fl64->l_type) >> 1; |
2402 | 2510 | fl64.l_whence = tswap16(target_fl64->l_whence); |
2403 | 2511 | fl64.l_start = tswapl(target_fl64->l_start); |
... | ... | @@ -2406,7 +2514,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) |
2406 | 2514 | unlock_user_struct(target_fl64, arg, 0); |
2407 | 2515 | ret = fcntl(fd, cmd >> 1, &fl64); |
2408 | 2516 | if (ret == 0) { |
2409 | - lock_user_struct(target_fl64, arg, 0); | |
2517 | + if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0)) | |
2518 | + return -TARGET_EFAULT; | |
2410 | 2519 | target_fl64->l_type = tswap16(fl64.l_type) >> 1; |
2411 | 2520 | target_fl64->l_whence = tswap16(fl64.l_whence); |
2412 | 2521 | target_fl64->l_start = tswapl(fl64.l_start); |
... | ... | @@ -2417,14 +2526,15 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) |
2417 | 2526 | break; |
2418 | 2527 | case TARGET_F_SETLK64: |
2419 | 2528 | case TARGET_F_SETLKW64: |
2420 | - lock_user_struct(target_fl64, arg, 1); | |
2529 | + if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1)) | |
2530 | + return -TARGET_EFAULT; | |
2421 | 2531 | fl64.l_type = tswap16(target_fl64->l_type) >> 1; |
2422 | 2532 | fl64.l_whence = tswap16(target_fl64->l_whence); |
2423 | 2533 | fl64.l_start = tswapl(target_fl64->l_start); |
2424 | 2534 | fl64.l_len = tswapl(target_fl64->l_len); |
2425 | 2535 | fl64.l_pid = tswap16(target_fl64->l_pid); |
2426 | 2536 | unlock_user_struct(target_fl64, arg, 0); |
2427 | - ret = fcntl(fd, cmd >> 1, &fl64); | |
2537 | + ret = fcntl(fd, cmd >> 1, &fl64); | |
2428 | 2538 | break; |
2429 | 2539 | |
2430 | 2540 | case F_GETFL: |
... | ... | @@ -2577,23 +2687,25 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, |
2577 | 2687 | } |
2578 | 2688 | #endif |
2579 | 2689 | |
2580 | -static inline void target_to_host_timespec(struct timespec *host_ts, | |
2581 | - abi_ulong target_addr) | |
2690 | +static inline abi_long target_to_host_timespec(struct timespec *host_ts, | |
2691 | + abi_ulong target_addr) | |
2582 | 2692 | { |
2583 | 2693 | struct target_timespec *target_ts; |
2584 | 2694 | |
2585 | - lock_user_struct(target_ts, target_addr, 1); | |
2695 | + if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) | |
2696 | + return -TARGET_EFAULT; | |
2586 | 2697 | host_ts->tv_sec = tswapl(target_ts->tv_sec); |
2587 | 2698 | host_ts->tv_nsec = tswapl(target_ts->tv_nsec); |
2588 | 2699 | unlock_user_struct(target_ts, target_addr, 0); |
2589 | 2700 | } |
2590 | 2701 | |
2591 | -static inline void host_to_target_timespec(abi_ulong target_addr, | |
2592 | - struct timespec *host_ts) | |
2702 | +static inline abi_long host_to_target_timespec(abi_ulong target_addr, | |
2703 | + struct timespec *host_ts) | |
2593 | 2704 | { |
2594 | 2705 | struct target_timespec *target_ts; |
2595 | 2706 | |
2596 | - lock_user_struct(target_ts, target_addr, 0); | |
2707 | + if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) | |
2708 | + return -TARGET_EFAULT; | |
2597 | 2709 | target_ts->tv_sec = tswapl(host_ts->tv_sec); |
2598 | 2710 | target_ts->tv_nsec = tswapl(host_ts->tv_nsec); |
2599 | 2711 | unlock_user_struct(target_ts, target_addr, 1); |
... | ... | @@ -2629,17 +2741,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2629 | 2741 | break; |
2630 | 2742 | case TARGET_NR_read: |
2631 | 2743 | page_unprotect_range(arg2, arg3); |
2632 | - p = lock_user(arg2, arg3, 0); | |
2744 | + if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) | |
2745 | + goto efault; | |
2633 | 2746 | ret = get_errno(read(arg1, p, arg3)); |
2634 | 2747 | unlock_user(p, arg2, ret); |
2635 | 2748 | break; |
2636 | 2749 | case TARGET_NR_write: |
2637 | - p = lock_user(arg2, arg3, 1); | |
2750 | + if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) | |
2751 | + goto efault; | |
2638 | 2752 | ret = get_errno(write(arg1, p, arg3)); |
2639 | 2753 | unlock_user(p, arg2, 0); |
2640 | 2754 | break; |
2641 | 2755 | case TARGET_NR_open: |
2642 | - p = lock_user_string(arg1); | |
2756 | + if (!(p = lock_user_string(arg1))) { | |
2757 | + return -TARGET_EFAULT; | |
2758 | + goto fail; | |
2759 | + } | |
2643 | 2760 | ret = get_errno(open(path(p), |
2644 | 2761 | target_to_host_bitmask(arg2, fcntl_flags_tbl), |
2645 | 2762 | arg3)); |
... | ... | @@ -2647,21 +2764,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2647 | 2764 | break; |
2648 | 2765 | #if defined(TARGET_NR_openat) && defined(__NR_openat) |
2649 | 2766 | case TARGET_NR_openat: |
2650 | - if (!arg2) { | |
2651 | - ret = -TARGET_EFAULT; | |
2652 | - goto fail; | |
2653 | - } | |
2654 | - p = lock_user_string(arg2); | |
2655 | - if (!access_ok(VERIFY_READ, p, 1)) | |
2656 | - /* Don't "goto fail" so that cleanup can happen. */ | |
2657 | - ret = -TARGET_EFAULT; | |
2658 | - else | |
2659 | - ret = get_errno(sys_openat(arg1, | |
2660 | - path(p), | |
2661 | - target_to_host_bitmask(arg3, fcntl_flags_tbl), | |
2662 | - arg4)); | |
2663 | - if (p) | |
2664 | - unlock_user(p, arg2, 0); | |
2767 | + if (!(p = lock_user_string(arg2))) | |
2768 | + goto efault; | |
2769 | + ret = get_errno(sys_openat(arg1, | |
2770 | + path(p), | |
2771 | + target_to_host_bitmask(arg3, fcntl_flags_tbl), | |
2772 | + arg4)); | |
2773 | + unlock_user(p, arg2, 0); | |
2665 | 2774 | break; |
2666 | 2775 | #endif |
2667 | 2776 | case TARGET_NR_close: |
... | ... | @@ -2685,7 +2794,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2685 | 2794 | #endif |
2686 | 2795 | #ifdef TARGET_NR_creat /* not on alpha */ |
2687 | 2796 | case TARGET_NR_creat: |
2688 | - p = lock_user_string(arg1); | |
2797 | + if (!(p = lock_user_string(arg1))) | |
2798 | + goto efault; | |
2689 | 2799 | ret = get_errno(creat(p, arg2)); |
2690 | 2800 | unlock_user(p, arg1, 0); |
2691 | 2801 | break; |
... | ... | @@ -2695,54 +2805,43 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2695 | 2805 | void * p2; |
2696 | 2806 | p = lock_user_string(arg1); |
2697 | 2807 | p2 = lock_user_string(arg2); |
2698 | - ret = get_errno(link(p, p2)); | |
2808 | + if (!p || !p2) | |
2809 | + ret = -TARGET_EFAULT; | |
2810 | + else | |
2811 | + ret = get_errno(link(p, p2)); | |
2699 | 2812 | unlock_user(p2, arg2, 0); |
2700 | 2813 | unlock_user(p, arg1, 0); |
2701 | 2814 | } |
2702 | 2815 | break; |
2703 | 2816 | #if defined(TARGET_NR_linkat) && defined(__NR_linkat) |
2704 | 2817 | case TARGET_NR_linkat: |
2705 | - if (!arg2 || !arg4) { | |
2706 | - ret = -TARGET_EFAULT; | |
2707 | - goto fail; | |
2708 | - } | |
2709 | 2818 | { |
2710 | 2819 | void * p2 = NULL; |
2820 | + if (!arg2 || !arg4) | |
2821 | + goto efault; | |
2711 | 2822 | p = lock_user_string(arg2); |
2712 | 2823 | p2 = lock_user_string(arg4); |
2713 | - if (!access_ok(VERIFY_READ, p, 1) | |
2714 | - || !access_ok(VERIFY_READ, p2, 1)) | |
2715 | - /* Don't "goto fail" so that cleanup can happen. */ | |
2824 | + if (!p || !p2) | |
2716 | 2825 | ret = -TARGET_EFAULT; |
2717 | 2826 | else |
2718 | 2827 | ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5)); |
2719 | - if (p2) | |
2720 | - unlock_user(p, arg2, 0); | |
2721 | - if (p) | |
2722 | - unlock_user(p2, arg4, 0); | |
2828 | + unlock_user(p, arg2, 0); | |
2829 | + unlock_user(p2, arg4, 0); | |
2723 | 2830 | } |
2724 | 2831 | break; |
2725 | 2832 | #endif |
2726 | 2833 | case TARGET_NR_unlink: |
2727 | - p = lock_user_string(arg1); | |
2834 | + if (!(p = lock_user_string(arg1))) | |
2835 | + goto efault; | |
2728 | 2836 | ret = get_errno(unlink(p)); |
2729 | 2837 | unlock_user(p, arg1, 0); |
2730 | 2838 | break; |
2731 | 2839 | #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) |
2732 | 2840 | case TARGET_NR_unlinkat: |
2733 | - if (!arg2) { | |
2734 | - ret = -TARGET_EFAULT; | |
2735 | - goto fail; | |
2736 | - } | |
2737 | - p = lock_user_string(arg2); | |
2738 | - if (!access_ok(VERIFY_READ, p, 1)) | |
2739 | - /* Don't "goto fail" so that cleanup can happen. */ | |
2740 | - ret = -TARGET_EFAULT; | |
2741 | - else | |
2742 | - ret = get_errno(sys_unlinkat(arg1, p, arg3)); | |
2743 | - if (p) | |
2744 | - unlock_user(p, arg2, 0); | |
2745 | - break; | |
2841 | + if (!(p = lock_user_string(arg2))) | |
2842 | + goto efault; | |
2843 | + ret = get_errno(sys_unlinkat(arg1, p, arg3)); | |
2844 | + unlock_user(p, arg2, 0); | |
2746 | 2845 | #endif |
2747 | 2846 | case TARGET_NR_execve: |
2748 | 2847 | { |
... | ... | @@ -2771,7 +2870,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2771 | 2870 | addr = tgetl(gp); |
2772 | 2871 | if (!addr) |
2773 | 2872 | break; |
2774 | - *q = lock_user_string(addr); | |
2873 | + if (!(*q = lock_user_string(addr))) { | |
2874 | + ret = -TARGET_EFAULT; | |
2875 | + goto execve_fail; | |
2876 | + } | |
2775 | 2877 | } |
2776 | 2878 | *q = NULL; |
2777 | 2879 | |
... | ... | @@ -2780,14 +2882,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2780 | 2882 | addr = tgetl(gp); |
2781 | 2883 | if (!addr) |
2782 | 2884 | break; |
2783 | - *q = lock_user_string(addr); | |
2885 | + if (!(*q = lock_user_string(addr))) { | |
2886 | + ret = -TARGET_EFAULT; | |
2887 | + goto execve_fail; | |
2888 | + } | |
2784 | 2889 | } |
2785 | 2890 | *q = NULL; |
2786 | 2891 | |
2787 | - p = lock_user_string(arg1); | |
2892 | + if (!(p = lock_user_string(arg1))) { | |
2893 | + ret = -TARGET_EFAULT; | |
2894 | + goto execve_fail; | |
2895 | + } | |
2788 | 2896 | ret = get_errno(execve(p, argp, envp)); |
2789 | 2897 | unlock_user(p, arg1, 0); |
2790 | 2898 | |
2899 | + execve_fail: | |
2791 | 2900 | for (gp = guest_argp, q = argp; *q; |
2792 | 2901 | gp += sizeof(abi_ulong), q++) { |
2793 | 2902 | addr = tgetl(gp); |
... | ... | @@ -2801,7 +2910,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2801 | 2910 | } |
2802 | 2911 | break; |
2803 | 2912 | case TARGET_NR_chdir: |
2804 | - p = lock_user_string(arg1); | |
2913 | + if (!(p = lock_user_string(arg1))) | |
2914 | + goto efault; | |
2805 | 2915 | ret = get_errno(chdir(p)); |
2806 | 2916 | unlock_user(p, arg1, 0); |
2807 | 2917 | break; |
... | ... | @@ -2816,28 +2926,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2816 | 2926 | break; |
2817 | 2927 | #endif |
2818 | 2928 | case TARGET_NR_mknod: |
2819 | - p = lock_user_string(arg1); | |
2929 | + if (!(p = lock_user_string(arg1))) | |
2930 | + goto efault; | |
2820 | 2931 | ret = get_errno(mknod(p, arg2, arg3)); |
2821 | 2932 | unlock_user(p, arg1, 0); |
2822 | 2933 | break; |
2823 | 2934 | #if defined(TARGET_NR_mknodat) && defined(__NR_mknodat) |
2824 | 2935 | case TARGET_NR_mknodat: |
2825 | - if (!arg2) { | |
2826 | - ret = -TARGET_EFAULT; | |
2827 | - goto fail; | |
2828 | - } | |
2829 | - p = lock_user_string(arg2); | |
2830 | - if (!access_ok(VERIFY_READ, p, 1)) | |
2831 | - /* Don't "goto fail" so that cleanup can happen. */ | |
2832 | - ret = -TARGET_EFAULT; | |
2833 | - else | |
2834 | - ret = get_errno(sys_mknodat(arg1, p, arg3, arg4)); | |
2835 | - if (p) | |
2836 | - unlock_user(p, arg2, 0); | |
2936 | + if (!(p = lock_user_string(arg2))) | |
2937 | + goto efault; | |
2938 | + ret = get_errno(sys_mknodat(arg1, p, arg3, arg4)); | |
2939 | + unlock_user(p, arg2, 0); | |
2837 | 2940 | break; |
2838 | 2941 | #endif |
2839 | 2942 | case TARGET_NR_chmod: |
2840 | - p = lock_user_string(arg1); | |
2943 | + if (!(p = lock_user_string(arg1))) | |
2944 | + goto efault; | |
2841 | 2945 | ret = get_errno(chmod(p, arg2)); |
2842 | 2946 | unlock_user(p, arg1, 0); |
2843 | 2947 | break; |
... | ... | @@ -2866,15 +2970,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2866 | 2970 | p = lock_user_string(arg1); |
2867 | 2971 | p2 = lock_user_string(arg2); |
2868 | 2972 | p3 = lock_user_string(arg3); |
2869 | - ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, (const void *)arg5)); | |
2870 | - unlock_user(p, arg1, 0); | |
2871 | - unlock_user(p2, arg2, 0); | |
2872 | - unlock_user(p3, arg3, 0); | |
2973 | + if (!p || !p2 || !p3) | |
2974 | + ret = -TARGET_EFAULT; | |
2975 | + else | |
2976 | + /* FIXME - arg5 should be locked, but it isn't clear how to | |
2977 | + * do that since it's not guaranteed to be a NULL-terminated | |
2978 | + * string. | |
2979 | + */ | |
2980 | + ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5))); | |
2981 | + unlock_user(p, arg1, 0); | |
2982 | + unlock_user(p2, arg2, 0); | |
2983 | + unlock_user(p3, arg3, 0); | |
2873 | 2984 | break; |
2874 | 2985 | } |
2875 | 2986 | #ifdef TARGET_NR_umount |
2876 | 2987 | case TARGET_NR_umount: |
2877 | - p = lock_user_string(arg1); | |
2988 | + if (!(p = lock_user_string(arg1))) | |
2989 | + goto efault; | |
2878 | 2990 | ret = get_errno(umount(p)); |
2879 | 2991 | unlock_user(p, arg1, 0); |
2880 | 2992 | break; |
... | ... | @@ -2910,7 +3022,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2910 | 3022 | struct utimbuf tbuf, *host_tbuf; |
2911 | 3023 | struct target_utimbuf *target_tbuf; |
2912 | 3024 | if (arg2) { |
2913 | - lock_user_struct(target_tbuf, arg2, 1); | |
3025 | + if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1)) | |
3026 | + goto efault; | |
2914 | 3027 | tbuf.actime = tswapl(target_tbuf->actime); |
2915 | 3028 | tbuf.modtime = tswapl(target_tbuf->modtime); |
2916 | 3029 | unlock_user_struct(target_tbuf, arg2, 0); |
... | ... | @@ -2918,7 +3031,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2918 | 3031 | } else { |
2919 | 3032 | host_tbuf = NULL; |
2920 | 3033 | } |
2921 | - p = lock_user_string(arg1); | |
3034 | + if (!(p = lock_user_string(arg1))) | |
3035 | + goto efault; | |
2922 | 3036 | ret = get_errno(utime(p, host_tbuf)); |
2923 | 3037 | unlock_user(p, arg1, 0); |
2924 | 3038 | } |
... | ... | @@ -2935,7 +3049,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2935 | 3049 | } else { |
2936 | 3050 | tvp = NULL; |
2937 | 3051 | } |
2938 | - p = lock_user_string(arg1); | |
3052 | + if (!(p = lock_user_string(arg1))) | |
3053 | + goto efault; | |
2939 | 3054 | ret = get_errno(utimes(p, tvp)); |
2940 | 3055 | unlock_user(p, arg1, 0); |
2941 | 3056 | } |
... | ... | @@ -2949,24 +3064,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2949 | 3064 | goto unimplemented; |
2950 | 3065 | #endif |
2951 | 3066 | case TARGET_NR_access: |
2952 | - p = lock_user_string(arg1); | |
3067 | + if (!(p = lock_user_string(arg1))) | |
3068 | + goto efault; | |
2953 | 3069 | ret = get_errno(access(p, arg2)); |
2954 | 3070 | unlock_user(p, arg1, 0); |
2955 | 3071 | break; |
2956 | 3072 | #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) |
2957 | 3073 | case TARGET_NR_faccessat: |
2958 | - if (!arg2) { | |
2959 | - ret = -TARGET_EFAULT; | |
2960 | - goto fail; | |
2961 | - } | |
2962 | - p = lock_user_string(arg2); | |
2963 | - if (!access_ok(VERIFY_READ, p, 1)) | |
2964 | - /* Don't "goto fail" so that cleanup can happen. */ | |
2965 | - ret = -TARGET_EFAULT; | |
2966 | - else | |
2967 | - ret = get_errno(sys_faccessat(arg1, p, arg3, arg4)); | |
2968 | - if (p) | |
2969 | - unlock_user(p, arg2, 0); | |
3074 | + if (!(p = lock_user_string(arg2))) | |
3075 | + goto efault; | |
3076 | + ret = get_errno(sys_faccessat(arg1, p, arg3, arg4)); | |
3077 | + unlock_user(p, arg2, 0); | |
2970 | 3078 | break; |
2971 | 3079 | #endif |
2972 | 3080 | #ifdef TARGET_NR_nice /* not on alpha */ |
... | ... | @@ -2990,57 +3098,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
2990 | 3098 | void *p2; |
2991 | 3099 | p = lock_user_string(arg1); |
2992 | 3100 | p2 = lock_user_string(arg2); |
2993 | - ret = get_errno(rename(p, p2)); | |
3101 | + if (!p || !p2) | |
3102 | + ret = -TARGET_EFAULT; | |
3103 | + else | |
3104 | + ret = get_errno(rename(p, p2)); | |
2994 | 3105 | unlock_user(p2, arg2, 0); |
2995 | 3106 | unlock_user(p, arg1, 0); |
2996 | 3107 | } |
2997 | 3108 | break; |
2998 | 3109 | #if defined(TARGET_NR_renameat) && defined(__NR_renameat) |
2999 | 3110 | case TARGET_NR_renameat: |
3000 | - if (!arg2 || !arg4) { | |
3001 | - ret = -TARGET_EFAULT; | |
3002 | - goto fail; | |
3003 | - } | |
3004 | 3111 | { |
3005 | - void *p2 = NULL; | |
3112 | + void *p2; | |
3006 | 3113 | p = lock_user_string(arg2); |
3007 | 3114 | p2 = lock_user_string(arg4); |
3008 | - if (!access_ok(VERIFY_READ, p, 1) | |
3009 | - || !access_ok(VERIFY_READ, p2, 1)) | |
3010 | - /* Don't "goto fail" so that cleanup can happen. */ | |
3115 | + if (!p || !p2) | |
3011 | 3116 | ret = -TARGET_EFAULT; |
3012 | 3117 | else |
3013 | 3118 | ret = get_errno(sys_renameat(arg1, p, arg3, p2)); |
3014 | - if (p2) | |
3015 | - unlock_user(p2, arg4, 0); | |
3016 | - if (p) | |
3017 | - unlock_user(p, arg2, 0); | |
3119 | + unlock_user(p2, arg4, 0); | |
3120 | + unlock_user(p, arg2, 0); | |
3018 | 3121 | } |
3019 | 3122 | break; |
3020 | 3123 | #endif |
3021 | 3124 | case TARGET_NR_mkdir: |
3022 | - p = lock_user_string(arg1); | |
3125 | + if (!(p = lock_user_string(arg1))) | |
3126 | + goto efault; | |
3023 | 3127 | ret = get_errno(mkdir(p, arg2)); |
3024 | 3128 | unlock_user(p, arg1, 0); |
3025 | 3129 | break; |
3026 | 3130 | #if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat) |
3027 | 3131 | case TARGET_NR_mkdirat: |
3028 | - if (!arg2) { | |
3029 | - ret = -TARGET_EFAULT; | |
3030 | - goto fail; | |
3031 | - } | |
3032 | - p = lock_user_string(arg2); | |
3033 | - if (!access_ok(VERIFY_READ, p, 1)) | |
3034 | - /* Don't "goto fail" so that cleanup can happen. */ | |
3035 | - ret = -TARGET_EFAULT; | |
3036 | - else | |
3037 | - ret = get_errno(sys_mkdirat(arg1, p, arg3)); | |
3038 | - if (p) | |
3039 | - unlock_user(p, arg2, 0); | |
3132 | + if (!(p = lock_user_string(arg2))) | |
3133 | + goto efault; | |
3134 | + ret = get_errno(sys_mkdirat(arg1, p, arg3)); | |
3135 | + unlock_user(p, arg2, 0); | |
3040 | 3136 | break; |
3041 | 3137 | #endif |
3042 | 3138 | case TARGET_NR_rmdir: |
3043 | - p = lock_user_string(arg1); | |
3139 | + if (!(p = lock_user_string(arg1))) | |
3140 | + goto efault; | |
3044 | 3141 | ret = get_errno(rmdir(p)); |
3045 | 3142 | unlock_user(p, arg1, 0); |
3046 | 3143 | break; |
... | ... | @@ -3069,7 +3166,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3069 | 3166 | struct tms tms; |
3070 | 3167 | ret = get_errno(times(&tms)); |
3071 | 3168 | if (arg1) { |
3072 | - tmsp = lock_user(arg1, sizeof(struct target_tms), 0); | |
3169 | + tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0); | |
3170 | + if (!tmsp) | |
3171 | + goto efault; | |
3073 | 3172 | tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime)); |
3074 | 3173 | tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime)); |
3075 | 3174 | tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime)); |
... | ... | @@ -3088,13 +3187,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3088 | 3187 | goto unimplemented; |
3089 | 3188 | #endif |
3090 | 3189 | case TARGET_NR_acct: |
3091 | - p = lock_user_string(arg1); | |
3190 | + if (!(p = lock_user_string(arg1))) | |
3191 | + goto efault; | |
3092 | 3192 | ret = get_errno(acct(path(p))); |
3093 | 3193 | unlock_user(p, arg1, 0); |
3094 | 3194 | break; |
3095 | 3195 | #ifdef TARGET_NR_umount2 /* not on alpha */ |
3096 | 3196 | case TARGET_NR_umount2: |
3097 | - p = lock_user_string(arg1); | |
3197 | + if (!(p = lock_user_string(arg1))) | |
3198 | + goto efault; | |
3098 | 3199 | ret = get_errno(umount2(p, arg2)); |
3099 | 3200 | unlock_user(p, arg1, 0); |
3100 | 3201 | break; |
... | ... | @@ -3128,7 +3229,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3128 | 3229 | ret = get_errno(umask(arg1)); |
3129 | 3230 | break; |
3130 | 3231 | case TARGET_NR_chroot: |
3131 | - p = lock_user_string(arg1); | |
3232 | + if (!(p = lock_user_string(arg1))) | |
3233 | + goto efault; | |
3132 | 3234 | ret = get_errno(chroot(p)); |
3133 | 3235 | unlock_user(p, arg1, 0); |
3134 | 3236 | break; |
... | ... | @@ -3155,7 +3257,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3155 | 3257 | struct target_old_sigaction *old_act; |
3156 | 3258 | struct target_sigaction act, oact, *pact; |
3157 | 3259 | if (arg2) { |
3158 | - lock_user_struct(old_act, arg2, 1); | |
3260 | + if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) | |
3261 | + goto efault; | |
3159 | 3262 | act._sa_handler = old_act->_sa_handler; |
3160 | 3263 | target_siginitset(&act.sa_mask, old_act->sa_mask); |
3161 | 3264 | act.sa_flags = old_act->sa_flags; |
... | ... | @@ -3167,7 +3270,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3167 | 3270 | } |
3168 | 3271 | ret = get_errno(do_sigaction(arg1, pact, &oact)); |
3169 | 3272 | if (!is_error(ret) && arg3) { |
3170 | - lock_user_struct(old_act, arg3, 0); | |
3273 | + if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) | |
3274 | + goto efault; | |
3171 | 3275 | old_act->_sa_handler = oact._sa_handler; |
3172 | 3276 | old_act->sa_mask = oact.sa_mask.sig[0]; |
3173 | 3277 | old_act->sa_flags = oact.sa_flags; |
... | ... | @@ -3178,7 +3282,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3178 | 3282 | struct target_sigaction act, oact, *pact, *old_act; |
3179 | 3283 | |
3180 | 3284 | if (arg2) { |
3181 | - lock_user_struct(old_act, arg2, 1); | |
3285 | + if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) | |
3286 | + goto efault; | |
3182 | 3287 | act._sa_handler = old_act->_sa_handler; |
3183 | 3288 | target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]); |
3184 | 3289 | act.sa_flags = old_act->sa_flags; |
... | ... | @@ -3191,7 +3296,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3191 | 3296 | ret = get_errno(do_sigaction(arg1, pact, &oact)); |
3192 | 3297 | |
3193 | 3298 | if (!is_error(ret) && arg3) { |
3194 | - lock_user_struct(old_act, arg3, 0); | |
3299 | + if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) | |
3300 | + goto efault; | |
3195 | 3301 | old_act->_sa_handler = oact._sa_handler; |
3196 | 3302 | old_act->sa_flags = oact.sa_flags; |
3197 | 3303 | old_act->sa_mask.sig[0] = oact.sa_mask.sig[0]; |
... | ... | @@ -3209,18 +3315,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3209 | 3315 | struct target_sigaction *act; |
3210 | 3316 | struct target_sigaction *oact; |
3211 | 3317 | |
3212 | - if (arg2) | |
3213 | - lock_user_struct(act, arg2, 1); | |
3214 | - else | |
3318 | + if (arg2) { | |
3319 | + if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) | |
3320 | + goto efault; | |
3321 | + } else | |
3215 | 3322 | act = NULL; |
3216 | - if (arg3) | |
3217 | - lock_user_struct(oact, arg3, 0); | |
3218 | - else | |
3323 | + if (arg3) { | |
3324 | + if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) { | |
3325 | + ret = -TARGET_EFAULT; | |
3326 | + goto rt_sigaction_fail; | |
3327 | + } | |
3328 | + } else | |
3219 | 3329 | oact = NULL; |
3220 | 3330 | ret = get_errno(do_sigaction(arg1, act, oact)); |
3221 | - if (arg2) | |
3331 | + rt_sigaction_fail: | |
3332 | + if (act) | |
3222 | 3333 | unlock_user_struct(act, arg2, 0); |
3223 | - if (arg3) | |
3334 | + if (oact) | |
3224 | 3335 | unlock_user_struct(oact, arg3, 1); |
3225 | 3336 | } |
3226 | 3337 | break; |
... | ... | @@ -3270,7 +3381,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3270 | 3381 | ret = -TARGET_EINVAL; |
3271 | 3382 | goto fail; |
3272 | 3383 | } |
3273 | - p = lock_user(arg2, sizeof(target_sigset_t), 1); | |
3384 | + if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) | |
3385 | + goto efault; | |
3274 | 3386 | target_to_host_old_sigset(&set, p); |
3275 | 3387 | unlock_user(p, arg2, 0); |
3276 | 3388 | set_ptr = &set; |
... | ... | @@ -3280,7 +3392,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3280 | 3392 | } |
3281 | 3393 | ret = get_errno(sigprocmask(arg1, set_ptr, &oldset)); |
3282 | 3394 | if (!is_error(ret) && arg3) { |
3283 | - p = lock_user(arg3, sizeof(target_sigset_t), 0); | |
3395 | + if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) | |
3396 | + goto efault; | |
3284 | 3397 | host_to_target_old_sigset(p, &oldset); |
3285 | 3398 | unlock_user(p, arg3, sizeof(target_sigset_t)); |
3286 | 3399 | } |
... | ... | @@ -3307,7 +3420,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3307 | 3420 | ret = -TARGET_EINVAL; |
3308 | 3421 | goto fail; |
3309 | 3422 | } |
3310 | - p = lock_user(arg2, sizeof(target_sigset_t), 1); | |
3423 | + if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) | |
3424 | + goto efault; | |
3311 | 3425 | target_to_host_sigset(&set, p); |
3312 | 3426 | unlock_user(p, arg2, 0); |
3313 | 3427 | set_ptr = &set; |
... | ... | @@ -3317,7 +3431,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3317 | 3431 | } |
3318 | 3432 | ret = get_errno(sigprocmask(how, set_ptr, &oldset)); |
3319 | 3433 | if (!is_error(ret) && arg3) { |
3320 | - p = lock_user(arg3, sizeof(target_sigset_t), 0); | |
3434 | + if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) | |
3435 | + goto efault; | |
3321 | 3436 | host_to_target_sigset(p, &oldset); |
3322 | 3437 | unlock_user(p, arg3, sizeof(target_sigset_t)); |
3323 | 3438 | } |
... | ... | @@ -3329,7 +3444,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3329 | 3444 | sigset_t set; |
3330 | 3445 | ret = get_errno(sigpending(&set)); |
3331 | 3446 | if (!is_error(ret)) { |
3332 | - p = lock_user(arg1, sizeof(target_sigset_t), 0); | |
3447 | + if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) | |
3448 | + goto efault; | |
3333 | 3449 | host_to_target_old_sigset(p, &set); |
3334 | 3450 | unlock_user(p, arg1, sizeof(target_sigset_t)); |
3335 | 3451 | } |
... | ... | @@ -3341,7 +3457,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3341 | 3457 | sigset_t set; |
3342 | 3458 | ret = get_errno(sigpending(&set)); |
3343 | 3459 | if (!is_error(ret)) { |
3344 | - p = lock_user(arg1, sizeof(target_sigset_t), 0); | |
3460 | + if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) | |
3461 | + goto efault; | |
3345 | 3462 | host_to_target_sigset(p, &set); |
3346 | 3463 | unlock_user(p, arg1, sizeof(target_sigset_t)); |
3347 | 3464 | } |
... | ... | @@ -3351,7 +3468,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3351 | 3468 | case TARGET_NR_sigsuspend: |
3352 | 3469 | { |
3353 | 3470 | sigset_t set; |
3354 | - p = lock_user(arg1, sizeof(target_sigset_t), 1); | |
3471 | + if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) | |
3472 | + goto efault; | |
3355 | 3473 | target_to_host_old_sigset(&set, p); |
3356 | 3474 | unlock_user(p, arg1, 0); |
3357 | 3475 | ret = get_errno(sigsuspend(&set)); |
... | ... | @@ -3361,7 +3479,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3361 | 3479 | case TARGET_NR_rt_sigsuspend: |
3362 | 3480 | { |
3363 | 3481 | sigset_t set; |
3364 | - p = lock_user(arg1, sizeof(target_sigset_t), 1); | |
3482 | + if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) | |
3483 | + goto efault; | |
3365 | 3484 | target_to_host_sigset(&set, p); |
3366 | 3485 | unlock_user(p, arg1, 0); |
3367 | 3486 | ret = get_errno(sigsuspend(&set)); |
... | ... | @@ -3373,7 +3492,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3373 | 3492 | struct timespec uts, *puts; |
3374 | 3493 | siginfo_t uinfo; |
3375 | 3494 | |
3376 | - p = lock_user(arg1, sizeof(target_sigset_t), 1); | |
3495 | + if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) | |
3496 | + goto efault; | |
3377 | 3497 | target_to_host_sigset(&set, p); |
3378 | 3498 | unlock_user(p, arg1, 0); |
3379 | 3499 | if (arg3) { |
... | ... | @@ -3384,7 +3504,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3384 | 3504 | } |
3385 | 3505 | ret = get_errno(sigtimedwait(&set, &uinfo, puts)); |
3386 | 3506 | if (!is_error(ret) && arg2) { |
3387 | - p = lock_user(arg2, sizeof(target_sigset_t), 0); | |
3507 | + if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_sigset_t), 0))) | |
3508 | + goto efault; | |
3388 | 3509 | host_to_target_siginfo(p, &uinfo); |
3389 | 3510 | unlock_user(p, arg2, sizeof(target_sigset_t)); |
3390 | 3511 | } |
... | ... | @@ -3393,7 +3514,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3393 | 3514 | case TARGET_NR_rt_sigqueueinfo: |
3394 | 3515 | { |
3395 | 3516 | siginfo_t uinfo; |
3396 | - p = lock_user(arg3, sizeof(target_sigset_t), 1); | |
3517 | + if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1))) | |
3518 | + goto efault; | |
3397 | 3519 | target_to_host_siginfo(&uinfo, p); |
3398 | 3520 | unlock_user(p, arg1, 0); |
3399 | 3521 | ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); |
... | ... | @@ -3410,7 +3532,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3410 | 3532 | ret = do_rt_sigreturn(cpu_env); |
3411 | 3533 | break; |
3412 | 3534 | case TARGET_NR_sethostname: |
3413 | - p = lock_user_string(arg1); | |
3535 | + if (!(p = lock_user_string(arg1))) | |
3536 | + goto efault; | |
3414 | 3537 | ret = get_errno(sethostname(p, arg2)); |
3415 | 3538 | unlock_user(p, arg1, 0); |
3416 | 3539 | break; |
... | ... | @@ -3420,7 +3543,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3420 | 3543 | int resource = arg1; |
3421 | 3544 | struct target_rlimit *target_rlim; |
3422 | 3545 | struct rlimit rlim; |
3423 | - lock_user_struct(target_rlim, arg2, 1); | |
3546 | + if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) | |
3547 | + goto efault; | |
3424 | 3548 | rlim.rlim_cur = tswapl(target_rlim->rlim_cur); |
3425 | 3549 | rlim.rlim_max = tswapl(target_rlim->rlim_max); |
3426 | 3550 | unlock_user_struct(target_rlim, arg2, 0); |
... | ... | @@ -3436,7 +3560,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3436 | 3560 | |
3437 | 3561 | ret = get_errno(getrlimit(resource, &rlim)); |
3438 | 3562 | if (!is_error(ret)) { |
3439 | - lock_user_struct(target_rlim, arg2, 0); | |
3563 | + if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) | |
3564 | + goto efault; | |
3440 | 3565 | rlim.rlim_cur = tswapl(target_rlim->rlim_cur); |
3441 | 3566 | rlim.rlim_max = tswapl(target_rlim->rlim_max); |
3442 | 3567 | unlock_user_struct(target_rlim, arg2, 1); |
... | ... | @@ -3475,7 +3600,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3475 | 3600 | abi_ulong inp, outp, exp, tvp; |
3476 | 3601 | long nsel; |
3477 | 3602 | |
3478 | - lock_user_struct(sel, arg1, 1); | |
3603 | + if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) | |
3604 | + goto efault; | |
3479 | 3605 | nsel = tswapl(sel->n); |
3480 | 3606 | inp = tswapl(sel->inp); |
3481 | 3607 | outp = tswapl(sel->outp); |
... | ... | @@ -3491,31 +3617,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3491 | 3617 | void *p2; |
3492 | 3618 | p = lock_user_string(arg1); |
3493 | 3619 | p2 = lock_user_string(arg2); |
3494 | - ret = get_errno(symlink(p, p2)); | |
3620 | + if (!p || !p2) | |
3621 | + ret = -TARGET_EFAULT; | |
3622 | + else | |
3623 | + ret = get_errno(symlink(p, p2)); | |
3495 | 3624 | unlock_user(p2, arg2, 0); |
3496 | 3625 | unlock_user(p, arg1, 0); |
3497 | 3626 | } |
3498 | 3627 | break; |
3499 | 3628 | #if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat) |
3500 | 3629 | case TARGET_NR_symlinkat: |
3501 | - if (!arg1 || !arg3) { | |
3502 | - ret = -TARGET_EFAULT; | |
3503 | - goto fail; | |
3504 | - } | |
3505 | 3630 | { |
3506 | - void *p2 = NULL; | |
3631 | + void *p2; | |
3507 | 3632 | p = lock_user_string(arg1); |
3508 | 3633 | p2 = lock_user_string(arg3); |
3509 | - if (!access_ok(VERIFY_READ, p, 1) | |
3510 | - || !access_ok(VERIFY_READ, p2, 1)) | |
3511 | - /* Don't "goto fail" so that cleanup can happen. */ | |
3634 | + if (!p || !p2) | |
3512 | 3635 | ret = -TARGET_EFAULT; |
3513 | 3636 | else |
3514 | 3637 | ret = get_errno(sys_symlinkat(p, arg2, p2)); |
3515 | - if (p2) | |
3516 | - unlock_user(p2, arg3, 0); | |
3517 | - if (p) | |
3518 | - unlock_user(p, arg1, 0); | |
3638 | + unlock_user(p2, arg3, 0); | |
3639 | + unlock_user(p, arg1, 0); | |
3519 | 3640 | } |
3520 | 3641 | break; |
3521 | 3642 | #endif |
... | ... | @@ -3527,32 +3648,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3527 | 3648 | { |
3528 | 3649 | void *p2; |
3529 | 3650 | p = lock_user_string(arg1); |
3530 | - p2 = lock_user(arg2, arg3, 0); | |
3531 | - ret = get_errno(readlink(path(p), p2, arg3)); | |
3651 | + p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); | |
3652 | + if (!p || !p2) | |
3653 | + ret = -TARGET_EFAULT; | |
3654 | + else | |
3655 | + ret = get_errno(readlink(path(p), p2, arg3)); | |
3532 | 3656 | unlock_user(p2, arg2, ret); |
3533 | 3657 | unlock_user(p, arg1, 0); |
3534 | 3658 | } |
3535 | 3659 | break; |
3536 | 3660 | #if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat) |
3537 | 3661 | case TARGET_NR_readlinkat: |
3538 | - if (!arg2 || !arg3) { | |
3539 | - ret = -TARGET_EFAULT; | |
3540 | - goto fail; | |
3541 | - } | |
3542 | 3662 | { |
3543 | - void *p2 = NULL; | |
3663 | + void *p2; | |
3544 | 3664 | p = lock_user_string(arg2); |
3545 | - p2 = lock_user(arg3, arg4, 0); | |
3546 | - if (!access_ok(VERIFY_READ, p, 1) | |
3547 | - || !access_ok(VERIFY_READ, p2, 1)) | |
3548 | - /* Don't "goto fail" so that cleanup can happen. */ | |
3665 | + p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); | |
3666 | + if (!p || !p2) | |
3549 | 3667 | ret = -TARGET_EFAULT; |
3550 | 3668 | else |
3551 | 3669 | ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4)); |
3552 | - if (p2) | |
3553 | - unlock_user(p2, arg3, ret); | |
3554 | - if (p) | |
3555 | - unlock_user(p, arg2, 0); | |
3670 | + unlock_user(p2, arg3, ret); | |
3671 | + unlock_user(p, arg2, 0); | |
3556 | 3672 | } |
3557 | 3673 | break; |
3558 | 3674 | #endif |
... | ... | @@ -3562,7 +3678,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3562 | 3678 | #endif |
3563 | 3679 | #ifdef TARGET_NR_swapon |
3564 | 3680 | case TARGET_NR_swapon: |
3565 | - p = lock_user_string(arg1); | |
3681 | + if (!(p = lock_user_string(arg1))) | |
3682 | + goto efault; | |
3566 | 3683 | ret = get_errno(swapon(p, arg2)); |
3567 | 3684 | unlock_user(p, arg1, 0); |
3568 | 3685 | break; |
... | ... | @@ -3579,7 +3696,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3579 | 3696 | { |
3580 | 3697 | abi_ulong *v; |
3581 | 3698 | abi_ulong v1, v2, v3, v4, v5, v6; |
3582 | - v = lock_user(arg1, 6 * sizeof(abi_ulong), 1); | |
3699 | + if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1))) | |
3700 | + goto efault; | |
3583 | 3701 | v1 = tswapl(v[0]); |
3584 | 3702 | v2 = tswapl(v[1]); |
3585 | 3703 | v3 = tswapl(v[2]); |
... | ... | @@ -3650,7 +3768,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3650 | 3768 | break; |
3651 | 3769 | #endif |
3652 | 3770 | case TARGET_NR_truncate: |
3653 | - p = lock_user_string(arg1); | |
3771 | + if (!(p = lock_user_string(arg1))) | |
3772 | + goto efault; | |
3654 | 3773 | ret = get_errno(truncate(p, arg2)); |
3655 | 3774 | unlock_user(p, arg1, 0); |
3656 | 3775 | break; |
... | ... | @@ -3662,18 +3781,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3662 | 3781 | break; |
3663 | 3782 | #if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat) |
3664 | 3783 | case TARGET_NR_fchmodat: |
3665 | - if (!arg2) { | |
3666 | - ret = -TARGET_EFAULT; | |
3667 | - goto fail; | |
3668 | - } | |
3669 | - p = lock_user_string(arg2); | |
3670 | - if (!access_ok(VERIFY_READ, p, 1)) | |
3671 | - /* Don't "goto fail" so that cleanup can happen. */ | |
3672 | - ret = -TARGET_EFAULT; | |
3673 | - else | |
3674 | - ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4)); | |
3675 | - if (p) | |
3676 | - unlock_user(p, arg2, 0); | |
3784 | + if (!(p = lock_user_string(arg2))) | |
3785 | + goto efault; | |
3786 | + ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4)); | |
3787 | + unlock_user(p, arg2, 0); | |
3677 | 3788 | break; |
3678 | 3789 | #endif |
3679 | 3790 | case TARGET_NR_getpriority: |
... | ... | @@ -3690,25 +3801,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3690 | 3801 | goto unimplemented; |
3691 | 3802 | #endif |
3692 | 3803 | case TARGET_NR_statfs: |
3693 | - p = lock_user_string(arg1); | |
3804 | + if (!(p = lock_user_string(arg1))) | |
3805 | + goto efault; | |
3694 | 3806 | ret = get_errno(statfs(path(p), &stfs)); |
3695 | 3807 | unlock_user(p, arg1, 0); |
3696 | 3808 | convert_statfs: |
3697 | 3809 | if (!is_error(ret)) { |
3698 | 3810 | struct target_statfs *target_stfs; |
3699 | 3811 | |
3700 | - lock_user_struct(target_stfs, arg2, 0); | |
3701 | - /* ??? put_user is probably wrong. */ | |
3702 | - put_user(stfs.f_type, &target_stfs->f_type); | |
3703 | - put_user(stfs.f_bsize, &target_stfs->f_bsize); | |
3704 | - put_user(stfs.f_blocks, &target_stfs->f_blocks); | |
3705 | - put_user(stfs.f_bfree, &target_stfs->f_bfree); | |
3706 | - put_user(stfs.f_bavail, &target_stfs->f_bavail); | |
3707 | - put_user(stfs.f_files, &target_stfs->f_files); | |
3708 | - put_user(stfs.f_ffree, &target_stfs->f_ffree); | |
3709 | - put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); | |
3710 | - put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); | |
3711 | - put_user(stfs.f_namelen, &target_stfs->f_namelen); | |
3812 | + if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0)) | |
3813 | + goto efault; | |
3814 | + __put_user(stfs.f_type, &target_stfs->f_type); | |
3815 | + __put_user(stfs.f_bsize, &target_stfs->f_bsize); | |
3816 | + __put_user(stfs.f_blocks, &target_stfs->f_blocks); | |
3817 | + __put_user(stfs.f_bfree, &target_stfs->f_bfree); | |
3818 | + __put_user(stfs.f_bavail, &target_stfs->f_bavail); | |
3819 | + __put_user(stfs.f_files, &target_stfs->f_files); | |
3820 | + __put_user(stfs.f_ffree, &target_stfs->f_ffree); | |
3821 | + __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); | |
3822 | + __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); | |
3823 | + __put_user(stfs.f_namelen, &target_stfs->f_namelen); | |
3712 | 3824 | unlock_user_struct(target_stfs, arg2, 1); |
3713 | 3825 | } |
3714 | 3826 | break; |
... | ... | @@ -3717,26 +3829,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3717 | 3829 | goto convert_statfs; |
3718 | 3830 | #ifdef TARGET_NR_statfs64 |
3719 | 3831 | case TARGET_NR_statfs64: |
3720 | - p = lock_user_string(arg1); | |
3832 | + if (!(p = lock_user_string(arg1))) | |
3833 | + goto efault; | |
3721 | 3834 | ret = get_errno(statfs(path(p), &stfs)); |
3722 | 3835 | unlock_user(p, arg1, 0); |
3723 | 3836 | convert_statfs64: |
3724 | 3837 | if (!is_error(ret)) { |
3725 | 3838 | struct target_statfs64 *target_stfs; |
3726 | 3839 | |
3727 | - lock_user_struct(target_stfs, arg3, 0); | |
3728 | - /* ??? put_user is probably wrong. */ | |
3729 | - put_user(stfs.f_type, &target_stfs->f_type); | |
3730 | - put_user(stfs.f_bsize, &target_stfs->f_bsize); | |
3731 | - put_user(stfs.f_blocks, &target_stfs->f_blocks); | |
3732 | - put_user(stfs.f_bfree, &target_stfs->f_bfree); | |
3733 | - put_user(stfs.f_bavail, &target_stfs->f_bavail); | |
3734 | - put_user(stfs.f_files, &target_stfs->f_files); | |
3735 | - put_user(stfs.f_ffree, &target_stfs->f_ffree); | |
3736 | - put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); | |
3737 | - put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); | |
3738 | - put_user(stfs.f_namelen, &target_stfs->f_namelen); | |
3739 | - unlock_user_struct(target_stfs, arg3, 0); | |
3840 | + if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0)) | |
3841 | + goto efault; | |
3842 | + __put_user(stfs.f_type, &target_stfs->f_type); | |
3843 | + __put_user(stfs.f_bsize, &target_stfs->f_bsize); | |
3844 | + __put_user(stfs.f_blocks, &target_stfs->f_blocks); | |
3845 | + __put_user(stfs.f_bfree, &target_stfs->f_bfree); | |
3846 | + __put_user(stfs.f_bavail, &target_stfs->f_bavail); | |
3847 | + __put_user(stfs.f_files, &target_stfs->f_files); | |
3848 | + __put_user(stfs.f_ffree, &target_stfs->f_ffree); | |
3849 | + __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); | |
3850 | + __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); | |
3851 | + __put_user(stfs.f_namelen, &target_stfs->f_namelen); | |
3852 | + unlock_user_struct(target_stfs, arg3, 1); | |
3740 | 3853 | } |
3741 | 3854 | break; |
3742 | 3855 | case TARGET_NR_fstatfs64: |
... | ... | @@ -3839,7 +3952,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3839 | 3952 | #endif |
3840 | 3953 | |
3841 | 3954 | case TARGET_NR_syslog: |
3842 | - p = lock_user_string(arg2); | |
3955 | + if (!(p = lock_user_string(arg2))) | |
3956 | + goto efault; | |
3843 | 3957 | ret = get_errno(sys_syslog((int)arg1, p, (int)arg3)); |
3844 | 3958 | unlock_user(p, arg2, 0); |
3845 | 3959 | break; |
... | ... | @@ -3880,12 +3994,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3880 | 3994 | } |
3881 | 3995 | break; |
3882 | 3996 | case TARGET_NR_stat: |
3883 | - p = lock_user_string(arg1); | |
3997 | + if (!(p = lock_user_string(arg1))) | |
3998 | + goto efault; | |
3884 | 3999 | ret = get_errno(stat(path(p), &st)); |
3885 | 4000 | unlock_user(p, arg1, 0); |
3886 | 4001 | goto do_stat; |
3887 | 4002 | case TARGET_NR_lstat: |
3888 | - p = lock_user_string(arg1); | |
4003 | + if (!(p = lock_user_string(arg1))) | |
4004 | + goto efault; | |
3889 | 4005 | ret = get_errno(lstat(path(p), &st)); |
3890 | 4006 | unlock_user(p, arg1, 0); |
3891 | 4007 | goto do_stat; |
... | ... | @@ -3896,7 +4012,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3896 | 4012 | if (!is_error(ret)) { |
3897 | 4013 | struct target_stat *target_st; |
3898 | 4014 | |
3899 | - lock_user_struct(target_st, arg2, 0); | |
4015 | + if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) | |
4016 | + goto efault; | |
3900 | 4017 | #if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32)) |
3901 | 4018 | target_st->st_dev = tswap32(st.st_dev); |
3902 | 4019 | #else |
... | ... | @@ -3979,7 +4096,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3979 | 4096 | break; |
3980 | 4097 | #ifdef TARGET_NR_swapoff |
3981 | 4098 | case TARGET_NR_swapoff: |
3982 | - p = lock_user_string(arg1); | |
4099 | + if (!(p = lock_user_string(arg1))) | |
4100 | + goto efault; | |
3983 | 4101 | ret = get_errno(swapoff(p)); |
3984 | 4102 | unlock_user(p, arg1, 0); |
3985 | 4103 | break; |
... | ... | @@ -3991,8 +4109,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
3991 | 4109 | ret = get_errno(sysinfo(&value)); |
3992 | 4110 | if (!is_error(ret) && arg1) |
3993 | 4111 | { |
3994 | - /* ??? __put_user is probably wrong. */ | |
3995 | - lock_user_struct(target_value, arg1, 0); | |
4112 | + if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0)) | |
4113 | + goto efault; | |
3996 | 4114 | __put_user(value.uptime, &target_value->uptime); |
3997 | 4115 | __put_user(value.loads[0], &target_value->loads[0]); |
3998 | 4116 | __put_user(value.loads[1], &target_value->loads[1]); |
... | ... | @@ -4030,7 +4148,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4030 | 4148 | break; |
4031 | 4149 | #endif |
4032 | 4150 | case TARGET_NR_setdomainname: |
4033 | - p = lock_user_string(arg1); | |
4151 | + if (!(p = lock_user_string(arg1))) | |
4152 | + goto efault; | |
4034 | 4153 | ret = get_errno(setdomainname(p, arg2)); |
4035 | 4154 | unlock_user(p, arg1, 0); |
4036 | 4155 | break; |
... | ... | @@ -4039,7 +4158,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4039 | 4158 | { |
4040 | 4159 | struct new_utsname * buf; |
4041 | 4160 | |
4042 | - lock_user_struct(buf, arg1, 0); | |
4161 | + if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0)) | |
4162 | + goto efault; | |
4043 | 4163 | ret = get_errno(sys_uname(buf)); |
4044 | 4164 | if (!is_error(ret)) { |
4045 | 4165 | /* Overrite the native machine name with whatever is being |
... | ... | @@ -4124,7 +4244,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4124 | 4244 | |
4125 | 4245 | dirp = malloc(count); |
4126 | 4246 | if (!dirp) { |
4127 | - ret = -TARGET_EFAULT; | |
4247 | + ret = -TARGET_ENOMEM; | |
4128 | 4248 | goto fail; |
4129 | 4249 | } |
4130 | 4250 | |
... | ... | @@ -4138,7 +4258,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4138 | 4258 | |
4139 | 4259 | count1 = 0; |
4140 | 4260 | de = dirp; |
4141 | - target_dirp = lock_user(arg2, count, 0); | |
4261 | + if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) | |
4262 | + goto efault; | |
4142 | 4263 | tde = target_dirp; |
4143 | 4264 | while (len > 0) { |
4144 | 4265 | reclen = de->d_reclen; |
... | ... | @@ -4157,8 +4278,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4157 | 4278 | count1 += treclen; |
4158 | 4279 | } |
4159 | 4280 | ret = count1; |
4281 | + unlock_user(target_dirp, arg2, ret); | |
4160 | 4282 | } |
4161 | - unlock_user(target_dirp, arg2, ret); | |
4162 | 4283 | free(dirp); |
4163 | 4284 | } |
4164 | 4285 | #else |
... | ... | @@ -4166,7 +4287,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4166 | 4287 | struct dirent *dirp; |
4167 | 4288 | abi_long count = arg3; |
4168 | 4289 | |
4169 | - dirp = lock_user(arg2, count, 0); | |
4290 | + if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) | |
4291 | + goto efault; | |
4170 | 4292 | ret = get_errno(sys_getdents(arg1, dirp, count)); |
4171 | 4293 | if (!is_error(ret)) { |
4172 | 4294 | struct dirent *de; |
... | ... | @@ -4193,7 +4315,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4193 | 4315 | { |
4194 | 4316 | struct dirent64 *dirp; |
4195 | 4317 | abi_long count = arg3; |
4196 | - dirp = lock_user(arg2, count, 0); | |
4318 | + if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) | |
4319 | + goto efault; | |
4197 | 4320 | ret = get_errno(sys_getdents64(arg1, dirp, count)); |
4198 | 4321 | if (!is_error(ret)) { |
4199 | 4322 | struct dirent64 *de; |
... | ... | @@ -4229,7 +4352,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4229 | 4352 | struct pollfd *pfd; |
4230 | 4353 | unsigned int i; |
4231 | 4354 | |
4232 | - target_pfd = lock_user(arg1, sizeof(struct target_pollfd) * nfds, 1); | |
4355 | + target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1); | |
4356 | + if (!target_pfd) | |
4357 | + goto efault; | |
4233 | 4358 | pfd = alloca(sizeof(struct pollfd) * nfds); |
4234 | 4359 | for(i = 0; i < nfds; i++) { |
4235 | 4360 | pfd[i].fd = tswap32(target_pfd[i].fd); |
... | ... | @@ -4258,7 +4383,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4258 | 4383 | struct iovec *vec; |
4259 | 4384 | |
4260 | 4385 | vec = alloca(count * sizeof(struct iovec)); |
4261 | - lock_iovec(vec, arg2, count, 0); | |
4386 | + lock_iovec(VERIFY_WRITE, vec, arg2, count, 0); | |
4262 | 4387 | ret = get_errno(readv(arg1, vec, count)); |
4263 | 4388 | unlock_iovec(vec, arg2, count, 1); |
4264 | 4389 | } |
... | ... | @@ -4269,7 +4394,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4269 | 4394 | struct iovec *vec; |
4270 | 4395 | |
4271 | 4396 | vec = alloca(count * sizeof(struct iovec)); |
4272 | - lock_iovec(vec, arg2, count, 1); | |
4397 | + lock_iovec(VERIFY_READ, vec, arg2, count, 1); | |
4273 | 4398 | ret = get_errno(writev(arg1, vec, count)); |
4274 | 4399 | unlock_iovec(vec, arg2, count, 0); |
4275 | 4400 | } |
... | ... | @@ -4292,7 +4417,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4292 | 4417 | struct sched_param *target_schp; |
4293 | 4418 | struct sched_param schp; |
4294 | 4419 | |
4295 | - lock_user_struct(target_schp, arg2, 1); | |
4420 | + if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) | |
4421 | + goto efault; | |
4296 | 4422 | schp.sched_priority = tswap32(target_schp->sched_priority); |
4297 | 4423 | unlock_user_struct(target_schp, arg2, 0); |
4298 | 4424 | ret = get_errno(sched_setparam(arg1, &schp)); |
... | ... | @@ -4304,7 +4430,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4304 | 4430 | struct sched_param schp; |
4305 | 4431 | ret = get_errno(sched_getparam(arg1, &schp)); |
4306 | 4432 | if (!is_error(ret)) { |
4307 | - lock_user_struct(target_schp, arg2, 0); | |
4433 | + if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) | |
4434 | + goto efault; | |
4308 | 4435 | target_schp->sched_priority = tswap32(schp.sched_priority); |
4309 | 4436 | unlock_user_struct(target_schp, arg2, 1); |
4310 | 4437 | } |
... | ... | @@ -4314,7 +4441,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4314 | 4441 | { |
4315 | 4442 | struct sched_param *target_schp; |
4316 | 4443 | struct sched_param schp; |
4317 | - lock_user_struct(target_schp, arg3, 1); | |
4444 | + if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) | |
4445 | + goto efault; | |
4318 | 4446 | schp.sched_priority = tswap32(target_schp->sched_priority); |
4319 | 4447 | unlock_user_struct(target_schp, arg3, 0); |
4320 | 4448 | ret = get_errno(sched_setscheduler(arg1, arg2, &schp)); |
... | ... | @@ -4378,18 +4506,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4378 | 4506 | #ifdef TARGET_NR_pread |
4379 | 4507 | case TARGET_NR_pread: |
4380 | 4508 | page_unprotect_range(arg2, arg3); |
4381 | - p = lock_user(arg2, arg3, 0); | |
4509 | + if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) | |
4510 | + goto efault; | |
4382 | 4511 | ret = get_errno(pread(arg1, p, arg3, arg4)); |
4383 | 4512 | unlock_user(p, arg2, ret); |
4384 | 4513 | break; |
4385 | 4514 | case TARGET_NR_pwrite: |
4386 | - p = lock_user(arg2, arg3, 1); | |
4515 | + if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) | |
4516 | + goto efault; | |
4387 | 4517 | ret = get_errno(pwrite(arg1, p, arg3, arg4)); |
4388 | 4518 | unlock_user(p, arg2, 0); |
4389 | 4519 | break; |
4390 | 4520 | #endif |
4391 | 4521 | case TARGET_NR_getcwd: |
4392 | - p = lock_user(arg1, arg2, 0); | |
4522 | + if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0))) | |
4523 | + goto efault; | |
4393 | 4524 | ret = get_errno(sys_getcwd1(p, arg2)); |
4394 | 4525 | unlock_user(p, arg1, ret); |
4395 | 4526 | break; |
... | ... | @@ -4400,9 +4531,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4400 | 4531 | case TARGET_NR_sigaltstack: |
4401 | 4532 | #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \ |
4402 | 4533 | defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) |
4403 | - ret = do_sigaltstack((struct target_sigaltstack *)arg1, | |
4404 | - (struct target_sigaltstack *)arg2, | |
4405 | - get_sp_from_cpustate((CPUState *)cpu_env)); | |
4534 | + ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env)); | |
4406 | 4535 | break; |
4407 | 4536 | #else |
4408 | 4537 | goto unimplemented; |
... | ... | @@ -4429,7 +4558,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4429 | 4558 | ret = get_errno(getrlimit(arg1, &rlim)); |
4430 | 4559 | if (!is_error(ret)) { |
4431 | 4560 | struct target_rlimit *target_rlim; |
4432 | - lock_user_struct(target_rlim, arg2, 0); | |
4561 | + if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) | |
4562 | + goto efault; | |
4433 | 4563 | target_rlim->rlim_cur = tswapl(rlim.rlim_cur); |
4434 | 4564 | target_rlim->rlim_max = tswapl(rlim.rlim_max); |
4435 | 4565 | unlock_user_struct(target_rlim, arg2, 1); |
... | ... | @@ -4439,7 +4569,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4439 | 4569 | #endif |
4440 | 4570 | #ifdef TARGET_NR_truncate64 |
4441 | 4571 | case TARGET_NR_truncate64: |
4442 | - p = lock_user_string(arg1); | |
4572 | + if (!(p = lock_user_string(arg1))) | |
4573 | + goto efault; | |
4443 | 4574 | ret = target_truncate64(cpu_env, p, arg2, arg3, arg4); |
4444 | 4575 | unlock_user(p, arg1, 0); |
4445 | 4576 | break; |
... | ... | @@ -4451,14 +4582,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4451 | 4582 | #endif |
4452 | 4583 | #ifdef TARGET_NR_stat64 |
4453 | 4584 | case TARGET_NR_stat64: |
4454 | - p = lock_user_string(arg1); | |
4585 | + if (!(p = lock_user_string(arg1))) | |
4586 | + goto efault; | |
4455 | 4587 | ret = get_errno(stat(path(p), &st)); |
4456 | 4588 | unlock_user(p, arg1, 0); |
4457 | 4589 | goto do_stat64; |
4458 | 4590 | #endif |
4459 | 4591 | #ifdef TARGET_NR_lstat64 |
4460 | 4592 | case TARGET_NR_lstat64: |
4461 | - p = lock_user_string(arg1); | |
4593 | + if (!(p = lock_user_string(arg1))) | |
4594 | + goto efault; | |
4462 | 4595 | ret = get_errno(lstat(path(p), &st)); |
4463 | 4596 | unlock_user(p, arg1, 0); |
4464 | 4597 | goto do_stat64; |
... | ... | @@ -4472,52 +4605,53 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4472 | 4605 | #ifdef TARGET_ARM |
4473 | 4606 | if (((CPUARMState *)cpu_env)->eabi) { |
4474 | 4607 | struct target_eabi_stat64 *target_st; |
4475 | - lock_user_struct(target_st, arg2, 1); | |
4608 | + | |
4609 | + if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) | |
4610 | + goto efault; | |
4476 | 4611 | memset(target_st, 0, sizeof(struct target_eabi_stat64)); |
4477 | - /* put_user is probably wrong. */ | |
4478 | - put_user(st.st_dev, &target_st->st_dev); | |
4479 | - put_user(st.st_ino, &target_st->st_ino); | |
4612 | + __put_user(st.st_dev, &target_st->st_dev); | |
4613 | + __put_user(st.st_ino, &target_st->st_ino); | |
4480 | 4614 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
4481 | - put_user(st.st_ino, &target_st->__st_ino); | |
4482 | -#endif | |
4483 | - put_user(st.st_mode, &target_st->st_mode); | |
4484 | - put_user(st.st_nlink, &target_st->st_nlink); | |
4485 | - put_user(st.st_uid, &target_st->st_uid); | |
4486 | - put_user(st.st_gid, &target_st->st_gid); | |
4487 | - put_user(st.st_rdev, &target_st->st_rdev); | |
4488 | - /* XXX: better use of kernel struct */ | |
4489 | - put_user(st.st_size, &target_st->st_size); | |
4490 | - put_user(st.st_blksize, &target_st->st_blksize); | |
4491 | - put_user(st.st_blocks, &target_st->st_blocks); | |
4492 | - put_user(st.st_atime, &target_st->target_st_atime); | |
4493 | - put_user(st.st_mtime, &target_st->target_st_mtime); | |
4494 | - put_user(st.st_ctime, &target_st->target_st_ctime); | |
4495 | - unlock_user_struct(target_st, arg2, 0); | |
4615 | + __put_user(st.st_ino, &target_st->__st_ino); | |
4616 | +#endif | |
4617 | + __put_user(st.st_mode, &target_st->st_mode); | |
4618 | + __put_user(st.st_nlink, &target_st->st_nlink); | |
4619 | + __put_user(st.st_uid, &target_st->st_uid); | |
4620 | + __put_user(st.st_gid, &target_st->st_gid); | |
4621 | + __put_user(st.st_rdev, &target_st->st_rdev); | |
4622 | + __put_user(st.st_size, &target_st->st_size); | |
4623 | + __put_user(st.st_blksize, &target_st->st_blksize); | |
4624 | + __put_user(st.st_blocks, &target_st->st_blocks); | |
4625 | + __put_user(st.st_atime, &target_st->target_st_atime); | |
4626 | + __put_user(st.st_mtime, &target_st->target_st_mtime); | |
4627 | + __put_user(st.st_ctime, &target_st->target_st_ctime); | |
4628 | + unlock_user_struct(target_st, arg2, 1); | |
4496 | 4629 | } else |
4497 | 4630 | #endif |
4498 | 4631 | { |
4499 | 4632 | struct target_stat64 *target_st; |
4500 | - lock_user_struct(target_st, arg2, 1); | |
4633 | + | |
4634 | + if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) | |
4635 | + goto efault; | |
4501 | 4636 | memset(target_st, 0, sizeof(struct target_stat64)); |
4502 | - /* ??? put_user is probably wrong. */ | |
4503 | - put_user(st.st_dev, &target_st->st_dev); | |
4504 | - put_user(st.st_ino, &target_st->st_ino); | |
4637 | + __put_user(st.st_dev, &target_st->st_dev); | |
4638 | + __put_user(st.st_ino, &target_st->st_ino); | |
4505 | 4639 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
4506 | - put_user(st.st_ino, &target_st->__st_ino); | |
4640 | + __put_user(st.st_ino, &target_st->__st_ino); | |
4507 | 4641 | #endif |
4508 | - put_user(st.st_mode, &target_st->st_mode); | |
4509 | - put_user(st.st_nlink, &target_st->st_nlink); | |
4510 | - put_user(st.st_uid, &target_st->st_uid); | |
4511 | - put_user(st.st_gid, &target_st->st_gid); | |
4512 | - put_user(st.st_rdev, &target_st->st_rdev); | |
4642 | + __put_user(st.st_mode, &target_st->st_mode); | |
4643 | + __put_user(st.st_nlink, &target_st->st_nlink); | |
4644 | + __put_user(st.st_uid, &target_st->st_uid); | |
4645 | + __put_user(st.st_gid, &target_st->st_gid); | |
4646 | + __put_user(st.st_rdev, &target_st->st_rdev); | |
4513 | 4647 | /* XXX: better use of kernel struct */ |
4514 | - put_user(st.st_size, &target_st->st_size); | |
4515 | - put_user(st.st_blksize, &target_st->st_blksize); | |
4516 | - put_user(st.st_blocks, &target_st->st_blocks); | |
4517 | - put_user(st.st_atime, &target_st->target_st_atime); | |
4518 | - put_user(st.st_mtime, &target_st->target_st_mtime); | |
4519 | - put_user(st.st_ctime, &target_st->target_st_ctime); | |
4520 | - unlock_user_struct(target_st, arg2, 0); | |
4648 | + __put_user(st.st_size, &target_st->st_size); | |
4649 | + __put_user(st.st_blksize, &target_st->st_blksize); | |
4650 | + __put_user(st.st_blocks, &target_st->st_blocks); | |
4651 | + __put_user(st.st_atime, &target_st->target_st_atime); | |
4652 | + __put_user(st.st_mtime, &target_st->target_st_mtime); | |
4653 | + __put_user(st.st_ctime, &target_st->target_st_ctime); | |
4654 | + unlock_user_struct(target_st, arg2, 1); | |
4521 | 4655 | } |
4522 | 4656 | } |
4523 | 4657 | } |
... | ... | @@ -4525,7 +4659,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4525 | 4659 | #endif |
4526 | 4660 | #ifdef USE_UID16 |
4527 | 4661 | case TARGET_NR_lchown: |
4528 | - p = lock_user_string(arg1); | |
4662 | + if (!(p = lock_user_string(arg1))) | |
4663 | + goto efault; | |
4529 | 4664 | ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3))); |
4530 | 4665 | unlock_user(p, arg1, 0); |
4531 | 4666 | break; |
... | ... | @@ -4557,7 +4692,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4557 | 4692 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
4558 | 4693 | ret = get_errno(getgroups(gidsetsize, grouplist)); |
4559 | 4694 | if (!is_error(ret)) { |
4560 | - target_grouplist = lock_user(arg2, gidsetsize * 2, 0); | |
4695 | + target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0); | |
4696 | + if (!target_grouplist) | |
4697 | + goto efault; | |
4561 | 4698 | for(i = 0;i < gidsetsize; i++) |
4562 | 4699 | target_grouplist[i] = tswap16(grouplist[i]); |
4563 | 4700 | unlock_user(target_grouplist, arg2, gidsetsize * 2); |
... | ... | @@ -4572,7 +4709,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4572 | 4709 | int i; |
4573 | 4710 | |
4574 | 4711 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
4575 | - target_grouplist = lock_user(arg2, gidsetsize * 2, 1); | |
4712 | + target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1); | |
4713 | + if (!target_grouplist) { | |
4714 | + ret = -TARGET_EFAULT; | |
4715 | + goto fail; | |
4716 | + } | |
4576 | 4717 | for(i = 0;i < gidsetsize; i++) |
4577 | 4718 | grouplist[i] = tswap16(target_grouplist[i]); |
4578 | 4719 | unlock_user(target_grouplist, arg2, 0); |
... | ... | @@ -4584,18 +4725,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4584 | 4725 | break; |
4585 | 4726 | #if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) |
4586 | 4727 | case TARGET_NR_fchownat: |
4587 | - if (!arg2) { | |
4588 | - ret = -TARGET_EFAULT; | |
4589 | - goto fail; | |
4590 | - } | |
4591 | - p = lock_user_string(arg2); | |
4592 | - if (!access_ok(VERIFY_READ, p, 1)) | |
4593 | - /* Don't "goto fail" so that cleanup can happen. */ | |
4594 | - ret = -TARGET_EFAULT; | |
4595 | - else | |
4596 | - ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5)); | |
4597 | - if (p) | |
4598 | - unlock_user(p, arg2, 0); | |
4728 | + if (!(p = lock_user_string(arg2))) | |
4729 | + goto efault; | |
4730 | + ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5)); | |
4731 | + unlock_user(p, arg2, 0); | |
4599 | 4732 | break; |
4600 | 4733 | #endif |
4601 | 4734 | #ifdef TARGET_NR_setresuid |
... | ... | @@ -4639,7 +4772,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4639 | 4772 | break; |
4640 | 4773 | #endif |
4641 | 4774 | case TARGET_NR_chown: |
4642 | - p = lock_user_string(arg1); | |
4775 | + if (!(p = lock_user_string(arg1))) | |
4776 | + goto efault; | |
4643 | 4777 | ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3))); |
4644 | 4778 | unlock_user(p, arg1, 0); |
4645 | 4779 | break; |
... | ... | @@ -4659,7 +4793,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4659 | 4793 | |
4660 | 4794 | #ifdef TARGET_NR_lchown32 |
4661 | 4795 | case TARGET_NR_lchown32: |
4662 | - p = lock_user_string(arg1); | |
4796 | + if (!(p = lock_user_string(arg1))) | |
4797 | + goto efault; | |
4663 | 4798 | ret = get_errno(lchown(p, arg2, arg3)); |
4664 | 4799 | unlock_user(p, arg1, 0); |
4665 | 4800 | break; |
... | ... | @@ -4705,7 +4840,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4705 | 4840 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
4706 | 4841 | ret = get_errno(getgroups(gidsetsize, grouplist)); |
4707 | 4842 | if (!is_error(ret)) { |
4708 | - target_grouplist = lock_user(arg2, gidsetsize * 4, 0); | |
4843 | + target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0); | |
4844 | + if (!target_grouplist) { | |
4845 | + ret = -TARGET_EFAULT; | |
4846 | + goto fail; | |
4847 | + } | |
4709 | 4848 | for(i = 0;i < gidsetsize; i++) |
4710 | 4849 | target_grouplist[i] = tswap32(grouplist[i]); |
4711 | 4850 | unlock_user(target_grouplist, arg2, gidsetsize * 4); |
... | ... | @@ -4722,7 +4861,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4722 | 4861 | int i; |
4723 | 4862 | |
4724 | 4863 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
4725 | - target_grouplist = lock_user(arg2, gidsetsize * 4, 1); | |
4864 | + target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1); | |
4865 | + if (!target_grouplist) { | |
4866 | + ret = -TARGET_EFAULT; | |
4867 | + goto fail; | |
4868 | + } | |
4726 | 4869 | for(i = 0;i < gidsetsize; i++) |
4727 | 4870 | grouplist[i] = tswap32(target_grouplist[i]); |
4728 | 4871 | unlock_user(target_grouplist, arg2, 0); |
... | ... | @@ -4773,7 +4916,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4773 | 4916 | #endif |
4774 | 4917 | #ifdef TARGET_NR_chown32 |
4775 | 4918 | case TARGET_NR_chown32: |
4776 | - p = lock_user_string(arg1); | |
4919 | + if (!(p = lock_user_string(arg1))) | |
4920 | + goto efault; | |
4777 | 4921 | ret = get_errno(chown(p, arg2, arg3)); |
4778 | 4922 | unlock_user(p, arg1, 0); |
4779 | 4923 | break; |
... | ... | @@ -4843,7 +4987,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4843 | 4987 | case TARGET_F_GETLK64: |
4844 | 4988 | #ifdef TARGET_ARM |
4845 | 4989 | if (((CPUARMState *)cpu_env)->eabi) { |
4846 | - lock_user_struct(target_efl, arg3, 1); | |
4990 | + if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) { | |
4991 | + ret = -TARGET_EFAULT; | |
4992 | + goto fail; | |
4993 | + } | |
4847 | 4994 | fl.l_type = tswap16(target_efl->l_type); |
4848 | 4995 | fl.l_whence = tswap16(target_efl->l_whence); |
4849 | 4996 | fl.l_start = tswap64(target_efl->l_start); |
... | ... | @@ -4853,7 +5000,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4853 | 5000 | } else |
4854 | 5001 | #endif |
4855 | 5002 | { |
4856 | - lock_user_struct(target_fl, arg3, 1); | |
5003 | + if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) { | |
5004 | + ret = -TARGET_EFAULT; | |
5005 | + goto fail; | |
5006 | + } | |
4857 | 5007 | fl.l_type = tswap16(target_fl->l_type); |
4858 | 5008 | fl.l_whence = tswap16(target_fl->l_whence); |
4859 | 5009 | fl.l_start = tswap64(target_fl->l_start); |
... | ... | @@ -4865,7 +5015,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4865 | 5015 | if (ret == 0) { |
4866 | 5016 | #ifdef TARGET_ARM |
4867 | 5017 | if (((CPUARMState *)cpu_env)->eabi) { |
4868 | - lock_user_struct(target_efl, arg3, 0); | |
5018 | + if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0)) { | |
5019 | + ret = -TARGET_EFAULT; | |
5020 | + goto fail; | |
5021 | + } | |
4869 | 5022 | target_efl->l_type = tswap16(fl.l_type); |
4870 | 5023 | target_efl->l_whence = tswap16(fl.l_whence); |
4871 | 5024 | target_efl->l_start = tswap64(fl.l_start); |
... | ... | @@ -4875,7 +5028,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4875 | 5028 | } else |
4876 | 5029 | #endif |
4877 | 5030 | { |
4878 | - lock_user_struct(target_fl, arg3, 0); | |
5031 | + if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) { | |
5032 | + ret = -TARGET_EFAULT; | |
5033 | + goto fail; | |
5034 | + } | |
4879 | 5035 | target_fl->l_type = tswap16(fl.l_type); |
4880 | 5036 | target_fl->l_whence = tswap16(fl.l_whence); |
4881 | 5037 | target_fl->l_start = tswap64(fl.l_start); |
... | ... | @@ -4890,7 +5046,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4890 | 5046 | case TARGET_F_SETLKW64: |
4891 | 5047 | #ifdef TARGET_ARM |
4892 | 5048 | if (((CPUARMState *)cpu_env)->eabi) { |
4893 | - lock_user_struct(target_efl, arg3, 1); | |
5049 | + if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) { | |
5050 | + ret = -TARGET_EFAULT; | |
5051 | + goto fail; | |
5052 | + } | |
4894 | 5053 | fl.l_type = tswap16(target_efl->l_type); |
4895 | 5054 | fl.l_whence = tswap16(target_efl->l_whence); |
4896 | 5055 | fl.l_start = tswap64(target_efl->l_start); |
... | ... | @@ -4900,7 +5059,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4900 | 5059 | } else |
4901 | 5060 | #endif |
4902 | 5061 | { |
4903 | - lock_user_struct(target_fl, arg3, 1); | |
5062 | + if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) { | |
5063 | + ret = -TARGET_EFAULT; | |
5064 | + goto fail; | |
5065 | + } | |
4904 | 5066 | fl.l_type = tswap16(target_fl->l_type); |
4905 | 5067 | fl.l_whence = tswap16(target_fl->l_whence); |
4906 | 5068 | fl.l_start = tswap64(target_fl->l_start); |
... | ... | @@ -4998,8 +5160,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
4998 | 5160 | |
4999 | 5161 | #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) |
5000 | 5162 | case TARGET_NR_set_tid_address: |
5001 | - ret = get_errno(set_tid_address((int *) arg1)); | |
5002 | - break; | |
5163 | + ret = get_errno(set_tid_address((int *)g2h(arg1))); | |
5164 | + break; | |
5003 | 5165 | #endif |
5004 | 5166 | |
5005 | 5167 | #if defined(TARGET_NR_tkill) && defined(__NR_tkill) |
... | ... | @@ -5028,14 +5190,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
5028 | 5190 | if (!arg2) |
5029 | 5191 | ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4)); |
5030 | 5192 | else { |
5031 | - p = lock_user_string(arg2); | |
5032 | - if (!access_ok(VERIFY_READ, p, 1)) | |
5033 | - /* Don't "goto fail" so that cleanup can happen. */ | |
5193 | + if (!(p = lock_user_string(arg2))) { | |
5034 | 5194 | ret = -TARGET_EFAULT; |
5035 | - else | |
5036 | - ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4)); | |
5037 | - if (p) | |
5038 | - unlock_user(p, arg2, 0); | |
5195 | + goto fail; | |
5196 | + } | |
5197 | + ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4)); | |
5198 | + unlock_user(p, arg2, 0); | |
5039 | 5199 | } |
5040 | 5200 | } |
5041 | 5201 | break; |
... | ... | @@ -5050,11 +5210,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
5050 | 5210 | ret = -TARGET_ENOSYS; |
5051 | 5211 | break; |
5052 | 5212 | } |
5053 | - fail: | |
5213 | +fail: | |
5054 | 5214 | #ifdef DEBUG |
5055 | 5215 | gemu_log(" = %ld\n", ret); |
5056 | 5216 | #endif |
5057 | 5217 | if(do_strace) |
5058 | 5218 | print_syscall_ret(num, ret); |
5059 | 5219 | return ret; |
5220 | +efault: | |
5221 | + ret = -TARGET_EFAULT; | |
5222 | + goto fail; | |
5060 | 5223 | } | ... | ... |
linux-user/uaccess.c
0 โ 100644
1 | +/* User memory access */ | |
2 | +#include <stdio.h> | |
3 | +#include <string.h> | |
4 | + | |
5 | +#include "qemu.h" | |
6 | + | |
7 | +/* copy_from_user() and copy_to_user() are usually used to copy data | |
8 | + * buffers between the target and host. These internally perform | |
9 | + * locking/unlocking of the memory. | |
10 | + */ | |
11 | +abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len) | |
12 | +{ | |
13 | + abi_long ret = 0; | |
14 | + void *ghptr; | |
15 | + | |
16 | + if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) { | |
17 | + memcpy(hptr, ghptr, len); | |
18 | + unlock_user(ghptr, gaddr, 0); | |
19 | + } else | |
20 | + ret = -TARGET_EFAULT; | |
21 | + | |
22 | + return ret; | |
23 | +} | |
24 | + | |
25 | + | |
26 | +abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len) | |
27 | +{ | |
28 | + abi_long ret = 0; | |
29 | + void *ghptr; | |
30 | + | |
31 | + if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) { | |
32 | + memcpy(ghptr, hptr, len); | |
33 | + unlock_user(ghptr, gaddr, len); | |
34 | + } else | |
35 | + ret = -TARGET_EFAULT; | |
36 | + | |
37 | + return ret; | |
38 | +} | |
39 | + | |
40 | + | |
41 | +/* Return the length of a string in target memory. */ | |
42 | +/* FIXME - this doesn't check access_ok() - it's rather complicated to | |
43 | + * do it correctly because we need to check the bytes in a page and then | |
44 | + * skip to the next page and check the bytes there until we find the | |
45 | + * terminator. There should be a general function to do this that | |
46 | + * can look for any byte terminator in a buffer - not strlen(). | |
47 | + */ | |
48 | +abi_long target_strlen(abi_ulong gaddr) | |
49 | +{ | |
50 | + return strlen(g2h(gaddr)); | |
51 | +} | ... | ... |
linux-user/vm86.c
... | ... | @@ -64,7 +64,9 @@ void save_v86_state(CPUX86State *env) |
64 | 64 | TaskState *ts = env->opaque; |
65 | 65 | struct target_vm86plus_struct * target_v86; |
66 | 66 | |
67 | - lock_user_struct(target_v86, ts->target_v86, 0); | |
67 | + if (!lock_user_struct(VERIFY_WRITE, target_v86, ts->target_v86, 0)) | |
68 | + /* FIXME - should return an error */ | |
69 | + return; | |
68 | 70 | /* put the VM86 registers in the userspace register structure */ |
69 | 71 | target_v86->regs.eax = tswap32(env->regs[R_EAX]); |
70 | 72 | target_v86->regs.ebx = tswap32(env->regs[R_EBX]); |
... | ... | @@ -424,7 +426,8 @@ int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr) |
424 | 426 | ts->vm86_saved_regs.gs = env->segs[R_GS].selector; |
425 | 427 | |
426 | 428 | ts->target_v86 = vm86_addr; |
427 | - lock_user_struct(target_v86, vm86_addr, 1); | |
429 | + if (!lock_user_struct(VERIFY_READ, target_v86, vm86_addr, 1)) | |
430 | + return -EFAULT; | |
428 | 431 | /* build vm86 CPU state */ |
429 | 432 | ts->v86flags = tswap32(target_v86->regs.eflags); |
430 | 433 | env->eflags = (env->eflags & ~SAFE_MASK) | | ... | ... |
m68k-semi.c
... | ... | @@ -107,7 +107,9 @@ static void translate_stat(CPUState *env, target_ulong addr, struct stat *s) |
107 | 107 | { |
108 | 108 | struct m68k_gdb_stat *p; |
109 | 109 | |
110 | - p = lock_user(addr, sizeof(struct m68k_gdb_stat), 0); | |
110 | + if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0))) | |
111 | + /* FIXME - should this return an error code? */ | |
112 | + return; | |
111 | 113 | p->gdb_st_dev = cpu_to_be32(s->st_dev); |
112 | 114 | p->gdb_st_ino = cpu_to_be32(s->st_ino); |
113 | 115 | p->gdb_st_mode = cpu_to_be32(s->st_mode); |
... | ... | @@ -168,9 +170,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
168 | 170 | ARG(2), ARG(3)); |
169 | 171 | return; |
170 | 172 | } else { |
171 | - p = lock_user_string(ARG(0)); | |
172 | - result = open(p, translate_openflags(ARG(2)), ARG(3)); | |
173 | - unlock_user(p, ARG(0), 0); | |
173 | + if (!(p = lock_user_string(ARG(0)))) { | |
174 | + /* FIXME - check error code? */ | |
175 | + result = -1; | |
176 | + } else { | |
177 | + result = open(p, translate_openflags(ARG(2)), ARG(3)); | |
178 | + unlock_user(p, ARG(0), 0); | |
179 | + } | |
174 | 180 | } |
175 | 181 | break; |
176 | 182 | case HOSTED_CLOSE: |
... | ... | @@ -196,9 +202,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
196 | 202 | ARG(0), ARG(1), len); |
197 | 203 | return; |
198 | 204 | } else { |
199 | - p = lock_user(ARG(1), len, 0); | |
200 | - result = read(ARG(0), p, len); | |
201 | - unlock_user(p, ARG(1), len); | |
205 | + if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) { | |
206 | + /* FIXME - check error code? */ | |
207 | + result = -1; | |
208 | + } else { | |
209 | + result = read(ARG(0), p, len); | |
210 | + unlock_user(p, ARG(1), len); | |
211 | + } | |
202 | 212 | } |
203 | 213 | break; |
204 | 214 | case HOSTED_WRITE: |
... | ... | @@ -208,9 +218,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
208 | 218 | ARG(0), ARG(1), len); |
209 | 219 | return; |
210 | 220 | } else { |
211 | - p = lock_user(ARG(1), len, 1); | |
212 | - result = write(ARG(0), p, len); | |
213 | - unlock_user(p, ARG(0), 0); | |
221 | + if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) { | |
222 | + /* FIXME - check error code? */ | |
223 | + result = -1; | |
224 | + } else { | |
225 | + result = write(ARG(0), p, len); | |
226 | + unlock_user(p, ARG(0), 0); | |
227 | + } | |
214 | 228 | } |
215 | 229 | break; |
216 | 230 | case HOSTED_LSEEK: |
... | ... | @@ -237,7 +251,12 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
237 | 251 | } else { |
238 | 252 | p = lock_user_string(ARG(0)); |
239 | 253 | q = lock_user_string(ARG(2)); |
240 | - result = rename(p, q); | |
254 | + if (!p || !q) { | |
255 | + /* FIXME - check error code? */ | |
256 | + result = -1; | |
257 | + } else { | |
258 | + result = rename(p, q); | |
259 | + } | |
241 | 260 | unlock_user(p, ARG(0), 0); |
242 | 261 | unlock_user(q, ARG(2), 0); |
243 | 262 | } |
... | ... | @@ -248,9 +267,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
248 | 267 | ARG(0), (int)ARG(1)); |
249 | 268 | return; |
250 | 269 | } else { |
251 | - p = lock_user_string(ARG(0)); | |
252 | - result = unlink(p); | |
253 | - unlock_user(p, ARG(0), 0); | |
270 | + if (!(p = lock_user_string(ARG(0)))) { | |
271 | + /* FIXME - check error code? */ | |
272 | + result = -1; | |
273 | + } else { | |
274 | + result = unlink(p); | |
275 | + unlock_user(p, ARG(0), 0); | |
276 | + } | |
254 | 277 | } |
255 | 278 | break; |
256 | 279 | case HOSTED_STAT: |
... | ... | @@ -260,9 +283,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
260 | 283 | return; |
261 | 284 | } else { |
262 | 285 | struct stat s; |
263 | - p = lock_user_string(ARG(0)); | |
264 | - result = stat(p, &s); | |
265 | - unlock_user(p, ARG(0), 0); | |
286 | + if (!(p = lock_user_string(ARG(0)))) { | |
287 | + /* FIXME - check error code? */ | |
288 | + result = -1; | |
289 | + } else { | |
290 | + result = stat(p, &s); | |
291 | + unlock_user(p, ARG(0), 0); | |
292 | + } | |
266 | 293 | if (result == 0) { |
267 | 294 | translate_stat(env, ARG(2), &s); |
268 | 295 | } |
... | ... | @@ -291,10 +318,15 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
291 | 318 | struct gdb_timeval *p; |
292 | 319 | result = qemu_gettimeofday(&tv); |
293 | 320 | if (result != 0) { |
294 | - p = lock_user(ARG(0), sizeof(struct gdb_timeval), 0); | |
295 | - p->tv_sec = cpu_to_be32(tv.tv_sec); | |
296 | - p->tv_usec = cpu_to_be64(tv.tv_usec); | |
297 | - unlock_user(p, ARG(0), sizeof(struct gdb_timeval)); | |
321 | + if (!(p = lock_user(VERIFY_WRITE, | |
322 | + ARG(0), sizeof(struct gdb_timeval), 0))) { | |
323 | + /* FIXME - check error code? */ | |
324 | + result = -1; | |
325 | + } else { | |
326 | + p->tv_sec = cpu_to_be32(tv.tv_sec); | |
327 | + p->tv_usec = cpu_to_be64(tv.tv_usec); | |
328 | + unlock_user(p, ARG(0), sizeof(struct gdb_timeval)); | |
329 | + } | |
298 | 330 | } |
299 | 331 | } |
300 | 332 | break; |
... | ... | @@ -312,9 +344,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) |
312 | 344 | ARG(0), (int)ARG(1)); |
313 | 345 | return; |
314 | 346 | } else { |
315 | - p = lock_user_string(ARG(0)); | |
316 | - result = system(p); | |
317 | - unlock_user(p, ARG(0), 0); | |
347 | + if (!(p = lock_user_string(ARG(0)))) { | |
348 | + /* FIXME - check error code? */ | |
349 | + result = -1; | |
350 | + } else { | |
351 | + result = system(p); | |
352 | + unlock_user(p, ARG(0), 0); | |
353 | + } | |
318 | 354 | } |
319 | 355 | break; |
320 | 356 | case HOSTED_INIT_SIM: | ... | ... |
softmmu-semi.h
... | ... | @@ -41,7 +41,7 @@ static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len, |
41 | 41 | cpu_memory_rw_debug(env, addr, p, len, 0); |
42 | 42 | return p; |
43 | 43 | } |
44 | -#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy) | |
44 | +#define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy) | |
45 | 45 | static char *softmmu_lock_user_string(CPUState *env, uint32_t addr) |
46 | 46 | { |
47 | 47 | char *p; | ... | ... |