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.
This commit is contained in:
Дмитрий Левин 2016-07-09 21:52:43 +00:00
parent d1cedf0fdb
commit d07eac3ac4

35
net.c
View File

@ -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;