This part contains the changes to the message queue IPC syscalls. The
functions for reading and writing the msqid_ds structure have been
updated to use the kernel-like APIs. Also, additional checking has been
added to the implementations of msgsnd() and msgrecv().



                                Stuart

Stuart R. Anderson                               [EMAIL PROTECTED]
Network & Software Engineering                   http://www.netsweng.com/
1024D/37A79149:                                  0791 D3B8 9A4C 2CDC A31F
                                                 BD03 0A62 E534 37A7 9149
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;
 }

Reply via email to