forked from OSchip/llvm-project
[sanitizer] Move recvmsg and recv interceptors to sanitizer_common.
This patch moves recv and recvfrom interceptors from MSan and TSan to sanitizer_common to enable them in ASan. Differential Revision: http://reviews.llvm.org/D17479 llvm-svn: 261841
This commit is contained in:
parent
12737b7f72
commit
7389936f57
|
@ -978,30 +978,6 @@ INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
|
|||
#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 @@ void InitializeInterceptors() {
|
|||
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);
|
||||
|
|
|
@ -5333,6 +5333,43 @@ INTERCEPTOR(char *, ctermid_r, char *s) {
|
|||
#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 @@ static void InitializeCommonInterceptors() {
|
|||
INIT_PROCESS_VM_READV;
|
||||
INIT_CTERMID;
|
||||
INIT_CTERMID_R;
|
||||
INIT_RECV_RECVFROM;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1814,17 +1814,6 @@ TSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) {
|
|||
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));
|
||||
|
@ -2716,7 +2705,6 @@ void InitializeInterceptors() {
|
|||
|
||||
TSAN_INTERCEPT(send);
|
||||
TSAN_INTERCEPT(sendmsg);
|
||||
TSAN_INTERCEPT(recv);
|
||||
|
||||
TSAN_INTERCEPT(unlink);
|
||||
TSAN_INTERCEPT(tmpfile);
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <pthread.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue