From 9a8216ea7b3466c2ef0393aae4c59447344ac092 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 27 Jun 2016 00:02:50 +0000 Subject: [PATCH] Mpersify fetchers of struct msghdr and struct mmsghdr * fetch_struct_msghdr.c: New file. * fetch_struct_mmsghdr.c: Likewise. * Makefile.am (strace_SOURCES): Add them. * net.c (struct msghdr32, struct mmsghdr32, copy_from_msghdr32, fetch_msghdr, fetch_mmsghdr): Remove. (decode_msghdr, dumpiov_in_msghdr): Use fetch_struct_msghdr instead of fetch_msghdr. (decode_mmsghdr): Change msg_len argument to use_msg_len. Use fetch_struct_mmsghdr instead of fetch_mmsghdr. Return fetch_struct_mmsghdr's return code. (decode_mmsg): Rename to decode_mmsgvec. Take addr and len arguments. Do not print vlen and flags. Check decode_mmsghdr's return code. Print mmsghdr array using square brackets. (dumpiov_in_mmsghdr): Use fetch_struct_mmsghdr instead of fetch_mmsghdr. (SYS_FUNC(sendmmsg), SYS_FUNC(recvmmsg)): Use decode_mmsgvec instead of decode_mmsg. Print vlen and flags. * tests/mmsg.c (main): Update expected output. --- Makefile.am | 2 + fetch_struct_mmsghdr.c | 82 +++++++++++++++++++++++ fetch_struct_msghdr.c | 79 ++++++++++++++++++++++ net.c | 145 +++++++++++++---------------------------- tests/mmsg.c | 8 +-- 5 files changed, 212 insertions(+), 104 deletions(-) create mode 100644 fetch_struct_mmsghdr.c create mode 100644 fetch_struct_msghdr.c diff --git a/Makefile.am b/Makefile.am index 1a578376..b310ec9a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -108,6 +108,8 @@ strace_SOURCES = \ fcntl.c \ fetch_seccomp_fprog.c \ fetch_struct_flock.c \ + fetch_struct_mmsghdr.c \ + fetch_struct_msghdr.c \ fetch_struct_statfs.c \ file.c \ file_handle.c \ diff --git a/fetch_struct_mmsghdr.c b/fetch_struct_mmsghdr.c new file mode 100644 index 00000000..932de69b --- /dev/null +++ b/fetch_struct_mmsghdr.c @@ -0,0 +1,82 @@ +/* + * 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 DEF_MPERS_TYPE(struct_mmsghdr) + +#include "msghdr.h" +typedef struct mmsghdr struct_mmsghdr; + +#include MPERS_DEFS + +/* + * On success, return the number of fetched bytes. + * On error, return 0; + * + * This function cannot use umove_or_printaddr because + * it is called by dumpio and therefore cannot print anything. + */ + +MPERS_PRINTER_DECL(int, fetch_struct_mmsghdr, + struct tcb *tcp, const unsigned long addr, void *p) +{ + struct mmsghdr *p_native = p; + struct_mmsghdr v_compat; + + if (sizeof(*p_native) == sizeof(v_compat)) + return umove(tcp, addr, p_native) ? 0 : sizeof(*p_native); + + if (umove(tcp, addr, &v_compat)) + return 0; + + p_native->msg_hdr.msg_name = (void *) (unsigned long) + v_compat.msg_hdr.msg_name; + + p_native->msg_hdr.msg_namelen = + v_compat.msg_hdr.msg_namelen; + + p_native->msg_hdr.msg_iov = (void *) (unsigned long) + v_compat.msg_hdr.msg_iov; + + p_native->msg_hdr.msg_iovlen = + v_compat.msg_hdr.msg_iovlen; + + p_native->msg_hdr.msg_control = (void *) (unsigned long) + v_compat.msg_hdr.msg_control; + + p_native->msg_hdr.msg_controllen = + v_compat.msg_hdr.msg_controllen; + + p_native->msg_hdr.msg_flags = + v_compat.msg_hdr.msg_flags; + + p_native->msg_len = + v_compat.msg_len; + + return sizeof(v_compat); +} diff --git a/fetch_struct_msghdr.c b/fetch_struct_msghdr.c new file mode 100644 index 00000000..78b505b8 --- /dev/null +++ b/fetch_struct_msghdr.c @@ -0,0 +1,79 @@ +/* + * 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 DEF_MPERS_TYPE(struct_msghdr) + +#include "msghdr.h" +typedef struct msghdr struct_msghdr; + +#include MPERS_DEFS + +/* + * On success, return the number of fetched bytes. + * On error, return 0; + * + * This function cannot use umove_or_printaddr because + * it is called by dumpio and therefore cannot print anything. + */ + +MPERS_PRINTER_DECL(int, fetch_struct_msghdr, + struct tcb *tcp, const unsigned long addr, void *p) +{ + struct msghdr *p_native = p; + struct_msghdr v_compat; + + if (sizeof(*p_native) == sizeof(v_compat)) + return umove(tcp, addr, p_native) ? 0 : sizeof(*p_native); + + if (umove(tcp, addr, &v_compat)) + return 0; + + p_native->msg_name = (void *) (unsigned long) + v_compat.msg_name; + + p_native->msg_namelen = + v_compat.msg_namelen; + + p_native->msg_iov = (void *) (unsigned long) + v_compat.msg_iov; + + p_native->msg_iovlen = + v_compat.msg_iovlen; + + p_native->msg_control = (void *) (unsigned long) + v_compat.msg_control; + + p_native->msg_controllen = + v_compat.msg_controllen; + + p_native->msg_flags = + v_compat.msg_flags; + + return sizeof(v_compat); +} diff --git a/net.c b/net.c index 3a7f9403..7616a5b9 100644 --- a/net.c +++ b/net.c @@ -427,80 +427,12 @@ print_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size) tprints("}"); } -struct msghdr32 { - uint32_t /* void* */ msg_name; - uint32_t /* socklen_t */msg_namelen; - uint32_t /* iovec* */ msg_iov; - uint32_t /* size_t */ msg_iovlen; - uint32_t /* void* */ msg_control; - uint32_t /* size_t */ msg_controllen; - uint32_t /* int */ msg_flags; -}; -struct mmsghdr32 { - struct msghdr32 msg_hdr; - uint32_t /* unsigned */ msg_len; -}; - -#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 -static void -copy_from_msghdr32(struct msghdr *to_msg, struct msghdr32 *from_msg32) -{ - to_msg->msg_name = (void*)(long)from_msg32->msg_name; - to_msg->msg_namelen = from_msg32->msg_namelen; - to_msg->msg_iov = (void*)(long)from_msg32->msg_iov; - to_msg->msg_iovlen = from_msg32->msg_iovlen; - to_msg->msg_control = (void*)(long)from_msg32->msg_control; - to_msg->msg_controllen = from_msg32->msg_controllen; - to_msg->msg_flags = from_msg32->msg_flags; -} -#endif - -static bool -fetch_msghdr(struct tcb *tcp, long addr, struct msghdr *msg) -{ -#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 - if (current_wordsize == 4) { - struct msghdr32 msg32; - - if (umove(tcp, addr, &msg32) < 0) - return false; - copy_from_msghdr32(msg, &msg32); - } else -#endif - if (umove(tcp, addr, msg) < 0) - return false; - return true; -} - -static bool -fetch_mmsghdr(struct tcb *tcp, long addr, unsigned int idx, struct mmsghdr *mmsg) -{ -#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 - if (current_wordsize == 4) { - struct mmsghdr32 mmsg32; - - addr += sizeof(struct mmsghdr32) * idx; - if (umove(tcp, addr, &mmsg32) < 0) - return false; - - copy_from_msghdr32(&mmsg->msg_hdr, &mmsg32.msg_hdr); - mmsg->msg_len = mmsg32.msg_len; - } else -#endif - { - addr += sizeof(*mmsg) * idx; - if (umove(tcp, addr, mmsg) < 0) - return false; - } - return true; -} - static void decode_msghdr(struct tcb *tcp, long addr, unsigned long data_size) { struct msghdr msg; - if (verbose(tcp) && fetch_msghdr(tcp, addr, &msg)) + if (addr && verbose(tcp) && fetch_struct_msghdr(tcp, addr, &msg)) print_msghdr(tcp, &msg, data_size); else printaddr(addr); @@ -511,62 +443,63 @@ dumpiov_in_msghdr(struct tcb *tcp, long addr, unsigned long data_size) { struct msghdr msg; - if (fetch_msghdr(tcp, addr, &msg)) + if (fetch_struct_msghdr(tcp, addr, &msg)) dumpiov_upto(tcp, msg.msg_iovlen, (long)msg.msg_iov, data_size); } -static void -decode_mmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len) +static int +decode_mmsghdr(struct tcb *tcp, long addr, bool use_msg_len) { struct mmsghdr mmsg; + int fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg); - if (fetch_mmsghdr(tcp, addr, idx, &mmsg)) { + if (fetched) { tprints("{"); - print_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len); + print_msghdr(tcp, &mmsg.msg_hdr, use_msg_len ? mmsg.msg_len : -1UL); tprintf(", %u}", mmsg.msg_len); - } - else + } else { printaddr(addr); + } + + return fetched; } static void -decode_mmsg(struct tcb *tcp, unsigned long msg_len) +decode_mmsgvec(struct tcb *tcp, unsigned long addr, unsigned int len, + bool use_msg_len) { - /* mmsgvec */ if (syserror(tcp)) { - printaddr(tcp->u_arg[1]); + printaddr(addr); } else { - unsigned int len = tcp->u_rval; - unsigned int i; + unsigned int i, fetched; - tprints("{"); - for (i = 0; i < len; ++i) { + tprints("["); + for (i = 0; i < len; ++i, addr += fetched) { if (i) tprints(", "); - decode_mmsghdr(tcp, tcp->u_arg[1], i, msg_len); + fetched = decode_mmsghdr(tcp, addr, use_msg_len); + if (!fetched) + break; } - tprints("}"); + tprints("]"); } - /* vlen */ - tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); - /* flags */ - printflags(msg_flags, tcp->u_arg[3], "MSG_???"); } void dumpiov_in_mmsghdr(struct tcb *tcp, long addr) { unsigned int len = tcp->u_rval; - unsigned int i; + unsigned int i, fetched; struct mmsghdr mmsg; - for (i = 0; i < len; ++i) { - if (fetch_mmsghdr(tcp, addr, i, &mmsg)) { - tprintf(" = %lu buffers in vector %u\n", - (unsigned long)mmsg.msg_hdr.msg_iovlen, i); - dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen, - (long)mmsg.msg_hdr.msg_iov, mmsg.msg_len); - } + for (i = 0; i < len; ++i, addr += fetched) { + fetched = fetch_struct_mmsghdr(tcp, addr, &mmsg); + if (!fetched) + break; + tprintf(" = %lu buffers in vector %u\n", + (unsigned long)mmsg.msg_hdr.msg_iovlen, i); + dumpiov_upto(tcp, mmsg.msg_hdr.msg_iovlen, + (long)mmsg.msg_hdr.msg_iov, mmsg.msg_len); } } @@ -727,12 +660,18 @@ SYS_FUNC(sendmmsg) tprints(", "); if (!verbose(tcp)) { printaddr(tcp->u_arg[1]); + /* vlen */ tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); + /* flags */ printflags(msg_flags, tcp->u_arg[3], "MSG_???"); + return RVAL_DECODED; } } else { - if (verbose(tcp)) - decode_mmsg(tcp, (unsigned long) -1L); + decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, false); + /* vlen */ + tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); + /* flags */ + printflags(msg_flags, tcp->u_arg[3], "MSG_???"); } return 0; } @@ -820,7 +759,9 @@ SYS_FUNC(recvmmsg) tcp->auxstr = sprint_timespec(tcp, tcp->u_arg[4]); } else { printaddr(tcp->u_arg[1]); + /* vlen */ tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); + /* flags */ printflags(msg_flags, tcp->u_arg[3], "MSG_???"); tprints(", "); print_timespec(tcp, tcp->u_arg[4]); @@ -828,7 +769,11 @@ SYS_FUNC(recvmmsg) return 0; } else { if (verbose(tcp)) { - decode_mmsg(tcp, 0); + decode_mmsgvec(tcp, tcp->u_arg[1], tcp->u_rval, true); + /* vlen */ + tprintf(", %u, ", (unsigned int) tcp->u_arg[2]); + /* flags */ + printflags(msg_flags, tcp->u_arg[3], "MSG_???"); tprints(", "); /* timeout on entrance */ tprints(tcp->auxstr); diff --git a/tests/mmsg.c b/tests/mmsg.c index 00e1ef33..d82b7cdd 100644 --- a/tests/mmsg.c +++ b/tests/mmsg.c @@ -139,12 +139,12 @@ main(void) perror_msg_and_skip("sendmmsg"); assert(r == (int) n_w_mmh); assert(close(1) == 0); - tprintf("sendmmsg(1, {{{msg_name=NULL, msg_namelen=0" + tprintf("sendmmsg(1, [{{msg_name=NULL, msg_namelen=0" ", msg_iov=[{\"%s\", %u}, {\"%s\", %u}], msg_iovlen=%u" ", msg_controllen=0, msg_flags=0}, %u}" ", {{msg_name=NULL, msg_namelen=0" ", msg_iov=[{\"%s\", %u}], msg_iovlen=%u" - ", msg_controllen=0, msg_flags=0}, %u}}, %u" + ", msg_controllen=0, msg_flags=0}, %u}], %u" ", MSG_DONTROUTE|MSG_NOSIGNAL) = %d\n" " = %u buffers in vector 0\n" " * %u bytes in buffer 0\n" @@ -213,12 +213,12 @@ main(void) assert(recv_mmsg(0, r_mmh, n_r_mmh, MSG_DONTWAIT, NULL) == (int) n_r_mmh); assert(close(0) == 0); - tprintf("recvmmsg(0, {{{msg_name=NULL, msg_namelen=0" + tprintf("recvmmsg(0, [{{msg_name=NULL, msg_namelen=0" ", msg_iov=[{\"%s\", %u}], msg_iovlen=%u" ", msg_controllen=0, msg_flags=0}, %u}" ", {{msg_name=NULL, msg_namelen=0" ", msg_iov=[{\"%s\", %u}, {\"\", %u}], msg_iovlen=%u" - ", msg_controllen=0, msg_flags=0}, %u}}, %u" + ", msg_controllen=0, msg_flags=0}, %u}], %u" ", MSG_DONTWAIT, NULL) = %d (left NULL)\n" " = %u buffers in vector 0\n" " * %u bytes in buffer 0\n" -- 2.40.0