diff options
author | Sergey Matveev <earthdok@google.com> | 2014-02-06 18:48:23 +0000 |
---|---|---|
committer | Sergey Matveev <earthdok@google.com> | 2014-02-06 18:48:23 +0000 |
commit | 544d07f8615dbab28cab18df9fd9e5f629486d02 (patch) | |
tree | 15b4de607106e44e64eca918f9783bd523d99439 | |
parent | e2367945783c6704b8c00c1e8b20041f72b93391 (diff) | |
download | bcm5719-llvm-544d07f8615dbab28cab18df9fd9e5f629486d02.tar.gz bcm5719-llvm-544d07f8615dbab28cab18df9fd9e5f629486d02.zip |
[sanitizer] One does not simply intercept getifaddrs().
Upgrade the interceptor, and attempt to fix the Android build.
llvm-svn: 200936
5 files changed, 64 insertions, 19 deletions
diff --git a/compiler-rt/lib/msan/lit_tests/ifaddrs.cc b/compiler-rt/lib/msan/lit_tests/ifaddrs.cc index 082fbe854ec..fe11a9542dd 100644 --- a/compiler-rt/lib/msan/lit_tests/ifaddrs.cc +++ b/compiler-rt/lib/msan/lit_tests/ifaddrs.cc @@ -6,11 +6,18 @@ #include <errno.h> #include <ifaddrs.h> #include <stdio.h> +#include <string.h> #include <vector> #include <sanitizer/msan_interface.h> +#define CHECK_AND_PUSH(addr, size) \ + if (addr) { \ + assert(-1 == __msan_test_shadow(addr, sizeof(size))); \ + ranges.push_back(std::make_pair((void *)addr, (size_t)size)); \ + } + int main(int argc, char *argv[]) { struct ifaddrs *ifas; @@ -24,18 +31,20 @@ int main(int argc, char *argv[]) { assert(res == 0); assert(-1 == __msan_test_shadow(&ifas, sizeof(ifaddrs *))); - std::vector<ifaddrs *> ifas_vector; + std::vector<std::pair<void *, size_t> > ranges; ifaddrs *p = ifas; while (p) { - ifas_vector.push_back(p); - assert(-1 == __msan_test_shadow(p, sizeof(ifaddrs))); + CHECK_AND_PUSH(p, sizeof(ifaddrs)); + CHECK_AND_PUSH(p->ifa_name, strlen(p->ifa_name) + 1); + CHECK_AND_PUSH(p->ifa_addr, sizeof(*p->ifa_addr)); + CHECK_AND_PUSH(p->ifa_netmask, sizeof(*p->ifa_netmask)); + CHECK_AND_PUSH(p->ifa_broadaddr, sizeof(*p->ifa_broadaddr)); + CHECK_AND_PUSH(p->ifa_dstaddr, sizeof(*p->ifa_dstaddr)); 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))); - } + for (int i = 0; i < ranges.size(); i++) + assert(0 == __msan_test_shadow(ranges[i].first, ranges[i].second)); 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 95b5766775f..67fc2e035f6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3195,17 +3195,29 @@ INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) { // 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) { +INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **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; + __sanitizer_ifaddrs *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); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs)); + if (p->ifa_name) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name, + REAL(strlen)(p->ifa_name) + 1); + if (p->ifa_addr) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz); + if (p->ifa_netmask) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz); + // ifa_ifu is a union, but ifa_ifu.ifu_dstaddr also points to a struct + // sockaddr, so the following is sufficient. + if (p->ifa_ifu.ifu_broadaddr) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_ifu.ifu_broadaddr, + struct_sockaddr_sz); + // FIXME(smatveev): Unpoison p->ifa_data as well. + p = p->ifa_next; } } return res; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index c929005e7e9..154b5d2f5e7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -182,6 +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 +#define SANITIZER_INTERCEPT_GETIFADDRS SI_LINUX_NOT_ANDROID | 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 c6306aa88e2..1e882e324c5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -23,7 +23,6 @@ #include <dirent.h> #include <errno.h> #include <grp.h> -#include <ifaddrs.h> #include <limits.h> #include <net/if.h> #include <net/if_arp.h> @@ -67,6 +66,7 @@ #endif #if !SANITIZER_ANDROID +#include <ifaddrs.h> #include <sys/ucontext.h> #include <wordexp.h> #endif @@ -146,13 +146,13 @@ 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); #endif // SANITIZER_MAC && !SANITIZER_IOS #if !SANITIZER_ANDROID + unsigned struct_sockaddr_sz = sizeof(struct sockaddr); unsigned ucontext_t_sz = sizeof(ucontext_t); #endif // !SANITIZER_ANDROID @@ -973,6 +973,15 @@ CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch); CHECK_TYPE_SIZE(clock_t); -COMPILER_CHECK(0 == offsetof(ifaddrs, ifa_next)); +#if !SANITIZER_ANDROID +CHECK_TYPE_SIZE(ifaddrs); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_broadaddr); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr); +CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data); +#endif #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 eef015f76ff..4fe9d92a03c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -43,7 +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; + extern unsigned struct_sockaddr_sz; #if !SANITIZER_ANDROID extern unsigned ucontext_t_sz; @@ -204,13 +204,28 @@ namespace __sanitizer { uptr __unused5; #endif }; - #endif // SANITIZER_LINUX && !SANITIZER_ANDROID +#endif // SANITIZER_LINUX && !SANITIZER_ANDROID struct __sanitizer_iovec { - void *iov_base; + void *iov_base; uptr iov_len; }; +#if !SANITIZER_ANDROID + struct __sanitizer_ifaddrs { + struct __sanitizer_ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + void *ifa_addr; // (struct sockaddr *) + void *ifa_netmask; // (struct sockaddr *) + union { + void *ifu_broadaddr; // (struct sockaddr *) + void *ifu_dstaddr; // (struct sockaddr *) + } ifa_ifu; + void *ifa_data; + }; +#endif // !SANITIZER_ANDROID + #if SANITIZER_MAC typedef unsigned long __sanitizer_pthread_key_t; #else |