From: Dmitry V. Levin Date: Fri, 22 Jul 2016 01:17:25 +0000 (+0000) Subject: Fix corner cases of ipc syscall decoding X-Git-Tag: v4.13~12 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b412d75f747b3cd25300b76d536365b00096bd5e;p=strace Fix corner cases of ipc syscall decoding * 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. --- diff --git a/Makefile.am b/Makefile.am index adddc615..1e7554e1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 index 00000000..00a9d0d3 --- /dev/null +++ b/ipc.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Dmitry V. Levin + * 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; +} diff --git a/ipc_msg.c b/ipc_msg.c index 965e2e49..daa00365 100644 --- 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], diff --git a/linux/dummy.h b/linux/dummy.h index cfc2c3e3..587163ce 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -104,7 +104,6 @@ #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 diff --git a/linux/s390/syscallent.h b/linux/s390/syscallent.h index af300e97..fb5ddc1c 100644 --- a/linux/s390/syscallent.h +++ b/linux/s390/syscallent.h @@ -145,7 +145,7 @@ [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" }, diff --git a/linux/s390x/syscallent.h b/linux/s390x/syscallent.h index f41f2eb8..bf9c9fa9 100644 --- a/linux/s390x/syscallent.h +++ b/linux/s390x/syscallent.h @@ -139,7 +139,7 @@ [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" }, diff --git a/linux/subcall.h b/linux/subcall.h index c5ead536..6d867518 100644 --- a/linux/subcall.h +++ b/linux/subcall.h @@ -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" }, diff --git a/syscall.c b/syscall.c index 7a842ccc..ca7e83dd 100644 --- 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 index 00000000..b338678d --- /dev/null +++ b/xlat/ipccalls.in @@ -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