diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-12 11:57:48 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-12 11:57:48 +0100 |
commit | 3e759d4293076b9358a25bb61d50d3e6fff5b0e2 (patch) | |
tree | 3b9fa810c804ac68d6795ae38e9bedfb909cea8b | |
parent | afea7dd4a597e15e74ec3de5a78288056296311b (diff) | |
download | strace-3e759d4293076b9358a25bb61d50d3e6fff5b0e2.tar.gz strace-3e759d4293076b9358a25bb61d50d3e6fff5b0e2.tar.bz2 strace-3e759d4293076b9358a25bb61d50d3e6fff5b0e2.tar.xz |
Handle recv[m]msg for non-native 32-bit personality syscalls
* net.c (printmsghdr): If current_wordsize is 4 and long is wider than it,
read 32-bit struct msghdr and expand it into a native one before using it.
(printmmsghdr): Likewise for struct mmsghdr.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | net.c | 60 |
1 files changed, 56 insertions, 4 deletions
@@ -1428,11 +1428,42 @@ do_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; +}; + static void printmsghdr(struct tcb *tcp, long addr, unsigned long data_size) { struct msghdr msg; +#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 + if (current_wordsize == 4) { + struct msghdr32 msg32; + + if (umove(tcp, addr, &msg32) < 0) { + tprintf("%#lx", addr); + return; + } + msg.msg_name = (void*)(long)msg32.msg_name; + msg.msg_namelen = msg32.msg_namelen; + msg.msg_iov = (void*)(long)msg32.msg_iov; + msg.msg_iovlen = msg32.msg_iovlen; + msg.msg_control = (void*)(long)msg32.msg_control; + msg.msg_controllen = msg32.msg_controllen; + msg.msg_flags = msg32.msg_flags; + } else +#endif if (umove(tcp, addr, &msg) < 0) { tprintf("%#lx", addr); return; @@ -1448,10 +1479,31 @@ printmmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len unsigned msg_len; } mmsg; - addr += sizeof(mmsg) * idx; - if (umove(tcp, addr, &mmsg) < 0) { - tprintf("%#lx", addr); - return; +#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 + if (current_wordsize == 4) { + struct mmsghdr32 mmsg32; + + addr += sizeof(mmsg32) * idx; + if (umove(tcp, addr, &mmsg32) < 0) { + tprintf("%#lx", addr); + return; + } + mmsg.msg_hdr.msg_name = (void*)(long)mmsg32.msg_hdr.msg_name; + mmsg.msg_hdr.msg_namelen = mmsg32.msg_hdr.msg_namelen; + mmsg.msg_hdr.msg_iov = (void*)(long)mmsg32.msg_hdr.msg_iov; + mmsg.msg_hdr.msg_iovlen = mmsg32.msg_hdr.msg_iovlen; + mmsg.msg_hdr.msg_control = (void*)(long)mmsg32.msg_hdr.msg_control; + mmsg.msg_hdr.msg_controllen = mmsg32.msg_hdr.msg_controllen; + mmsg.msg_hdr.msg_flags = mmsg32.msg_hdr.msg_flags; + mmsg.msg_len = mmsg32.msg_len; + } else +#endif + { + addr += sizeof(mmsg) * idx; + if (umove(tcp, addr, &mmsg) < 0) { + tprintf("%#lx", addr); + return; + } } tprints("{"); do_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len); |