forked from OSchip/llvm-project
[sanitizer] Interceptors for gethostbyname and friends.
llvm-svn: 182573
This commit is contained in:
parent
5c24cca0f0
commit
ab25369d04
|
@ -127,6 +127,7 @@ set(SANITIZER_COMMON_CFLAGS
|
||||||
-fomit-frame-pointer
|
-fomit-frame-pointer
|
||||||
-funwind-tables
|
-funwind-tables
|
||||||
-fno-stack-protector
|
-fno-stack-protector
|
||||||
|
-Wno-gnu # Variadic macros with 0 arguments for ...
|
||||||
-O3
|
-O3
|
||||||
)
|
)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
# include <emmintrin.h>
|
# include <emmintrin.h>
|
||||||
|
@ -651,6 +652,108 @@ TEST(MemorySanitizer, bind_getsockname) {
|
||||||
close(sock);
|
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) {
|
TEST(MemorySanitizer, getcwd) {
|
||||||
char path[PATH_MAX + 1];
|
char path[PATH_MAX + 1];
|
||||||
char* res = getcwd(path, sizeof(path));
|
char* res = getcwd(path, sizeof(path));
|
||||||
|
|
|
@ -796,6 +796,152 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
|
||||||
#define INIT_GETSOCKNAME
|
#define INIT_GETSOCKNAME
|
||||||
#endif
|
#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 \
|
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
|
||||||
INIT_STRCASECMP; \
|
INIT_STRCASECMP; \
|
||||||
INIT_STRNCASECMP; \
|
INIT_STRNCASECMP; \
|
||||||
|
@ -820,4 +966,6 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
|
||||||
INIT_INET; \
|
INIT_INET; \
|
||||||
INIT_PTHREAD_GETSCHEDPARAM; \
|
INIT_PTHREAD_GETSCHEDPARAM; \
|
||||||
INIT_GETADDRINFO; \
|
INIT_GETADDRINFO; \
|
||||||
INIT_GETSOCKNAME;
|
INIT_GETSOCKNAME; \
|
||||||
|
INIT_GETHOSTBYNAME; \
|
||||||
|
INIT_GETHOSTBYNAME_R;
|
||||||
|
|
|
@ -72,5 +72,7 @@
|
||||||
# define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
|
# define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
|
||||||
# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
|
# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
|
||||||
# define SANITIZER_INTERCEPT_GETSOCKNAME 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
|
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
|
||||||
|
|
|
@ -144,4 +144,12 @@ COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_canonname) ==
|
||||||
COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_next) ==
|
COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_next) ==
|
||||||
offsetof(struct 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
|
#endif // SANITIZER_LINUX || SANITIZER_MAC
|
||||||
|
|
|
@ -101,6 +101,15 @@ namespace __sanitizer {
|
||||||
#endif
|
#endif
|
||||||
struct __sanitizer_addrinfo *ai_next;
|
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
|
} // namespace __sanitizer
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -313,6 +313,14 @@ void StatOutput(u64 *stat) {
|
||||||
name[StatInt_inet_pton] = " inet_pton ";
|
name[StatInt_inet_pton] = " inet_pton ";
|
||||||
name[StatInt_getaddrinfo] = " getaddrinfo ";
|
name[StatInt_getaddrinfo] = " getaddrinfo ";
|
||||||
name[StatInt_getsockname] = " getsockname ";
|
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[StatAnnotation] = "Dynamic annotations ";
|
||||||
name[StatAnnotateHappensBefore] = " HappensBefore ";
|
name[StatAnnotateHappensBefore] = " HappensBefore ";
|
||||||
|
|
|
@ -308,6 +308,14 @@ enum StatType {
|
||||||
StatInt_inet_pton,
|
StatInt_inet_pton,
|
||||||
StatInt_getaddrinfo,
|
StatInt_getaddrinfo,
|
||||||
StatInt_getsockname,
|
StatInt_getsockname,
|
||||||
|
StatInt_gethostent,
|
||||||
|
StatInt_gethostbyname,
|
||||||
|
StatInt_gethostbyname2,
|
||||||
|
StatInt_gethostbyaddr,
|
||||||
|
StatInt_gethostent_r,
|
||||||
|
StatInt_gethostbyname_r,
|
||||||
|
StatInt_gethostbyname2_r,
|
||||||
|
StatInt_gethostbyaddr_r,
|
||||||
|
|
||||||
// Dynamic annotations.
|
// Dynamic annotations.
|
||||||
StatAnnotation,
|
StatAnnotation,
|
||||||
|
|
Loading…
Reference in New Issue