forked from OSchip/llvm-project
[msan] Intercept sendmmsg, recvmmsg.
Summary: Extend the sendmsg test to cover all recv*. Reviewers: vitalybuka Subscribers: llvm-commits, kubamracek Differential Revision: https://reviews.llvm.org/D41620 llvm-svn: 321774
This commit is contained in:
parent
ca30902ff8
commit
f2b2169ded
|
@ -2810,7 +2810,7 @@ INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
|
|||
#define INIT_MODF
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_RECVMSG
|
||||
#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
|
||||
static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
|
||||
SSIZE_T maxlen) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
|
||||
|
@ -2823,7 +2823,9 @@ static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
|
|||
if (msg->msg_control && msg->msg_controllen)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_RECVMSG
|
||||
INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
|
||||
int flags) {
|
||||
void *ctx;
|
||||
|
@ -2846,7 +2848,30 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
|
|||
#define INIT_RECVMSG
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_SENDMSG
|
||||
#if SANITIZER_INTERCEPT_RECVMMSG
|
||||
INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
|
||||
unsigned int vlen, int flags, void *timeout) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
|
||||
if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
|
||||
int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
|
||||
if (res >= 0) {
|
||||
if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
||||
for (int i = 0; i < res; ++i) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
|
||||
sizeof(msgvec[i].msg_len));
|
||||
write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
|
||||
COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
|
||||
#else
|
||||
#define INIT_RECVMMSG
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
|
||||
static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
|
||||
const unsigned kCmsgDataOffset =
|
||||
RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));
|
||||
|
@ -2896,7 +2921,9 @@ static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
|
|||
if (msg->msg_control && msg->msg_controllen)
|
||||
read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_SENDMSG
|
||||
INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
|
||||
int flags) {
|
||||
void *ctx;
|
||||
|
@ -2915,6 +2942,30 @@ INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
|
|||
#define INIT_SENDMSG
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_SENDMMSG
|
||||
INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
|
||||
unsigned vlen, int flags) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
|
||||
if (fd >= 0) {
|
||||
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
||||
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
||||
}
|
||||
int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
|
||||
if (res >= 0 && msgvec)
|
||||
for (int i = 0; i < res; ++i) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
|
||||
sizeof(msgvec[i].msg_len));
|
||||
if (common_flags()->intercept_send)
|
||||
read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
|
||||
#else
|
||||
#define INIT_SENDMMSG
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_GETPEERNAME
|
||||
INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
|
||||
void *ctx;
|
||||
|
@ -6483,6 +6534,8 @@ static void InitializeCommonInterceptors() {
|
|||
INIT_MODF;
|
||||
INIT_RECVMSG;
|
||||
INIT_SENDMSG;
|
||||
INIT_RECVMMSG;
|
||||
INIT_SENDMMSG;
|
||||
INIT_GETPEERNAME;
|
||||
INIT_IOCTL;
|
||||
INIT_INET_ATON;
|
||||
|
|
|
@ -221,6 +221,8 @@
|
|||
#define SANITIZER_INTERCEPT_MODF SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX
|
||||
#define SANITIZER_INTERCEPT_SENDMMSG SI_LINUX
|
||||
#define SANITIZER_INTERCEPT_GETPEERNAME SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_IOCTL SI_POSIX
|
||||
#define SANITIZER_INTERCEPT_INET_ATON SI_POSIX
|
||||
|
|
|
@ -1026,6 +1026,12 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
|
|||
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
|
||||
CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
CHECK_TYPE_SIZE(mmsghdr);
|
||||
CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
|
||||
CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);
|
||||
#endif
|
||||
|
||||
COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
|
||||
CHECK_SIZE_AND_OFFSET(dirent, d_ino);
|
||||
#if SANITIZER_MAC
|
||||
|
|
|
@ -482,6 +482,13 @@ namespace __sanitizer {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
struct __sanitizer_mmsghdr {
|
||||
__sanitizer_msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if SANITIZER_MAC
|
||||
struct __sanitizer_dirent {
|
||||
unsigned long long d_ino;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SEND
|
||||
// RUN: %clangxx_msan %s -DSENDTO -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO
|
||||
// RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG
|
||||
// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMMSG
|
||||
|
||||
// RUN: %clangxx_msan %s -DSEND -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
// RUN: %clangxx_msan %s -DSENDTO -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
// RUN: %clangxx_msan %s -DSENDMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
// RUN: %clangxx_msan %s -DSENDMMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
|
||||
// RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && \
|
||||
// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
|
@ -12,6 +14,8 @@
|
|||
// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
// RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && \
|
||||
// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && \
|
||||
// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
|
||||
|
||||
// UNSUPPORTED: android
|
||||
|
||||
|
@ -20,54 +24,32 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
const int kBufSize = 10;
|
||||
int sockfd;
|
||||
const int kRecvBufSize = 100;
|
||||
int sockfd[2];
|
||||
|
||||
int main() {
|
||||
int ret;
|
||||
int sent;
|
||||
char buf[kBufSize] = {0};
|
||||
pthread_t client_thread;
|
||||
struct sockaddr_in serveraddr;
|
||||
struct sockaddr_in6 serveraddr6;
|
||||
char rbuf[kRecvBufSize];
|
||||
|
||||
memset(&serveraddr, 0, sizeof(serveraddr));
|
||||
serveraddr.sin_family = AF_INET;
|
||||
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
serveraddr.sin_port = 0;
|
||||
struct sockaddr *addr = (struct sockaddr *)&serveraddr;
|
||||
socklen_t addrlen = sizeof(serveraddr);
|
||||
|
||||
sockfd = socket(addr->sa_family, SOCK_DGRAM, 0);
|
||||
if (sockfd <= 0) {
|
||||
// Try to fall-back to IPv6
|
||||
memset(&serveraddr6, 0, sizeof(serveraddr6));
|
||||
serveraddr6.sin6_family = AF_INET6;
|
||||
serveraddr6.sin6_addr = in6addr_any;
|
||||
serveraddr6.sin6_port = 0;
|
||||
addr = (struct sockaddr *)&serveraddr6;
|
||||
addrlen = sizeof(serveraddr6);
|
||||
|
||||
sockfd = socket(addr->sa_family, SOCK_DGRAM, 0);
|
||||
}
|
||||
assert(sockfd > 0);
|
||||
|
||||
bind(sockfd, addr, addrlen);
|
||||
getsockname(sockfd, addr, &addrlen);
|
||||
ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, sockfd);
|
||||
assert(!ret);
|
||||
|
||||
#if defined(POISON)
|
||||
__msan_poison(buf + 7, 1);
|
||||
#endif
|
||||
|
||||
#if defined(SENDMSG)
|
||||
#if defined(SENDMSG) || defined(SENDMMSG)
|
||||
struct iovec iov[2] = {{buf, 5}, {buf + 5, 5}};
|
||||
struct msghdr msg;
|
||||
msg.msg_name = addr;
|
||||
msg.msg_namelen = addrlen;
|
||||
msg.msg_name = nullptr;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_control = 0;
|
||||
|
@ -75,20 +57,95 @@ int main() {
|
|||
msg.msg_flags = 0;
|
||||
#endif
|
||||
|
||||
#if defined(SENDMMSG)
|
||||
struct iovec iov0[1] = {{buf, 7}};
|
||||
struct msghdr msg0;
|
||||
msg0.msg_name = nullptr;
|
||||
msg0.msg_namelen = 0;
|
||||
msg0.msg_iov = iov0;
|
||||
msg0.msg_iovlen = 1;
|
||||
msg0.msg_control = 0;
|
||||
msg0.msg_controllen = 0;
|
||||
msg0.msg_flags = 0;
|
||||
|
||||
struct mmsghdr mmsg[2];
|
||||
mmsg[0].msg_hdr = msg0; // good
|
||||
mmsg[1].msg_hdr = msg; // poisoned
|
||||
#endif
|
||||
|
||||
#if defined(SEND)
|
||||
ret = connect(sockfd, addr, addrlen);
|
||||
assert(ret == 0);
|
||||
ret = send(sockfd, buf, kBufSize, 0);
|
||||
sent = send(sockfd[0], buf, kBufSize, 0);
|
||||
// SEND: Uninitialized bytes in __interceptor_send at offset 7 inside [{{.*}}, 10)
|
||||
assert(ret > 0);
|
||||
assert(sent > 0);
|
||||
|
||||
ret = recv(sockfd[1], rbuf, kRecvBufSize, 0);
|
||||
assert(ret == sent);
|
||||
assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
|
||||
#elif defined(SENDTO)
|
||||
ret = sendto(sockfd, buf, kBufSize, 0, addr, addrlen);
|
||||
sent = sendto(sockfd[0], buf, kBufSize, 0, nullptr, 0);
|
||||
// SENDTO: Uninitialized bytes in __interceptor_sendto at offset 7 inside [{{.*}}, 10)
|
||||
assert(ret > 0);
|
||||
assert(sent > 0);
|
||||
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t sslen = sizeof(ss);
|
||||
ret = recvfrom(sockfd[1], rbuf, kRecvBufSize, 0, (struct sockaddr *)&ss,
|
||||
&sslen);
|
||||
assert(ret == sent);
|
||||
assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
|
||||
assert(__msan_test_shadow(&ss, sizeof(ss)) == sslen);
|
||||
#elif defined(SENDMSG)
|
||||
ret = sendmsg(sockfd, &msg, 0);
|
||||
sent = sendmsg(sockfd[0], &msg, 0);
|
||||
// SENDMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
|
||||
assert(ret > 0);
|
||||
assert(sent > 0);
|
||||
|
||||
struct iovec riov[2] = {{rbuf, 3}, {rbuf + 3, kRecvBufSize - 3}};
|
||||
struct msghdr rmsg;
|
||||
rmsg.msg_name = nullptr;
|
||||
rmsg.msg_namelen = 0;
|
||||
rmsg.msg_iov = riov;
|
||||
rmsg.msg_iovlen = 2;
|
||||
rmsg.msg_control = 0;
|
||||
rmsg.msg_controllen = 0;
|
||||
rmsg.msg_flags = 0;
|
||||
|
||||
ret = recvmsg(sockfd[1], &rmsg, 0);
|
||||
assert(ret == sent);
|
||||
assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
|
||||
#elif defined(SENDMMSG)
|
||||
sent = sendmmsg(sockfd[0], mmsg, 2, 0);
|
||||
// SENDMMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
|
||||
assert(sent == 2);
|
||||
if (ret >= 2)
|
||||
assert(mmsg[1].msg_len > 0);
|
||||
|
||||
struct iovec riov[2] = {{rbuf + kRecvBufSize / 2, kRecvBufSize / 2}};
|
||||
struct msghdr rmsg;
|
||||
rmsg.msg_name = nullptr;
|
||||
rmsg.msg_namelen = 0;
|
||||
rmsg.msg_iov = riov;
|
||||
rmsg.msg_iovlen = 1;
|
||||
rmsg.msg_control = 0;
|
||||
rmsg.msg_controllen = 0;
|
||||
rmsg.msg_flags = 0;
|
||||
|
||||
struct iovec riov0[2] = {{rbuf, kRecvBufSize / 2}};
|
||||
struct msghdr rmsg0;
|
||||
rmsg0.msg_name = nullptr;
|
||||
rmsg0.msg_namelen = 0;
|
||||
rmsg0.msg_iov = riov0;
|
||||
rmsg0.msg_iovlen = 1;
|
||||
rmsg0.msg_control = 0;
|
||||
rmsg0.msg_controllen = 0;
|
||||
rmsg0.msg_flags = 0;
|
||||
|
||||
struct mmsghdr rmmsg[2];
|
||||
rmmsg[0].msg_hdr = rmsg0;
|
||||
rmmsg[1].msg_hdr = rmsg;
|
||||
|
||||
ret = recvmmsg(sockfd[1], rmmsg, 2, 0, nullptr);
|
||||
assert(ret == sent);
|
||||
assert(__msan_test_shadow(rbuf, kRecvBufSize) == 7);
|
||||
assert(__msan_test_shadow(rbuf + kRecvBufSize / 2, kRecvBufSize / 2) == 10);
|
||||
#endif
|
||||
fprintf(stderr, "== done\n");
|
||||
// NEGATIVE: == done
|
||||
|
|
Loading…
Reference in New Issue