diff options
5 files changed, 74 insertions, 1 deletions
diff --git a/compiler-rt/lib/msan/lit_tests/ifaddrs.cc b/compiler-rt/lib/msan/lit_tests/ifaddrs.cc new file mode 100644 index 00000000000..082fbe854ec --- /dev/null +++ b/compiler-rt/lib/msan/lit_tests/ifaddrs.cc @@ -0,0 +1,41 @@ +// RUN: %clangxx_msan -m64 -O0 %s -o %t && %t %p 2>&1 +// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %t %p 2>&1 +// RUN: %clangxx_msan -m64 -O3 %s -o %t && %t %p 2>&1 + +#include <assert.h> +#include <errno.h> +#include <ifaddrs.h> +#include <stdio.h> + +#include <vector> + +#include <sanitizer/msan_interface.h> + +int main(int argc, char *argv[]) { + struct ifaddrs *ifas; + + assert(0 == __msan_test_shadow(&ifas, sizeof(ifaddrs *))); + int res = getifaddrs(&ifas); + if (res == -1) { + assert(errno == ENOSYS); + printf("getifaddrs() is not implemented\n"); + return 0; + } + assert(res == 0); + assert(-1 == __msan_test_shadow(&ifas, sizeof(ifaddrs *))); + + std::vector<ifaddrs *> ifas_vector; + ifaddrs *p = ifas; + while (p) { + ifas_vector.push_back(p); + assert(-1 == __msan_test_shadow(p, sizeof(ifaddrs))); + p = p->ifa_next; + } + + freeifaddrs(ifas); + for (int i = 0; i < ifas_vector.size(); i++) { + ifaddrs *p = ifas_vector[i]; + assert(0 == __msan_test_shadow(p, sizeof(ifaddrs))); + } + return 0; +} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index b29fd1c700b..95b5766775f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3191,6 +3191,31 @@ INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) { #define INIT_GETRESID #endif +#if SANITIZER_INTERCEPT_GETIFADDRS +// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to +// intercept freeifaddrs(). If that ceases to be the case, we might need to +// intercept it to poison the memory again. +INTERCEPTOR(int, getifaddrs, void **ifap) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap); + int res = REAL(getifaddrs)(ifap); + if (res == 0 && ifap) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *)); + void *p = *ifap; + while (p) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, struct_ifaddrs_sz); + // Pointer to the next item is stored in the first field. + p = *reinterpret_cast<void **>(p); + } + } + return res; +} +#define INIT_GETIFADDRS \ + COMMON_INTERCEPT_FUNCTION(getifaddrs); +#else +#define INIT_GETIFADDRS +#endif + #define SANITIZER_COMMON_INTERCEPTORS_INIT \ INIT_TEXTDOMAIN; \ INIT_STRCMP; \ @@ -3309,5 +3334,6 @@ INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) { INIT_TLS_GET_ADDR; \ INIT_LISTXATTR; \ INIT_GETXATTR; \ - INIT_GETRESID; + INIT_GETRESID; \ + INIT_GETIFADDRS; /**/ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index a70211b97f3..c929005e7e9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -182,5 +182,6 @@ #define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX #define SANITIZER_INTERCEPT_GETXATTR SI_LINUX #define SANITIZER_INTERCEPT_GETRESID SI_LINUX +#define SANITIZER_INTERCEPT_GETIFADDRS SI_LINUX | SI_MAC #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index c794fd1163f..c6306aa88e2 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -23,6 +23,7 @@ #include <dirent.h> #include <errno.h> #include <grp.h> +#include <ifaddrs.h> #include <limits.h> #include <net/if.h> #include <net/if_arp.h> @@ -145,6 +146,7 @@ namespace __sanitizer { unsigned struct_sigevent_sz = sizeof(struct sigevent); unsigned struct_sched_param_sz = sizeof(struct sched_param); unsigned struct_statfs_sz = sizeof(struct statfs); + unsigned struct_ifaddrs_sz = sizeof(struct ifaddrs); #if SANITIZER_MAC && !SANITIZER_IOS unsigned struct_statfs64_sz = sizeof(struct statfs64); @@ -971,4 +973,6 @@ CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch); CHECK_TYPE_SIZE(clock_t); +COMPILER_CHECK(0 == offsetof(ifaddrs, ifa_next)); + #endif // SANITIZER_LINUX || SANITIZER_MAC diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 7097be58a54..eef015f76ff 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -43,6 +43,7 @@ namespace __sanitizer { extern unsigned struct_sched_param_sz; extern unsigned struct_statfs_sz; extern unsigned struct_statfs64_sz; + extern unsigned struct_ifaddrs_sz; #if !SANITIZER_ANDROID extern unsigned ucontext_t_sz; |