Index: qemu/exec.c =================================================================== --- qemu.orig/exec.c 2007-03-26 11:18:49.000000000 -0400 +++ qemu/exec.c 2007-03-26 11:20:06.000000000 -0400 @@ -1785,6 +1785,29 @@ spin_unlock(&tb_lock); } +int page_check_range(target_ulong start, target_ulong len, int flags) +{ + PageDesc *p; + target_ulong end; + target_ulong addr; + + end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ + start = start & TARGET_PAGE_MASK; + + if( end < start ) return EFAULT; /* we've wrapped around */ + for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { + p = page_find(addr >> TARGET_PAGE_BITS); + if( !p ) return EFAULT; + if( !(p->flags & PAGE_VALID) ) return EFAULT; + + if (!(p->flags & PAGE_READ) && + (flags & PAGE_READ) ) return EFAULT; + if (!(p->flags & PAGE_WRITE) && + (flags & PAGE_WRITE) ) return EFAULT; + } + return 0; +} + /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was succesfully handled. */ int page_unprotect(target_ulong address, unsigned long pc, void *puc) Index: qemu/cpu-all.h =================================================================== --- qemu.orig/cpu-all.h 2007-03-26 11:18:49.000000000 -0400 +++ qemu/cpu-all.h 2007-03-26 11:20:06.000000000 -0400 @@ -689,6 +689,7 @@ int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); void page_unprotect_range(target_ulong data, target_ulong data_size); +int page_check_range(target_ulong start, target_ulong len, int flags); #define SINGLE_CPU_DEFINES #ifdef SINGLE_CPU_DEFINES Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-03-26 11:20:05.000000000 -0400 +++ qemu/linux-user/syscall.c 2007-03-26 14:11:21.000000000 -0400 @@ -406,28 +406,36 @@ return ret; } -static inline void target_to_host_sockaddr(struct sockaddr *addr, +static inline long target_to_host_sockaddr(struct sockaddr *addr, target_ulong target_addr, - socklen_t len) + socklen_t len, + int pg_access) { + long ret = 0; struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 1); + if( ret=page_check_range(target_saddr,len,pg_access) ) return ret; memcpy(addr, target_saddr, len); addr->sa_family = tswap16(target_saddr->sa_family); unlock_user(target_saddr, target_addr, 0); + return ret; } -static inline void host_to_target_sockaddr(target_ulong target_addr, +static inline long host_to_target_sockaddr(target_ulong target_addr, struct sockaddr *addr, - socklen_t len) + socklen_t len, + int pg_access) { + long ret = 0; struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 0); + if( ret=page_check_range(target_saddr,len,pg_access) ) return ret; memcpy(target_saddr, addr, len); target_saddr->sa_family = tswap16(addr->sa_family); unlock_user(target_saddr, target_addr, len); + return ret; } /* ??? Should this also swap msgh->name? */ @@ -788,18 +796,20 @@ static long do_bind(int sockfd, target_ulong target_addr, socklen_t addrlen) { + long ret = 0; void *addr = alloca(addrlen); - target_to_host_sockaddr(addr, target_addr, addrlen); + if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret; return get_errno(bind(sockfd, addr, addrlen)); } static long do_connect(int sockfd, target_ulong target_addr, socklen_t addrlen) { + long ret = 0; void *addr = alloca(addrlen); - target_to_host_sockaddr(addr, target_addr, addrlen); + if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret; return get_errno(connect(sockfd, addr, addrlen)); } @@ -814,11 +824,19 @@ target_ulong target_vec; lock_user_struct(msgp, target_msg, 1); + if( send ) + if( ret=page_check_range(msgp,sizeof(*msgp),PAGE_READ) ) return -ret; + else + if( ret=page_check_range(msgp,sizeof(*msgp),PAGE_WRITE) ) return -ret; if (msgp->msg_name) { msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); - target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), - msg.msg_namelen); + if( send ) + if( ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), + msg.msg_namelen,PAGE_READ) ) return -ret; + else + if( ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), + msg.msg_namelen,PAGE_WRITE) ) return -ret; } else { msg.msg_name = NULL; msg.msg_namelen = 0; @@ -851,11 +869,11 @@ { socklen_t addrlen = tget32(target_addrlen); void *addr = alloca(addrlen); - long ret; + long ret,ret2; ret = get_errno(accept(fd, addr, &addrlen)); if (!is_error(ret)) { - host_to_target_sockaddr(target_addr, addr, addrlen); + if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2; tput32(target_addrlen, addrlen); } return ret; @@ -864,13 +882,17 @@ static long do_getpeername(int fd, target_ulong target_addr, target_ulong target_addrlen) { - socklen_t addrlen = tget32(target_addrlen); - void *addr = alloca(addrlen); - long ret; + socklen_t addrlen; + void *addr; + long ret,ret2; + + if( ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE) ) return -ret; + addrlen = tget32(target_addrlen); + addr = alloca(addrlen); ret = get_errno(getpeername(fd, addr, &addrlen)); if (!is_error(ret)) { - host_to_target_sockaddr(target_addr, addr, addrlen); + if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2; tput32(target_addrlen, addrlen); } return ret; @@ -879,13 +901,17 @@ static long do_getsockname(int fd, target_ulong target_addr, target_ulong target_addrlen) { - socklen_t addrlen = tget32(target_addrlen); - void *addr = alloca(addrlen); - long ret; + socklen_t addrlen; + void *addr; + long ret,ret2; + + if( ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE) ) return -ret; + addrlen = tget32(target_addrlen); + addr = alloca(addrlen); ret = get_errno(getsockname(fd, addr, &addrlen)); if (!is_error(ret)) { - host_to_target_sockaddr(target_addr, addr, addrlen); + if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2; tput32(target_addrlen, addrlen); } return ret; @@ -913,9 +939,10 @@ long ret; host_msg = lock_user(msg, len, 1); + if( ret=page_check_range(host_msg,len,PAGE_READ) ) return -ret; if (target_addr) { addr = alloca(addrlen); - target_to_host_sockaddr(addr, target_addr, addrlen); + if( ret=target_to_host_sockaddr(addr, target_addr, addrlen, PAGE_READ) ) return -ret; ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen)); } else { ret = get_errno(send(fd, host_msg, len, flags)); @@ -930,9 +957,10 @@ socklen_t addrlen; void *addr; void *host_msg; - long ret; + long ret,ret2; host_msg = lock_user(msg, len, 0); + if( ret2=page_check_range(host_msg,len,PAGE_WRITE) ) return -ret2; if (target_addr) { addrlen = tget32(target_addrlen); addr = alloca(addrlen); @@ -943,7 +971,7 @@ } if (!is_error(ret)) { if (target_addr) { - host_to_target_sockaddr(target_addr, addr, addrlen); + if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2; tput32(target_addrlen, addrlen); } unlock_user(host_msg, msg, len); @@ -1150,13 +1178,16 @@ target_ulong __unused4; }; -static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip, - target_ulong target_addr) +static inline long target_to_host_ipc_perm(struct ipc_perm *host_ip, + target_ulong target_addr, + int pg_access) { + long ret = 0; struct target_ipc_perm *target_ip; struct target_semid_ds *target_sd; lock_user_struct(target_sd, target_addr, 1); + if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret; target_ip=&(target_sd->sem_perm); host_ip->__key = tswapl(target_ip->__key); host_ip->uid = tswapl(target_ip->uid); @@ -1165,15 +1196,20 @@ host_ip->cgid = tswapl(target_ip->cgid); host_ip->mode = tswapl(target_ip->mode); unlock_user_struct(target_sd, target_addr, 0); + + return ret; } -static inline void host_to_target_ipc_perm(target_ulong target_addr, - struct ipc_perm *host_ip) +static inline long host_to_target_ipc_perm(target_ulong target_addr, + struct ipc_perm *host_ip, + int pg_access) { + long ret = 0; struct target_ipc_perm *target_ip; struct target_semid_ds *target_sd; lock_user_struct(target_sd, target_addr, 0); + if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret; target_ip = &(target_sd->sem_perm); target_ip->__key = tswapl(host_ip->__key); target_ip->uid = tswapl(host_ip->uid); @@ -1182,32 +1218,44 @@ target_ip->cgid = tswapl(host_ip->cgid); target_ip->mode = tswapl(host_ip->mode); unlock_user_struct(target_sd, target_addr, 1); + + return ret; } -static inline void target_to_host_semid_ds(struct semid_ds *host_sd, - target_ulong target_addr) +static inline long target_to_host_semid_ds(struct semid_ds *host_sd, + target_ulong target_addr, + int pg_access) { + long ret = 0; struct target_semid_ds *target_sd; lock_user_struct(target_sd, target_addr, 1); - target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); + if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret; + target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr,pg_access); host_sd->sem_nsems = tswapl(target_sd->sem_nsems); host_sd->sem_otime = tswapl(target_sd->sem_otime); host_sd->sem_ctime = tswapl(target_sd->sem_ctime); unlock_user_struct(target_sd, target_addr, 0); + + return ret; } -static inline void host_to_target_semid_ds(target_ulong target_addr, - struct semid_ds *host_sd) +static inline long host_to_target_semid_ds(target_ulong target_addr, + struct semid_ds *host_sd, + int pg_access) { + long ret = 0; struct target_semid_ds *target_sd; lock_user_struct(target_sd, target_addr, 0); - host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); + host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm),pg_access); + if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret; target_sd->sem_nsems = tswapl(host_sd->sem_nsems); target_sd->sem_otime = tswapl(host_sd->sem_otime); target_sd->sem_ctime = tswapl(host_sd->sem_ctime); unlock_user_struct(target_sd, target_addr, 1); + + return ret; } union semun { @@ -1222,11 +1270,13 @@ target_long array; }; -static inline void target_to_host_semun(unsigned long cmd, +static inline long target_to_host_semun(unsigned long cmd, union semun *host_su, target_ulong target_addr, - struct semid_ds *ds) + struct semid_ds *ds, + int pg_access) { + long ret = 0; union target_semun *target_su; switch( cmd ) { @@ -1235,26 +1285,32 @@ case IPC_STAT: case IPC_SET: lock_user_struct(target_su, target_addr, 1); - target_to_host_semid_ds(ds,target_su->buf); + if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret; + if( ret=target_to_host_semid_ds(ds,target_su->buf, pg_access) ) return -ret; host_su->buf = ds; unlock_user_struct(target_su, target_addr, 0); break; case GETVAL: case SETVAL: lock_user_struct(target_su, target_addr, 1); + if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret; host_su->val = tswapl(target_su->val); unlock_user_struct(target_su, target_addr, 0); break; default: host_su->array = tswapl(target_su->array); } + + return ret; } -static inline void host_to_target_semun(unsigned long cmd, +static inline long host_to_target_semun(unsigned long cmd, target_ulong target_addr, union semun *host_su, - struct semid_ds *ds) + struct semid_ds *ds, + int pg_access) { + long ret = 0; union target_semun *target_su; switch( cmd ) { @@ -1263,18 +1319,22 @@ case IPC_STAT: case IPC_SET: lock_user_struct(target_su, target_addr, 0); - host_to_target_semid_ds(target_su->buf,ds); + if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret; + if( ret=host_to_target_semid_ds(target_su->buf,ds, pg_access) ) return -ret; unlock_user_struct(target_su, target_addr, 1); break; case GETVAL: case SETVAL: lock_user_struct(target_su, target_addr, 0); + if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret; target_su->val = tswapl(host_su->val); unlock_user_struct(target_su, target_addr, 1); break; default: target_su->array = tswapl(host_su->array); } + + return ret; } static inline long do_semctl(long first, long second, long third, long ptr) @@ -1286,34 +1346,34 @@ switch( cmd ) { case GETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); + if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE) ) return -ret; ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); + host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_WRITE); break; case SETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); + if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ) ) return -ret; ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); + host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ); break; case GETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); + if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE) ) return -ret; ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); + host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_WRITE); break; case SETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); + if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ) ) return -ret; ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); + host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ); break; case IPC_STAT: - target_to_host_semun(cmd,&arg,ptr,&dsarg); + if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE) ) return -ret; ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); + host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ); break; case IPC_SET: - target_to_host_semun(cmd,&arg,ptr,&dsarg); + if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ) ) return -ret; ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); + host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ); break; default: ret = get_errno(semctl(first, second, cmd, arg)); @@ -1340,13 +1400,16 @@ target_ulong __unused5; }; -static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, - target_ulong target_addr) +static inline long target_to_host_msqid_ds(struct msqid_ds *host_md, + target_ulong target_addr, + int pg_access) { + long ret = 0; struct target_msqid_ds *target_md; lock_user_struct(target_md, target_addr, 1); - target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); + if( ret=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret; + target_to_host_ipc_perm(&(host_md->msg_perm),target_addr,pg_access); host_md->msg_stime = tswapl(target_md->msg_stime); host_md->msg_rtime = tswapl(target_md->msg_rtime); host_md->msg_ctime = tswapl(target_md->msg_ctime); @@ -1356,15 +1419,19 @@ host_md->msg_lspid = tswapl(target_md->msg_lspid); host_md->msg_lrpid = tswapl(target_md->msg_lrpid); unlock_user_struct(target_md, target_addr, 0); + return ret; } -static inline void host_to_target_msqid_ds(target_ulong target_addr, - struct msqid_ds *host_md) +static inline long host_to_target_msqid_ds(target_ulong target_addr, + struct msqid_ds *host_md, + int pg_access) { + long ret = 0; struct target_msqid_ds *target_md; lock_user_struct(target_md, target_addr, 0); - host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); + if( ret=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret; + host_to_target_ipc_perm(target_addr,&(host_md->msg_perm),pg_access); target_md->msg_stime = tswapl(host_md->msg_stime); target_md->msg_rtime = tswapl(host_md->msg_rtime); target_md->msg_ctime = tswapl(host_md->msg_ctime); @@ -1374,6 +1441,8 @@ target_md->msg_lspid = tswapl(host_md->msg_lspid); target_md->msg_lrpid = tswapl(host_md->msg_lrpid); unlock_user_struct(target_md, target_addr, 1); + + return ret; } static inline long do_msgctl(long first, long second, long ptr) @@ -1383,10 +1452,15 @@ long ret = 0; switch( cmd ) { case IPC_STAT: + if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_WRITE) ) return -ret; + ret = get_errno(msgctl(first, cmd, &dsarg)); + host_to_target_msqid_ds(ptr,&dsarg,PAGE_WRITE); + break; case IPC_SET: - target_to_host_msqid_ds(&dsarg,ptr); + if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_READ) ) return -ret; ret = get_errno(msgctl(first, cmd, &dsarg)); - host_to_target_msqid_ds(ptr,&dsarg); + host_to_target_msqid_ds(ptr,&dsarg,PAGE_WRITE); + break; default: ret = get_errno(msgctl(first, cmd, &dsarg)); } @@ -1405,6 +1479,7 @@ long ret = 0; lock_user_struct(target_mb,msgp,0); + if( ret=page_check_range(target_mb,sizeof(long)+msgsz,PAGE_READ) ) return -ret; host_mb = malloc(msgsz+sizeof(long)); host_mb->mtype = tswapl(target_mb->mtype); memcpy(host_mb->mtext,target_mb->mtext,msgsz); @@ -1422,6 +1497,7 @@ long ret = 0; lock_user_struct(target_mb,msgp,0); + if( ret=page_check_range(target_mb,sizeof(long)+msgsz,PAGE_WRITE) ) return -ret; host_mb = malloc(msgsz+sizeof(long)); ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); if( ret > 0 ) @@ -2701,6 +2777,7 @@ struct target_sigaction act, oact, *pact; if (arg2) { lock_user_struct(old_act, arg2, 1); + if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_READ) ) return -ret; act._sa_handler = old_act->_sa_handler; target_siginitset(&act.sa_mask, old_act->sa_mask); act.sa_flags = old_act->sa_flags; @@ -2713,6 +2790,7 @@ ret = get_errno(do_sigaction(arg1, pact, &oact)); if (!is_error(ret) && arg3) { lock_user_struct(old_act, arg3, 0); + if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_WRITE) ) return -ret; old_act->_sa_handler = oact._sa_handler; old_act->sa_mask = oact.sa_mask.sig[0]; old_act->sa_flags = oact.sa_flags; @@ -2724,6 +2802,7 @@ if (arg2) { lock_user_struct(old_act, arg2, 1); + if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_READ) ) return -ret; act._sa_handler = old_act->_sa_handler; target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]); act.sa_flags = old_act->sa_flags; @@ -2737,6 +2816,7 @@ if (!is_error(ret) && arg3) { lock_user_struct(old_act, arg3, 0); + if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_WRITE) ) return -ret; old_act->_sa_handler = oact._sa_handler; old_act->sa_flags = oact.sa_flags; old_act->sa_mask.sig[0] = oact.sa_mask.sig[0]; @@ -2753,12 +2833,16 @@ struct target_sigaction *act; struct target_sigaction *oact; - if (arg2) + if (arg2) { lock_user_struct(act, arg2, 1); + if( ret=page_check_range(act,sizeof(*act),PAGE_READ) ) return -ret; + } else act = NULL; - if (arg3) + if (arg3) { lock_user_struct(oact, arg3, 0); + if( ret=page_check_range(oact,sizeof(*oact),PAGE_WRITE) ) return -ret; + } else oact = NULL; ret = get_errno(do_sigaction(arg1, act, oact)); @@ -2878,6 +2962,7 @@ ret = get_errno(sigpending(&set)); if (!is_error(ret)) { p = lock_user(arg1, sizeof(target_sigset_t), 0); + if( ret=page_check_range(p,sizeof(target_sigset_t),PAGE_WRITE) ) return -ret; host_to_target_sigset(p, &set); unlock_user(p, arg1, sizeof(target_sigset_t)); } @@ -3341,6 +3426,7 @@ struct target_stat *target_st; lock_user_struct(target_st, arg2, 0); + if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret; target_st->st_dev = tswap16(st.st_dev); target_st->st_ino = tswapl(st.st_ino); #if defined(TARGET_PPC) || defined(TARGET_MIPS) @@ -3840,6 +3926,7 @@ #ifdef TARGET_NR_stat64 case TARGET_NR_stat64: p = lock_user_string(arg1); + if( ret=page_check_range(p,1,PAGE_READ) ) return -ret; ret = get_errno(stat(path(p), &st)); unlock_user(p, arg1, 0); goto do_stat64; @@ -3847,6 +3934,7 @@ #ifdef TARGET_NR_lstat64 case TARGET_NR_lstat64: p = lock_user_string(arg1); + if( ret=page_check_range(p,1,PAGE_READ) ) return -ret; ret = get_errno(lstat(path(p), &st)); unlock_user(p, arg1, 0); goto do_stat64; @@ -3861,6 +3949,7 @@ if (((CPUARMState *)cpu_env)->eabi) { struct target_eabi_stat64 *target_st; lock_user_struct(target_st, arg2, 1); + if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret; memset(target_st, 0, sizeof(struct target_eabi_stat64)); /* put_user is probably wrong. */ put_user(st.st_dev, &target_st->st_dev); @@ -3886,6 +3975,7 @@ { struct target_stat64 *target_st; lock_user_struct(target_st, arg2, 1); + if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret; memset(target_st, 0, sizeof(struct target_stat64)); /* ??? put_user is probably wrong. */ put_user(st.st_dev, &target_st->st_dev);