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; | ... | ... |