https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71445

--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Created attachment 38682
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38682&action=edit
sanitizer-msghdr.patch

Completely untested patch with what I had in mind.
Seems cmsg_len is not really used in any interceptors (other than being checked
for size and offset), and while msg_iovlen and msg_controllen are, they are
never written to by libsanitizer.  There is
sanitizer_common/sanitizer_common_syscalls.inc
which uses the kernel structure and thus is fine in any case.
By always using just the low 32 bits of msg_iovlen and msg_controllen for
64-bit Linux, all that happens is that some COMMON_INTERCEPTOR_WRITE_RANGE
might not be performed or would be shorter than for the POSIX violating
structure layout.
I guess that is a reasonable price to pay.
But, as unlike msg_controllen and cmsg_len, msg_iovlen is signed integer, I
wonder if we also shouldn't change:
if (msg->msg_iov && msg->msg_iovlen)
in write_msghdr to:
if (msg->msg_iov && msg->msg_iovlen > 0)
and add
if (msg->msg_iovlen > 0)
guard before the write_iovec call.
But, I must say all of write_msghdr looks very weird to me.
I thought the syscall only writes the msg_flags field of the structure itself
upon success, all the other fields are read, so
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
looks bogus to me, I'd have expected COMMON_INTERCEPTOR_READ_RANGE on the
selected fields that are known to be read, and COMMON_INTERCEPTOR_WRITE_RANGE
in write_msghdr only for &msg->msg_flags.  Similarly, I believe what
msg->msg_iov points to is only read, never written, so again I think
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov, ...
should have been
COMMON_INTERCEPTOR_READ_RANGE, and most likely before the call rather than in
write_msghdr.

Reply via email to