From 77ef78a0a5dbaa364529bd05ed7a7bd9a71dd8d4 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 9 Jul 2013 09:53:37 +0000 Subject: [PATCH] [sanitizer] Intercept realpath and canonicalize_file_name. Handle realpath(path, NULL) form. llvm-svn: 185921 --- compiler-rt/lib/asan/asan_interceptors.cc | 3 ++ compiler-rt/lib/msan/msan_interceptors.cc | 9 ---- compiler-rt/lib/msan/tests/msan_test.cc | 17 +++++++ .../sanitizer_common_interceptors.inc | 44 ++++++++++++++++++- .../sanitizer_platform_interceptors.h | 2 + .../sanitizer_platform_limits_posix.cc | 3 ++ .../sanitizer_platform_limits_posix.h | 2 + compiler-rt/lib/tsan/rtl/tsan_stat.cc | 2 + compiler-rt/lib/tsan/rtl/tsan_stat.h | 2 + 9 files changed, 74 insertions(+), 10 deletions(-) diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index b9b722e3a3f9..a8e260bacaa9 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -99,6 +99,9 @@ void SetThreadName(const char *name) { // ---------------------- Wrappers ---------------- {{{1 using namespace __asan; // NOLINT +DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) +DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) + #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ ASAN_WRITE_RANGE(ptr, size) #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index aa3342ce207e..13d67b72d873 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -619,14 +619,6 @@ INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) { return res; } -INTERCEPTOR(char *, realpath, char *path, char *abspath) { - ENSURE_MSAN_INITED(); - char *res = REAL(realpath)(path, abspath); - if (res) - __msan_unpoison(abspath, REAL(strlen)(abspath) + 1); - return res; -} - INTERCEPTOR(int, getrlimit, int resource, void *rlim) { if (msan_init_is_running) return REAL(getrlimit)(resource, rlim); @@ -1208,7 +1200,6 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(socketpair); INTERCEPT_FUNCTION(fgets); INTERCEPT_FUNCTION(fgets_unlocked); - INTERCEPT_FUNCTION(realpath); INTERCEPT_FUNCTION(getrlimit); INTERCEPT_FUNCTION(getrlimit64); INTERCEPT_FUNCTION(statfs); diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index baf7956f5638..b73e35c7de02 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -939,6 +939,23 @@ TEST(MemorySanitizer, realpath) { EXPECT_NOT_POISONED(path[0]); } +TEST(MemorySanitizer, realpath_null) { + const char* relpath = "."; + char* res = realpath(relpath, NULL); + printf("%d, %s\n", errno, strerror(errno)); + assert(res); + EXPECT_NOT_POISONED(res[0]); + free(res); +} + +TEST(MemorySanitizer, canonicalize_file_name) { + const char* relpath = "."; + char* res = canonicalize_file_name(relpath); + assert(res); + EXPECT_NOT_POISONED(res[0]); + free(res); +} + TEST(MemorySanitizer, memcpy) { char* x = new char[2]; char* y = new char[2]; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 5c7de75e3b31..702e6bbd92eb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -1580,6 +1580,46 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) { #define INIT_TCGETATTR #endif + +#if SANITIZER_INTERCEPT_REALPATH +INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path); + if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); + + // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest + // version of a versioned symbol. For realpath(), this gives us something + // (called __old_realpath) that does not handle NULL in the second argument. + // Handle it as part of the interceptor. + char *allocated_path = 0; + if (!resolved_path) + allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1); + + char *res = REAL(realpath)(path, resolved_path); + if (allocated_path && !res) + WRAP(free)(allocated_path); + if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + return res; +} +#define INIT_REALPATH INTERCEPT_FUNCTION(realpath); +#else +#define INIT_REALPATH +#endif + +#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME +INTERCEPTOR(char *, canonicalize_file_name, const char *path) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path); + if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); + char *res = REAL(canonicalize_file_name)(path); + if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + return res; +} +#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name); +#else +#define INIT_CANONICALIZE_FILE_NAME +#endif + #define SANITIZER_COMMON_INTERCEPTORS_INIT \ INIT_STRCASECMP; \ INIT_STRNCASECMP; \ @@ -1634,4 +1674,6 @@ INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) { INIT_MBSNRTOWCS; \ INIT_WCSTOMBS; \ INIT_WCSNRTOMBS; \ - INIT_TCGETATTR; + INIT_TCGETATTR; \ + INIT_REALPATH; \ + INIT_CANONICALIZE_FILE_NAME; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 6edb250a14c5..4a84e0547918 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -106,5 +106,7 @@ # define SANITIZER_INTERCEPT_WCSTOMBS SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_WCSNRTOMBS SI_MAC || SI_LINUX_NOT_ANDROID # define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX +# define SANITIZER_INTERCEPT_REALPATH SI_NOT_WINDOWS +# define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME SI_LINUX_NOT_ANDROID #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 45218fc6bbdb..abb661109b8e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -194,6 +195,8 @@ namespace __sanitizer { #endif #endif + unsigned path_max = PATH_MAX; + // ioctl arguments unsigned struct_arpreq_sz = sizeof(struct arpreq); unsigned struct_ifreq_sz = sizeof(struct ifreq); 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 91f2f112a7b6..7258526b4129 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -195,6 +195,8 @@ namespace __sanitizer { extern int glob_nomatch; #endif + extern unsigned path_max; + #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined (__x86_64)) extern unsigned struct_user_regs_struct_sz; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index 1ce60e79b1fd..3f153b6e0ab8 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc @@ -349,6 +349,8 @@ void StatOutput(u64 *stat) { name[StatInt_wcsrtombs] = " wcsrtombs "; name[StatInt_wcsnrtombs] = " wcsnrtombs "; name[StatInt_tcgetattr] = " tcgetattr "; + name[StatInt_realpath] = " realpath "; + name[StatInt_canonicalize_file_name] = " canonicalize_file_name "; name[StatAnnotation] = "Dynamic annotations "; name[StatAnnotateHappensBefore] = " HappensBefore "; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index e57ce8d94dd1..36b298e4d9fb 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -344,6 +344,8 @@ enum StatType { StatInt_wcsrtombs, StatInt_wcsnrtombs, StatInt_tcgetattr, + StatInt_realpath, + StatInt_canonicalize_file_name, // Dynamic annotations. StatAnnotation,