Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-09-16 15:56:37.000000000 -0400 +++ qemu/linux-user/syscall.c 2007-09-16 15:56:42.000000000 -0400 @@ -1468,53 +1468,59 @@ target_ulong __unused5; }; -static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, - target_ulong target_addr) +static inline long copy_from_user_msqid_ds(struct msqid_ds *host_md, + struct target_msqid_ds *target_md) { - struct target_msqid_ds *target_md; + /* access has already been checked */ + copy_from_user_ipc_perm(&(host_md->msg_perm),&(target_md->msg_perm)); + __get_user(host_md->msg_stime, &target_md->msg_stime); + __get_user(host_md->msg_rtime, &target_md->msg_rtime); + __get_user(host_md->msg_ctime, &target_md->msg_ctime); + __get_user(host_md->__msg_cbytes, &target_md->__msg_cbytes); + __get_user(host_md->msg_qnum, &target_md->msg_qnum); + __get_user(host_md->msg_qbytes, &target_md->msg_qbytes); + __get_user(host_md->msg_lspid, &target_md->msg_lspid); + __get_user(host_md->msg_lrpid, &target_md->msg_lrpid); - lock_user_struct(target_md, target_addr, 1); - copy_from_user_ipc_perm(&(host_md->msg_perm),target_addr); - 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); - host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes); - host_md->msg_qnum = tswapl(target_md->msg_qnum); - host_md->msg_qbytes = tswapl(target_md->msg_qbytes); - 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 0; } -static inline void host_to_target_msqid_ds(target_ulong target_addr, +static inline long copy_to_usermsqid_ds(struct target_msqid_ds *target_md, struct msqid_ds *host_md) { - struct target_msqid_ds *target_md; + /* access has already been checked */ + copy_to_user_ipc_perm(&(target_md->msg_perm),&(host_md->msg_perm)); + __put_user(host_md->msg_stime, &target_md->msg_stime); + __put_user(host_md->msg_rtime, &target_md->msg_rtime); + __put_user(host_md->msg_ctime, &target_md->msg_ctime); + __put_user(host_md->__msg_cbytes, &target_md->__msg_cbytes); + __put_user(host_md->msg_qnum, &target_md->msg_qnum); + __put_user(host_md->msg_qbytes, &target_md->msg_qbytes); + __put_user(host_md->msg_lspid, &target_md->msg_lspid); + __put_user(host_md->msg_lrpid, &target_md->msg_lrpid); - lock_user_struct(target_md, target_addr, 0); - copy_to_user_ipc_perm(target_addr,&(host_md->msg_perm)); - 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); - target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes); - target_md->msg_qnum = tswapl(host_md->msg_qnum); - target_md->msg_qbytes = tswapl(host_md->msg_qbytes); - 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 0; } static inline long do_msgctl(long first, long second, long ptr) { struct msqid_ds dsarg; + struct target_msqid_ds *target_ds = (struct target_msqid_ds *)ptr; int cmd = second&0xff; long ret = 0; switch( cmd ) { case IPC_STAT: + if( copy_from_user(&dsarg,target_ds,sizeof(struct msqid_ds)) ) return -EFAULT; + copy_from_user_msqid_ds(&dsarg,target_ds); + ret = get_errno(msgctl(first, cmd, &dsarg)); + if( copy_to_usermsqid_ds(target_ds,&dsarg) ) return -EFAULT; + break; case IPC_SET: - target_to_host_msqid_ds(&dsarg,ptr); + if( copy_from_user(&dsarg,target_ds,sizeof(struct msqid_ds)) ) return -EFAULT; + copy_from_user_msqid_ds(&dsarg,target_ds); ret = get_errno(msgctl(first, cmd, &dsarg)); - host_to_target_msqid_ds(ptr,&dsarg); + if( copy_to_usermsqid_ds(target_ds,&dsarg) ) return -EFAULT; + break; default: ret = get_errno(msgctl(first, cmd, &dsarg)); } @@ -1522,41 +1528,45 @@ } struct target_msgbuf { - target_ulong mtype; + target_long mtype; char mtext[1]; }; static inline long do_msgsnd(long msqid, long msgp, long msgsz, long msgflg) { - struct target_msgbuf *target_mb; + struct target_msgbuf *target_mb = (struct target_msgbuf *)msgp; + target_long tmsgsz = tswap32(msgsz); struct msgbuf *host_mb; long ret = 0; - lock_user_struct(target_mb,msgp,0); - host_mb = malloc(msgsz+sizeof(long)); + if( tmsgsz < 0 ) return -EINVAL; + if( !access_ok(VERIFY_READ,target_mb,sizeof(target_long)) ) return -EFAULT; + if( !(target_mb->mtype > 0) ) return -EINVAL; + + host_mb = alloca(sizeof(long)+msgsz); + + if( copy_from_user(host_mb->mtext,target_mb->mtext,msgsz) ) return -EFAULT; host_mb->mtype = tswapl(target_mb->mtype); - memcpy(host_mb->mtext,target_mb->mtext,msgsz); ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); - free(host_mb); - unlock_user_struct(target_mb, msgp, 0); return ret; } static inline long do_msgrcv(long msqid, long msgp, long msgsz, long msgtype, long msgflg) { - struct target_msgbuf *target_mb; + struct target_msgbuf *target_mb = (struct target_msgbuf *)msgp; + target_long tmsgsz = tswap32(msgsz); struct msgbuf *host_mb; long ret = 0; - lock_user_struct(target_mb, msgp, 0); - host_mb = malloc(msgsz+sizeof(long)); - ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); + if( tmsgsz < 0 ) return -EINVAL; + + host_mb = alloca(sizeof(long)+msgsz); + + ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtype, msgflg)); if (ret > 0) - memcpy(target_mb->mtext, host_mb->mtext, ret); + if( copy_to_user(target_mb->mtext,host_mb->mtext,ret) ) return -EFAULT; target_mb->mtype = tswapl(host_mb->mtype); - free(host_mb); - unlock_user_struct(target_mb, msgp, 0); return ret; }