Fix corner cases of ipc syscall decoding
authorDmitry V. Levin <ldv@altlinux.org>
Fri, 22 Jul 2016 01:17:25 +0000 (01:17 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 22 Jul 2016 19:28:06 +0000 (19:28 +0000)
* xlat/ipccalls.in: New file.
* ipc.c: New file.
* Makefile.am (libstrace_a_SOURCES): Add it.
* linux/dummy.h (sys_ipc): Remove stub alias.
* syscall.c (decode_ipc_subcall): Treat 1st argument of ipc syscall
as "unsigned int".
[S390 || S390X]: Skip ipc cubcalls that have non-zero version.
[SPARC64]: Likewise, for the native personality.
Save ipc cubcall version for later use by specific ipc parsers.
* ipc_msg.c (SYS_FUNC(msgrcv)): Handle non-zero ipc subcall version.
[SPARC64]: Handle non-ipc_kludge case for the native personality.
* linux/subcall.h (msgrcv): Change nargs from 4 to 5.
* linux/s390/syscallent.h (ipc): Change nargs from 6 to 5.
* linux/s390x/syscallent.h (ipc): Likewise.

Makefile.am
ipc.c [new file with mode: 0644]
ipc_msg.c
linux/dummy.h
linux/s390/syscallent.h
linux/s390x/syscallent.h
linux/subcall.h
syscall.c
xlat/ipccalls.in [new file with mode: 0644]

index adddc6155582a597ab92f520c268f9e38bb57d71..1e7554e1a2786412c8196d74bb2cfbedcbe79f28 100644 (file)
@@ -66,6 +66,7 @@ libstrace_a_CFLAGS = $(strace_CFLAGS)
 libstrace_a_SOURCES =  \
        fstatfs.c \
        fstatfs64.c \
+       ipc.c \
        socketcall.c \
        statfs.c \
        statfs64.c \
diff --git a/ipc.c b/ipc.c
new file mode 100644 (file)
index 0000000..00a9d0d
--- /dev/null
+++ b/ipc.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+#include "xlat/ipccalls.h"
+
+SYS_FUNC(ipc)
+{
+       unsigned int call = tcp->u_arg[0];
+       unsigned int version = call >> 16;
+       call &= 0xffff;
+       const char *str = xlookup(ipccalls, call);
+
+       if (version)
+               tprintf("%u<<16|", version);
+
+       if (str)
+               tprints(str);
+       else
+               tprintf("%u", call);
+
+       unsigned int i;
+       for (i = 1; i < tcp->s_ent->nargs; ++i)
+               tprintf(", %#lx", tcp->u_arg[i]);
+
+       return RVAL_DECODED;
+}
index 965e2e493e2b54c1fa9f55c94d4af9722edeb444..daa0036529b125d746444b08f8c804fbbd459724 100644 (file)
--- a/ipc_msg.c
+++ b/ipc_msg.c
@@ -84,10 +84,10 @@ tprint_msgrcv(struct tcb *tcp, const long addr, const unsigned long count,
 }
 
 static int
-fetch_msgrcv_args(struct tcb *tcp, const long addr, long *pair)
+fetch_msgrcv_args(struct tcb *tcp, const long addr, unsigned long *pair)
 {
-       if (current_wordsize == sizeof(long)) {
-               if (umoven_or_printaddr(tcp, addr, 2 * sizeof(long), pair))
+       if (current_wordsize == sizeof(*pair)) {
+               if (umoven_or_printaddr(tcp, addr, 2 * sizeof(*pair), pair))
                        return -1;
        } else {
                unsigned int tmp[2];
@@ -106,12 +106,23 @@ SYS_FUNC(msgrcv)
                tprintf("%d, ", (int) tcp->u_arg[0]);
        } else {
                if (indirect_ipccall(tcp)) {
-                       long pair[2];
+                       const bool direct =
+#ifdef SPARC64
+                               current_wordsize == 8 ||
+#endif
+                               get_tcb_priv_ulong(tcp) != 0;
+                       if (direct) {
+                               tprint_msgrcv(tcp, tcp->u_arg[3],
+                                             tcp->u_arg[1], tcp->u_arg[4]);
+                       } else {
+                               unsigned long pair[2];
 
-                       if (fetch_msgrcv_args(tcp, tcp->u_arg[3], pair))
-                               tprintf(", %lu, ", tcp->u_arg[1]);
-                       else
-                               tprint_msgrcv(tcp, pair[0], tcp->u_arg[1], pair[1]);
+                               if (fetch_msgrcv_args(tcp, tcp->u_arg[3], pair))
+                                       tprintf(", %lu, ", tcp->u_arg[1]);
+                               else
+                                       tprint_msgrcv(tcp, pair[0],
+                                                     tcp->u_arg[1], pair[1]);
+                       }
                        printflags(ipc_msg_flags, tcp->u_arg[2], "MSG_???");
                } else {
                        tprint_msgrcv(tcp, tcp->u_arg[1],
index cfc2c3e3a2baa8fdea4eaa19833859ba4914481d..587163cefdf3a7fceabb87615e2069c54add611c 100644 (file)
 #define        sys_gettid              printargs
 #define        sys_idle                printargs
 #define        sys_inotify_init        printargs
-#define        sys_ipc                 printargs
 #define        sys_munlockall          printargs
 #define        sys_pause               printargs
 #define        sys_printargs           printargs
index af300e977ccd902f8ac19d71a98ecf2cf26855cd..fb5ddc1ceb477935f7b229b3ad84373fe9fafed3 100644 (file)
 [114] = { 4,   TP,             SEN(wait4),                     "wait4"                 },
 [115] = { 1,   TF,             SEN(swapoff),                   "swapoff"               },
 [116] = { 1,   0,              SEN(sysinfo),                   "sysinfo"               },
-[117] = { 6,   TI,             SEN(ipc),                       "ipc"                   },
+[117] = { 5,   TI,             SEN(ipc),                       "ipc"                   },
 [118] = { 1,   TD,             SEN(fsync),                     "fsync"                 },
 [119] = { 0,   TS,             SEN(sigreturn),                 "sigreturn"             },
 [120] = { 5,   TP,             SEN(clone),                     "clone"                 },
index f41f2eb8fc7d51c18e729756bfe690b28552f012..bf9c9fa9383f5391c09f6434d5e49c7d8a044486 100644 (file)
 [114] = { 4,   TP,             SEN(wait4),                     "wait4"                 },
 [115] = { 1,   TF,             SEN(swapoff),                   "swapoff"               },
 [116] = { 1,   0,              SEN(sysinfo),                   "sysinfo"               },
-[117] = { 6,   TI,             SEN(ipc),                       "ipc"                   },
+[117] = { 5,   TI,             SEN(ipc),                       "ipc"                   },
 [118] = { 1,   TD,             SEN(fsync),                     "fsync"                 },
 [119] = { 0,   TS,             SEN(sigreturn),                 "sigreturn"             },
 [120] = { 5,   TP,             SEN(clone),                     "clone"                 },
index c5ead53621c57b57e2ae7d5394e5b472c3d3c716..6d86751848400cb8b93a979e647d39f1dca574ae 100644 (file)
@@ -68,7 +68,7 @@
 [SYS_ipc_subcall +  9] = { 6,  0,              SEN(printargs),         "ipc_subcall"           },
 [SYS_ipc_subcall + 10] = { 6,  0,              SEN(printargs),         "ipc_subcall"           },
 [SYS_ipc_subcall + 11] = { 4,  IS|TI,          SEN(msgsnd),            "msgsnd"                },
-[SYS_ipc_subcall + 12] = { 4,  IS|TI,          SEN(msgrcv),            "msgrcv"                },
+[SYS_ipc_subcall + 12] = { 5,  IS|TI,          SEN(msgrcv),            "msgrcv"                },
 [SYS_ipc_subcall + 13] = { 2,  IS|TI,          SEN(msgget),            "msgget"                },
 [SYS_ipc_subcall + 14] = { 4,  IS|TI,          SEN(msgctl),            "msgctl"                },
 [SYS_ipc_subcall + 15] = { 6,  0,              SEN(printargs),         "ipc_subcall"           },
index 7a842ccc3ed6ae3c47d9dc4cfad8fd8061ea1a56..ca7e83dd528661739fa2aa8d9e84b553203bbed1 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -594,15 +594,37 @@ decode_socket_subcall(struct tcb *tcp)
 static void
 decode_ipc_subcall(struct tcb *tcp)
 {
-       unsigned int i, n;
+       unsigned int call = tcp->u_arg[0];
+       const unsigned int version = call >> 16;
 
-       if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
+       if (version) {
+# if defined S390 || defined S390X
                return;
+# else
+#  ifdef SPARC64
+               if (current_wordsize == 8)
+                       return;
+#  endif
+               set_tcb_priv_ulong(tcp, version);
+               call &= 0xffff;
+# endif
+       }
 
-       tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
+       switch (call) {
+               case  1: case  2: case  3: case  4:
+               case 11: case 12: case 13: case 14:
+               case 21: case 22: case 23: case 24:
+                       break;
+               default:
+                       return;
+       }
+
+       tcp->scno = SYS_ipc_subcall + call;
        tcp->qual_flg = qual_flags[tcp->scno];
        tcp->s_ent = &sysent[tcp->scno];
-       n = tcp->s_ent->nargs;
+
+       const unsigned int n = tcp->s_ent->nargs;
+       unsigned int i;
        for (i = 0; i < n; i++)
                tcp->u_arg[i] = tcp->u_arg[i + 1];
 }
diff --git a/xlat/ipccalls.in b/xlat/ipccalls.in
new file mode 100644 (file)
index 0000000..b338678
--- /dev/null
@@ -0,0 +1,12 @@
+SEMOP           1
+SEMGET          2
+SEMCTL          3
+SEMTIMEDOP      4
+MSGSND         11
+MSGRCV         12
+MSGGET         13
+MSGCTL         14
+SHMAT          21
+SHMDT          22
+SHMGET         23
+SHMCTL         24