Index: lib/msan/msan_interceptors.cc =================================================================== --- lib/msan/msan_interceptors.cc +++ lib/msan/msan_interceptors.cc @@ -978,30 +978,6 @@ #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT #endif -INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { - ENSURE_MSAN_INITED(); - SSIZE_T res = REAL(recv)(fd, buf, len, flags); - if (res > 0) - __msan_unpoison(buf, res); - return res; -} - -INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, - void *srcaddr, int *addrlen) { - ENSURE_MSAN_INITED(); - SIZE_T srcaddr_sz; - if (srcaddr) srcaddr_sz = *addrlen; - SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); - if (res > 0) { - __msan_unpoison(buf, res); - if (srcaddr) { - SIZE_T sz = *addrlen; - __msan_unpoison(srcaddr, Min(sz, srcaddr_sz)); - } - } - return res; -} - INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { GET_MALLOC_STACK_TRACE; if (UNLIKELY(!msan_inited)) { @@ -1647,8 +1623,6 @@ INTERCEPT_FUNCTION(gethostname); MSAN_MAYBE_INTERCEPT_EPOLL_WAIT; MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT; - INTERCEPT_FUNCTION(recv); - INTERCEPT_FUNCTION(recvfrom); INTERCEPT_FUNCTION(dladdr); INTERCEPT_FUNCTION(dlerror); INTERCEPT_FUNCTION(dl_iterate_phdr); Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -5333,6 +5333,43 @@ #define INIT_CTERMID_R #endif +#if SANITIZER_INTERCEPT_RECV_RECVFROM +INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + SSIZE_T res = REAL(recv)(fd, buf, len, flags); + if (res > 0) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len); + } + if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); + return res; +} + +INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, + void *srcaddr, int *addrlen) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr, + addrlen); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + SIZE_T srcaddr_sz; + if (srcaddr) srcaddr_sz = *addrlen; + SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); + if (res > 0) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len); + if (srcaddr) + COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr, + Min((SIZE_T)*addrlen, srcaddr_sz)); + } + return res; +} +#define INIT_RECV_RECVFROM \ + COMMON_INTERCEPT_FUNCTION(recv); \ + COMMON_INTERCEPT_FUNCTION(recvfrom); +#else +#define INIT_RECV_RECVFROM +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -5509,4 +5546,5 @@ INIT_PROCESS_VM_READV; INIT_CTERMID; INIT_CTERMID_R; + INIT_RECV_RECVFROM; } Index: lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_interceptors.h +++ lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -272,5 +272,6 @@ #define SANITIZER_INTERCEPT_CTERMID_R SI_MAC || SI_FREEBSD #define SANITIZER_INTERCEPTOR_HOOKS SI_LINUX +#define SANITIZER_INTERCEPT_RECV_RECVFROM 1 #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H Index: lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- lib/tsan/rtl/tsan_interceptors.cc +++ lib/tsan/rtl/tsan_interceptors.cc @@ -1811,17 +1811,6 @@ return res; } -TSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) { - SCOPED_TSAN_INTERCEPTOR(recv, fd, buf, len, flags); - if (fd >= 0) - FdAccess(thr, pc, fd); - int res = REAL(recv)(fd, buf, len, flags); - if (res >= 0 && fd >= 0) { - FdAcquire(thr, pc, fd); - } - return res; -} - TSAN_INTERCEPTOR(int, unlink, char *path) { SCOPED_TSAN_INTERCEPTOR(unlink, path); Release(thr, pc, File2addr(path)); @@ -2698,7 +2687,6 @@ TSAN_INTERCEPT(send); TSAN_INTERCEPT(sendmsg); - TSAN_INTERCEPT(recv); TSAN_INTERCEPT(unlink); TSAN_INTERCEPT(tmpfile); Index: test/asan/TestCases/Linux/recvfrom.cc =================================================================== --- /dev/null +++ test/asan/TestCases/Linux/recvfrom.cc @@ -0,0 +1,79 @@ +// Test that ASan detects buffer overflow on read from socket via recvfrom. +// +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include +#include +#include +#include + +const int kPortNum = 1234; +const int kBufSize = 10; + +static void *server_thread_udp(void *data) { + char buf[kBufSize / 2]; + struct sockaddr_in serveraddr; // server's addr + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + fprintf(stderr, "ERROR opening socket\n"); + + memset((char *) &serveraddr, 0, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); + serveraddr.sin_port = htons(kPortNum); + + if (bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) + fprintf(stderr, "ERROR on binding\n"); + + recvfrom(sockfd, buf, kBufSize, 0, NULL, NULL); // BOOM + // CHECK: {{WRITE of size 10 at 0x.* thread T1}} + // CHECK: {{ #1 0x.* in server_thread_udp.*recvfrom.cc:}}[[@LINE-2]] + // CHECK: {{Address 0x.* is located in stack of thread T1 at offset}} + // CHECK-NEXT: in{{.*}}server_thread_udp{{.*}}recvfrom.cc + return NULL; +} + +int main() { + char buf[kBufSize] = "123456789"; + struct sockaddr_in serveraddr; // server's addr + + pthread_t server_thread; + if (pthread_create(&server_thread, NULL, server_thread_udp, NULL)) { + fprintf(stderr, "Error creating thread\n"); + exit(1); + } + + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + struct hostent *server; + char hostname[] = "localhost"; + if (sockfd < 0) + fprintf(stderr, "ERROR opening socket\n"); + + server = gethostbyname(hostname); + if (!server) { + fprintf(stderr,"ERROR, no such host as %s\n", hostname); + exit(1); + } + + memset((char *) &serveraddr, 0, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + memcpy((char *)&serveraddr.sin_addr.s_addr, (char *)server->h_addr, + server->h_length); + serveraddr.sin_port = htons(kPortNum); + sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *) &serveraddr, + sizeof(serveraddr)); + + if (pthread_join(server_thread, NULL)) { + fprintf(stderr, "Error joining thread\n"); + exit(1); + } + + return 0; +}