The recv(), recvfrom() and recvmsg() calls allow a MSG_TRUNC flag, which
indicates that the kernel should return the available size of an
incoming message, rather than the received size.
When strace-ing a truncated recv(), strace will try to access a
return-value size area of the tracee's buffer, which may be larger than
the actual buffer:
$ obj/strace -e trace=recvfrom ~/tmp/recv-test
recvfrom(3, "\1\2\3\4\0\0\0\0", 4, MSG_TRUNC, NULL, NULL) = 8
If I add a non-readable guard page after the tracee's recv buffer, we
see strace failing to read the vm area:
$ obj/strace -e trace=recvfrom ~/tmp/recv-test+guard
recvfrom(3, obj/strace: umoven: short read (4 < 8) @0x7f0b0d7ddffc
0x7f0b0d7ddffc, 4, MSG_TRUNC, NULL, NULL) = 8
This change restricts the maximum read size to the size of the tracee's
actual buffer.
The recvmsg() handler will do the right thing by using the .iov_len
data, so no change is required there.
* net.c (sys_recv, sys_recvfrom): Clamp maximum sockbuf size.
printaddr(tcp->u_arg[1]);
} else {
decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
- tcp->u_rval);
+ MIN((kernel_ulong_t) tcp->u_rval,
+ tcp->u_arg[2]));
}
tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
printaddr(tcp->u_arg[1]);
} else {
decode_sockbuf(tcp, tcp->u_arg[0], tcp->u_arg[1],
- tcp->u_rval);
+ MIN((kernel_ulong_t) tcp->u_rval,
+ tcp->u_arg[2]));
}
/* size */
tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);