Significantly improved SYSV IPC call handling.  Unfortunately some of
this stuff doesn't use safe_dereference when it should.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@38 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/ChangeLog b/ChangeLog
index 5683545..14cf886 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-03-29  Tom Hughes <thh@cyberscience.com>
+
+	* vg_syscall_mem.c: Significantly improved SYSV IPC call
+	handling.  Unfortunately some of this stuff doesn't use
+	safe_dereference when it should.
+
 2002-03-27  Frederic Gobry  <gobry@puck.ch>
 
 	* configure.in: added support for maintainer mode. Now, to
diff --git a/coregrind/vg_unsafe.h b/coregrind/vg_unsafe.h
index 9fa9153..52c459b 100644
--- a/coregrind/vg_unsafe.h
+++ b/coregrind/vg_unsafe.h
@@ -46,6 +46,9 @@
 #include <net/if.h>       /* for struct ifreq et al */
 #include <net/if_arp.h>   /* for struct arpreq */
 #include <net/route.h>    /* for struct rtentry */
+#include <asm/ipc.h>      /* for struct ipc_kludge */
+#include <linux/msg.h>    /* for struct msgbuf */
+#include <linux/sem.h>    /* for struct sembuf */
 
 #include <linux/isdn.h>   /* for ISDN ioctls */
 #include <linux/module.h> /* for struct module */
diff --git a/vg_syscall_mem.c b/vg_syscall_mem.c
index 0f585d9..ce660f4 100644
--- a/vg_syscall_mem.c
+++ b/vg_syscall_mem.c
@@ -1114,14 +1114,83 @@
                         arg1,arg2,arg3,arg4,arg5,arg6);
          switch (arg1 /* call */) {
             case 1: /* IPCOP_semop */
-            case 2: /* IPCOP_semget */
-            case 3: /* IPCOP_semctl */
-            case 11: /* IPCOP_msgsnd */
-            case 12: /* IPCOP_msgrcv */
-            case 13: /* IPCOP_msgget */
-            case 14: /* IPCOP_msgctl */
+               must_be_readable ( "semop(sops)", arg5, 
+                                  arg3 * sizeof(struct sembuf) );
                KERNEL_DO_SYSCALL(res);
                break;
+            case 2: /* IPCOP_semget */
+            case 3: /* IPCOP_semctl */
+               KERNEL_DO_SYSCALL(res);
+               break;
+            case 11: /* IPCOP_msgsnd */
+               {
+                  struct msgbuf *msgp = (struct msgbuf *)arg5;
+                  Int msgsz = arg3;
+
+                  must_be_readable ( "msgsnd(msgp->mtype)", 
+                                     (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+                  must_be_readable ( "msgsnd(msgp->mtext)", 
+                                     (UInt)msgp->mtext, msgsz );
+
+                  KERNEL_DO_SYSCALL(res);
+                  break;
+               }
+            case 12: /* IPCOP_msgrcv */
+               {
+                  struct msgbuf *msgp = ((struct ipc_kludge *)arg5)->msgp;
+                  Int msgsz = arg3;
+
+                  must_be_writable ( "msgsnd(msgp->mtype)", 
+                                     (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+                  must_be_writable ( "msgsnd(msgp->mtext)", 
+                                     (UInt)msgp->mtext, msgsz );
+
+                  KERNEL_DO_SYSCALL(res);
+
+                  if ( !VG_(is_kerror)(res) && res > 0 ) {
+                     make_readable ( (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+                     make_readable ( (UInt)msgp->mtext, res );
+                  }
+                  break;
+               }
+            case 13: /* IPCOP_msgget */
+               KERNEL_DO_SYSCALL(res);
+               break;
+            case 14: /* IPCOP_msgctl */
+               {
+                  switch (arg3 /* cmd */) {
+                     case IPC_STAT:
+                        must_be_writable ( "msgctl(buf)", arg5, 
+                                           sizeof(struct msqid_ds) );
+                        KERNEL_DO_SYSCALL(res);
+                        if ( !VG_(is_kerror)(res) && res > 0 ) {
+                           make_readable ( arg5, sizeof(struct msqid_ds) );
+                        }
+                        break;
+                     case IPC_SET:
+                        must_be_readable ( "msgctl(buf)", arg5, 
+                                           sizeof(struct msqid_ds) );
+                        KERNEL_DO_SYSCALL(res);
+                        break;
+                     case IPC_STAT|IPC_64:
+                        must_be_writable ( "msgctl(buf)", arg5, 
+                                           sizeof(struct msqid64_ds) );
+                        KERNEL_DO_SYSCALL(res);
+                        if ( !VG_(is_kerror)(res) && res > 0 ) {
+                           make_readable ( arg5, sizeof(struct msqid64_ds) );
+                        }
+                        break;
+                     case IPC_SET|IPC_64:
+                        must_be_readable ( "msgctl(buf)", arg5, 
+                                           sizeof(struct msqid64_ds) );
+                        KERNEL_DO_SYSCALL(res);
+                        break;
+                     default:
+                        KERNEL_DO_SYSCALL(res);
+                        break;
+                  }
+                  break;
+               }
             case 21: /* IPCOP_shmat */
                {
                   Int shmid = arg2;
diff --git a/vg_unsafe.h b/vg_unsafe.h
index 9fa9153..52c459b 100644
--- a/vg_unsafe.h
+++ b/vg_unsafe.h
@@ -46,6 +46,9 @@
 #include <net/if.h>       /* for struct ifreq et al */
 #include <net/if_arp.h>   /* for struct arpreq */
 #include <net/route.h>    /* for struct rtentry */
+#include <asm/ipc.h>      /* for struct ipc_kludge */
+#include <linux/msg.h>    /* for struct msgbuf */
+#include <linux/sem.h>    /* for struct sembuf */
 
 #include <linux/isdn.h>   /* for ISDN ioctls */
 #include <linux/module.h> /* for struct module */