[sanitizer] Interceptors for gethostbyname and friends.

llvm-svn: 182573
This commit is contained in:
Evgeniy Stepanov 2013-05-23 11:10:23 +00:00
parent 5c24cca0f0
commit ab25369d04
8 changed files with 288 additions and 1 deletions

View File

@ -127,6 +127,7 @@ set(SANITIZER_COMMON_CFLAGS
-fomit-frame-pointer
-funwind-tables
-fno-stack-protector
-Wno-gnu # Variadic macros with 0 arguments for ...
-O3
)
if(NOT WIN32)

View File

@ -45,6 +45,7 @@
#include <dirent.h>
#include <pwd.h>
#include <sys/socket.h>
#include <netdb.h>
#if defined(__i386__) || defined(__x86_64__)
# include <emmintrin.h>
@ -651,6 +652,108 @@ TEST(MemorySanitizer, bind_getsockname) {
close(sock);
}
#define EXPECT_HOSTENT_NOT_POISONED(he) \
do { \
EXPECT_NOT_POISONED(*(he)); \
ASSERT_NE((void *) 0, (he)->h_name); \
ASSERT_NE((void *) 0, (he)->h_aliases); \
ASSERT_NE((void *) 0, (he)->h_addr_list); \
EXPECT_NOT_POISONED(strlen((he)->h_name)); \
char **p = (he)->h_aliases; \
while (*p) { \
EXPECT_NOT_POISONED(strlen(*p)); \
++p; \
} \
char **q = (he)->h_addr_list; \
while (*q) { \
EXPECT_NOT_POISONED(*q[0]); \
++q; \
} \
EXPECT_NOT_POISONED(*q); \
} while (0)
TEST(MemorySanitizer, gethostent) {
struct hostent *he = gethostent();
ASSERT_NE((void *)NULL, he);
EXPECT_HOSTENT_NOT_POISONED(he);
}
TEST(MemorySanitizer, gethostbyname) {
struct hostent *he = gethostbyname("localhost");
ASSERT_NE((void *)NULL, he);
EXPECT_HOSTENT_NOT_POISONED(he);
}
TEST(MemorySanitizer, gethostbyname2) {
struct hostent *he = gethostbyname2("localhost", AF_INET);
ASSERT_NE((void *)NULL, he);
EXPECT_HOSTENT_NOT_POISONED(he);
}
TEST(MemorySanitizer, gethostbyaddr) {
in_addr_t addr = inet_addr("127.0.0.1");
EXPECT_NOT_POISONED(addr);
struct hostent *he = gethostbyaddr(&addr, sizeof(addr), AF_INET);
ASSERT_NE((void *)NULL, he);
EXPECT_HOSTENT_NOT_POISONED(he);
}
TEST(MemorySanitizer, gethostent_r) {
char buf[2000];
struct hostent he;
struct hostent *result;
int err;
int res = gethostent_r(&he, buf, sizeof(buf), &result, &err);
ASSERT_EQ(0, res);
EXPECT_NOT_POISONED(result);
ASSERT_NE((void *)NULL, result);
EXPECT_HOSTENT_NOT_POISONED(result);
EXPECT_NOT_POISONED(err);
}
TEST(MemorySanitizer, gethostbyname_r) {
char buf[2000];
struct hostent he;
struct hostent *result;
int err;
int res = gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err);
ASSERT_EQ(0, res);
EXPECT_NOT_POISONED(result);
ASSERT_NE((void *)NULL, result);
EXPECT_HOSTENT_NOT_POISONED(result);
EXPECT_NOT_POISONED(err);
}
TEST(MemorySanitizer, gethostbyname2_r) {
char buf[2000];
struct hostent he;
struct hostent *result;
int err;
int res = gethostbyname2_r("localhost", AF_INET, &he, buf, sizeof(buf),
&result, &err);
ASSERT_EQ(0, res);
EXPECT_NOT_POISONED(result);
ASSERT_NE((void *)NULL, result);
EXPECT_HOSTENT_NOT_POISONED(result);
EXPECT_NOT_POISONED(err);
}
TEST(MemorySanitizer, gethostbyaddr_r) {
char buf[2000];
struct hostent he;
struct hostent *result;
int err;
in_addr_t addr = inet_addr("127.0.0.1");
EXPECT_NOT_POISONED(addr);
int res = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &he, buf, sizeof(buf),
&result, &err);
ASSERT_EQ(0, res);
EXPECT_NOT_POISONED(result);
ASSERT_NE((void *)NULL, result);
EXPECT_HOSTENT_NOT_POISONED(result);
EXPECT_NOT_POISONED(err);
}
TEST(MemorySanitizer, getcwd) {
char path[PATH_MAX + 1];
char* res = getcwd(path, sizeof(path));

View File

@ -796,6 +796,152 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
#define INIT_GETSOCKNAME
#endif
static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
if (h->h_name)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
char **p = h->h_aliases;
while (*p) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
++p;
}
COMMON_INTERCEPTOR_WRITE_RANGE(
ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
p = h->h_addr_list;
while (*p) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
++p;
}
COMMON_INTERCEPTOR_WRITE_RANGE(
ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
}
#if SANITIZER_INTERCEPT_GETHOSTBYNAME
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
if (res) write_hostent(ctx, res);
return res;
}
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
int type) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
if (res) write_hostent(ctx, res);
return res;
}
INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
struct __sanitizer_hostent *res = REAL(gethostent)();
if (res) write_hostent(ctx, res);
return res;
}
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
if (res) write_hostent(ctx, res);
return res;
}
#define INIT_GETHOSTBYNAME \
INTERCEPT_FUNCTION(gethostent); \
INTERCEPT_FUNCTION(gethostbyaddr); \
INTERCEPT_FUNCTION(gethostbyname); \
INTERCEPT_FUNCTION(gethostbyname2);
#else
#define INIT_GETHOSTBYNAME
#endif
#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
h_errnop);
int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
if (res == 0) {
if (result) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
if (*result) write_hostent(ctx, *result);
}
if (h_errnop)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
}
return res;
}
INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
__sanitizer_hostent **result, int *h_errnop) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
buflen, result, h_errnop);
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
h_errnop);
if (res == 0) {
if (result) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
if (*result) write_hostent(ctx, *result);
}
if (h_errnop)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
}
return res;
}
INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
char *buf, SIZE_T buflen, __sanitizer_hostent **result,
int *h_errnop) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
h_errnop);
int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
if (res == 0) {
if (result) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
if (*result) write_hostent(ctx, *result);
}
if (h_errnop)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
}
return res;
}
INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
__sanitizer_hostent **result, int *h_errnop) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
result, h_errnop);
int res =
REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
if (res == 0) {
if (result) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
if (*result) write_hostent(ctx, *result);
}
if (h_errnop)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
}
return res;
}
#define INIT_GETHOSTBYNAME_R \
INTERCEPT_FUNCTION(gethostent_r); \
INTERCEPT_FUNCTION(gethostbyaddr_r); \
INTERCEPT_FUNCTION(gethostbyname_r); \
INTERCEPT_FUNCTION(gethostbyname2_r);
#else
#define INIT_GETHOSTBYNAME_R
#endif
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
INIT_STRCASECMP; \
INIT_STRNCASECMP; \
@ -820,4 +966,6 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
INIT_INET; \
INIT_PTHREAD_GETSCHEDPARAM; \
INIT_GETADDRINFO; \
INIT_GETSOCKNAME;
INIT_GETSOCKNAME; \
INIT_GETHOSTBYNAME; \
INIT_GETHOSTBYNAME_R;

