diff options
5 files changed, 169 insertions, 30 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 16117cd28b6..165d206bad8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2498,6 +2498,37 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg, #define INIT_RECVMSG #endif +#if SANITIZER_INTERCEPT_SENDMSG +static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg, + SSIZE_T maxlen) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, msg, sizeof(*msg)); + if (msg->msg_name && msg->msg_namelen) + COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen); + if (msg->msg_iov && msg->msg_iovlen) + COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov, + sizeof(*msg->msg_iov) * msg->msg_iovlen); + read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen); + if (msg->msg_control && msg->msg_controllen) + COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_control, msg->msg_controllen); +} + +INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg, + int flags) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags); + if (fd >= 0) { + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); + } + SSIZE_T res = REAL(sendmsg)(fd, msg, flags); + if (res >= 0 && msg) read_msghdr(ctx, msg, res); + return res; +} +#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg); +#else +#define INIT_SENDMSG +#endif + #if SANITIZER_INTERCEPT_GETPEERNAME INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) { void *ctx; @@ -5529,6 +5560,39 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, #define INIT_RECV_RECVFROM #endif +#if SANITIZER_INTERCEPT_SEND_SENDTO +INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags); + if (fd >= 0) { + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); + } + SSIZE_T res = REAL(send)(fd, buf, len, flags); + if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); + return res; +} + +INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags, + void *srcaddr, int addrlen) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, srcaddr, addrlen); + if (fd >= 0) { + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); + } + if (srcaddr && addrlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, srcaddr, addrlen); + SSIZE_T res = REAL(sendto)(fd, buf, len, flags, srcaddr, addrlen); + if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); + return res; +} +#define INIT_SEND_SENDTO \ + COMMON_INTERCEPT_FUNCTION(send); \ + COMMON_INTERCEPT_FUNCTION(sendto); +#else +#define INIT_SEND_SENDTO +#endif + #if SANITIZER_INTERCEPT_STAT INTERCEPTOR(int, stat, const char *path, void *buf) { void *ctx; @@ -5684,6 +5748,7 @@ static void InitializeCommonInterceptors() { INIT_ACCEPT4; INIT_MODF; INIT_RECVMSG; + INIT_SENDMSG; INIT_GETPEERNAME; INIT_IOCTL; INIT_INET_ATON; @@ -5796,6 +5861,7 @@ static void InitializeCommonInterceptors() { INIT_CTERMID; INIT_CTERMID_R; INIT_RECV_RECVFROM; + INIT_SEND_SENDTO; INIT_STAT; INIT___XSTAT; INIT___XSTAT64; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 43957b26627..edf3d4fe5ba 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -155,6 +155,7 @@ #define SANITIZER_INTERCEPT_ACCEPT4 SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_MODF SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_RECVMSG SI_NOT_WINDOWS +#define SANITIZER_INTERCEPT_SENDMSG SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_GETPEERNAME SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_IOCTL SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_INET_ATON SI_NOT_WINDOWS @@ -308,6 +309,7 @@ #define SANITIZER_INTERCEPTOR_HOOKS SI_LINUX #define SANITIZER_INTERCEPT_RECV_RECVFROM SI_NOT_WINDOWS +#define SANITIZER_INTERCEPT_SEND_SENDTO SI_NOT_WINDOWS #define SANITIZER_INTERCEPT_STAT (SI_FREEBSD || SI_MAC || SI_ANDROID) #define SANITIZER_INTERCEPT___XSTAT !SANITIZER_INTERCEPT_STAT && SI_NOT_WINDOWS diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 9c664145bcd..fb6227651d2 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -1615,26 +1615,6 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { } #endif -TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { - SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); - if (fd >= 0) { - FdAccess(thr, pc, fd); - FdRelease(thr, pc, fd); - } - int res = REAL(send)(fd, buf, len, flags); - return res; -} - -TSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) { - SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags); - if (fd >= 0) { - FdAccess(thr, pc, fd); - FdRelease(thr, pc, fd); - } - int res = REAL(sendmsg)(fd, msg, flags); - return res; -} - TSAN_INTERCEPTOR(int, unlink, char *path) { SCOPED_TSAN_INTERCEPTOR(unlink, path); Release(thr, pc, File2addr(path)); @@ -2560,9 +2540,6 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pipe); TSAN_INTERCEPT(pipe2); - TSAN_INTERCEPT(send); - TSAN_INTERCEPT(sendmsg); - TSAN_INTERCEPT(unlink); TSAN_INTERCEPT(tmpfile); TSAN_MAYBE_INTERCEPT_TMPFILE64; diff --git a/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc b/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc index 739d2a23815..81a5702fca1 100644 --- a/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc +++ b/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc @@ -1,6 +1,7 @@ // Test that ASan detects buffer overflow on read from socket via recvfrom. // -// RUN: %clangxx_asan %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan %s -DRECVFROM -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RECVFROM +// RUN: %clangxx_asan %s -DSENDTO -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SENDTO // // UNSUPPORTED: android @@ -25,21 +26,31 @@ const int kBufSize = 10; int sockfd; static void *client_thread_udp(void *data) { +#ifdef SENDTO + const char buf[kBufSize / 2] = {0, }; +#else const char buf[kBufSize] = {0, }; +#endif struct sockaddr_in serveraddr; socklen_t addrlen = sizeof(serveraddr); int succeeded = getsockname(sockfd, (struct sockaddr *)&serveraddr, &addrlen); CHECK_ERROR(succeeded < 0, "in getsockname"); - succeeded = sendto(sockfd, buf, kBufSize, 0, - (struct sockaddr *)&serveraddr, sizeof(serveraddr)); + succeeded = sendto(sockfd, buf, kBufSize, 0, (struct sockaddr *)&serveraddr, + sizeof(serveraddr)); + // CHECK-SENDTO: {{READ of size 10 at 0x.* thread T1}} + // CHECK-SENDTO: {{ #1 0x.* in client_thread_udp.*recvfrom.cc:}}[[@LINE-3]] CHECK_ERROR(succeeded < 0, "in sending message"); return NULL; } int main() { +#ifdef RECVFROM char buf[kBufSize / 2]; +#else + char buf[kBufSize]; +#endif pthread_t client_thread; struct sockaddr_in serveraddr; @@ -59,10 +70,10 @@ int main() { CHECK_ERROR(succeeded, "creating thread"); recvfrom(sockfd, buf, kBufSize, 0, NULL, NULL); // BOOM - // CHECK: {{WRITE of size 10 at 0x.* thread T0}} - // CHECK: {{ #1 0x.* in main.*recvfrom.cc:}}[[@LINE-2]] - // CHECK: {{Address 0x.* is located in stack of thread T0 at offset}} - // CHECK-NEXT: in{{.*}}main{{.*}}recvfrom.cc + // CHECK-RECVFROM: {{WRITE of size 10 at 0x.* thread T0}} + // CHECK-RECVFROM: {{ #1 0x.* in main.*recvfrom.cc:}}[[@LINE-2]] + // CHECK-RECVFROM: {{Address 0x.* is located in stack of thread T0 at offset}} + // CHECK-RECVFROM-NEXT: in{{.*}}main{{.*}}recvfrom.cc succeeded = pthread_join(client_thread, NULL); CHECK_ERROR(succeeded, "joining thread"); return 0; diff --git a/compiler-rt/test/msan/Linux/sendmsg.cc b/compiler-rt/test/msan/Linux/sendmsg.cc new file mode 100644 index 00000000000..b73062221d3 --- /dev/null +++ b/compiler-rt/test/msan/Linux/sendmsg.cc @@ -0,0 +1,83 @@ +// RUN: %clangxx_msan %s -DSEND -DBUF -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SEND +// RUN: %clangxx_msan %s -DSENDTO -DBUF -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO +// RUN: %clangxx_msan %s -DSENDMSG -DBUF -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG + +// FIXME: intercept connect() and add a SEND+ADDR test +// RUN: %clangxx_msan %s -DSENDTO -DADDR -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO-ADDR +// RUN: %clangxx_msan %s -DSENDMSG -DADDR -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG-ADDR + +// 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 + +// UNSUPPORTED: android + +#include <assert.h> +#include <stdio.h> +#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; + +int main() { + int ret; + char buf[kBufSize] = {0}; + pthread_t client_thread; + struct sockaddr_in serveraddr; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + memset(&serveraddr, 0, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); + serveraddr.sin_port = 0; + + bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); + socklen_t addrlen = sizeof(serveraddr); + getsockname(sockfd, (struct sockaddr *)&serveraddr, &addrlen); + +#if defined(ADDR) + assert(addrlen > 3); + __msan_poison(((char *)&serveraddr) + 3, 1); +#elif defined(BUF) + __msan_poison(buf + 7, 1); +#endif + +#if defined(SENDMSG) + struct iovec iov[2] = {{buf, 5}, {buf + 5, 5}}; + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &serveraddr; + msg.msg_namelen = addrlen; + msg.msg_iov = iov; + msg.msg_iovlen = 2; +#endif + +#if defined(SEND) + ret = connect(sockfd, (struct sockaddr *)&serveraddr, addrlen); + assert(ret == 0); + ret = send(sockfd, buf, kBufSize, 0); + // SEND: Uninitialized bytes in __interceptor_send at offset 7 inside [{{.*}}, 10) + assert(ret > 0); +#elif defined(SENDTO) + ret = + sendto(sockfd, buf, kBufSize, 0, (struct sockaddr *)&serveraddr, addrlen); + // SENDTO: Uninitialized bytes in __interceptor_sendto at offset 7 inside [{{.*}}, 10) + // SENDTO-ADDR: Uninitialized bytes in __interceptor_sendto at offset 3 inside [{{.*}}, + assert(ret > 0); +#elif defined(SENDMSG) + ret = sendmsg(sockfd, &msg, 0); + // SENDMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5) + // SENDMSG-ADDR: Uninitialized bytes in {{.*}} at offset 3 inside [{{.*}}, + assert(ret > 0); +#endif + fprintf(stderr, "== done\n"); + // NEGATIVE: == done + return 0; +} |