From d07eac3ac4104b89855ca5c4ba04cd2a285c6749 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 9 Jul 2016 21:52:43 +0000 Subject: [PATCH] Fix decoding of getsockname, getpeername, accept, and accept4 syscalls * net.c (fetch_socklen): New function. (decode_sockname): Use it. On entering syscall, decode early and return RVAL_DECODED when possible. On error, print the address length passed to the kernel. Do not print more bytes of the socket address than actually returned by the kernel. --- net.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/net.c b/net.c index 03922f61..86d93fc2 100644 --- a/net.c +++ b/net.c @@ -189,24 +189,43 @@ SYS_FUNC(listen) return RVAL_DECODED; } +static bool +fetch_socklen(struct tcb *tcp, int *plen, + const unsigned long sockaddr, const unsigned long socklen) +{ + return verbose(tcp) && sockaddr && socklen + && umove(tcp, socklen, plen) == 0; +} + static int decode_sockname(struct tcb *tcp) { + int ulen, rlen; + if (entering(tcp)) { printfd(tcp, tcp->u_arg[0]); tprints(", "); - return 0; + if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) { + /* abuse of auxstr to retain state */ + tcp->auxstr = (void *) (long) ulen; + return 0; + } else { + printaddr(tcp->u_arg[1]); + tprints(", "); + printaddr(tcp->u_arg[2]); + return RVAL_DECODED; + } } - int len; - if (!tcp->u_arg[2] || !verbose(tcp) || syserror(tcp) || - umove(tcp, tcp->u_arg[2], &len) < 0) { + ulen = (long) tcp->auxstr; + tcp->auxstr = NULL; + + if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) { printaddr(tcp->u_arg[1]); - tprints(", "); - printaddr(tcp->u_arg[2]); + tprintf(", [%d]", ulen); } else { - decode_sockaddr(tcp, tcp->u_arg[1], len); - tprintf(", [%d]", len); + decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen); + tprintf(", [%d]", rlen); } return RVAL_DECODED; -- 2.40.0