View File

@ -72,5 +72,7 @@
# define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_GETSOCKNAME SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_GETHOSTBYNAME_R SI_LINUX
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

View File

@ -144,4 +144,12 @@ COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_canonname) ==
COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_next) ==
offsetof(struct addrinfo, ai_next));
COMPILER_CHECK(sizeof(struct __sanitizer_hostent) == sizeof(struct hostent));
COMPILER_CHECK(offsetof(struct __sanitizer_hostent, h_name) ==
offsetof(struct hostent, h_name));
COMPILER_CHECK(offsetof(struct __sanitizer_hostent, h_aliases) ==
offsetof(struct hostent, h_aliases));
COMPILER_CHECK(offsetof(struct __sanitizer_hostent, h_addr_list) ==
offsetof(struct hostent, h_addr_list));
#endif // SANITIZER_LINUX || SANITIZER_MAC

View File

@ -101,6 +101,15 @@ namespace __sanitizer {
#endif
struct __sanitizer_addrinfo *ai_next;
};
struct __sanitizer_hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
} // namespace __sanitizer
#endif

View File

@ -313,6 +313,14 @@ void StatOutput(u64 *stat) {
name[StatInt_inet_pton] = " inet_pton ";
name[StatInt_getaddrinfo] = " getaddrinfo ";
name[StatInt_getsockname] = " getsockname ";
name[StatInt_gethostent] = " gethostent ";
name[StatInt_gethostbyname] = " gethostbyname ";
name[StatInt_gethostbyname2] = " gethostbyname2 ";
name[StatInt_gethostbyaddr] = " gethostbyaddr ";
name[StatInt_gethostent_r] = " gethostent_r ";
name[StatInt_gethostbyname_r] = " gethostbyname_r ";
name[StatInt_gethostbyname2_r] = " gethostbyname2_r ";
name[StatInt_gethostbyaddr_r] = " gethostbyaddr_r ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";

View File

@ -308,6 +308,14 @@ enum StatType {
StatInt_inet_pton,
StatInt_getaddrinfo,
StatInt_getsockname,
StatInt_gethostent,
StatInt_gethostbyname,
StatInt_gethostbyname2,
StatInt_gethostbyaddr,
StatInt_gethostent_r,
StatInt_gethostbyname_r,
StatInt_gethostbyname2_r,
StatInt_gethostbyaddr_r,
// Dynamic annotations.
StatAnnotation,